[Scummvm-git-logs] scummvm master -> 7aae5d45c9c40d5aa8c9f6e5cc0bc4c58eed09c5
dreammaster
paulfgilbert at gmail.com
Fri Apr 17 02:31:08 UTC 2020
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c4d188249c ULTIMA4: Shifted abyss jump to debugger command
4e1a461b53 ULTIMA4: Hook up bulk of the cheat actions to keybinder
e0607343af ULTIMA4: Split up controllers into their own files
7aae5d45c9 ULTIMA4: Moving more controller classes to controllers/
Commit: c4d188249c271ec66146903127ef7df0d64af161
https://github.com/scummvm/scummvm/commit/c4d188249c271ec66146903127ef7df0d64af161
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-16T19:27:48-07:00
Commit Message:
ULTIMA4: Shifted abyss jump to debugger command
Changed paths:
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/core/debugger.h
engines/ultima/ultima4/game/game.cpp
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 3643a0bccc..f2b9915d96 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -79,6 +79,7 @@ Debugger::Debugger() : Shared::Debugger() {
registerCmd("yell", WRAP_METHOD(Debugger, cmdYell));
registerCmd("3d", WRAP_METHOD(Debugger, cmd3d));
+ registerCmd("abyss", WRAP_METHOD(Debugger, cmdAbyss));
registerCmd("collisions", WRAP_METHOD(Debugger, cmdCollisions));
registerCmd("companions", WRAP_METHOD(Debugger, cmdCompanions));
registerCmd("destroy", WRAP_METHOD(Debugger, cmdDestroy));
@@ -1074,6 +1075,23 @@ bool Debugger::cmd3d(int argc, const char **argv) {
return isDebuggerActive();
}
+bool Debugger::cmdAbyss(int argc, const char **argv) {
+ // first teleport to the abyss
+ g_context->_location->_coords.x = 0xe9;
+ g_context->_location->_coords.y = 0xe9;
+ g_game->setMap(mapMgr->get(MAP_ABYSS), 1, NULL);
+
+ // then to the final altar
+ g_context->_location->_coords.x = 7;
+ g_context->_location->_coords.y = 7;
+ g_context->_location->_coords.z = 7;
+ g_ultima->_saveGame->_orientation = DIR_NORTH;
+ g_context->_party->lightTorch(100, false);
+
+ cmdIgnite(0, nullptr);
+ return isDebuggerActive();
+}
+
bool Debugger::cmdCollisions(int argc, const char **argv) {
_collisionOverride = !_collisionOverride;
print("Collision detection %s",
diff --git a/engines/ultima/ultima4/core/debugger.h b/engines/ultima/ultima4/core/debugger.h
index e1cddf4f6a..3bc7ec6c21 100644
--- a/engines/ultima/ultima4/core/debugger.h
+++ b/engines/ultima/ultima4/core/debugger.h
@@ -235,6 +235,11 @@ private:
*/
bool cmd3d(int argc, const char **argv);
+ /**
+ * Teleports to the Abyss final altar
+ */
+ bool cmdAbyss(int argc, const char **argv);
+
/**
* Collision detection on/off
*/
diff --git a/engines/ultima/ultima4/game/game.cpp b/engines/ultima/ultima4/game/game.cpp
index fdfa57eb0f..ff82a024e6 100644
--- a/engines/ultima/ultima4/game/game.cpp
+++ b/engines/ultima/ultima4/game/game.cpp
@@ -600,25 +600,6 @@ bool GameController::keyPressed(int key) {
if ((g_context->_location->_context & CTX_DUNGEON) && strchr("abefjlotxy", key))
screenMessage("%cNot here!%c\n", FG_GREY, FG_WHITE);
- else
- switch (key) {
- case 'c' + U4_ALT:
- if (settings._debug && g_context->_location->_map->isWorldMap()) {
- /* first teleport to the abyss */
- g_context->_location->_coords.x = 0xe9;
- g_context->_location->_coords.y = 0xe9;
- setMap(mapMgr->get(MAP_ABYSS), 1, NULL);
- /* then to the final altar */
- g_context->_location->_coords.x = 7;
- g_context->_location->_coords.y = 7;
- g_context->_location->_coords.z = 7;
- }
- break;
-
- default:
- valid = false;
- break;
- }
if (valid && endTurn) {
if (eventHandler->getController() == g_game)
Commit: 4e1a461b532ca56765e2c24dfac00b3b3e3d4260
https://github.com/scummvm/scummvm/commit/4e1a461b532ca56765e2c24dfac00b3b3e3d4260
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-16T19:27:48-07:00
Commit Message:
ULTIMA4: Hook up bulk of the cheat actions to keybinder
Changed paths:
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/meta_engine.cpp
engines/ultima/ultima4/meta_engine.h
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index f2b9915d96..1cfb1585d7 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -92,6 +92,7 @@ Debugger::Debugger() : Shared::Debugger() {
registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
registerCmd("items", WRAP_METHOD(Debugger, cmdItems));
registerCmd("karma", WRAP_METHOD(Debugger, cmdKarma));
+ registerCmd("leave", WRAP_METHOD(Debugger, cmdLeave));
registerCmd("location", WRAP_METHOD(Debugger, cmdLocation));
registerCmd("mixtures", WRAP_METHOD(Debugger, cmdMixtures));
registerCmd("moon", WRAP_METHOD(Debugger, cmdMoon));
@@ -218,7 +219,7 @@ bool Debugger::cmdAttack(int argc, const char **argv) {
printN("Attack: ");
if (g_context->_party->isFlying()) {
- screenMessage("\n%cDrift only!%c\n", FG_GREY, FG_WHITE);
+ print("\n%cDrift only!%c", FG_GREY, FG_WHITE);
return isDebuggerActive();
}
@@ -300,7 +301,7 @@ bool Debugger::cmdCastSpell(int argc, const char **argv) {
if (spell == -1)
return isDebuggerActive();
- screenMessage("%s!\n", spellGetName(spell)); //Prints spell name at prompt
+ print("%s!", spellGetName(spell)); //Prints spell name at prompt
g_context->_stats->setView(STATS_PARTY_OVERVIEW);
@@ -317,7 +318,7 @@ bool Debugger::cmdCastSpell(int argc, const char **argv) {
break;
case Spell::PARAM_PHASE: {
- screenMessage("To Phase: ");
+ printN("To Phase: ");
#ifdef IOS
U4IOS::IOSConversationChoiceHelper choiceController;
choiceController.fullSizeChoicePanel();
@@ -615,7 +616,7 @@ bool Debugger::cmdIgnite(int argc, const char **argv) {
}
bool Debugger::cmdJimmy(int argc, const char **argv) {
- screenMessage("Jimmy: ");
+ printN("Jimmy: ");
Direction dir = gameGetDirection();
if (dir == DIR_NONE)
@@ -1121,7 +1122,7 @@ bool Debugger::cmdDestroy(int argc, const char **argv) {
print("destroy <direction>");
return isDebuggerActive();
} else {
- screenMessage("Destroy Object\nDir: ");
+ printN("Destroy Object\nDir: ");
dir = gameGetDirection();
}
@@ -1226,9 +1227,9 @@ bool Debugger::cmdGoto(int argc, const char **argv) {
print("teleport <destination name>");
return true;
} else {
- screenMessage("Goto: ");
+ printN("Goto: ");
dest = gameGetInput(32);
- screenMessage("\n");
+ print("");
}
dest.toLowercase();
@@ -1240,7 +1241,7 @@ bool Debugger::cmdGoto(int argc, const char **argv) {
destNameLower.toLowercase();
if (destNameLower.find(dest) != Common::String::npos) {
- screenMessage("\n%s\n", mapMgr->get(destid)->getName().c_str());
+ print("\n%s", mapMgr->get(destid)->getName().c_str());
g_context->_location->_coords = g_context->_location->_map->_portals[p]->_coords;
found = true;
break;
@@ -1270,12 +1271,12 @@ bool Debugger::cmdGoto(int argc, const char **argv) {
bool Debugger::cmdHelp(int argc, const char **argv) {
if (!isDebuggerActive()) {
- screenMessage("Help!\n");
+ print("Help!");
screenPrompt();
}
- /* Help! send me to Lord British (who conveniently is right around where you are)! */
- g_game->setMap(mapMgr->get(100), 1, NULL);
+ // Help! send me to Lord British
+ g_game->setMap(mapMgr->get(100), 1, nullptr);
g_context->_location->_coords.x = 19;
g_context->_location->_coords.y = 8;
g_context->_location->_coords.z = 0;
@@ -1356,7 +1357,7 @@ bool Debugger::cmdMixtures(int argc, const char **argv) {
for (int i = 0; i < SPELL_MAX; i++)
g_ultima->_saveGame->_mixtures[i] = 99;
- screenMessage("All mixtures given");
+ print("All mixtures given");
return isDebuggerActive();
}
@@ -1382,7 +1383,7 @@ bool Debugger::cmdMoon(int argc, const char **argv) {
bool Debugger::cmdOpacity(int argc, const char **argv) {
g_context->_opacity = !g_context->_opacity;
- screenMessage("Opacity is %s", g_context->_opacity ? "on" : "off");
+ print("Opacity is %s", g_context->_opacity ? "on" : "off");
return isDebuggerActive();
}
@@ -1420,8 +1421,8 @@ bool Debugger::cmdSummon(int argc, const char **argv) {
print("summon <creature name>");
return true;
} else {
- screenMessage("Summon!\n");
- screenMessage("What?\n");
+ print("Summon!");
+ print("What?");
creature = gameGetInput();
}
@@ -1485,13 +1486,13 @@ bool Debugger::cmdTransport(int argc, const char **argv) {
} else if (isDebuggerActive()) {
dir = DIR_NONE;
} else {
- screenMessage("%s\n", tile->getName().c_str());
+ print("%s", tile->getName().c_str());
// Get the direction in which to create the transport
ReadDirController readDir;
eventHandler->pushController(&readDir);
- screenMessage("Dir: ");
+ printN("Dir: ");
dir = readDir.waitFor();
}
@@ -1558,7 +1559,7 @@ bool Debugger::cmdVirtue(int argc, const char **argv) {
g_ultima->_saveGame->_karma[i] = 0;
g_context->_stats->update();
- screenMessage("Full virtues");
+ print("Full virtues");
} else {
int virtue = strToInt(argv[1]);
diff --git a/engines/ultima/ultima4/meta_engine.cpp b/engines/ultima/ultima4/meta_engine.cpp
index cee8d0af2e..39d58b1ce2 100644
--- a/engines/ultima/ultima4/meta_engine.cpp
+++ b/engines/ultima/ultima4/meta_engine.cpp
@@ -92,6 +92,24 @@ static const KeybindingRecord PARTY_KEYS[] = {
};
static const KeybindingRecord CHEAT_KEYS[] = {
+ { KEYBIND_CHEAT_COLLISIONS, "CHEAT-COLLISIONS", "Toggle Collision Handling", "collisions", "A+c", nullptr },
+ { KEYBIND_CHEAT_DESTROY, "CHEAT-DESTROY", "Destroy Object", "destroy", "A+d", nullptr },
+ { KEYBIND_CHEAT_EQUIPMENT, "CHEAT-EQUIPMENT", "Full Equipment", "equipment", "A+e", nullptr },
+ { KEYBIND_CHEAT_GOTO, "CHEAT-GOTO", "Goto location", "goto", "A+g", nullptr },
+ { KEYBIND_CHEAT_HELP, "CHEAT-HELP", "Help - Teleport to Lord British", "goto", "A+h", nullptr },
+ { KEYBIND_CHEAT_ITEMS, "CHEAT-ITEMS", "Give Items", "items", "A+i", nullptr },
+ { KEYBIND_CHEAT_KARMA, "CHEAT-KARMA", "List Karma", "karma", "A+k", nullptr },
+ { KEYBIND_CHEAT_LEAVE, "CHEAT-LEAVE", "Leave Location", "leave", "A+l", nullptr },
+ { KEYBIND_CHEAT_MIXTURES, "CHEAT-MIXTURES", "Give Mixtures", "mixtures", "A+m", nullptr },
+ { KEYBIND_CHEAT_PARTY, "CHEAT-PARTY", "Full Party", "companions", "A+p", nullptr },
+ { KEYBIND_CHEAT_REAGENTS, "CHEAT-REAGENTS", "Give Reagents", "reagents", "A+r", nullptr },
+ { KEYBIND_CHEAT_STATS, "CHEAT-STATS", "Full Stats", "fullstats", "A+s", nullptr },
+ { KEYBIND_CHEAT_TRANSPORT, "CHEAT-TRANSPORT", "Create Transport", "transport", "A+t", nullptr },
+ { KEYBIND_CHEAT_UP, "CHEAT-UP", "Up Level", "up", "A+UP", nullptr },
+ { KEYBIND_CHEAT_DOWN, "CHEAT-DOWN", "Down Level", "down", "A+DOWN", nullptr },
+ { KEYBIND_CHEAT_VIRTUE, "CHEAT-VIRTUE", "Grant Virtue", "virtue", "A+v", nullptr },
+ { KEYBIND_CHEAT_WIND, "CHEAT-WIND", "Change Wind", "wind", "A+w", nullptr },
+
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr, nullptr }
};
diff --git a/engines/ultima/ultima4/meta_engine.h b/engines/ultima/ultima4/meta_engine.h
index 46f711a306..512a7b5092 100644
--- a/engines/ultima/ultima4/meta_engine.h
+++ b/engines/ultima/ultima4/meta_engine.h
@@ -44,6 +44,13 @@ enum KeybindingAction {
KEYBIND_PARTY4, KEYBIND_PARTY5, KEYBIND_PARTY6, KEYBIND_PARTY7,
KEYBIND_PARTY8,
+ KEYBIND_CHEAT_COLLISIONS, KEYBIND_CHEAT_DESTROY,
+ KEYBIND_CHEAT_EQUIPMENT, KEYBIND_CHEAT_GOTO, KEYBIND_CHEAT_HELP,
+ KEYBIND_CHEAT_ITEMS, KEYBIND_CHEAT_KARMA, KEYBIND_CHEAT_LEAVE,
+ KEYBIND_CHEAT_MIXTURES, KEYBIND_CHEAT_PARTY, KEYBIND_CHEAT_REAGENTS,
+ KEYBIND_CHEAT_STATS, KEYBIND_CHEAT_TRANSPORT, KEYBIND_CHEAT_UP,
+ KEYBIND_CHEAT_DOWN, KEYBIND_CHEAT_VIRTUE, KEYBIND_CHEAT_WIND,
+
KEYBIND_NONE
};
Commit: e0607343af8f2698f5ad6079af4c1f8fc9825060
https://github.com/scummvm/scummvm/commit/e0607343af8f2698f5ad6079af4c1f8fc9825060
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-16T19:27:48-07:00
Commit Message:
ULTIMA4: Split up controllers into their own files
Changed paths:
A engines/ultima/ultima4/controllers/alpha_action_controller.cpp
A engines/ultima/ultima4/controllers/alpha_action_controller.h
A engines/ultima/ultima4/controllers/controller.cpp
A engines/ultima/ultima4/controllers/controller.h
A engines/ultima/ultima4/controllers/game_controller.cpp
A engines/ultima/ultima4/controllers/game_controller.h
A engines/ultima/ultima4/controllers/key_handler_controller.cpp
A engines/ultima/ultima4/controllers/key_handler_controller.h
A engines/ultima/ultima4/controllers/read_choice_controller.cpp
A engines/ultima/ultima4/controllers/read_choice_controller.h
A engines/ultima/ultima4/controllers/read_dir_controller.cpp
A engines/ultima/ultima4/controllers/read_dir_controller.h
A engines/ultima/ultima4/controllers/read_int_controller.cpp
A engines/ultima/ultima4/controllers/read_int_controller.h
A engines/ultima/ultima4/controllers/read_player_controller.cpp
A engines/ultima/ultima4/controllers/read_player_controller.h
A engines/ultima/ultima4/controllers/read_string_controller.cpp
A engines/ultima/ultima4/controllers/read_string_controller.h
A engines/ultima/ultima4/controllers/wait_controller.cpp
A engines/ultima/ultima4/controllers/wait_controller.h
A engines/ultima/ultima4/controllers/ztats_controller.cpp
A engines/ultima/ultima4/controllers/ztats_controller.h
R engines/ultima/ultima4/events/controller.cpp
R engines/ultima/ultima4/events/controller.h
engines/ultima/module.mk
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/core/debugger_actions.cpp
engines/ultima/ultima4/events/event.cpp
engines/ultima/ultima4/events/event.h
engines/ultima/ultima4/events/event_scummvm.cpp
engines/ultima/ultima4/game/death.cpp
engines/ultima/ultima4/game/game.cpp
engines/ultima/ultima4/game/game.h
engines/ultima/ultima4/game/intro.cpp
engines/ultima/ultima4/game/intro.h
engines/ultima/ultima4/game/item.cpp
engines/ultima/ultima4/game/person.cpp
engines/ultima/ultima4/map/combat.cpp
engines/ultima/ultima4/map/combat.h
engines/ultima/ultima4/map/shrine.cpp
engines/ultima/ultima4/meta_engine.cpp
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index a3834e9d8b..d7c91d2381 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -134,6 +134,17 @@ MODULE_OBJS := \
ultima1/widgets/urban_widget.o \
ultima1/widgets/wench.o \
ultima1/game.o \
+ ultima4/controllers/alpha_action_controller.o \
+ ultima4/controllers/controller.o \
+ ultima4/controllers/game_controller.o \
+ ultima4/controllers/key_handler_controller.o \
+ ultima4/controllers/read_choice_controller.o \
+ ultima4/controllers/read_dir_controller.o \
+ ultima4/controllers/read_int_controller.o \
+ ultima4/controllers/read_player_controller.o \
+ ultima4/controllers/read_string_controller.o \
+ ultima4/controllers/wait_controller.o \
+ ultima4/controllers/ztats_controller.o \
ultima4/conversation/conversation.o \
ultima4/conversation/dialogueloader.o \
ultima4/conversation/dialogueloader_hw.o \
@@ -148,7 +159,6 @@ MODULE_OBJS := \
ultima4/core/error.o \
ultima4/core/settings.o \
ultima4/core/utils.o \
- ultima4/events/controller.o \
ultima4/events/event.o \
ultima4/events/event_scummvm.o \
ultima4/events/timed_event_mgr.o \
diff --git a/engines/ultima/ultima4/controllers/alpha_action_controller.cpp b/engines/ultima/ultima4/controllers/alpha_action_controller.cpp
new file mode 100644
index 0000000000..48d62058be
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/alpha_action_controller.cpp
@@ -0,0 +1,59 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/alpha_action_controller.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/gfx/screen.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+bool AlphaActionController::keyPressed(int key) {
+ if (Common::isLower(key))
+ key = toupper(key);
+
+ if (key >= 'A' && key <= toupper(_lastValidLetter)) {
+ _value = key - 'A';
+ doneWaiting();
+ } else if (key == U4_SPACE || key == U4_ESC || key == U4_ENTER) {
+ screenMessage("\n");
+ _value = -1;
+ doneWaiting();
+ } else {
+ screenMessage("\n%s", _prompt.c_str());
+ g_screen->update();
+ return KeyHandler::defaultHandler(key, NULL);
+ }
+ return true;
+}
+
+int AlphaActionController::get(char lastValidLetter, const Common::String &prompt, EventHandler *eh) {
+ if (!eh)
+ eh = eventHandler;
+
+ AlphaActionController ctrl(lastValidLetter, prompt);
+ eh->pushController(&ctrl);
+ return ctrl.waitFor();
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/alpha_action_controller.h b/engines/ultima/ultima4/controllers/alpha_action_controller.h
new file mode 100644
index 0000000000..90efd64793
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/alpha_action_controller.h
@@ -0,0 +1,52 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_ALPHA_ACTION_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_ALPHA_ACTION_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/events/event.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to handle input for commands requiring a letter
+ * argument in the range 'a' - lastValidLetter.
+ */
+class AlphaActionController : public WaitableController<int> {
+public:
+ AlphaActionController(char letter, const Common::String &p) : _lastValidLetter(letter), _prompt(p) {
+ }
+ bool keyPressed(int key) override;
+
+ static int get(char lastValidLetter, const Common::String &prompt, EventHandler *eh = NULL);
+
+private:
+ char _lastValidLetter;
+ Common::String _prompt;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/events/controller.cpp b/engines/ultima/ultima4/controllers/controller.cpp
similarity index 97%
rename from engines/ultima/ultima4/events/controller.cpp
rename to engines/ultima/ultima4/controllers/controller.cpp
index d5bafa1e8a..50f086848a 100644
--- a/engines/ultima/ultima4/events/controller.cpp
+++ b/engines/ultima/ultima4/controllers/controller.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "ultima/ultima4/events/controller.h"
+#include "ultima/ultima4/controllers/controller.h"
#include "ultima/ultima4/events/event.h"
namespace Ultima {
diff --git a/engines/ultima/ultima4/events/controller.h b/engines/ultima/ultima4/controllers/controller.h
similarity index 94%
rename from engines/ultima/ultima4/events/controller.h
rename to engines/ultima/ultima4/controllers/controller.h
index 726cc7d683..012f367c89 100644
--- a/engines/ultima/ultima4/events/controller.h
+++ b/engines/ultima/ultima4/controllers/controller.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef ULTIMA4_CONTROLLER_H
-#define ULTIMA4_CONTROLLER_H
+#ifndef ULTIMA4_CONTROLLERS_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_CONTROLLER_H
#include "ultima/ultima4/meta_engine.h"
@@ -113,6 +113,13 @@ private:
bool _exitWhenDone;
};
+class TurnCompleter {
+public:
+ virtual ~TurnCompleter() {
+ }
+ virtual void finishTurn() = 0;
+};
+
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/game_controller.cpp b/engines/ultima/ultima4/controllers/game_controller.cpp
new file mode 100644
index 0000000000..e6d8f57c29
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/game_controller.cpp
@@ -0,0 +1,842 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/game_controller.h"
+#include "ultima/ultima4/core/config.h"
+#include "ultima/ultima4/core/debugger.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/game/game.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/death.h"
+#include "ultima/ultima4/game/moongate.h"
+#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/gfx/imagemgr.h"
+#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/map/annotation.h"
+#include "ultima/ultima4/map/city.h"
+#include "ultima/ultima4/map/dungeon.h"
+#include "ultima/ultima4/map/mapmgr.h"
+#include "ultima/ultima4/map/shrine.h"
+#include "ultima/ultima4/ultima4.h"
+#include "common/system.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+using namespace std;
+
+GameController *g_game = NULL;
+
+static const MouseArea MOUSE_AREAS[] = {
+ { 3, { { 8, 8 }, { 8, 184 }, { 96, 96 } }, MC_WEST, { U4_ENTER, 0, U4_LEFT } },
+ { 3, { { 8, 8 }, { 184, 8 }, { 96, 96 } }, MC_NORTH, { U4_ENTER, 0, U4_UP } },
+ { 3, { { 184, 8 }, { 184, 184 }, { 96, 96 } }, MC_EAST, { U4_ENTER, 0, U4_RIGHT } },
+ { 3, { { 8, 184 }, { 184, 184 }, { 96, 96 } }, MC_SOUTH, { U4_ENTER, 0, U4_DOWN } },
+ { 0, { { 0, 0 }, { 0, 0 }, { 0, 0 } }, MC_NORTH, { 0, 0, 0 } }
+};
+
+GameController::GameController() : _mapArea(BORDER_WIDTH, BORDER_HEIGHT, VIEWPORT_W, VIEWPORT_H), _paused(false), _pausedTimer(0) {
+ g_game = this;
+}
+
+void GameController::initScreen() {
+ Image *screen = imageMgr->get("screen")->_image;
+
+ screen->fillRect(0, 0, screen->width(), screen->height(), 0, 0, 0);
+ g_screen->update();
+}
+
+void GameController::initScreenWithoutReloadingState() {
+ g_music->play();
+ imageMgr->get(BKGD_BORDERS)->_image->draw(0, 0);
+ g_context->_stats->update(); /* draw the party stats */
+
+ screenMessage("Press Alt-h for help\n");
+ screenPrompt();
+
+ eventHandler->pushMouseAreaSet(MOUSE_AREAS);
+
+ eventHandler->setScreenUpdate(&gameUpdateScreen);
+}
+
+void GameController::init() {
+ initScreen();
+
+ // initialize the global game context, conversation and game state variables
+ g_context = new Context();
+ g_context->_line = TEXT_AREA_H - 1;
+ g_context->col = 0;
+ g_context->_stats = new StatsArea();
+ g_context->_moonPhase = 0;
+ g_context->_windDirection = DIR_NORTH;
+ g_context->_windCounter = 0;
+ g_context->_windLock = false;
+ g_context->_aura = new Aura();
+ g_context->_horseSpeed = 0;
+ g_context->_opacity = 1;
+ g_context->_lastCommandTime = g_system->getMillis();
+ g_context->_lastShip = NULL;
+}
+
+void GameController::setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter) {
+ int viewMode;
+ LocationContext context;
+ int activePlayer = g_context->_party->getActivePlayer();
+ MapCoords coords;
+
+ if (!turnCompleter)
+ turnCompleter = this;
+
+ if (portal)
+ coords = portal->_start;
+ else
+ coords = MapCoords(map->_width / 2, map->_height / 2);
+
+ /* If we don't want to save the location, then just return to the previous location,
+ as there may still be ones in the stack we want to keep */
+ if (!saveLocation)
+ exitToParentMap();
+
+ switch (map->_type) {
+ case Map::WORLD:
+ context = CTX_WORLDMAP;
+ viewMode = VIEW_NORMAL;
+ break;
+ case Map::DUNGEON:
+ context = CTX_DUNGEON;
+ viewMode = VIEW_DUNGEON;
+ if (portal)
+ g_ultima->_saveGame->_orientation = DIR_EAST;
+ break;
+ case Map::COMBAT:
+ coords = MapCoords(-1, -1); /* set these to -1 just to be safe; we don't need them */
+ context = CTX_COMBAT;
+ viewMode = VIEW_NORMAL;
+ activePlayer = -1; /* different active player for combat, defaults to 'None' */
+ break;
+ case Map::SHRINE:
+ context = CTX_SHRINE;
+ viewMode = VIEW_NORMAL;
+ break;
+ case Map::CITY:
+ default:
+ context = CTX_CITY;
+ viewMode = VIEW_NORMAL;
+ break;
+ }
+ g_context->_location = new Location(coords, map, viewMode, context, turnCompleter, g_context->_location);
+ g_context->_location->addObserver(this);
+ g_context->_party->setActivePlayer(activePlayer);
+#ifdef IOS
+ U4IOS::updateGameControllerContext(c->location->context);
+#endif
+
+ /* now, actually set our new tileset */
+ _mapArea.setTileset(map->_tileset);
+
+ if (isCity(map)) {
+ City *city = dynamic_cast<City *>(map);
+ city->addPeople();
+ }
+}
+
+int GameController::exitToParentMap() {
+ if (!g_context->_location)
+ return 0;
+
+ if (g_context->_location->_prev != NULL) {
+ // Create the balloon for Hythloth
+ if (g_context->_location->_map->_id == MAP_HYTHLOTH)
+ createBalloon(g_context->_location->_prev->_map);
+
+ // free map info only if previous location was on a different map
+ if (g_context->_location->_prev->_map != g_context->_location->_map) {
+ g_context->_location->_map->_annotations->clear();
+ g_context->_location->_map->clearObjects();
+
+ /* quench the torch of we're on the world map */
+ if (g_context->_location->_prev->_map->isWorldMap())
+ g_context->_party->quenchTorch();
+ }
+ locationFree(&g_context->_location);
+
+ // restore the tileset to the one the current map uses
+ _mapArea.setTileset(g_context->_location->_map->_tileset);
+#ifdef IOS
+ U4IOS::updateGameControllerContext(c->location->context);
+#endif
+
+ return 1;
+ }
+ return 0;
+}
+
+void GameController::finishTurn() {
+ g_context->_lastCommandTime = g_system->getMillis();
+ Creature *attacker = NULL;
+
+ while (1) {
+
+ /* adjust food and moves */
+ g_context->_party->endTurn();
+
+ /* count down the aura, if there is one */
+ g_context->_aura->passTurn();
+
+ gameCheckHullIntegrity();
+
+ /* update party stats */
+ //c->stats->setView(STATS_PARTY_OVERVIEW);
+
+ screenUpdate(&this->_mapArea, true, false);
+ screenWait(1);
+
+ /* Creatures cannot spawn, move or attack while the avatar is on the balloon */
+ if (!g_context->_party->isFlying()) {
+
+ // apply effects from tile avatar is standing on
+ g_context->_party->applyEffect(g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_GROUND_OBJECTS)->getEffect());
+
+ // Move creatures and see if something is attacking the avatar
+ attacker = g_context->_location->_map->moveObjects(g_context->_location->_coords);
+
+ // Something's attacking! Start combat!
+ if (attacker) {
+ gameCreatureAttack(attacker);
+ return;
+ }
+
+ // cleanup old creatures and spawn new ones
+ creatureCleanup();
+ checkRandomCreatures();
+ checkBridgeTrolls();
+ }
+
+ /* update map annotations */
+ g_context->_location->_map->_annotations->passTurn();
+
+ if (!g_context->_party->isImmobilized())
+ break;
+
+ if (g_context->_party->isDead()) {
+ deathStart(0);
+ return;
+ } else {
+ screenMessage("Zzzzzz\n");
+ screenWait(4);
+ }
+ }
+
+ if (g_context->_location->_context == CTX_DUNGEON) {
+ Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
+ if (g_context->_party->getTorchDuration() <= 0)
+ screenMessage("It's Dark!\n");
+ else g_context->_party->burnTorch();
+
+ /* handle dungeon traps */
+ if (dungeon->currentToken() == DUNGEON_TRAP) {
+ dungeonHandleTrap((TrapType)dungeon->currentSubToken());
+ // a little kludgey to have a second test for this
+ // right here. But without it you can survive an
+ // extra turn after party death and do some things
+ // that could cause a crash, like Hole up and Camp.
+ if (g_context->_party->isDead()) {
+ deathStart(0);
+ return;
+ }
+ }
+ }
+
+
+ /* draw a prompt */
+ screenPrompt();
+ //screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
+}
+
+void GameController::flashTile(const Coords &coords, MapTile tile, int frames) {
+ g_context->_location->_map->_annotations->add(coords, tile, true);
+
+ screenTileUpdate(&g_game->_mapArea, coords);
+
+ screenWait(frames);
+ g_context->_location->_map->_annotations->remove(coords, tile);
+
+ screenTileUpdate(&g_game->_mapArea, coords, false);
+}
+
+void GameController::flashTile(const Coords &coords, const Common::String &tilename, int timeFactor) {
+ Tile *tile = g_context->_location->_map->_tileset->getByName(tilename);
+ ASSERT(tile, "no tile named '%s' found in tileset", tilename.c_str());
+ flashTile(coords, tile->getId(), timeFactor);
+}
+
+void GameController::update(Party *party, PartyEvent &event) {
+ int i;
+
+ switch (event._type) {
+ case PartyEvent::LOST_EIGHTH:
+ // inform a player he has lost zero or more eighths of avatarhood.
+ screenMessage("\n %cThou hast lost\n an eighth!%c\n", FG_YELLOW, FG_WHITE);
+ break;
+ case PartyEvent::ADVANCED_LEVEL:
+ screenMessage("\n%c%s\nThou art now Level %d%c\n", FG_YELLOW, event._player->getName().c_str(), event._player->getRealLevel(), FG_WHITE);
+ gameSpellEffect('r', -1, SOUND_MAGIC); // Same as resurrect spell
+ break;
+ case PartyEvent::STARVING:
+ screenMessage("\n%cStarving!!!%c\n", FG_YELLOW, FG_WHITE);
+ /* FIXME: add sound effect here */
+
+ // 2 damage to each party member for starving!
+ for (i = 0; i < g_ultima->_saveGame->_members; i++)
+ g_context->_party->member(i)->applyDamage(2);
+ break;
+ default:
+ break;
+ }
+}
+
+void GameController::update(Location *location, MoveEvent &event) {
+ switch (location->_map->_type) {
+ case Map::DUNGEON:
+ avatarMovedInDungeon(event);
+ break;
+ case Map::COMBAT:
+ // FIXME: let the combat controller handle it
+ dynamic_cast<CombatController *>(eventHandler->getController())->movePartyMember(event);
+ break;
+ default:
+ avatarMoved(event);
+ break;
+ }
+}
+
+void GameController::keybinder(KeybindingAction action) {
+ MetaEngine::executeAction(action);
+}
+
+bool GameController::keyPressed(int key) {
+ bool valid = true;
+ int endTurn = 1;
+ Object *obj;
+ MapTile *tile;
+
+ /* Translate context-sensitive action key into a useful command */
+ if (key == U4_ENTER && settings._enhancements && settings._enhancementsOptions._smartEnterKey) {
+ /* Attempt to guess based on the character's surroundings etc, what
+ action they want */
+
+ /* Do they want to board something? */
+ if (g_context->_transportContext == TRANSPORT_FOOT) {
+ obj = g_context->_location->_map->objectAt(g_context->_location->_coords);
+ if (obj && (obj->getTile().getTileType()->isShip() ||
+ obj->getTile().getTileType()->isHorse() ||
+ obj->getTile().getTileType()->isBalloon()))
+ key = 'b';
+ }
+ /* Klimb/Descend Balloon */
+ else if (g_context->_transportContext == TRANSPORT_BALLOON) {
+ if (g_context->_party->isFlying())
+ key = 'd';
+ else {
+#ifdef IOS
+ U4IOS::IOSSuperButtonHelper superHelper;
+ key = ReadChoiceController::get("xk \033\n");
+#else
+ key = 'k';
+#endif
+ }
+ }
+ /* X-it transport */
+ else key = 'x';
+
+ /* Klimb? */
+ if ((g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_KLIMB) != NULL))
+ key = 'k';
+ /* Descend? */
+ else if ((g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_DESCEND) != NULL))
+ key = 'd';
+
+ if (g_context->_location->_context == CTX_DUNGEON) {
+ Dungeon *dungeon = static_cast<Dungeon *>(g_context->_location->_map);
+ bool up = dungeon->ladderUpAt(g_context->_location->_coords);
+ bool down = dungeon->ladderDownAt(g_context->_location->_coords);
+ if (up && down) {
+#ifdef IOS
+ U4IOS::IOSClimbHelper climbHelper;
+ key = ReadChoiceController::get("kd \033\n");
+#else
+ key = 'k'; // This is consistent with the previous code. Ideally, I would have a UI here as well.
+#endif
+ } else if (up) {
+ key = 'k';
+ } else {
+ key = 'd';
+ }
+ }
+
+ /* Enter? */
+ if (g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_ENTER) != NULL)
+ key = 'e';
+
+ /* Get Chest? */
+ if (!g_context->_party->isFlying()) {
+ tile = g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_GROUND_OBJECTS);
+
+ if (tile->getTileType()->isChest()) key = 'g';
+ }
+
+ /* None of these? Default to search */
+ if (key == U4_ENTER) key = 's';
+ }
+
+ if ((g_context->_location->_context & CTX_DUNGEON) && strchr("abefjlotxy", key))
+ screenMessage("%cNot here!%c\n", FG_GREY, FG_WHITE);
+
+ if (valid && endTurn) {
+ if (eventHandler->getController() == g_game)
+ g_context->_location->_turnCompleter->finishTurn();
+ } else if (!endTurn) {
+ /* if our turn did not end, then manually redraw the text prompt */
+ screenPrompt();
+ }
+
+ return valid || KeyHandler::defaultHandler(key, NULL);
+}
+
+void GameController::initMoons() {
+ int trammelphase = g_ultima->_saveGame->_trammelPhase,
+ feluccaphase = g_ultima->_saveGame->_feluccaPhase;
+
+ ASSERT(g_context != NULL, "Game context doesn't exist!");
+ ASSERT(g_ultima->_saveGame != NULL, "Savegame doesn't exist!");
+ //ASSERT(mapIsWorldMap(c->location->map) && c->location->viewMode == VIEW_NORMAL, "Can only call gameInitMoons() from the world map!");
+
+ g_ultima->_saveGame->_trammelPhase = g_ultima->_saveGame->_feluccaPhase = 0;
+ g_context->_moonPhase = 0;
+
+ while ((g_ultima->_saveGame->_trammelPhase != trammelphase) ||
+ (g_ultima->_saveGame->_feluccaPhase != feluccaphase))
+ updateMoons(false);
+}
+
+void GameController::updateMoons(bool showmoongates) {
+ int realMoonPhase,
+ oldTrammel,
+ trammelSubphase;
+ const Coords *gate;
+
+ if (g_context->_location->_map->isWorldMap()) {
+ oldTrammel = g_ultima->_saveGame->_trammelPhase;
+
+ if (++g_context->_moonPhase >= MOON_PHASES * MOON_SECONDS_PER_PHASE * 4)
+ g_context->_moonPhase = 0;
+
+ trammelSubphase = g_context->_moonPhase % (MOON_SECONDS_PER_PHASE * 4 * 3);
+ realMoonPhase = (g_context->_moonPhase / (4 * MOON_SECONDS_PER_PHASE));
+
+ g_ultima->_saveGame->_trammelPhase = realMoonPhase / 3;
+ g_ultima->_saveGame->_feluccaPhase = realMoonPhase % 8;
+
+ if (g_ultima->_saveGame->_trammelPhase > 7)
+ g_ultima->_saveGame->_trammelPhase = 7;
+
+ if (showmoongates) {
+ /* update the moongates if trammel changed */
+ if (trammelSubphase == 0) {
+ gate = moongateGetGateCoordsForPhase(oldTrammel);
+ if (gate)
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate)
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
+ } else if (trammelSubphase == 1) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
+ }
+ } else if (trammelSubphase == 2) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
+ }
+ } else if (trammelSubphase == 3) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
+ }
+ } else if ((trammelSubphase > 3) && (trammelSubphase < (MOON_SECONDS_PER_PHASE * 4 * 3) - 3)) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
+ }
+ } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 3) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
+ }
+ } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 2) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
+ }
+ } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 1) {
+ gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
+ if (gate) {
+ g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
+ g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
+ }
+ }
+ }
+ }
+}
+
+void GameController::avatarMoved(MoveEvent &event) {
+ if (event._userEvent) {
+
+ // is filterMoveMessages even used? it doesn't look like the option is hooked up in the configuration menu
+ if (!settings._filterMoveMessages) {
+ switch (g_context->_transportContext) {
+ case TRANSPORT_FOOT:
+ case TRANSPORT_HORSE:
+ screenMessage("%s\n", getDirectionName(event._dir));
+ break;
+ case TRANSPORT_SHIP:
+ if (event._result & MOVE_TURNED)
+ screenMessage("Turn %s!\n", getDirectionName(event._dir));
+ else if (event._result & MOVE_SLOWED)
+ screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
+ else
+ screenMessage("Sail %s!\n", getDirectionName(event._dir));
+ break;
+ case TRANSPORT_BALLOON:
+ screenMessage("%cDrift Only!%c\n", FG_GREY, FG_WHITE);
+ break;
+ default:
+ error("bad transportContext %d in avatarMoved()", g_context->_transportContext);
+ }
+ }
+
+ /* movement was blocked */
+ if (event._result & MOVE_BLOCKED) {
+
+ /* if shortcuts are enabled, try them! */
+ if (settings._shortcutCommands) {
+ MapCoords new_coords = g_context->_location->_coords;
+ MapTile *tile;
+
+ new_coords.move(event._dir, g_context->_location->_map);
+ tile = g_context->_location->_map->tileAt(new_coords, WITH_OBJECTS);
+
+ if (tile->getTileType()->isDoor()) {
+ g_debugger->openAt(new_coords);
+ event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
+ } else if (tile->getTileType()->isLockedDoor()) {
+ g_debugger->jimmyAt(new_coords);
+ event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
+ } /*else if (mapPersonAt(c->location->map, new_coords) != NULL) {
+ talkAtCoord(newx, newy, 1, NULL);
+ event.result = MOVE_SUCCEEDED | MOVE_END_TURN;
+ }*/
+ }
+
+ /* if we're still blocked */
+ if ((event._result & MOVE_BLOCKED) && !settings._filterMoveMessages) {
+ soundPlay(SOUND_BLOCKED, false);
+ screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
+ }
+ } else if (g_context->_transportContext == TRANSPORT_FOOT || g_context->_transportContext == TRANSPORT_HORSE) {
+ /* movement was slowed */
+ if (event._result & MOVE_SLOWED) {
+ soundPlay(SOUND_WALK_SLOWED);
+ screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
+ } else {
+ soundPlay(SOUND_WALK_NORMAL);
+ }
+ }
+ }
+
+ /* exited map */
+ if (event._result & MOVE_EXIT_TO_PARENT) {
+ screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
+ exitToParentMap();
+ g_music->play();
+ }
+
+ /* things that happen while not on board the balloon */
+ if (g_context->_transportContext & ~TRANSPORT_BALLOON)
+ checkSpecialCreatures(event._dir);
+ /* things that happen while on foot or horseback */
+ if ((g_context->_transportContext & TRANSPORT_FOOT_OR_HORSE) &&
+ !(event._result & (MOVE_SLOWED | MOVE_BLOCKED))) {
+ if (checkMoongates())
+ event._result = (MoveResult)(MOVE_MAP_CHANGE | MOVE_END_TURN);
+ }
+}
+
+void GameController::avatarMovedInDungeon(MoveEvent &event) {
+ Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
+ Direction realDir = dirNormalize((Direction)g_ultima->_saveGame->_orientation, event._dir);
+
+ if (!settings._filterMoveMessages) {
+ if (event._userEvent) {
+ if (event._result & MOVE_TURNED) {
+ if (dirRotateCCW((Direction)g_ultima->_saveGame->_orientation) == realDir)
+ screenMessage("Turn Left\n");
+ else screenMessage("Turn Right\n");
+ }
+ /* show 'Advance' or 'Retreat' in dungeons */
+ else screenMessage("%s\n", realDir == g_ultima->_saveGame->_orientation ? "Advance" : "Retreat");
+ }
+
+ if (event._result & MOVE_BLOCKED)
+ screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
+ }
+
+ /* if we're exiting the map, do this */
+ if (event._result & MOVE_EXIT_TO_PARENT) {
+ screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
+ exitToParentMap();
+ g_music->play();
+ }
+
+ /* check to see if we're entering a dungeon room */
+ if (event._result & MOVE_SUCCEEDED) {
+ if (dungeon->currentToken() == DUNGEON_ROOM) {
+ int room = (int)dungeon->currentSubToken(); /* get room number */
+
+ /**
+ * recalculate room for the abyss -- there are 16 rooms for every 2 levels,
+ * each room marked with 0xD* where (* == room number 0-15).
+ * for levels 1 and 2, there are 16 rooms, levels 3 and 4 there are 16 rooms, etc.
+ */
+ if (g_context->_location->_map->_id == MAP_ABYSS)
+ room = (0x10 * (g_context->_location->_coords.z / 2)) + room;
+
+ Dungeon *dng = dynamic_cast<Dungeon *>(g_context->_location->_map);
+ dng->_currentRoom = room;
+
+ /* set the map and start combat! */
+ CombatController *cc = new CombatController(dng->_roomMaps[room]);
+ cc->initDungeonRoom(room, dirReverse(realDir));
+ cc->begin();
+ }
+ }
+}
+
+void GameController::timerFired() {
+ if (_pausedTimer > 0) {
+ _pausedTimer--;
+ if (_pausedTimer <= 0) {
+ _pausedTimer = 0;
+ _paused = false; /* unpause the game */
+ }
+ }
+
+ if (!_paused && !_pausedTimer) {
+ if (++g_context->_windCounter >= MOON_SECONDS_PER_PHASE * 4) {
+ if (xu4_random(4) == 1 && !g_context->_windLock)
+ g_context->_windDirection = dirRandomDir(MASK_DIR_ALL);
+ g_context->_windCounter = 0;
+ }
+
+ /* balloon moves about 4 times per second */
+ if ((g_context->_transportContext == TRANSPORT_BALLOON) &&
+ g_context->_party->isFlying()) {
+ g_context->_location->move(dirReverse((Direction) g_context->_windDirection), false);
+ }
+
+ updateMoons(true);
+
+ screenCycle();
+
+ /*
+ * force pass if no commands within last 20 seconds
+ */
+ Controller *controller = eventHandler->getController();
+ if (controller != NULL && (eventHandler->getController() == g_game ||
+ dynamic_cast<CombatController *>(eventHandler->getController()) != NULL) &&
+ gameTimeSinceLastCommand() > 20) {
+
+ /* pass the turn, and redraw the text area so the prompt is shown */
+ MetaEngine::executeAction(KEYBIND_PASS);
+ screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
+ }
+ }
+
+}
+
+void GameController::checkSpecialCreatures(Direction dir) {
+ int i;
+ Object *obj;
+ static const struct {
+ int x, y;
+ Direction dir;
+ } pirateInfo[] = {
+ { 224, 220, DIR_EAST }, /* N'M" O'A" */
+ { 224, 228, DIR_EAST }, /* O'E" O'A" */
+ { 226, 220, DIR_EAST }, /* O'E" O'C" */
+ { 227, 228, DIR_EAST }, /* O'E" O'D" */
+ { 228, 227, DIR_SOUTH }, /* O'D" O'E" */
+ { 229, 225, DIR_SOUTH }, /* O'B" O'F" */
+ { 229, 223, DIR_NORTH }, /* N'P" O'F" */
+ { 228, 222, DIR_NORTH } /* N'O" O'E" */
+ };
+
+ /*
+ * if heading east into pirates cove (O'A" N'N"), generate pirate
+ * ships
+ */
+ if (dir == DIR_EAST &&
+ g_context->_location->_coords.x == 0xdd &&
+ g_context->_location->_coords.y == 0xe0) {
+ for (i = 0; i < 8; i++) {
+ obj = g_context->_location->_map->addCreature(creatureMgr->getById(PIRATE_ID), MapCoords(pirateInfo[i].x, pirateInfo[i].y));
+ obj->setDirection(pirateInfo[i].dir);
+ }
+ }
+
+ /*
+ * if heading south towards the shrine of humility, generate
+ * daemons unless horn has been blown
+ */
+ if (dir == DIR_SOUTH &&
+ g_context->_location->_coords.x >= 229 &&
+ g_context->_location->_coords.x < 234 &&
+ g_context->_location->_coords.y >= 212 &&
+ g_context->_location->_coords.y < 217 &&
+ *g_context->_aura != Aura::HORN) {
+ for (i = 0; i < 8; i++)
+ g_context->_location->_map->addCreature(creatureMgr->getById(DAEMON_ID), MapCoords(231, g_context->_location->_coords.y + 1, g_context->_location->_coords.z));
+ }
+}
+
+bool GameController::checkMoongates() {
+ Coords dest;
+
+ if (moongateFindActiveGateAt(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase, g_context->_location->_coords, dest)) {
+
+ gameSpellEffect(-1, -1, SOUND_MOONGATE); // Default spell effect (screen inversion without 'spell' sound effects)
+
+ if (g_context->_location->_coords != dest) {
+ g_context->_location->_coords = dest;
+ gameSpellEffect(-1, -1, SOUND_MOONGATE); // Again, after arriving
+ }
+
+ if (moongateIsEntryToShrineOfSpirituality(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase)) {
+ Shrine *shrine_spirituality;
+
+ shrine_spirituality = dynamic_cast<Shrine *>(mapMgr->get(MAP_SHRINE_SPIRITUALITY));
+
+ if (!g_context->_party->canEnterShrine(VIRT_SPIRITUALITY))
+ return true;
+
+ setMap(shrine_spirituality, 1, NULL);
+ g_music->play();
+
+ shrine_spirituality->enter();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void GameController::creatureCleanup() {
+ ObjectDeque::iterator i;
+ Map *map = g_context->_location->_map;
+
+ for (i = map->_objects.begin(); i != map->_objects.end();) {
+ Object *obj = *i;
+ MapCoords o_coords = obj->getCoords();
+
+ if ((obj->getType() == Object::CREATURE) && (o_coords.z == g_context->_location->_coords.z) &&
+ o_coords.distance(g_context->_location->_coords, g_context->_location->_map) > MAX_CREATURE_DISTANCE) {
+
+ /* delete the object and remove it from the map */
+ i = map->removeObject(i);
+ } else i++;
+ }
+}
+
+void GameController::checkRandomCreatures() {
+ int canSpawnHere = g_context->_location->_map->isWorldMap() || g_context->_location->_context & CTX_DUNGEON;
+#ifdef IOS
+ int spawnDivisor = c->location->context & CTX_DUNGEON ? (53 - (c->location->coords.z << 2)) : 53;
+#else
+ int spawnDivisor = g_context->_location->_context & CTX_DUNGEON ? (32 - (g_context->_location->_coords.z << 2)) : 32;
+#endif
+
+ /* If there are too many creatures already,
+ or we're not on the world map, don't worry about it! */
+ if (!canSpawnHere ||
+ g_context->_location->_map->getNumberOfCreatures() >= MAX_CREATURES_ON_MAP ||
+ xu4_random(spawnDivisor) != 0)
+ return;
+
+ gameSpawnCreature(NULL);
+}
+
+void GameController::checkBridgeTrolls() {
+ const Tile *bridge = g_context->_location->_map->_tileset->getByName("bridge");
+ if (!bridge)
+ return;
+
+ // TODO: CHEST: Make a user option to not make chests block bridge trolls
+ if (!g_context->_location->_map->isWorldMap() ||
+ g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)->_id != bridge->getId() ||
+ xu4_random(8) != 0)
+ return;
+
+ screenMessage("\nBridge Trolls!\n");
+
+ Creature *m = g_context->_location->_map->addCreature(creatureMgr->getById(TROLL_ID), g_context->_location->_coords);
+ CombatController *cc = new CombatController(MAP_BRIDGE_CON);
+ cc->init(m);
+ cc->begin();
+}
+
+bool GameController::createBalloon(Map *map) {
+ ObjectDeque::iterator i;
+
+ /* see if the balloon has already been created (and not destroyed) */
+ for (i = map->_objects.begin(); i != map->_objects.end(); i++) {
+ Object *obj = *i;
+ if (obj->getTile().getTileType()->isBalloon())
+ return false;
+ }
+
+ const Tile *balloon = map->_tileset->getByName("balloon");
+ ASSERT(balloon, "no balloon tile found in tileset");
+ map->addObject(balloon->getId(), balloon->getId(), map->getLabel("balloon"));
+ return true;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/game_controller.h b/engines/ultima/ultima4/controllers/game_controller.h
new file mode 100644
index 0000000000..6ba364b1ec
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/game_controller.h
@@ -0,0 +1,174 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_GAME_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_GAME_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/core/coords.h"
+#include "ultima/ultima4/core/observer.h"
+#include "ultima/ultima4/game/portal.h"
+#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/map/location.h"
+#include "ultima/ultima4/map/tileview.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * The main game controller that handles basic game flow and keypresses.
+ *
+ * @todo
+ * <ul>
+ * <li>separate the dungeon specific stuff into another class (subclass?)</li>
+ * </ul>
+ */
+class GameController : public Controller, public Observer<Party *, PartyEvent &>, public Observer<Location *, MoveEvent &>,
+ public TurnCompleter {
+public:
+ GameController();
+
+ /* controller functions */
+
+ /**
+ * Keybinder actions
+ */
+ void keybinder(KeybindingAction action) override;
+
+ /**
+ * The main key handler for the game. Interpretes each key as a
+ * command - 'a' for attack, 't' for talk, etc.
+ */
+ bool keyPressed(int key) override;
+
+ /**
+ * This function is called every quarter second.
+ */
+ void timerFired() override;
+
+ /* main game functions */
+ void init();
+ void initScreen();
+ void initScreenWithoutReloadingState();
+ void setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter = NULL);
+
+ /**
+ * Exits the current map and location and returns to its parent location
+ * This restores all relevant information from the previous location,
+ * such as the map, map position, etc. (such as exiting a city)
+ **/
+ int exitToParentMap();
+
+ /**
+ * Terminates a game turn. This performs the post-turn housekeeping
+ * tasks like adjusting the party's food, incrementing the number of
+ * moves, etc.
+ */
+ void finishTurn() override;
+
+ /**
+ * Provide feedback to user after a party event happens.
+ */
+ void update(Party *party, PartyEvent &event) override;
+
+ /**
+ * Provide feedback to user after a movement event happens.
+ */
+ void update(Location *location, MoveEvent &event) override;
+
+ /**
+ * Initializes the moon state according to the savegame file. This method of
+ * initializing the moons (rather than just setting them directly) is necessary
+ * to make sure trammel and felucca stay in sync
+ */
+ void initMoons();
+
+ /**
+ * Updates the phases of the moons and shows
+ * the visual moongates on the map, if desired
+ */
+ void updateMoons(bool showmoongates);
+
+ /**
+ * Show an attack flash at x, y on the current map.
+ * This is used for 'being hit' or 'being missed'
+ * by weapons, cannon fire, spells, etc.
+ */
+ static void flashTile(const Coords &coords, MapTile tile, int timeFactor);
+
+ static void flashTile(const Coords &coords, const Common::String &tilename, int timeFactor);
+ static void doScreenAnimationsWhilePausing(int timeFactor);
+
+ TileView _mapArea;
+ bool _paused;
+ int _pausedTimer;
+
+private:
+ /**
+ * Handles feedback after avatar moved during normal 3rd-person view.
+ */
+ void avatarMoved(MoveEvent &event);
+
+ /**
+ * Handles feedback after moving the avatar in the 3-d dungeon view.
+ */
+ void avatarMovedInDungeon(MoveEvent &event);
+
+ /**
+ * Removes creatures from the current map if they are too far away from the avatar
+ */
+ void creatureCleanup();
+
+ /**
+ * Handles trolls under bridges
+ */
+ void checkBridgeTrolls();
+
+ /**
+ * Checks creature conditions and spawns new creatures if necessary
+ */
+ void checkRandomCreatures();
+
+ /**
+ * Checks for valid conditions and handles
+ * special creatures guarding the entrance to the
+ * abyss and to the shrine of spirituality
+ */
+ void checkSpecialCreatures(Direction dir);
+
+ /**
+ * Checks for and handles when the avatar steps on a moongate
+ */
+ bool checkMoongates();
+
+ /**
+ * Creates the balloon near Hythloth, but only if the balloon doesn't already exists somewhere
+ */
+ bool createBalloon(Map *map);
+};
+
+extern GameController *g_game;
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/key_handler_controller.cpp b/engines/ultima/ultima4/controllers/key_handler_controller.cpp
new file mode 100644
index 0000000000..1f8925b78d
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/key_handler_controller.cpp
@@ -0,0 +1,140 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/key_handler_controller.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/ultima4.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+
+KeyHandler::KeyHandler(Callback func, void *d, bool asyncronous) :
+ _handler(func),
+ _async(asyncronous),
+ _data(d) {
+}
+
+/**
+ * Sets the key-repeat characteristics of the keyboard.
+ */
+int KeyHandler::setKeyRepeat(int delay, int interval) {
+#ifdef TODO
+ return SDL_EnableKeyRepeat(delay, interval);
+#else
+ return 0;
+#endif
+}
+
+bool KeyHandler::globalHandler(int key) {
+ switch (key) {
+#if defined(MACOSX)
+ case U4_META + 'q': /* Cmd+q */
+ case U4_META + 'x': /* Cmd+x */
+#endif
+ case U4_ALT + 'x': /* Alt+x */
+#if defined(WIN32)
+ case U4_ALT + U4_FKEY + 3:
+#endif
+ g_ultima->quitGame();
+ EventHandler::end();
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool KeyHandler::defaultHandler(int key, void *data) {
+ bool valid = true;
+
+ switch (key) {
+ case '`':
+ if (g_context && g_context->_location)
+ debug(1, "x = %d, y = %d, level = %d, tile = %d (%s)\n", g_context->_location->_coords.x, g_context->_location->_coords.y, g_context->_location->_coords.z, g_context->_location->_map->translateToRawTileIndex(*g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)), g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_OBJECTS)->getName().c_str());
+ break;
+ default:
+ valid = false;
+ break;
+ }
+
+ return valid;
+}
+
+bool KeyHandler::ignoreKeys(int key, void *data) {
+ return true;
+}
+
+bool KeyHandler::handle(int key) {
+ bool processed = false;
+ if (!isKeyIgnored(key)) {
+ processed = globalHandler(key);
+ if (!processed)
+ processed = _handler(key, _data);
+ }
+
+ return processed;
+}
+
+bool KeyHandler::isKeyIgnored(int key) {
+ switch (key) {
+ case U4_RIGHT_SHIFT:
+ case U4_LEFT_SHIFT:
+ case U4_RIGHT_CTRL:
+ case U4_LEFT_CTRL:
+ case U4_RIGHT_ALT:
+ case U4_LEFT_ALT:
+ case U4_RIGHT_META:
+ case U4_LEFT_META:
+ case U4_TAB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool KeyHandler::operator==(Callback cb) const {
+ return (_handler == cb) ? true : false;
+}
+
+/*-------------------------------------------------------------------*/
+
+KeyHandlerController::KeyHandlerController(KeyHandler *handler) {
+ this->_handler = handler;
+}
+
+KeyHandlerController::~KeyHandlerController() {
+ delete _handler;
+}
+
+bool KeyHandlerController::keyPressed(int key) {
+ ASSERT(_handler != NULL, "key handler must be initialized");
+ return _handler->handle(key);
+}
+
+KeyHandler *KeyHandlerController::getKeyHandler() {
+ return _handler;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/key_handler_controller.h b/engines/ultima/ultima4/controllers/key_handler_controller.h
new file mode 100644
index 0000000000..f9f47b57cf
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/key_handler_controller.h
@@ -0,0 +1,123 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_KEY_HANDLER_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_KEY_HANDLER_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A class for handling keystrokes.
+ */
+class KeyHandler {
+public:
+ virtual ~KeyHandler() {}
+
+ /* Typedefs */
+ typedef bool (*Callback)(int, void *);
+
+ /** Additional information to be passed as data param for read buffer key handler */
+ typedef struct ReadBuffer {
+ int (*_handleBuffer)(Common::String *);
+ Common::String *_buffer;
+ int _bufferLen;
+ int _screenX, _screenY;
+ } ReadBuffer;
+
+ /** Additional information to be passed as data param for get choice key handler */
+ typedef struct GetChoice {
+ Common::String _choices;
+ int (*_handleChoice)(int);
+ } GetChoice;
+
+ /* Constructors */
+ KeyHandler(Callback func, void *data = NULL, bool asyncronous = true);
+
+ /* Static functions */
+ static int setKeyRepeat(int delay, int interval);
+
+ /**
+ * Handles any and all keystrokes.
+ * Generally used to exit the application, switch applications,
+ * minimize, maximize, etc.
+ */
+ static bool globalHandler(int key);
+
+ /* Static default key handler functions */
+ /**
+ * A default key handler that should be valid everywhere
+ */
+ static bool defaultHandler(int key, void *data);
+
+ /**
+ * A key handler that ignores keypresses
+ */
+ static bool ignoreKeys(int key, void *data);
+
+ /* Operators */
+ bool operator==(Callback cb) const;
+
+ /* Member functions */
+ /**
+ * Handles a keypress.
+ * First it makes sure the key combination is not ignored
+ * by the current key handler. Then, it passes the keypress
+ * through the global key handler. If the global handler
+ * does not process the keystroke, then the key handler
+ * handles it itself by calling its handler callback function.
+ */
+ bool handle(int key);
+
+ /**
+ * Returns true if the key or key combination is always ignored by xu4
+ */
+ virtual bool isKeyIgnored(int key);
+
+protected:
+ Callback _handler;
+ bool _async;
+ void *_data;
+};
+
+/**
+ * A controller that wraps a keyhander function. Keyhandlers are
+ * deprecated -- please use a controller instead.
+ */
+class KeyHandlerController : public Controller {
+public:
+ KeyHandlerController(KeyHandler *handler);
+ ~KeyHandlerController();
+
+ bool keyPressed(int key) override;
+ KeyHandler *getKeyHandler();
+
+private:
+ KeyHandler *_handler;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/read_choice_controller.cpp b/engines/ultima/ultima4/controllers/read_choice_controller.cpp
new file mode 100644
index 0000000000..105df96473
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_choice_controller.cpp
@@ -0,0 +1,62 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+
+ReadChoiceController::ReadChoiceController(const Common::String &choices) {
+ _choices = choices;
+}
+
+bool ReadChoiceController::keyPressed(int key) {
+ // Common::isUpper() accepts 1-byte characters, yet the modifier keys
+ // (ALT, SHIFT, ETC) produce values beyond 255
+ if ((key <= 0x7F) && (Common::isUpper(key)))
+ key = tolower(key);
+
+ _value = key;
+
+ if (_choices.empty() || _choices.findFirstOf(_value) < _choices.size()) {
+ // If the value is printable, display it
+ if (!Common::isSpace(key))
+ screenMessage("%c", toupper(key));
+ doneWaiting();
+ return true;
+ }
+
+ return false;
+}
+
+char ReadChoiceController::get(const Common::String &choices, EventHandler *eh) {
+ if (!eh)
+ eh = eventHandler;
+
+ ReadChoiceController ctrl(choices);
+ eh->pushController(&ctrl);
+ return ctrl.waitFor();
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/read_choice_controller.h b/engines/ultima/ultima4/controllers/read_choice_controller.h
new file mode 100644
index 0000000000..4410e2df3e
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_choice_controller.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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_READ_CHOICE_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_READ_CHOICE_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/events/event.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to read a single key from a provided list.
+ */
+class ReadChoiceController : public WaitableController<int> {
+public:
+ ReadChoiceController(const Common::String &choices);
+ bool keyPressed(int key) override;
+
+ static char get(const Common::String &choices, EventHandler *eh = NULL);
+
+protected:
+ Common::String _choices;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/read_dir_controller.cpp b/engines/ultima/ultima4/controllers/read_dir_controller.cpp
new file mode 100644
index 0000000000..11bf12f568
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_dir_controller.cpp
@@ -0,0 +1,76 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/read_dir_controller.h"
+#include "ultima/ultima4/map/direction.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+
+ReadDirController::ReadDirController() {
+ _value = DIR_NONE;
+}
+
+void ReadDirController::keybinder(KeybindingAction action) {
+ switch (action) {
+ case KEYBIND_UP:
+ _value = DIR_NORTH;
+ break;
+ case KEYBIND_DOWN:
+ _value = DIR_SOUTH;
+ break;
+ case KEYBIND_LEFT:
+ _value = DIR_WEST;
+ break;
+ case KEYBIND_RIGHT:
+ _value = DIR_EAST;
+ break;
+ case KEYBIND_PASS:
+ _value = DIR_NONE;
+ doneWaiting();
+ break;
+ default:
+ return;
+ }
+
+ doneWaiting();
+}
+
+bool ReadDirController::keyPressed(int key) {
+ switch (key) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_RETURN:
+ _value = DIR_NONE;
+ doneWaiting();
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/read_dir_controller.h b/engines/ultima/ultima4/controllers/read_dir_controller.h
new file mode 100644
index 0000000000..6f706ef59a
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_dir_controller.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_READ_DIR_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_READ_DIR_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/map/direction.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to read a direction enter with the arrow keys.
+ */
+class ReadDirController : public WaitableController<Direction> {
+public:
+ ReadDirController();
+
+ /**
+ * Key was pressed
+ */
+ bool keyPressed(int key) override;
+
+ /**
+ * Handles keybinder actions
+ */
+ void keybinder(KeybindingAction action) override;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/read_int_controller.cpp b/engines/ultima/ultima4/controllers/read_int_controller.cpp
new file mode 100644
index 0000000000..56083667b1
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_int_controller.cpp
@@ -0,0 +1,46 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/read_int_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+ReadIntController::ReadIntController(int maxlen, int screenX, int screenY) :
+ ReadStringController(maxlen, screenX, screenY, "0123456789 \n\r\010") {}
+
+int ReadIntController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
+ if (!eh)
+ eh = eventHandler;
+
+ ReadIntController ctrl(maxlen, screenX, screenY);
+ eh->pushController(&ctrl);
+ ctrl.waitFor();
+ return ctrl.getInt();
+}
+
+int ReadIntController::getInt() const {
+ return static_cast<int>(strtol(_value.c_str(), NULL, 10));
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/read_int_controller.h b/engines/ultima/ultima4/controllers/read_int_controller.h
new file mode 100644
index 0000000000..05d025e62d
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_int_controller.h
@@ -0,0 +1,46 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_READ_INT_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_READ_INT_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/read_string_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to read a integer, terminated by the enter key.
+ * Non-numeric keys are ignored.
+ */
+class ReadIntController : public ReadStringController {
+public:
+ ReadIntController(int maxlen, int screenX, int screenY);
+
+ static int get(int maxlen, int screenX, int screenY, EventHandler *eh = NULL);
+ int getInt() const;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/read_player_controller.cpp b/engines/ultima/ultima4/controllers/read_player_controller.cpp
new file mode 100644
index 0000000000..f64530ab61
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_player_controller.cpp
@@ -0,0 +1,64 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/read_player_controller.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/ultima4.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+ReadPlayerController::ReadPlayerController() : ReadChoiceController("12345678 \033\n") {
+#ifdef IOS
+ U4IOS::beginCharacterChoiceDialog();
+#endif
+}
+
+ReadPlayerController::~ReadPlayerController() {
+#ifdef IOS
+ U4IOS::endCharacterChoiceDialog();
+#endif
+}
+
+bool ReadPlayerController::keyPressed(int key) {
+ bool valid = ReadChoiceController::keyPressed(key);
+ if (valid) {
+ if (_value < '1' ||
+ _value > ('0' + g_ultima->_saveGame->_members))
+ _value = '0';
+ } else {
+ _value = '0';
+ }
+ return valid;
+}
+
+int ReadPlayerController::getPlayer() {
+ return _value - '1';
+}
+
+int ReadPlayerController::waitFor() {
+ ReadChoiceController::waitFor();
+ return getPlayer();
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/read_player_controller.h b/engines/ultima/ultima4/controllers/read_player_controller.h
new file mode 100644
index 0000000000..f67de6eb18
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_player_controller.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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_READ_PLAYER_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_READ_PLAYER_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to read a player number.
+ */
+class ReadPlayerController : public ReadChoiceController {
+public:
+ ReadPlayerController();
+ ~ReadPlayerController();
+ bool keyPressed(int key) override;
+
+ int getPlayer();
+ int waitFor() override;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/read_string_controller.cpp b/engines/ultima/ultima4/controllers/read_string_controller.cpp
new file mode 100644
index 0000000000..8380ea1c3b
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_string_controller.cpp
@@ -0,0 +1,109 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/read_string_controller.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/gfx/screen.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+ReadStringController::ReadStringController(int maxlen, int screenX, int screenY, const Common::String &accepted_chars) {
+ _maxLen = maxlen;
+ _screenX = screenX;
+ _screenY = screenY;
+ _view = NULL;
+ _accepted = accepted_chars;
+}
+
+ReadStringController::ReadStringController(int maxlen, TextView *view, const Common::String &accepted_chars) {
+ _maxLen = maxlen;
+ _screenX = view->getCursorX();
+ _screenY = view->getCursorY();
+ _view = view;
+ _accepted = accepted_chars;
+}
+
+bool ReadStringController::keyPressed(int key) {
+ int valid = true, len = _value.size();
+ size_t pos = Common::String::npos;
+
+ if (key < U4_ALT)
+ pos = _accepted.findFirstOf(key);
+
+ if (pos != Common::String::npos) {
+ if (key == Common::KEYCODE_BACKSPACE) {
+ if (len > 0) {
+ /* remove the last character */
+ _value.erase(len - 1, 1);
+
+ if (_view) {
+ _view->textAt(_screenX + len - 1, _screenY, " ");
+ _view->setCursorPos(_screenX + len - 1, _screenY, true);
+ } else {
+ screenHideCursor();
+ screenTextAt(_screenX + len - 1, _screenY, " ");
+ screenSetCursorPos(_screenX + len - 1, _screenY);
+ screenShowCursor();
+ }
+ }
+ } else if (key == '\n' || key == '\r') {
+ doneWaiting();
+ } else if (len < _maxLen) {
+ /* add a character to the end */
+ _value += key;
+
+ if (_view) {
+ _view->textAt(_screenX + len, _screenY, "%c", key);
+ } else {
+ screenHideCursor();
+ screenTextAt(_screenX + len, _screenY, "%c", key);
+ screenSetCursorPos(_screenX + len + 1, _screenY);
+ g_context->col = len + 1;
+ screenShowCursor();
+ }
+ }
+ } else valid = false;
+
+ return valid || KeyHandler::defaultHandler(key, NULL);
+}
+
+Common::String ReadStringController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
+ if (!eh)
+ eh = eventHandler;
+
+ ReadStringController ctrl(maxlen, screenX, screenY);
+ eh->pushController(&ctrl);
+ return ctrl.waitFor();
+}
+
+Common::String ReadStringController::get(int maxlen, TextView *view, EventHandler *eh) {
+ if (!eh)
+ eh = eventHandler;
+
+ ReadStringController ctrl(maxlen, view);
+ eh->pushController(&ctrl);
+ return ctrl.waitFor();
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/read_string_controller.h b/engines/ultima/ultima4/controllers/read_string_controller.h
new file mode 100644
index 0000000000..8f910c0487
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/read_string_controller.h
@@ -0,0 +1,65 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_READ_STRING_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_READ_STRING_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/game/textview.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to read a Common::String, terminated by the enter key.
+ */
+class ReadStringController : public WaitableController<Common::String> {
+public:
+ /**
+ * @param maxlen the maximum length of the Common::String
+ * @param screenX the screen column where to begin input
+ * @param screenY the screen row where to begin input
+ * @param accepted_chars a Common::String characters to be accepted for input
+ */
+ ReadStringController(int maxlen, int screenX, int screenY, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
+ ReadStringController(int maxlen, TextView *view, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
+ bool keyPressed(int key) override;
+
+ static Common::String get(int maxlen, int screenX, int screenY, EventHandler *eh = NULL);
+ static Common::String get(int maxlen, TextView *view, EventHandler *eh = NULL);
+#ifdef IOS
+ void setValue(const Common::String &utf8StringValue) {
+ value = utf8StringValue;
+ }
+#endif
+
+protected:
+ int _maxLen, _screenX, _screenY;
+ TextView *_view;
+ Common::String _accepted;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/wait_controller.cpp b/engines/ultima/ultima4/controllers/wait_controller.cpp
new file mode 100644
index 0000000000..121d99fde8
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/wait_controller.cpp
@@ -0,0 +1,52 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/wait_controller.h"
+#include "ultima/ultima4/events/event.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+WaitController::WaitController(unsigned int c) : Controller(), _cycles(c), _current(0) {
+}
+
+void WaitController::timerFired() {
+ if (++_current >= _cycles) {
+ _current = 0;
+ eventHandler->setControllerDone(true);
+ }
+}
+
+bool WaitController::keyPressed(int key) {
+ return true;
+}
+
+void WaitController::wait() {
+ Controller_startWait();
+}
+
+void WaitController::setCycles(int c) {
+ _cycles = c;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/wait_controller.h b/engines/ultima/ultima4/controllers/wait_controller.h
new file mode 100644
index 0000000000..b3717359af
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/wait_controller.h
@@ -0,0 +1,52 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_WAIT_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_WAIT_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * A controller to pause for a given length of time, ignoring all
+ * keyboard input.
+ */
+class WaitController : public Controller {
+public:
+ WaitController(unsigned int cycles);
+ bool keyPressed(int key) override;
+ void timerFired() override;
+
+ void wait();
+ void setCycles(int c);
+
+private:
+ unsigned int _cycles;
+ unsigned int _current;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/ztats_controller.cpp b/engines/ultima/ultima4/controllers/ztats_controller.cpp
new file mode 100644
index 0000000000..15b3d60dd4
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/ztats_controller.cpp
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/ztats_controller.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/ultima4.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+bool ZtatsController::keyPressed(int key) {
+ switch (key) {
+ case U4_UP:
+ case U4_LEFT:
+ g_context->_stats->prevItem();
+ return true;
+ case U4_DOWN:
+ case U4_RIGHT:
+ g_context->_stats->nextItem();
+ return true;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ if (g_ultima->_saveGame->_members >= key - '0')
+ g_context->_stats->setView(StatsView(STATS_CHAR1 + key - '1'));
+ return true;
+ case '0':
+ g_context->_stats->setView(StatsView(STATS_WEAPONS));
+ return true;
+ case U4_ESC:
+ case U4_SPACE:
+ case U4_ENTER:
+ g_context->_stats->setView(StatsView(STATS_PARTY_OVERVIEW));
+ doneWaiting();
+ return true;
+ default:
+ return KeyHandler::defaultHandler(key, NULL);
+ }
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/ztats_controller.h b/engines/ultima/ultima4/controllers/ztats_controller.h
new file mode 100644
index 0000000000..c76dd6bd02
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/ztats_controller.h
@@ -0,0 +1,42 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_ZTATS_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_ZTATS_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+/**
+ * Controls interaction while Ztats are being displayed.
+ */
+class ZtatsController : public WaitableController<void *> {
+public:
+ bool keyPressed(int key) override;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 1cfb1585d7..5e26fc5dc7 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -22,6 +22,10 @@
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/controllers/alpha_action_controller.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_dir_controller.h"
+#include "ultima/ultima4/controllers/ztats_controller.h"
#include "ultima/ultima4/game/armor.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/game.h"
diff --git a/engines/ultima/ultima4/core/debugger_actions.cpp b/engines/ultima/ultima4/core/debugger_actions.cpp
index 67366392c2..7144b136ba 100644
--- a/engines/ultima/ultima4/core/debugger_actions.cpp
+++ b/engines/ultima/ultima4/core/debugger_actions.cpp
@@ -23,6 +23,8 @@
#include "ultima/ultima4/core/debugger_actions.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_int_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/player.h"
diff --git a/engines/ultima/ultima4/events/event.cpp b/engines/ultima/ultima4/events/event.cpp
index 7e365902a7..1e80cc1979 100644
--- a/engines/ultima/ultima4/events/event.cpp
+++ b/engines/ultima/ultima4/events/event.cpp
@@ -21,12 +21,13 @@
*/
#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/map/location.h"
-#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/controllers/wait_controller.h"
#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/textview.h"
+#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/map/location.h"
#include "common/events.h"
namespace Ultima {
@@ -128,205 +129,5 @@ const MouseArea *EventHandler::getMouseAreaSet() const {
return NULL;
}
-/*-------------------------------------------------------------------*/
-
-ReadStringController::ReadStringController(int maxlen, int screenX, int screenY, const Common::String &accepted_chars) {
- _maxLen = maxlen;
- _screenX = screenX;
- _screenY = screenY;
- _view = NULL;
- _accepted = accepted_chars;
-}
-
-ReadStringController::ReadStringController(int maxlen, TextView *view, const Common::String &accepted_chars) {
- _maxLen = maxlen;
- _screenX = view->getCursorX();
- _screenY = view->getCursorY();
- _view = view;
- _accepted = accepted_chars;
-}
-
-bool ReadStringController::keyPressed(int key) {
- int valid = true, len = _value.size();
- size_t pos = Common::String::npos;
-
- if (key < U4_ALT)
- pos = _accepted.findFirstOf(key);
-
- if (pos != Common::String::npos) {
- if (key == Common::KEYCODE_BACKSPACE) {
- if (len > 0) {
- /* remove the last character */
- _value.erase(len - 1, 1);
-
- if (_view) {
- _view->textAt(_screenX + len - 1, _screenY, " ");
- _view->setCursorPos(_screenX + len - 1, _screenY, true);
- } else {
- screenHideCursor();
- screenTextAt(_screenX + len - 1, _screenY, " ");
- screenSetCursorPos(_screenX + len - 1, _screenY);
- screenShowCursor();
- }
- }
- } else if (key == '\n' || key == '\r') {
- doneWaiting();
- } else if (len < _maxLen) {
- /* add a character to the end */
- _value += key;
-
- if (_view) {
- _view->textAt(_screenX + len, _screenY, "%c", key);
- } else {
- screenHideCursor();
- screenTextAt(_screenX + len, _screenY, "%c", key);
- screenSetCursorPos(_screenX + len + 1, _screenY);
- g_context->col = len + 1;
- screenShowCursor();
- }
- }
- } else valid = false;
-
- return valid || KeyHandler::defaultHandler(key, NULL);
-}
-
-Common::String ReadStringController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
- if (!eh)
- eh = eventHandler;
-
- ReadStringController ctrl(maxlen, screenX, screenY);
- eh->pushController(&ctrl);
- return ctrl.waitFor();
-}
-
-Common::String ReadStringController::get(int maxlen, TextView *view, EventHandler *eh) {
- if (!eh)
- eh = eventHandler;
-
- ReadStringController ctrl(maxlen, view);
- eh->pushController(&ctrl);
- return ctrl.waitFor();
-}
-
-ReadIntController::ReadIntController(int maxlen, int screenX, int screenY) : ReadStringController(maxlen, screenX, screenY, "0123456789 \n\r\010") {}
-
-int ReadIntController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
- if (!eh)
- eh = eventHandler;
-
- ReadIntController ctrl(maxlen, screenX, screenY);
- eh->pushController(&ctrl);
- ctrl.waitFor();
- return ctrl.getInt();
-}
-
-int ReadIntController::getInt() const {
- return static_cast<int>(strtol(_value.c_str(), NULL, 10));
-}
-
-/*-------------------------------------------------------------------*/
-
-ReadChoiceController::ReadChoiceController(const Common::String &choices) {
- _choices = choices;
-}
-
-bool ReadChoiceController::keyPressed(int key) {
- // Common::isUpper() accepts 1-byte characters, yet the modifier keys
- // (ALT, SHIFT, ETC) produce values beyond 255
- if ((key <= 0x7F) && (Common::isUpper(key)))
- key = tolower(key);
-
- _value = key;
-
- if (_choices.empty() || _choices.findFirstOf(_value) < _choices.size()) {
- // If the value is printable, display it
- if (!Common::isSpace(key))
- screenMessage("%c", toupper(key));
- doneWaiting();
- return true;
- }
-
- return false;
-}
-
-char ReadChoiceController::get(const Common::String &choices, EventHandler *eh) {
- if (!eh)
- eh = eventHandler;
-
- ReadChoiceController ctrl(choices);
- eh->pushController(&ctrl);
- return ctrl.waitFor();
-}
-
-/*-------------------------------------------------------------------*/
-
-ReadDirController::ReadDirController() {
- _value = DIR_NONE;
-}
-
-void ReadDirController::keybinder(KeybindingAction action) {
- switch (action) {
- case KEYBIND_UP:
- _value = DIR_NORTH;
- break;
- case KEYBIND_DOWN:
- _value = DIR_SOUTH;
- break;
- case KEYBIND_LEFT:
- _value = DIR_WEST;
- break;
- case KEYBIND_RIGHT:
- _value = DIR_EAST;
- break;
- case KEYBIND_PASS:
- _value = DIR_NONE;
- doneWaiting();
- break;
- default:
- return;
- }
-
- doneWaiting();
-}
-
-bool ReadDirController::keyPressed(int key) {
- switch (key) {
- case Common::KEYCODE_ESCAPE:
- case Common::KEYCODE_SPACE:
- case Common::KEYCODE_RETURN:
- _value = DIR_NONE;
- doneWaiting();
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-/*-------------------------------------------------------------------*/
-
-WaitController::WaitController(unsigned int c) : Controller(), _cycles(c), _current(0) {}
-
-void WaitController::timerFired() {
- if (++_current >= _cycles) {
- _current = 0;
- eventHandler->setControllerDone(true);
- }
-}
-
-bool WaitController::keyPressed(int key) {
- return true;
-}
-
-void WaitController::wait() {
- Controller_startWait();
-}
-
-void WaitController::setCycles(int c) {
- _cycles = c;
-}
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/events/event.h b/engines/ultima/ultima4/events/event.h
index 50df579b29..ee85319f1b 100644
--- a/engines/ultima/ultima4/events/event.h
+++ b/engines/ultima/ultima4/events/event.h
@@ -23,13 +23,15 @@
#ifndef ULTIMA4_EVENT_H
#define ULTIMA4_EVENT_H
-#include "common/events.h"
-#include "common/list.h"
-#include "common/str.h"
-#include "ultima/ultima4/events/controller.h"
+#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/events/timed_event_mgr.h"
+#include "ultima/ultima4/controllers/key_handler_controller.h"
#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/gfx/screen.h"
#include "ultima/shared/std/containers.h"
+#include "common/events.h"
+#include "common/list.h"
+#include "common/str.h"
namespace Ultima {
namespace Ultima4 {
@@ -58,190 +60,6 @@ namespace Ultima4 {
#define U4_RIGHT_META Common::KEYCODE_RMETA
#define U4_LEFT_META Common::KEYCODE_LMETA
-struct MouseArea;
-class EventHandler;
-class TextView;
-
-/**
- * A class for handling keystrokes.
- */
-class KeyHandler {
-public:
- virtual ~KeyHandler() {}
-
- /* Typedefs */
- typedef bool (*Callback)(int, void *);
-
- /** Additional information to be passed as data param for read buffer key handler */
- typedef struct ReadBuffer {
- int (*_handleBuffer)(Common::String *);
- Common::String *_buffer;
- int _bufferLen;
- int _screenX, _screenY;
- } ReadBuffer;
-
- /** Additional information to be passed as data param for get choice key handler */
- typedef struct GetChoice {
- Common::String _choices;
- int (*_handleChoice)(int);
- } GetChoice;
-
- /* Constructors */
- KeyHandler(Callback func, void *data = NULL, bool asyncronous = true);
-
- /* Static functions */
- static int setKeyRepeat(int delay, int interval);
-
- /**
- * Handles any and all keystrokes.
- * Generally used to exit the application, switch applications,
- * minimize, maximize, etc.
- */
- static bool globalHandler(int key);
-
- /* Static default key handler functions */
- /**
- * A default key handler that should be valid everywhere
- */
- static bool defaultHandler(int key, void *data);
-
- /**
- * A key handler that ignores keypresses
- */
- static bool ignoreKeys(int key, void *data);
-
- /* Operators */
- bool operator==(Callback cb) const;
-
- /* Member functions */
- /**
- * Handles a keypress.
- * First it makes sure the key combination is not ignored
- * by the current key handler. Then, it passes the keypress
- * through the global key handler. If the global handler
- * does not process the keystroke, then the key handler
- * handles it itself by calling its handler callback function.
- */
- bool handle(int key);
-
- /**
- * Returns true if the key or key combination is always ignored by xu4
- */
- virtual bool isKeyIgnored(int key);
-
-protected:
- Callback _handler;
- bool _async;
- void *_data;
-};
-
-/**
- * A controller that wraps a keyhander function. Keyhandlers are
- * deprecated -- please use a controller instead.
- */
-class KeyHandlerController : public Controller {
-public:
- KeyHandlerController(KeyHandler *handler);
- ~KeyHandlerController();
-
- bool keyPressed(int key) override;
- KeyHandler *getKeyHandler();
-
-private:
- KeyHandler *_handler;
-};
-
-/**
- * A controller to read a Common::String, terminated by the enter key.
- */
-class ReadStringController : public WaitableController<Common::String> {
-public:
- /**
- * @param maxlen the maximum length of the Common::String
- * @param screenX the screen column where to begin input
- * @param screenY the screen row where to begin input
- * @param accepted_chars a Common::String characters to be accepted for input
- */
- ReadStringController(int maxlen, int screenX, int screenY, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
- ReadStringController(int maxlen, TextView *view, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
- bool keyPressed(int key) override;
-
- static Common::String get(int maxlen, int screenX, int screenY, EventHandler *eh = NULL);
- static Common::String get(int maxlen, TextView *view, EventHandler *eh = NULL);
-#ifdef IOS
- void setValue(const Common::String &utf8StringValue) {
- value = utf8StringValue;
- }
-#endif
-
-protected:
- int _maxLen, _screenX, _screenY;
- TextView *_view;
- Common::String _accepted;
-};
-
-/**
- * A controller to read a integer, terminated by the enter key.
- * Non-numeric keys are ignored.
- */
-class ReadIntController : public ReadStringController {
-public:
- ReadIntController(int maxlen, int screenX, int screenY);
-
- static int get(int maxlen, int screenX, int screenY, EventHandler *eh = NULL);
- int getInt() const;
-};
-
-/**
- * A controller to read a single key from a provided list.
- */
-class ReadChoiceController : public WaitableController<int> {
-public:
- ReadChoiceController(const Common::String &choices);
- bool keyPressed(int key) override;
-
- static char get(const Common::String &choices, EventHandler *eh = NULL);
-
-protected:
- Common::String _choices;
-};
-
-/**
- * A controller to read a direction enter with the arrow keys.
- */
-class ReadDirController : public WaitableController<Direction> {
-public:
- ReadDirController();
-
- /**
- * Key was pressed
- */
- bool keyPressed(int key) override;
-
- /**
- * Handles keybinder actions
- */
- void keybinder(KeybindingAction action) override;
-};
-
-/**
- * A controller to pause for a given length of time, ignoring all
- * keyboard input.
- */
-class WaitController : public Controller {
-public:
- WaitController(unsigned int cycles);
- bool keyPressed(int key) override;
- void timerFired() override;
-
- void wait();
- void setCycles(int c);
-
-private:
- unsigned int _cycles;
- unsigned int _current;
-};
-
#if defined(IOS)
#ifndef __OBJC__
typedef void *TimedManagerHelper;
diff --git a/engines/ultima/ultima4/events/event_scummvm.cpp b/engines/ultima/ultima4/events/event_scummvm.cpp
index 8f37bfc7cc..0c0e309e83 100644
--- a/engines/ultima/ultima4/events/event_scummvm.cpp
+++ b/engines/ultima/ultima4/events/event_scummvm.cpp
@@ -34,112 +34,6 @@
namespace Ultima {
namespace Ultima4 {
-KeyHandler::KeyHandler(Callback func, void *d, bool asyncronous) :
- _handler(func),
- _async(asyncronous),
- _data(d) {
-}
-
-/**
- * Sets the key-repeat characteristics of the keyboard.
- */
-int KeyHandler::setKeyRepeat(int delay, int interval) {
-#ifdef TODO
- return SDL_EnableKeyRepeat(delay, interval);
-#else
- return 0;
-#endif
-}
-
-bool KeyHandler::globalHandler(int key) {
- switch (key) {
-#if defined(MACOSX)
- case U4_META + 'q': /* Cmd+q */
- case U4_META + 'x': /* Cmd+x */
-#endif
- case U4_ALT + 'x': /* Alt+x */
-#if defined(WIN32)
- case U4_ALT + U4_FKEY + 3:
-#endif
- g_ultima->quitGame();
- EventHandler::end();
- return true;
- default:
- return false;
- }
-}
-
-bool KeyHandler::defaultHandler(int key, void *data) {
- bool valid = true;
-
- switch (key) {
- case '`':
- if (g_context && g_context->_location)
- debug(1, "x = %d, y = %d, level = %d, tile = %d (%s)\n", g_context->_location->_coords.x, g_context->_location->_coords.y, g_context->_location->_coords.z, g_context->_location->_map->translateToRawTileIndex(*g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)), g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_OBJECTS)->getName().c_str());
- break;
- default:
- valid = false;
- break;
- }
-
- return valid;
-}
-
-bool KeyHandler::ignoreKeys(int key, void *data) {
- return true;
-}
-
-bool KeyHandler::handle(int key) {
- bool processed = false;
- if (!isKeyIgnored(key)) {
- processed = globalHandler(key);
- if (!processed)
- processed = _handler(key, _data);
- }
-
- return processed;
-}
-
-bool KeyHandler::isKeyIgnored(int key) {
- switch (key) {
- case U4_RIGHT_SHIFT:
- case U4_LEFT_SHIFT:
- case U4_RIGHT_CTRL:
- case U4_LEFT_CTRL:
- case U4_RIGHT_ALT:
- case U4_LEFT_ALT:
- case U4_RIGHT_META:
- case U4_LEFT_META:
- case U4_TAB:
- return true;
- default:
- return false;
- }
-}
-
-bool KeyHandler::operator==(Callback cb) const {
- return (_handler == cb) ? true : false;
-}
-
-KeyHandlerController::KeyHandlerController(KeyHandler *handler) {
- this->_handler = handler;
-}
-
-KeyHandlerController::~KeyHandlerController() {
- delete _handler;
-}
-
-bool KeyHandlerController::keyPressed(int key) {
- ASSERT(_handler != NULL, "key handler must be initialized");
- return _handler->handle(key);
-}
-
-KeyHandler *KeyHandlerController::getKeyHandler() {
- return _handler;
-}
-
-/*-------------------------------------------------------------------*/
-
EventHandler::EventHandler() : _timer(settings._eventTimerGranularity), _updateScreen(NULL) {
}
diff --git a/engines/ultima/ultima4/game/death.cpp b/engines/ultima/ultima4/game/death.cpp
index f6b7651640..f40a432c69 100644
--- a/engines/ultima/ultima4/game/death.cpp
+++ b/engines/ultima/ultima4/game/death.cpp
@@ -20,22 +20,23 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
#include "ultima/ultima4/game/death.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/game.h"
+#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/game/portal.h"
+#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/controllers/wait_controller.h"
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/map/map.h"
#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/map/city.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/game/game.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/mapmgr.h"
#include "ultima/ultima4/sound/music.h"
-#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/game/portal.h"
-#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
-#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/ultima4.h"
#include "common/system.h"
namespace Ultima {
diff --git a/engines/ultima/ultima4/game/game.cpp b/engines/ultima/ultima4/game/game.cpp
index ff82a024e6..c779640cd8 100644
--- a/engines/ultima/ultima4/game/game.cpp
+++ b/engines/ultima/ultima4/game/game.cpp
@@ -21,6 +21,11 @@
*/
#include "ultima/ultima4/ultima4.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_dir_controller.h"
+#include "ultima/ultima4/controllers/read_int_controller.h"
+#include "ultima/ultima4/controllers/read_player_controller.h"
+#include "ultima/ultima4/controllers/read_string_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/debugger.h"
@@ -72,8 +77,6 @@ namespace Ultima4 {
using namespace std;
-GameController *g_game = NULL;
-
/*-----------------*/
/* Functions BEGIN */
@@ -82,132 +85,15 @@ void gameAdvanceLevel(PartyMember *player);
void gameInnHandler(void);
void gameLostEighth(Virtue virtue);
void gamePartyStarving(void);
-uint32 gameTimeSinceLastCommand(void);
void mixReagentsSuper();
/* action functions */
void wearArmor(int player = -1);
-/* creature functions */
-void gameCreatureAttack(Creature *obj);
-
/* Functions END */
/*---------------*/
-static const MouseArea MOUSE_AREAS[] = {
- { 3, { { 8, 8 }, { 8, 184 }, { 96, 96 } }, MC_WEST, { U4_ENTER, 0, U4_LEFT } },
- { 3, { { 8, 8 }, { 184, 8 }, { 96, 96 } }, MC_NORTH, { U4_ENTER, 0, U4_UP } },
- { 3, { { 184, 8 }, { 184, 184 }, { 96, 96 } }, MC_EAST, { U4_ENTER, 0, U4_RIGHT } },
- { 3, { { 8, 184 }, { 184, 184 }, { 96, 96 } }, MC_SOUTH, { U4_ENTER, 0, U4_DOWN } },
- { 0, { { 0, 0 }, { 0, 0 }, { 0, 0 } }, MC_NORTH, { 0, 0, 0 } }
-};
-
-ReadPlayerController::ReadPlayerController() : ReadChoiceController("12345678 \033\n") {
-#ifdef IOS
- U4IOS::beginCharacterChoiceDialog();
-#endif
-}
-
-ReadPlayerController::~ReadPlayerController() {
-#ifdef IOS
- U4IOS::endCharacterChoiceDialog();
-#endif
-}
-
-bool ReadPlayerController::keyPressed(int key) {
- bool valid = ReadChoiceController::keyPressed(key);
- if (valid) {
- if (_value < '1' ||
- _value > ('0' + g_ultima->_saveGame->_members))
- _value = '0';
- } else {
- _value = '0';
- }
- return valid;
-}
-
-int ReadPlayerController::getPlayer() {
- return _value - '1';
-}
-
-int ReadPlayerController::waitFor() {
- ReadChoiceController::waitFor();
- return getPlayer();
-}
-
-bool AlphaActionController::keyPressed(int key) {
- if (Common::isLower(key))
- key = toupper(key);
-
- if (key >= 'A' && key <= toupper(_lastValidLetter)) {
- _value = key - 'A';
- doneWaiting();
- } else if (key == U4_SPACE || key == U4_ESC || key == U4_ENTER) {
- screenMessage("\n");
- _value = -1;
- doneWaiting();
- } else {
- screenMessage("\n%s", _prompt.c_str());
- g_screen->update();
- return KeyHandler::defaultHandler(key, NULL);
- }
- return true;
-}
-
-int AlphaActionController::get(char lastValidLetter, const Common::String &prompt, EventHandler *eh) {
- if (!eh)
- eh = eventHandler;
-
- AlphaActionController ctrl(lastValidLetter, prompt);
- eh->pushController(&ctrl);
- return ctrl.waitFor();
-}
-
-GameController::GameController() : _mapArea(BORDER_WIDTH, BORDER_HEIGHT, VIEWPORT_W, VIEWPORT_H), _paused(false), _pausedTimer(0) {
- g_game = this;
-}
-
-void GameController::initScreen() {
- Image *screen = imageMgr->get("screen")->_image;
-
- screen->fillRect(0, 0, screen->width(), screen->height(), 0, 0, 0);
- g_screen->update();
-}
-
-void GameController::initScreenWithoutReloadingState() {
- g_music->play();
- imageMgr->get(BKGD_BORDERS)->_image->draw(0, 0);
- g_context->_stats->update(); /* draw the party stats */
-
- screenMessage("Press Alt-h for help\n");
- screenPrompt();
-
- eventHandler->pushMouseAreaSet(MOUSE_AREAS);
-
- eventHandler->setScreenUpdate(&gameUpdateScreen);
-}
-
-
-void GameController::init() {
- initScreen();
-
- // initialize the global game context, conversation and game state variables
- g_context = new Context();
- g_context->_line = TEXT_AREA_H - 1;
- g_context->col = 0;
- g_context->_stats = new StatsArea();
- g_context->_moonPhase = 0;
- g_context->_windDirection = DIR_NORTH;
- g_context->_windCounter = 0;
- g_context->_windLock = false;
- g_context->_aura = new Aura();
- g_context->_horseSpeed = 0;
- g_context->_opacity = 1;
- g_context->_lastCommandTime = g_system->getMillis();
- g_context->_lastShip = NULL;
-}
-
/**
* Sets the view mode.
*/
@@ -241,238 +127,6 @@ void gameUpdateScreen() {
}
}
-void GameController::setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter) {
- int viewMode;
- LocationContext context;
- int activePlayer = g_context->_party->getActivePlayer();
- MapCoords coords;
-
- if (!turnCompleter)
- turnCompleter = this;
-
- if (portal)
- coords = portal->_start;
- else
- coords = MapCoords(map->_width / 2, map->_height / 2);
-
- /* If we don't want to save the location, then just return to the previous location,
- as there may still be ones in the stack we want to keep */
- if (!saveLocation)
- exitToParentMap();
-
- switch (map->_type) {
- case Map::WORLD:
- context = CTX_WORLDMAP;
- viewMode = VIEW_NORMAL;
- break;
- case Map::DUNGEON:
- context = CTX_DUNGEON;
- viewMode = VIEW_DUNGEON;
- if (portal)
- g_ultima->_saveGame->_orientation = DIR_EAST;
- break;
- case Map::COMBAT:
- coords = MapCoords(-1, -1); /* set these to -1 just to be safe; we don't need them */
- context = CTX_COMBAT;
- viewMode = VIEW_NORMAL;
- activePlayer = -1; /* different active player for combat, defaults to 'None' */
- break;
- case Map::SHRINE:
- context = CTX_SHRINE;
- viewMode = VIEW_NORMAL;
- break;
- case Map::CITY:
- default:
- context = CTX_CITY;
- viewMode = VIEW_NORMAL;
- break;
- }
- g_context->_location = new Location(coords, map, viewMode, context, turnCompleter, g_context->_location);
- g_context->_location->addObserver(this);
- g_context->_party->setActivePlayer(activePlayer);
-#ifdef IOS
- U4IOS::updateGameControllerContext(c->location->context);
-#endif
-
- /* now, actually set our new tileset */
- _mapArea.setTileset(map->_tileset);
-
- if (isCity(map)) {
- City *city = dynamic_cast<City *>(map);
- city->addPeople();
- }
-}
-
-int GameController::exitToParentMap() {
- if (!g_context->_location)
- return 0;
-
- if (g_context->_location->_prev != NULL) {
- // Create the balloon for Hythloth
- if (g_context->_location->_map->_id == MAP_HYTHLOTH)
- createBalloon(g_context->_location->_prev->_map);
-
- // free map info only if previous location was on a different map
- if (g_context->_location->_prev->_map != g_context->_location->_map) {
- g_context->_location->_map->_annotations->clear();
- g_context->_location->_map->clearObjects();
-
- /* quench the torch of we're on the world map */
- if (g_context->_location->_prev->_map->isWorldMap())
- g_context->_party->quenchTorch();
- }
- locationFree(&g_context->_location);
-
- // restore the tileset to the one the current map uses
- _mapArea.setTileset(g_context->_location->_map->_tileset);
-#ifdef IOS
- U4IOS::updateGameControllerContext(c->location->context);
-#endif
-
- return 1;
- }
- return 0;
-}
-
-void GameController::finishTurn() {
- g_context->_lastCommandTime = g_system->getMillis();
- Creature *attacker = NULL;
-
- while (1) {
-
- /* adjust food and moves */
- g_context->_party->endTurn();
-
- /* count down the aura, if there is one */
- g_context->_aura->passTurn();
-
- gameCheckHullIntegrity();
-
- /* update party stats */
- //c->stats->setView(STATS_PARTY_OVERVIEW);
-
- screenUpdate(&this->_mapArea, true, false);
- screenWait(1);
-
- /* Creatures cannot spawn, move or attack while the avatar is on the balloon */
- if (!g_context->_party->isFlying()) {
-
- // apply effects from tile avatar is standing on
- g_context->_party->applyEffect(g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_GROUND_OBJECTS)->getEffect());
-
- // Move creatures and see if something is attacking the avatar
- attacker = g_context->_location->_map->moveObjects(g_context->_location->_coords);
-
- // Something's attacking! Start combat!
- if (attacker) {
- gameCreatureAttack(attacker);
- return;
- }
-
- // cleanup old creatures and spawn new ones
- creatureCleanup();
- checkRandomCreatures();
- checkBridgeTrolls();
- }
-
- /* update map annotations */
- g_context->_location->_map->_annotations->passTurn();
-
- if (!g_context->_party->isImmobilized())
- break;
-
- if (g_context->_party->isDead()) {
- deathStart(0);
- return;
- } else {
- screenMessage("Zzzzzz\n");
- screenWait(4);
- }
- }
-
- if (g_context->_location->_context == CTX_DUNGEON) {
- Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
- if (g_context->_party->getTorchDuration() <= 0)
- screenMessage("It's Dark!\n");
- else g_context->_party->burnTorch();
-
- /* handle dungeon traps */
- if (dungeon->currentToken() == DUNGEON_TRAP) {
- dungeonHandleTrap((TrapType)dungeon->currentSubToken());
- // a little kludgey to have a second test for this
- // right here. But without it you can survive an
- // extra turn after party death and do some things
- // that could cause a crash, like Hole up and Camp.
- if (g_context->_party->isDead()) {
- deathStart(0);
- return;
- }
- }
- }
-
-
- /* draw a prompt */
- screenPrompt();
- //screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
-}
-
-void GameController::flashTile(const Coords &coords, MapTile tile, int frames) {
- g_context->_location->_map->_annotations->add(coords, tile, true);
-
- screenTileUpdate(&g_game->_mapArea, coords);
-
- screenWait(frames);
- g_context->_location->_map->_annotations->remove(coords, tile);
-
- screenTileUpdate(&g_game->_mapArea, coords, false);
-}
-
-void GameController::flashTile(const Coords &coords, const Common::String &tilename, int timeFactor) {
- Tile *tile = g_context->_location->_map->_tileset->getByName(tilename);
- ASSERT(tile, "no tile named '%s' found in tileset", tilename.c_str());
- flashTile(coords, tile->getId(), timeFactor);
-}
-
-void GameController::update(Party *party, PartyEvent &event) {
- int i;
-
- switch (event._type) {
- case PartyEvent::LOST_EIGHTH:
- // inform a player he has lost zero or more eighths of avatarhood.
- screenMessage("\n %cThou hast lost\n an eighth!%c\n", FG_YELLOW, FG_WHITE);
- break;
- case PartyEvent::ADVANCED_LEVEL:
- screenMessage("\n%c%s\nThou art now Level %d%c\n", FG_YELLOW, event._player->getName().c_str(), event._player->getRealLevel(), FG_WHITE);
- gameSpellEffect('r', -1, SOUND_MAGIC); // Same as resurrect spell
- break;
- case PartyEvent::STARVING:
- screenMessage("\n%cStarving!!!%c\n", FG_YELLOW, FG_WHITE);
- /* FIXME: add sound effect here */
-
- // 2 damage to each party member for starving!
- for (i = 0; i < g_ultima->_saveGame->_members; i++)
- g_context->_party->member(i)->applyDamage(2);
- break;
- default:
- break;
- }
-}
-
-void GameController::update(Location *location, MoveEvent &event) {
- switch (location->_map->_type) {
- case Map::DUNGEON:
- avatarMovedInDungeon(event);
- break;
- case Map::COMBAT:
- // FIXME: let the combat controller handle it
- dynamic_cast<CombatController *>(eventHandler->getController())->movePartyMember(event);
- break;
- default:
- avatarMoved(event);
- break;
- }
-}
-
void gameSpellEffect(int spell, int player, Sound sound) {
int time;
@@ -519,99 +173,6 @@ void gameSpellEffect(int spell, int player, Sound sound) {
}
}
-void GameController::keybinder(KeybindingAction action) {
- MetaEngine::executeAction(action);
-}
-
-bool GameController::keyPressed(int key) {
- bool valid = true;
- int endTurn = 1;
- Object *obj;
- MapTile *tile;
-
- /* Translate context-sensitive action key into a useful command */
- if (key == U4_ENTER && settings._enhancements && settings._enhancementsOptions._smartEnterKey) {
- /* Attempt to guess based on the character's surroundings etc, what
- action they want */
-
- /* Do they want to board something? */
- if (g_context->_transportContext == TRANSPORT_FOOT) {
- obj = g_context->_location->_map->objectAt(g_context->_location->_coords);
- if (obj && (obj->getTile().getTileType()->isShip() ||
- obj->getTile().getTileType()->isHorse() ||
- obj->getTile().getTileType()->isBalloon()))
- key = 'b';
- }
- /* Klimb/Descend Balloon */
- else if (g_context->_transportContext == TRANSPORT_BALLOON) {
- if (g_context->_party->isFlying())
- key = 'd';
- else {
-#ifdef IOS
- U4IOS::IOSSuperButtonHelper superHelper;
- key = ReadChoiceController::get("xk \033\n");
-#else
- key = 'k';
-#endif
- }
- }
- /* X-it transport */
- else key = 'x';
-
- /* Klimb? */
- if ((g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_KLIMB) != NULL))
- key = 'k';
- /* Descend? */
- else if ((g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_DESCEND) != NULL))
- key = 'd';
-
- if (g_context->_location->_context == CTX_DUNGEON) {
- Dungeon *dungeon = static_cast<Dungeon *>(g_context->_location->_map);
- bool up = dungeon->ladderUpAt(g_context->_location->_coords);
- bool down = dungeon->ladderDownAt(g_context->_location->_coords);
- if (up && down) {
-#ifdef IOS
- U4IOS::IOSClimbHelper climbHelper;
- key = ReadChoiceController::get("kd \033\n");
-#else
- key = 'k'; // This is consistent with the previous code. Ideally, I would have a UI here as well.
-#endif
- } else if (up) {
- key = 'k';
- } else {
- key = 'd';
- }
- }
-
- /* Enter? */
- if (g_context->_location->_map->portalAt(g_context->_location->_coords, ACTION_ENTER) != NULL)
- key = 'e';
-
- /* Get Chest? */
- if (!g_context->_party->isFlying()) {
- tile = g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_GROUND_OBJECTS);
-
- if (tile->getTileType()->isChest()) key = 'g';
- }
-
- /* None of these? Default to search */
- if (key == U4_ENTER) key = 's';
- }
-
- if ((g_context->_location->_context & CTX_DUNGEON) && strchr("abefjlotxy", key))
- screenMessage("%cNot here!%c\n", FG_GREY, FG_WHITE);
-
- if (valid && endTurn) {
- if (eventHandler->getController() == g_game)
- g_context->_location->_turnCompleter->finishTurn();
- } else if (!endTurn) {
- /* if our turn did not end, then manually redraw the text prompt */
- screenPrompt();
- }
-
- return valid || KeyHandler::defaultHandler(key, NULL);
-}
-
Common::String gameGetInput(int maxlen) {
screenEnableCursor();
screenShowCursor();
@@ -678,42 +239,6 @@ Direction gameGetDirection() {
}
}
-bool ZtatsController::keyPressed(int key) {
- switch (key) {
- case U4_UP:
- case U4_LEFT:
- g_context->_stats->prevItem();
- return true;
- case U4_DOWN:
- case U4_RIGHT:
- g_context->_stats->nextItem();
- return true;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- if (g_ultima->_saveGame->_members >= key - '0')
- g_context->_stats->setView(StatsView(STATS_CHAR1 + key - '1'));
- return true;
- case '0':
- g_context->_stats->setView(StatsView(STATS_WEAPONS));
- return true;
- case U4_ESC:
- case U4_SPACE:
- case U4_ENTER:
- g_context->_stats->setView(StatsView(STATS_PARTY_OVERVIEW));
- doneWaiting();
- return true;
- default:
- return KeyHandler::defaultHandler(key, NULL);
- }
-}
-
-
bool fireAt(const Coords &coords, bool originAvatar) {
bool validObject = false;
bool hitsAvatar = false;
@@ -772,233 +297,6 @@ bool fireAt(const Coords &coords, bool originAvatar) {
return objectHit;
}
-void GameController::initMoons() {
- int trammelphase = g_ultima->_saveGame->_trammelPhase,
- feluccaphase = g_ultima->_saveGame->_feluccaPhase;
-
- ASSERT(g_context != NULL, "Game context doesn't exist!");
- ASSERT(g_ultima->_saveGame != NULL, "Savegame doesn't exist!");
- //ASSERT(mapIsWorldMap(c->location->map) && c->location->viewMode == VIEW_NORMAL, "Can only call gameInitMoons() from the world map!");
-
- g_ultima->_saveGame->_trammelPhase = g_ultima->_saveGame->_feluccaPhase = 0;
- g_context->_moonPhase = 0;
-
- while ((g_ultima->_saveGame->_trammelPhase != trammelphase) ||
- (g_ultima->_saveGame->_feluccaPhase != feluccaphase))
- updateMoons(false);
-}
-
-void GameController::updateMoons(bool showmoongates) {
- int realMoonPhase,
- oldTrammel,
- trammelSubphase;
- const Coords *gate;
-
- if (g_context->_location->_map->isWorldMap()) {
- oldTrammel = g_ultima->_saveGame->_trammelPhase;
-
- if (++g_context->_moonPhase >= MOON_PHASES * MOON_SECONDS_PER_PHASE * 4)
- g_context->_moonPhase = 0;
-
- trammelSubphase = g_context->_moonPhase % (MOON_SECONDS_PER_PHASE * 4 * 3);
- realMoonPhase = (g_context->_moonPhase / (4 * MOON_SECONDS_PER_PHASE));
-
- g_ultima->_saveGame->_trammelPhase = realMoonPhase / 3;
- g_ultima->_saveGame->_feluccaPhase = realMoonPhase % 8;
-
- if (g_ultima->_saveGame->_trammelPhase > 7)
- g_ultima->_saveGame->_trammelPhase = 7;
-
- if (showmoongates) {
- /* update the moongates if trammel changed */
- if (trammelSubphase == 0) {
- gate = moongateGetGateCoordsForPhase(oldTrammel);
- if (gate)
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate)
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
- } else if (trammelSubphase == 1) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
- }
- } else if (trammelSubphase == 2) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
- }
- } else if (trammelSubphase == 3) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
- }
- } else if ((trammelSubphase > 3) && (trammelSubphase < (MOON_SECONDS_PER_PHASE * 4 * 3) - 3)) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
- }
- } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 3) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
- }
- } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 2) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
- }
- } else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 1) {
- gate = moongateGetGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
- if (gate) {
- g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
- g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
- }
- }
- }
- }
-}
-
-void GameController::avatarMoved(MoveEvent &event) {
- if (event._userEvent) {
-
- // is filterMoveMessages even used? it doesn't look like the option is hooked up in the configuration menu
- if (!settings._filterMoveMessages) {
- switch (g_context->_transportContext) {
- case TRANSPORT_FOOT:
- case TRANSPORT_HORSE:
- screenMessage("%s\n", getDirectionName(event._dir));
- break;
- case TRANSPORT_SHIP:
- if (event._result & MOVE_TURNED)
- screenMessage("Turn %s!\n", getDirectionName(event._dir));
- else if (event._result & MOVE_SLOWED)
- screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
- else
- screenMessage("Sail %s!\n", getDirectionName(event._dir));
- break;
- case TRANSPORT_BALLOON:
- screenMessage("%cDrift Only!%c\n", FG_GREY, FG_WHITE);
- break;
- default:
- error("bad transportContext %d in avatarMoved()", g_context->_transportContext);
- }
- }
-
- /* movement was blocked */
- if (event._result & MOVE_BLOCKED) {
-
- /* if shortcuts are enabled, try them! */
- if (settings._shortcutCommands) {
- MapCoords new_coords = g_context->_location->_coords;
- MapTile *tile;
-
- new_coords.move(event._dir, g_context->_location->_map);
- tile = g_context->_location->_map->tileAt(new_coords, WITH_OBJECTS);
-
- if (tile->getTileType()->isDoor()) {
- g_debugger->openAt(new_coords);
- event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
- } else if (tile->getTileType()->isLockedDoor()) {
- g_debugger->jimmyAt(new_coords);
- event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
- } /*else if (mapPersonAt(c->location->map, new_coords) != NULL) {
- talkAtCoord(newx, newy, 1, NULL);
- event.result = MOVE_SUCCEEDED | MOVE_END_TURN;
- }*/
- }
-
- /* if we're still blocked */
- if ((event._result & MOVE_BLOCKED) && !settings._filterMoveMessages) {
- soundPlay(SOUND_BLOCKED, false);
- screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
- }
- } else if (g_context->_transportContext == TRANSPORT_FOOT || g_context->_transportContext == TRANSPORT_HORSE) {
- /* movement was slowed */
- if (event._result & MOVE_SLOWED) {
- soundPlay(SOUND_WALK_SLOWED);
- screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
- } else {
- soundPlay(SOUND_WALK_NORMAL);
- }
- }
- }
-
- /* exited map */
- if (event._result & MOVE_EXIT_TO_PARENT) {
- screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
- exitToParentMap();
- g_music->play();
- }
-
- /* things that happen while not on board the balloon */
- if (g_context->_transportContext & ~TRANSPORT_BALLOON)
- checkSpecialCreatures(event._dir);
- /* things that happen while on foot or horseback */
- if ((g_context->_transportContext & TRANSPORT_FOOT_OR_HORSE) &&
- !(event._result & (MOVE_SLOWED | MOVE_BLOCKED))) {
- if (checkMoongates())
- event._result = (MoveResult)(MOVE_MAP_CHANGE | MOVE_END_TURN);
- }
-}
-
-void GameController::avatarMovedInDungeon(MoveEvent &event) {
- Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
- Direction realDir = dirNormalize((Direction)g_ultima->_saveGame->_orientation, event._dir);
-
- if (!settings._filterMoveMessages) {
- if (event._userEvent) {
- if (event._result & MOVE_TURNED) {
- if (dirRotateCCW((Direction)g_ultima->_saveGame->_orientation) == realDir)
- screenMessage("Turn Left\n");
- else screenMessage("Turn Right\n");
- }
- /* show 'Advance' or 'Retreat' in dungeons */
- else screenMessage("%s\n", realDir == g_ultima->_saveGame->_orientation ? "Advance" : "Retreat");
- }
-
- if (event._result & MOVE_BLOCKED)
- screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
- }
-
- /* if we're exiting the map, do this */
- if (event._result & MOVE_EXIT_TO_PARENT) {
- screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
- exitToParentMap();
- g_music->play();
- }
-
- /* check to see if we're entering a dungeon room */
- if (event._result & MOVE_SUCCEEDED) {
- if (dungeon->currentToken() == DUNGEON_ROOM) {
- int room = (int)dungeon->currentSubToken(); /* get room number */
-
- /**
- * recalculate room for the abyss -- there are 16 rooms for every 2 levels,
- * each room marked with 0xD* where (* == room number 0-15).
- * for levels 1 and 2, there are 16 rooms, levels 3 and 4 there are 16 rooms, etc.
- */
- if (g_context->_location->_map->_id == MAP_ABYSS)
- room = (0x10 * (g_context->_location->_coords.z / 2)) + room;
-
- Dungeon *dng = dynamic_cast<Dungeon *>(g_context->_location->_map);
- dng->_currentRoom = room;
-
- /* set the map and start combat! */
- CombatController *cc = new CombatController(dng->_roomMaps[room]);
- cc->initDungeonRoom(room, dirReverse(realDir));
- cc->begin();
- }
- }
-}
-
-
/**
* Peers at a city from A-P (Lycaeum telescope) and functions like a gem
*/
@@ -1062,48 +360,6 @@ void peer(bool useGem) {
g_game->_paused = false;
}
-void GameController::timerFired() {
- if (_pausedTimer > 0) {
- _pausedTimer--;
- if (_pausedTimer <= 0) {
- _pausedTimer = 0;
- _paused = false; /* unpause the game */
- }
- }
-
- if (!_paused && !_pausedTimer) {
- if (++g_context->_windCounter >= MOON_SECONDS_PER_PHASE * 4) {
- if (xu4_random(4) == 1 && !g_context->_windLock)
- g_context->_windDirection = dirRandomDir(MASK_DIR_ALL);
- g_context->_windCounter = 0;
- }
-
- /* balloon moves about 4 times per second */
- if ((g_context->_transportContext == TRANSPORT_BALLOON) &&
- g_context->_party->isFlying()) {
- g_context->_location->move(dirReverse((Direction) g_context->_windDirection), false);
- }
-
- updateMoons(true);
-
- screenCycle();
-
- /*
- * force pass if no commands within last 20 seconds
- */
- Controller *controller = eventHandler->getController();
- if (controller != NULL && (eventHandler->getController() == g_game ||
- dynamic_cast<CombatController *>(eventHandler->getController()) != NULL) &&
- gameTimeSinceLastCommand() > 20) {
-
- /* pass the turn, and redraw the text area so the prompt is shown */
- MetaEngine::executeAction(KEYBIND_PASS);
- screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
- }
- }
-
-}
-
/**
* Checks the hull integrity of the ship and handles
* the ship sinking, if necessary
@@ -1138,83 +394,6 @@ void gameCheckHullIntegrity() {
}
}
-void GameController::checkSpecialCreatures(Direction dir) {
- int i;
- Object *obj;
- static const struct {
- int x, y;
- Direction dir;
- } pirateInfo[] = {
- { 224, 220, DIR_EAST }, /* N'M" O'A" */
- { 224, 228, DIR_EAST }, /* O'E" O'A" */
- { 226, 220, DIR_EAST }, /* O'E" O'C" */
- { 227, 228, DIR_EAST }, /* O'E" O'D" */
- { 228, 227, DIR_SOUTH }, /* O'D" O'E" */
- { 229, 225, DIR_SOUTH }, /* O'B" O'F" */
- { 229, 223, DIR_NORTH }, /* N'P" O'F" */
- { 228, 222, DIR_NORTH } /* N'O" O'E" */
- };
-
- /*
- * if heading east into pirates cove (O'A" N'N"), generate pirate
- * ships
- */
- if (dir == DIR_EAST &&
- g_context->_location->_coords.x == 0xdd &&
- g_context->_location->_coords.y == 0xe0) {
- for (i = 0; i < 8; i++) {
- obj = g_context->_location->_map->addCreature(creatureMgr->getById(PIRATE_ID), MapCoords(pirateInfo[i].x, pirateInfo[i].y));
- obj->setDirection(pirateInfo[i].dir);
- }
- }
-
- /*
- * if heading south towards the shrine of humility, generate
- * daemons unless horn has been blown
- */
- if (dir == DIR_SOUTH &&
- g_context->_location->_coords.x >= 229 &&
- g_context->_location->_coords.x < 234 &&
- g_context->_location->_coords.y >= 212 &&
- g_context->_location->_coords.y < 217 &&
- *g_context->_aura != Aura::HORN) {
- for (i = 0; i < 8; i++)
- g_context->_location->_map->addCreature(creatureMgr->getById(DAEMON_ID), MapCoords(231, g_context->_location->_coords.y + 1, g_context->_location->_coords.z));
- }
-}
-
-bool GameController::checkMoongates() {
- Coords dest;
-
- if (moongateFindActiveGateAt(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase, g_context->_location->_coords, dest)) {
-
- gameSpellEffect(-1, -1, SOUND_MOONGATE); // Default spell effect (screen inversion without 'spell' sound effects)
-
- if (g_context->_location->_coords != dest) {
- g_context->_location->_coords = dest;
- gameSpellEffect(-1, -1, SOUND_MOONGATE); // Again, after arriving
- }
-
- if (moongateIsEntryToShrineOfSpirituality(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase)) {
- Shrine *shrine_spirituality;
-
- shrine_spirituality = dynamic_cast<Shrine *>(mapMgr->get(MAP_SHRINE_SPIRITUALITY));
-
- if (!g_context->_party->canEnterShrine(VIRT_SPIRITUALITY))
- return true;
-
- setMap(shrine_spirituality, 1, NULL);
- g_music->play();
-
- shrine_spirituality->enter();
- }
-
- return true;
- }
-
- return false;
-}
-
/**
* Fixes objects initially loaded by saveGameMonstersRead,
* and alters movement behavior accordingly to match the creature
@@ -1446,60 +625,6 @@ void gameSetActivePlayer(int player) {
}
}
-void GameController::creatureCleanup() {
- ObjectDeque::iterator i;
- Map *map = g_context->_location->_map;
-
- for (i = map->_objects.begin(); i != map->_objects.end();) {
- Object *obj = *i;
- MapCoords o_coords = obj->getCoords();
-
- if ((obj->getType() == Object::CREATURE) && (o_coords.z == g_context->_location->_coords.z) &&
- o_coords.distance(g_context->_location->_coords, g_context->_location->_map) > MAX_CREATURE_DISTANCE) {
-
- /* delete the object and remove it from the map */
- i = map->removeObject(i);
- } else i++;
- }
-}
-
-void GameController::checkRandomCreatures() {
- int canSpawnHere = g_context->_location->_map->isWorldMap() || g_context->_location->_context & CTX_DUNGEON;
-#ifdef IOS
- int spawnDivisor = c->location->context & CTX_DUNGEON ? (53 - (c->location->coords.z << 2)) : 53;
-#else
- int spawnDivisor = g_context->_location->_context & CTX_DUNGEON ? (32 - (g_context->_location->_coords.z << 2)) : 32;
-#endif
-
- /* If there are too many creatures already,
- or we're not on the world map, don't worry about it! */
- if (!canSpawnHere ||
- g_context->_location->_map->getNumberOfCreatures() >= MAX_CREATURES_ON_MAP ||
- xu4_random(spawnDivisor) != 0)
- return;
-
- gameSpawnCreature(NULL);
-}
-
-void GameController::checkBridgeTrolls() {
- const Tile *bridge = g_context->_location->_map->_tileset->getByName("bridge");
- if (!bridge)
- return;
-
- // TODO: CHEST: Make a user option to not make chests block bridge trolls
- if (!g_context->_location->_map->isWorldMap() ||
- g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)->_id != bridge->getId() ||
- xu4_random(8) != 0)
- return;
-
- screenMessage("\nBridge Trolls!\n");
-
- Creature *m = g_context->_location->_map->addCreature(creatureMgr->getById(TROLL_ID), g_context->_location->_coords);
- CombatController *cc = new CombatController(MAP_BRIDGE_CON);
- cc->init(m);
- cc->begin();
-}
-
/**
* Spawns a creature (m) just offscreen of the avatar.
* If (m==NULL) then it finds its own creature to spawn and spawns it.
@@ -1626,22 +751,6 @@ void gameDestroyAllCreatures(void) {
g_context->_location->_map->alertGuards();
}
-bool GameController::createBalloon(Map *map) {
- ObjectDeque::iterator i;
-
- /* see if the balloon has already been created (and not destroyed) */
- for (i = map->_objects.begin(); i != map->_objects.end(); i++) {
- Object *obj = *i;
- if (obj->getTile().getTileType()->isBalloon())
- return false;
- }
-
- const Tile *balloon = map->_tileset->getByName("balloon");
- ASSERT(balloon, "no balloon tile found in tileset");
- map->addObject(balloon->getId(), balloon->getId(), map->getLabel("balloon"));
- return true;
-}
-
// Colors assigned to reagents based on my best reading of them
// from the book of wisdom. Maybe we could use BOLD to distinguish
// the two grey and the two red reagents.
diff --git a/engines/ultima/ultima4/game/game.h b/engines/ultima/ultima4/game/game.h
index 7bef392a38..980a8ca42e 100644
--- a/engines/ultima/ultima4/game/game.h
+++ b/engines/ultima/ultima4/game/game.h
@@ -23,13 +23,13 @@
#ifndef ULTIMA4_GAME_H
#define ULTIMA4_GAME_H
-#include "ultima/ultima4/events/controller.h"
#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/map/map.h"
+#include "ultima/ultima4/controllers/game_controller.h"
#include "ultima/ultima4/core/observer.h"
-#include "ultima/ultima4/sound/sound.h"
-#include "ultima/ultima4/map/tileview.h"
#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/map/map.h"
+#include "ultima/ultima4/map/tileview.h"
+#include "ultima/ultima4/sound/sound.h"
namespace Ultima {
namespace Ultima4 {
@@ -53,186 +53,9 @@ typedef enum {
VIEW_MIXTURES
} ViewMode;
-/**
- * A controller to read a player number.
- */
-class ReadPlayerController : public ReadChoiceController {
-public:
- ReadPlayerController();
- ~ReadPlayerController();
- bool keyPressed(int key) override;
-
- int getPlayer();
- int waitFor() override;
-};
-
-/**
- * A controller to handle input for commands requiring a letter
- * argument in the range 'a' - lastValidLetter.
- */
-class AlphaActionController : public WaitableController<int> {
-public:
- AlphaActionController(char letter, const Common::String &p) : _lastValidLetter(letter), _prompt(p) {}
- bool keyPressed(int key) override;
-
- static int get(char lastValidLetter, const Common::String &prompt, EventHandler *eh = NULL);
-
-private:
- char _lastValidLetter;
- Common::String _prompt;
-};
-
-/**
- * Controls interaction while Ztats are being displayed.
- */
-class ZtatsController : public WaitableController<void *> {
-public:
- bool keyPressed(int key) override;
-};
-
-class TurnCompleter {
-public:
- virtual ~TurnCompleter() {}
- virtual void finishTurn() = 0;
-};
-
-/**
- * The main game controller that handles basic game flow and keypresses.
- *
- * @todo
- * <ul>
- * <li>separate the dungeon specific stuff into another class (subclass?)</li>
- * </ul>
- */
-class GameController : public Controller, public Observer<Party *, PartyEvent &>, public Observer<Location *, MoveEvent &>,
- public TurnCompleter {
-public:
- GameController();
-
- /* controller functions */
-
- /**
- * Keybinder actions
- */
- void keybinder(KeybindingAction action) override;
-
- /**
- * The main key handler for the game. Interpretes each key as a
- * command - 'a' for attack, 't' for talk, etc.
- */
- bool keyPressed(int key) override;
-
- /**
- * This function is called every quarter second.
- */
- void timerFired() override;
-
- /* main game functions */
- void init();
- void initScreen();
- void initScreenWithoutReloadingState();
- void setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter = NULL);
-
- /**
- * Exits the current map and location and returns to its parent location
- * This restores all relevant information from the previous location,
- * such as the map, map position, etc. (such as exiting a city)
- **/
- int exitToParentMap();
-
- /**
- * Terminates a game turn. This performs the post-turn housekeeping
- * tasks like adjusting the party's food, incrementing the number of
- * moves, etc.
- */
- void finishTurn() override;
-
- /**
- * Provide feedback to user after a party event happens.
- */
- void update(Party *party, PartyEvent &event) override;
-
- /**
- * Provide feedback to user after a movement event happens.
- */
- void update(Location *location, MoveEvent &event) override;
-
- /**
- * Initializes the moon state according to the savegame file. This method of
- * initializing the moons (rather than just setting them directly) is necessary
- * to make sure trammel and felucca stay in sync
- */
- void initMoons();
-
- /**
- * Updates the phases of the moons and shows
- * the visual moongates on the map, if desired
- */
- void updateMoons(bool showmoongates);
-
- /**
- * Show an attack flash at x, y on the current map.
- * This is used for 'being hit' or 'being missed'
- * by weapons, cannon fire, spells, etc.
- */
- static void flashTile(const Coords &coords, MapTile tile, int timeFactor);
-
- static void flashTile(const Coords &coords, const Common::String &tilename, int timeFactor);
- static void doScreenAnimationsWhilePausing(int timeFactor);
-
- TileView _mapArea;
- bool _paused;
- int _pausedTimer;
-
-private:
- /**
- * Handles feedback after avatar moved during normal 3rd-person view.
- */
- void avatarMoved(MoveEvent &event);
-
- /**
- * Handles feedback after moving the avatar in the 3-d dungeon view.
- */
- void avatarMovedInDungeon(MoveEvent &event);
-
- /**
- * Removes creatures from the current map if they are too far away from the avatar
- */
- void creatureCleanup();
-
- /**
- * Handles trolls under bridges
- */
- void checkBridgeTrolls();
-
- /**
- * Checks creature conditions and spawns new creatures if necessary
- */
- void checkRandomCreatures();
-
- /**
- * Checks for valid conditions and handles
- * special creatures guarding the entrance to the
- * abyss and to the shrine of spirituality
- */
- void checkSpecialCreatures(Direction dir);
-
- /**
- * Checks for and handles when the avatar steps on a moongate
- */
- bool checkMoongates();
-
- /**
- * Creates the balloon near Hythloth, but only if the balloon doesn't already exists somewhere
- */
- bool createBalloon(Map *map);
-};
-
-extern GameController *g_game;
-
/* map and screen functions */
void gameSetViewMode(ViewMode newMode);
-void gameUpdateScreen(void);
+void gameUpdateScreen();
/* spell functions */
void gameSpellEffect(int spell, int player, Sound sound);
@@ -242,16 +65,18 @@ bool gamePeerCity(int city, void *data);
void peer(bool useGem = true);
bool fireAt(const Coords &coords, bool originAvatar);
Direction gameGetDirection();
+uint32 gameTimeSinceLastCommand();
/* checking functions */
-void gameCheckHullIntegrity(void);
+void gameCheckHullIntegrity();
/* creature functions */
bool creatureRangeAttack(const Coords &coords, Creature *m);
-void gameCreatureCleanup(void);
+void gameCreatureCleanup();
bool gameSpawnCreature(const class Creature *m);
void gameFixupObjects(Map *map);
-void gameDestroyAllCreatures(void);
+void gameDestroyAllCreatures();
+void gameCreatureAttack(Creature *obj);
/* etc */
Common::String gameGetInput(int maxlen = 32);
diff --git a/engines/ultima/ultima4/game/intro.cpp b/engines/ultima/ultima4/game/intro.cpp
index 3694bc6bb7..54e430eb98 100644
--- a/engines/ultima/ultima4/game/intro.cpp
+++ b/engines/ultima/ultima4/game/intro.cpp
@@ -20,24 +20,26 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/game/intro.h"
+#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/game/menu.h"
+#include "ultima/ultima4/controllers/read_string_controller.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/core/config.h"
+#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/core/error.h"
+#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/gfx/imagemgr.h"
-#include "ultima/ultima4/game/menu.h"
-#include "ultima/ultima4/sound/music.h"
-#include "ultima/ultima4/sound/sound.h"
-#include "ultima/ultima4/game/player.h"
#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/filesys/u4file.h"
+#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/map/shrine.h"
#include "ultima/ultima4/map/tileset.h"
#include "ultima/ultima4/map/tilemap.h"
-#include "ultima/ultima4/filesys/u4file.h"
-#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/sound/music.h"
+#include "ultima/ultima4/sound/sound.h"
+#include "ultima/ultima4/ultima4.h"
#include "common/savefile.h"
#include "common/system.h"
diff --git a/engines/ultima/ultima4/game/intro.h b/engines/ultima/ultima4/game/intro.h
index 5fe7978488..c9eb33f344 100644
--- a/engines/ultima/ultima4/game/intro.h
+++ b/engines/ultima/ultima4/game/intro.h
@@ -23,12 +23,12 @@
#ifndef ULTIMA4_INTRO_H
#define ULTIMA4_INTRO_H
-#include "ultima/ultima4/events/controller.h"
-#include "ultima/ultima4/game/menu.h"
+#include "ultima/ultima4/controllers/controller.h"
#include "ultima/ultima4/core/observer.h"
#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/gfx/imageview.h"
+#include "ultima/ultima4/game/menu.h"
#include "ultima/ultima4/game/textview.h"
+#include "ultima/ultima4/gfx/imageview.h"
#include "ultima/ultima4/map/tileview.h"
namespace Ultima {
diff --git a/engines/ultima/ultima4/game/item.cpp b/engines/ultima/ultima4/game/item.cpp
index 2b1915b97b..15a5d3d7d9 100644
--- a/engines/ultima/ultima4/game/item.cpp
+++ b/engines/ultima/ultima4/game/item.cpp
@@ -21,24 +21,25 @@
*/
#include "ultima/ultima4/game/item.h"
-#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/game/codex.h"
-#include "ultima/ultima4/map/combat.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/map/dungeon.h"
#include "ultima/ultima4/game/game.h"
-#include "ultima/ultima4/map/location.h"
-#include "ultima/ultima4/map/map.h"
-#include "ultima/ultima4/map/mapmgr.h"
#include "ultima/ultima4/game/names.h"
#include "ultima/ultima4/game/player.h"
#include "ultima/ultima4/game/portal.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/weapon.h"
+#include "ultima/ultima4/controllers/alpha_action_controller.h"
+#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/map/annotation.h"
+#include "ultima/ultima4/map/combat.h"
+#include "ultima/ultima4/map/dungeon.h"
+#include "ultima/ultima4/map/location.h"
+#include "ultima/ultima4/map/map.h"
+#include "ultima/ultima4/map/mapmgr.h"
#include "ultima/ultima4/map/tileset.h"
#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/game/weapon.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/game/person.cpp b/engines/ultima/ultima4/game/person.cpp
index 070b9ed556..3236a2c9e3 100644
--- a/engines/ultima/ultima4/game/person.cpp
+++ b/engines/ultima/ultima4/game/person.cpp
@@ -20,25 +20,27 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/game/person.h"
-#include "ultima/ultima4/map/city.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/conversation/conversation.h"
-#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/game/game.h" // Included for ReadPlayerController
-#include "ultima/ultima4/map/location.h"
-#include "ultima/ultima4/sound/music.h"
#include "ultima/ultima4/game/names.h"
#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/script.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_int_controller.h"
+#include "ultima/ultima4/controllers/read_player_controller.h"
+#include "ultima/ultima4/conversation/conversation.h"
+#include "ultima/ultima4/core/config.h"
+#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/core/types.h"
-#include "ultima/ultima4/filesys/u4file.h"
#include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/game/script.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/filesys/u4file.h"
+#include "ultima/ultima4/map/city.h"
+#include "ultima/ultima4/map/location.h"
+#include "ultima/ultima4/sound/music.h"
+#include "ultima/ultima4/ultima4.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/map/combat.cpp b/engines/ultima/ultima4/map/combat.cpp
index 8707f7355c..01302dec95 100644
--- a/engines/ultima/ultima4/map/combat.cpp
+++ b/engines/ultima/ultima4/map/combat.cpp
@@ -20,7 +20,16 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
+#include "ultima/ultima4/map/combat.h"
+#include "ultima/ultima4/map/annotation.h"
+#include "ultima/ultima4/map/dungeon.h"
+#include "ultima/ultima4/map/location.h"
+#include "ultima/ultima4/map/mapmgr.h"
+#include "ultima/ultima4/map/movement.h"
+#include "ultima/ultima4/map/tileset.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_dir_controller.h"
+#include "ultima/ultima4/controllers/ztats_controller.h"
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/core/utils.h"
@@ -38,14 +47,8 @@
#include "ultima/ultima4/game/stats.h"
#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/map/combat.h"
-#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/map/dungeon.h"
-#include "ultima/ultima4/map/location.h"
-#include "ultima/ultima4/map/mapmgr.h"
-#include "ultima/ultima4/map/movement.h"
-#include "ultima/ultima4/map/tileset.h"
#include "ultima/shared/std/containers.h"
+#include "ultima/ultima4/ultima4.h"
#include "common/system.h"
namespace Ultima {
diff --git a/engines/ultima/ultima4/map/combat.h b/engines/ultima/ultima4/map/combat.h
index 700a54cca3..31d9780794 100644
--- a/engines/ultima/ultima4/map/combat.h
+++ b/engines/ultima/ultima4/map/combat.h
@@ -25,14 +25,14 @@
#include "ultima/ultima4/map/direction.h"
#include "ultima/ultima4/map/map.h"
-#include "ultima/ultima4/events/controller.h"
+#include "ultima/ultima4/controllers/controller.h"
+#include "ultima/ultima4/core/observer.h"
+#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/game/creature.h"
#include "ultima/ultima4/game/game.h"
#include "ultima/ultima4/game/object.h"
-#include "ultima/ultima4/core/observer.h"
#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/core/types.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/map/shrine.cpp b/engines/ultima/ultima4/map/shrine.cpp
index 34278c383f..3c9f623913 100644
--- a/engines/ultima/ultima4/map/shrine.cpp
+++ b/engines/ultima/ultima4/map/shrine.cpp
@@ -20,25 +20,28 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/core/config.h"
-#include "ultima/ultima4/map/shrine.h"
#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/game/game.h"
-#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/mapmgr.h"
+#include "ultima/ultima4/map/shrine.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_string_controller.h"
+#include "ultima/ultima4/controllers/wait_controller.h"
+#include "ultima/ultima4/core/config.h"
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/game.h"
#include "ultima/ultima4/game/creature.h"
-#include "ultima/ultima4/sound/music.h"
#include "ultima/ultima4/game/names.h"
#include "ultima/ultima4/game/player.h"
#include "ultima/ultima4/game/portal.h"
+#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/sound/music.h"
+#include "ultima/ultima4/ultima4.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/meta_engine.cpp b/engines/ultima/ultima4/meta_engine.cpp
index 39d58b1ce2..fec9fa983f 100644
--- a/engines/ultima/ultima4/meta_engine.cpp
+++ b/engines/ultima/ultima4/meta_engine.cpp
@@ -108,7 +108,7 @@ static const KeybindingRecord CHEAT_KEYS[] = {
{ KEYBIND_CHEAT_UP, "CHEAT-UP", "Up Level", "up", "A+UP", nullptr },
{ KEYBIND_CHEAT_DOWN, "CHEAT-DOWN", "Down Level", "down", "A+DOWN", nullptr },
{ KEYBIND_CHEAT_VIRTUE, "CHEAT-VIRTUE", "Grant Virtue", "virtue", "A+v", nullptr },
- { KEYBIND_CHEAT_WIND, "CHEAT-WIND", "Change Wind", "wind", "A+w", nullptr },
+ { KEYBIND_CHEAT_WIND, "CHEAT-WIND", "Change Wind", "wind", "A+w", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr, nullptr }
};
Commit: 7aae5d45c9c40d5aa8c9f6e5cc0bc4c58eed09c5
https://github.com/scummvm/scummvm/commit/7aae5d45c9c40d5aa8c9f6e5cc0bc4c58eed09c5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-16T19:30:47-07:00
Commit Message:
ULTIMA4: Moving more controller classes to controllers/
Changed paths:
A engines/ultima/ultima4/controllers/camp_controller.cpp
A engines/ultima/ultima4/controllers/camp_controller.h
A engines/ultima/ultima4/controllers/combat_controller.cpp
A engines/ultima/ultima4/controllers/combat_controller.h
A engines/ultima/ultima4/controllers/inn_controller.cpp
A engines/ultima/ultima4/controllers/inn_controller.h
A engines/ultima/ultima4/controllers/intro_controller.cpp
A engines/ultima/ultima4/controllers/intro_controller.h
A engines/ultima/ultima4/controllers/menu_controller.cpp
A engines/ultima/ultima4/controllers/menu_controller.h
A engines/ultima/ultima4/controllers/reagents_menu_controller.cpp
A engines/ultima/ultima4/controllers/reagents_menu_controller.h
R engines/ultima/ultima4/game/intro.cpp
R engines/ultima/ultima4/game/intro.h
R engines/ultima/ultima4/map/camp.cpp
R engines/ultima/ultima4/map/camp.h
R engines/ultima/ultima4/map/combat.cpp
R engines/ultima/ultima4/map/combat.h
engines/ultima/module.mk
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/core/debugger_actions.cpp
engines/ultima/ultima4/game/creature.cpp
engines/ultima/ultima4/game/game.cpp
engines/ultima/ultima4/game/item.cpp
engines/ultima/ultima4/game/menu.cpp
engines/ultima/ultima4/game/menu.h
engines/ultima/ultima4/game/player.cpp
engines/ultima/ultima4/game/script.cpp
engines/ultima/ultima4/game/spell.cpp
engines/ultima/ultima4/game/stats.cpp
engines/ultima/ultima4/game/stats.h
engines/ultima/ultima4/gfx/screen.cpp
engines/ultima/ultima4/gfx/screen_scummvm.cpp
engines/ultima/ultima4/map/dungeon.h
engines/ultima/ultima4/ultima4.cpp
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index d7c91d2381..113ebdd5ab 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -135,14 +135,20 @@ MODULE_OBJS := \
ultima1/widgets/wench.o \
ultima1/game.o \
ultima4/controllers/alpha_action_controller.o \
+ ultima4/controllers/camp_controller.o \
+ ultima4/controllers/combat_controller.o \
ultima4/controllers/controller.o \
ultima4/controllers/game_controller.o \
+ ultima4/controllers/inn_controller.o \
+ ultima4/controllers/intro_controller.o \
ultima4/controllers/key_handler_controller.o \
+ ultima4/controllers/menu_controller.o \
ultima4/controllers/read_choice_controller.o \
ultima4/controllers/read_dir_controller.o \
ultima4/controllers/read_int_controller.o \
ultima4/controllers/read_player_controller.o \
ultima4/controllers/read_string_controller.o \
+ ultima4/controllers/reagents_menu_controller.o \
ultima4/controllers/wait_controller.o \
ultima4/controllers/ztats_controller.o \
ultima4/conversation/conversation.o \
@@ -173,7 +179,6 @@ MODULE_OBJS := \
ultima4/game/creature.o \
ultima4/game/death.o \
ultima4/game/game.o \
- ultima4/game/intro.o \
ultima4/game/item.o \
ultima4/game/menu.o \
ultima4/game/menuitem.o \
@@ -200,9 +205,7 @@ MODULE_OBJS := \
ultima4/gfx/screen.o \
ultima4/gfx/screen_scummvm.o \
ultima4/map/annotation.o \
- ultima4/map/camp.o \
ultima4/map/city.o \
- ultima4/map/combat.o \
ultima4/map/direction.o \
ultima4/map/dungeon.o \
ultima4/map/dungeonview.o \
diff --git a/engines/ultima/ultima4/controllers/camp_controller.cpp b/engines/ultima/ultima4/controllers/camp_controller.cpp
new file mode 100644
index 0000000000..4630c4f166
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/camp_controller.cpp
@@ -0,0 +1,124 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/camp_controller.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/map/mapmgr.h"
+#include "ultima/ultima4/ultima4.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+CampController::CampController() {
+ MapId id;
+
+ /* setup camp (possible, but not for-sure combat situation */
+ if (g_context->_location->_context & CTX_DUNGEON)
+ id = MAP_CAMP_DNG;
+ else
+ id = MAP_CAMP_CON;
+
+ _map = getCombatMap(mapMgr->get(id));
+ g_game->setMap(_map, true, NULL, this);
+}
+
+void CampController::init(Creature *m) {
+ CombatController::init(m);
+ _camping = true;
+}
+
+void CampController::begin() {
+ // make sure everyone's asleep
+ for (int i = 0; i < g_context->_party->size(); i++)
+ g_context->_party->member(i)->putToSleep();
+
+ CombatController::begin();
+
+ g_music->camp();
+
+ screenMessage("Resting...\n");
+ screenDisableCursor();
+
+ EventHandler::wait_msecs(settings._campTime * 1000);
+
+ screenEnableCursor();
+
+ /* Is the party ambushed during their rest? */
+ if (settings._campingAlwaysCombat || (xu4_random(8) == 0)) {
+ const Creature *m = creatureMgr->randomAmbushing();
+
+ g_music->play();
+ screenMessage("Ambushed!\n");
+
+ /* create an ambushing creature (so it leaves a chest) */
+ setCreature(g_context->_location->_prev->_map->addCreature(m, g_context->_location->_prev->_coords));
+
+ /* fill the creature table with creatures and place them */
+ fillCreatureTable(m);
+ placeCreatures();
+
+ /* creatures go first! */
+ finishTurn();
+ } else {
+ /* Wake everyone up! */
+ for (int i = 0; i < g_context->_party->size(); i++)
+ g_context->_party->member(i)->wakeUp();
+
+ /* Make sure we've waited long enough for camping to be effective */
+ bool healed = false;
+ if (((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) >= 0x10000) ||
+ (((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff) != g_ultima->_saveGame->_lastCamp))
+ healed = heal();
+
+ screenMessage(healed ? "Party Healed!\n" : "No effect.\n");
+ g_ultima->_saveGame->_lastCamp = (g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff;
+
+ eventHandler->popController();
+ g_game->exitToParentMap();
+ g_music->fadeIn(CAMP_FADE_IN_TIME, true);
+ delete this;
+ }
+}
+
+void CampController::end(bool adjustKarma) {
+ // wake everyone up!
+ for (int i = 0; i < g_context->_party->size(); i++)
+ g_context->_party->member(i)->wakeUp();
+ CombatController::end(adjustKarma);
+}
+
+bool CampController::heal() {
+ // restore each party member to max mp, and restore some hp
+ bool healed = false;
+ for (int i = 0; i < g_context->_party->size(); i++) {
+ PartyMember *m = g_context->_party->member(i);
+ m->setMp(m->getMaxMp());
+ if ((m->getHp() < m->getMaxHp()) && m->heal(HT_CAMPHEAL))
+ healed = true;
+ }
+
+ return healed;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/map/camp.h b/engines/ultima/ultima4/controllers/camp_controller.h
similarity index 82%
rename from engines/ultima/ultima4/map/camp.h
rename to engines/ultima/ultima4/controllers/camp_controller.h
index a7e2f59a79..c4a973cde2 100644
--- a/engines/ultima/ultima4/map/camp.h
+++ b/engines/ultima/ultima4/controllers/camp_controller.h
@@ -20,10 +20,10 @@
*
*/
-#ifndef ULTIMA4_CAMP_H
-#define ULTIMA4_CAMP_H
+#ifndef ULTIMA4_CONTROLLERS_CAMP_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_CAMP_CONTROLLER_H
-#include "ultima/ultima4/map/combat.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
namespace Ultima {
namespace Ultima4 {
@@ -41,19 +41,6 @@ private:
bool heal();
};
-class InnController : public CombatController {
-public:
- InnController();
-
- void begin() override;
- void awardLoot() override;
-
-private:
- bool heal();
- void maybeMeetIsaac();
- void maybeAmbush();
-};
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/map/combat.cpp b/engines/ultima/ultima4/controllers/combat_controller.cpp
similarity index 99%
rename from engines/ultima/ultima4/map/combat.cpp
rename to engines/ultima/ultima4/controllers/combat_controller.cpp
index 01302dec95..c39e6b1168 100644
--- a/engines/ultima/ultima4/map/combat.cpp
+++ b/engines/ultima/ultima4/controllers/combat_controller.cpp
@@ -20,16 +20,16 @@
*
*/
-#include "ultima/ultima4/map/combat.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
+#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/controllers/read_dir_controller.h"
+#include "ultima/ultima4/controllers/ztats_controller.h"
#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/map/dungeon.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/mapmgr.h"
#include "ultima/ultima4/map/movement.h"
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/controllers/read_choice_controller.h"
-#include "ultima/ultima4/controllers/read_dir_controller.h"
-#include "ultima/ultima4/controllers/ztats_controller.h"
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/core/utils.h"
diff --git a/engines/ultima/ultima4/map/combat.h b/engines/ultima/ultima4/controllers/combat_controller.h
similarity index 100%
rename from engines/ultima/ultima4/map/combat.h
rename to engines/ultima/ultima4/controllers/combat_controller.h
diff --git a/engines/ultima/ultima4/map/camp.cpp b/engines/ultima/ultima4/controllers/inn_controller.cpp
similarity index 60%
rename from engines/ultima/ultima4/map/camp.cpp
rename to engines/ultima/ultima4/controllers/inn_controller.cpp
index 3f937ed8e3..75b511c836 100644
--- a/engines/ultima/ultima4/map/camp.cpp
+++ b/engines/ultima/ultima4/controllers/inn_controller.cpp
@@ -20,129 +20,17 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/map/camp.h"
-#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/map/city.h"
-#include "ultima/ultima4/map/combat.h"
-#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/controllers/inn_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
-#include "ultima/ultima4/events/event.h"
-#include "ultima/ultima4/game/game.h"
-#include "ultima/ultima4/map/location.h"
-#include "ultima/ultima4/map/map.h"
-#include "ultima/ultima4/map/mapmgr.h"
-#include "ultima/ultima4/game/creature.h"
-#include "ultima/ultima4/sound/music.h"
-#include "ultima/ultima4/game/names.h"
-#include "ultima/ultima4/game/object.h"
-#include "ultima/ultima4/game/person.h"
-#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
-#include "ultima/ultima4/game/stats.h"
-#include "ultima/ultima4/map/tileset.h"
#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/map/city.h"
+#include "ultima/ultima4/map/mapmgr.h"
namespace Ultima {
namespace Ultima4 {
-void campTimer(void *data);
-void campEnd(void);
-int campHeal(HealType heal_type);
void innTimer(void *data);
-CampController::CampController() {
- MapId id;
-
- /* setup camp (possible, but not for-sure combat situation */
- if (g_context->_location->_context & CTX_DUNGEON)
- id = MAP_CAMP_DNG;
- else
- id = MAP_CAMP_CON;
-
- _map = getCombatMap(mapMgr->get(id));
- g_game->setMap(_map, true, NULL, this);
-}
-
-void CampController::init(Creature *m) {
- CombatController::init(m);
- _camping = true;
-}
-
-void CampController::begin() {
- // make sure everyone's asleep
- for (int i = 0; i < g_context->_party->size(); i++)
- g_context->_party->member(i)->putToSleep();
-
- CombatController::begin();
-
- g_music->camp();
-
- screenMessage("Resting...\n");
- screenDisableCursor();
-
- EventHandler::wait_msecs(settings._campTime * 1000);
-
- screenEnableCursor();
-
- /* Is the party ambushed during their rest? */
- if (settings._campingAlwaysCombat || (xu4_random(8) == 0)) {
- const Creature *m = creatureMgr->randomAmbushing();
-
- g_music->play();
- screenMessage("Ambushed!\n");
-
- /* create an ambushing creature (so it leaves a chest) */
- setCreature(g_context->_location->_prev->_map->addCreature(m, g_context->_location->_prev->_coords));
-
- /* fill the creature table with creatures and place them */
- fillCreatureTable(m);
- placeCreatures();
-
- /* creatures go first! */
- finishTurn();
- } else {
- /* Wake everyone up! */
- for (int i = 0; i < g_context->_party->size(); i++)
- g_context->_party->member(i)->wakeUp();
-
- /* Make sure we've waited long enough for camping to be effective */
- bool healed = false;
- if (((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) >= 0x10000) ||
- (((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff) != g_ultima->_saveGame->_lastCamp))
- healed = heal();
-
- screenMessage(healed ? "Party Healed!\n" : "No effect.\n");
- g_ultima->_saveGame->_lastCamp = (g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff;
-
- eventHandler->popController();
- g_game->exitToParentMap();
- g_music->fadeIn(CAMP_FADE_IN_TIME, true);
- delete this;
- }
-}
-
-void CampController::end(bool adjustKarma) {
- // wake everyone up!
- for (int i = 0; i < g_context->_party->size(); i++)
- g_context->_party->member(i)->wakeUp();
- CombatController::end(adjustKarma);
-}
-
-bool CampController::heal() {
- // restore each party member to max mp, and restore some hp
- bool healed = false;
- for (int i = 0; i < g_context->_party->size(); i++) {
- PartyMember *m = g_context->_party->member(i);
- m->setMp(m->getMaxMp());
- if ((m->getHp() < m->getMaxHp()) && m->heal(HT_CAMPHEAL))
- healed = true;
- }
-
- return healed;
-}
-
InnController::InnController() {
_map = NULL;
/*
diff --git a/engines/ultima/ultima4/controllers/inn_controller.h b/engines/ultima/ultima4/controllers/inn_controller.h
new file mode 100644
index 0000000000..14ce371b0f
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/inn_controller.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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_INN_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_INN_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/combat_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+class InnController : public CombatController {
+public:
+ InnController();
+
+ void begin() override;
+ void awardLoot() override;
+
+private:
+ bool heal();
+ void maybeMeetIsaac();
+ void maybeAmbush();
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/game/intro.cpp b/engines/ultima/ultima4/controllers/intro_controller.cpp
similarity index 99%
rename from engines/ultima/ultima4/game/intro.cpp
rename to engines/ultima/ultima4/controllers/intro_controller.cpp
index 54e430eb98..f01aa7dfec 100644
--- a/engines/ultima/ultima4/game/intro.cpp
+++ b/engines/ultima/ultima4/controllers/intro_controller.cpp
@@ -20,11 +20,12 @@
*
*/
-#include "ultima/ultima4/game/intro.h"
-#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/game/menu.h"
+#include "ultima/ultima4/controllers/intro_controller.h"
+#include "ultima/ultima4/controllers/menu_controller.h"
#include "ultima/ultima4/controllers/read_string_controller.h"
#include "ultima/ultima4/controllers/read_choice_controller.h"
+#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/game/menu.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/core/error.h"
diff --git a/engines/ultima/ultima4/game/intro.h b/engines/ultima/ultima4/controllers/intro_controller.h
similarity index 100%
rename from engines/ultima/ultima4/game/intro.h
rename to engines/ultima/ultima4/controllers/intro_controller.h
diff --git a/engines/ultima/ultima4/controllers/menu_controller.cpp b/engines/ultima/ultima4/controllers/menu_controller.cpp
new file mode 100644
index 0000000000..54b720cec3
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/menu_controller.cpp
@@ -0,0 +1,79 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/menu_controller.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/game/menu.h"
+#include "ultima/ultima4/game/textview.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+MenuController::MenuController(Menu *menu, TextView *view) {
+ this->_menu = menu;
+ this->_view = view;
+}
+
+bool MenuController::keyPressed(int key) {
+ bool handled = true;
+ bool cursorOn = _view->getCursorEnabled();
+
+ if (cursorOn)
+ _view->disableCursor();
+
+ switch (key) {
+ case U4_UP:
+ _menu->prev();
+ break;
+ case U4_DOWN:
+ _menu->next();
+ break;
+ case U4_LEFT:
+ case U4_RIGHT:
+ case U4_ENTER: {
+ MenuEvent::Type action = MenuEvent::ACTIVATE;
+
+ if (key == U4_LEFT)
+ action = MenuEvent::DECREMENT;
+ else if (key == U4_RIGHT)
+ action = MenuEvent::INCREMENT;
+ _menu->activateItem(-1, action);
+ }
+ break;
+ default:
+ handled = _menu->activateItemByShortcut(key, MenuEvent::ACTIVATE);
+ }
+
+ _menu->show(_view);
+
+ if (cursorOn)
+ _view->enableCursor();
+ _view->update();
+
+ if (_menu->getClosed())
+ doneWaiting();
+
+ return handled;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/menu_controller.h b/engines/ultima/ultima4/controllers/menu_controller.h
new file mode 100644
index 0000000000..acfb74dd15
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/menu_controller.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_MENU_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_MENU_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+class Menu;
+class TextView;
+
+/**
+ * This class controls a menu. The value field of WaitableController
+ * isn't used.
+ */
+class MenuController : public WaitableController<void *> {
+public:
+ MenuController(Menu *menu, TextView *view);
+ bool keyPressed(int key);
+
+protected:
+ Menu *_menu;
+ TextView *_view;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/controllers/reagents_menu_controller.cpp b/engines/ultima/ultima4/controllers/reagents_menu_controller.cpp
new file mode 100644
index 0000000000..613f07c4c2
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/reagents_menu_controller.cpp
@@ -0,0 +1,80 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima4/controllers/reagents_menu_controller.h"
+#include "ultima/ultima4/game/menu.h"
+#include "ultima/ultima4/game/spell.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+bool ReagentsMenuController::keyPressed(int key) {
+ switch (key) {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h': {
+ /* select the corresponding reagent (if visible) */
+ Menu::MenuItemList::iterator mi = _menu->getById(key - 'a');
+ if ((*mi)->isVisible()) {
+ _menu->setCurrent(_menu->getById(key - 'a'));
+ keyPressed(U4_SPACE);
+ }
+ }
+ break;
+ case U4_LEFT:
+ case U4_RIGHT:
+ case U4_SPACE:
+ if (_menu->isVisible()) {
+ MenuItem *item = *_menu->getCurrent();
+
+ /* change whether or not it's selected */
+ item->setSelected(!item->isSelected());
+
+ if (item->isSelected())
+ _ingredients->addReagent((Reagent)item->getId());
+ else
+ _ingredients->removeReagent((Reagent)item->getId());
+ }
+ break;
+ case U4_ENTER:
+ eventHandler->setControllerDone();
+ break;
+
+ case U4_ESC:
+ _ingredients->revert();
+ eventHandler->setControllerDone();
+ break;
+
+ default:
+ return MenuController::keyPressed(key);
+ }
+
+ return true;
+}
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/controllers/reagents_menu_controller.h b/engines/ultima/ultima4/controllers/reagents_menu_controller.h
new file mode 100644
index 0000000000..af5d40127b
--- /dev/null
+++ b/engines/ultima/ultima4/controllers/reagents_menu_controller.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA4_CONTROLLERS_REAGENTS_MENU_CONTROLLER_H
+#define ULTIMA4_CONTROLLERS_REAGENTS_MENU_CONTROLLER_H
+
+#include "ultima/ultima4/controllers/menu_controller.h"
+
+namespace Ultima {
+namespace Ultima4 {
+
+class Ingredients;
+
+/**
+ * Controller for the reagents menu used when mixing spells. Fills
+ * the passed in Ingredients with the selected reagents.
+ */
+class ReagentsMenuController : public MenuController {
+public:
+ ReagentsMenuController(Menu *menu, Ingredients *i, TextView *view) : MenuController(menu, view), _ingredients(i) { }
+
+ /**
+ * Handles spell mixing for the Ultima V-style menu-system
+ */
+ bool keyPressed(int key) override;
+
+private:
+ Ingredients *_ingredients;
+};
+
+} // End of namespace Ultima4
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 5e26fc5dc7..8982fbae21 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -23,6 +23,7 @@
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/controllers/alpha_action_controller.h"
+#include "ultima/ultima4/controllers/camp_controller.h"
#include "ultima/ultima4/controllers/read_choice_controller.h"
#include "ultima/ultima4/controllers/read_dir_controller.h"
#include "ultima/ultima4/controllers/ztats_controller.h"
@@ -37,7 +38,6 @@
#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/map/camp.h"
#include "ultima/ultima4/map/city.h"
#include "ultima/ultima4/map/dungeonview.h"
#include "ultima/ultima4/map/mapmgr.h"
diff --git a/engines/ultima/ultima4/core/debugger_actions.cpp b/engines/ultima/ultima4/core/debugger_actions.cpp
index 7144b136ba..c8ec780f08 100644
--- a/engines/ultima/ultima4/core/debugger_actions.cpp
+++ b/engines/ultima/ultima4/core/debugger_actions.cpp
@@ -23,8 +23,10 @@
#include "ultima/ultima4/core/debugger_actions.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
#include "ultima/ultima4/controllers/read_choice_controller.h"
#include "ultima/ultima4/controllers/read_int_controller.h"
+#include "ultima/ultima4/controllers/reagents_menu_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/player.h"
@@ -33,7 +35,6 @@
#include "ultima/ultima4/gfx/textcolor.h"
#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/map/city.h"
-#include "ultima/ultima4/map/combat.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/game/creature.cpp b/engines/ultima/ultima4/game/creature.cpp
index 631189b9ae..489142653f 100644
--- a/engines/ultima/ultima4/game/creature.cpp
+++ b/engines/ultima/ultima4/game/creature.cpp
@@ -21,20 +21,20 @@
*/
#include "ultima/ultima4/game/creature.h"
-#include "ultima/ultima4/map/combat.h"
-#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/game/game.h"
+#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
+#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/error.h"
-#include "ultima/ultima4/game/game.h" /* required by specialAction and specialEffect functions */
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/gfx/textcolor.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/map.h"
-#include "ultima/ultima4/game/player.h" /* required by specialAction and specialEffect functions */
-#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/gfx/screen.h" /* FIXME: remove dependence on this */
-#include "ultima/ultima4/core/settings.h"
-#include "ultima/ultima4/gfx/textcolor.h" /* required to change the color of screen message text */
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/core/utils.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/game/game.cpp b/engines/ultima/ultima4/game/game.cpp
index c779640cd8..00839ee2f8 100644
--- a/engines/ultima/ultima4/game/game.cpp
+++ b/engines/ultima/ultima4/game/game.cpp
@@ -21,6 +21,9 @@
*/
#include "ultima/ultima4/ultima4.h"
+#include "ultima/ultima4/controllers/camp_controller.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
+#include "ultima/ultima4/controllers/intro_controller.h"
#include "ultima/ultima4/controllers/read_choice_controller.h"
#include "ultima/ultima4/controllers/read_dir_controller.h"
#include "ultima/ultima4/controllers/read_int_controller.h"
@@ -38,7 +41,6 @@
#include "ultima/ultima4/game/armor.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/death.h"
-#include "ultima/ultima4/game/intro.h"
#include "ultima/ultima4/game/item.h"
#include "ultima/ultima4/game/menu.h"
#include "ultima/ultima4/game/creature.h"
@@ -53,11 +55,9 @@
#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/map/camp.h"
#include "ultima/ultima4/map/city.h"
#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/map/dungeon.h"
-#include "ultima/ultima4/map/combat.h"
#include "ultima/ultima4/map/direction.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/mapmgr.h"
diff --git a/engines/ultima/ultima4/game/item.cpp b/engines/ultima/ultima4/game/item.cpp
index 15a5d3d7d9..91abf712a5 100644
--- a/engines/ultima/ultima4/game/item.cpp
+++ b/engines/ultima/ultima4/game/item.cpp
@@ -29,11 +29,11 @@
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/controllers/alpha_action_controller.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/map/combat.h"
#include "ultima/ultima4/map/dungeon.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/map.h"
diff --git a/engines/ultima/ultima4/game/menu.cpp b/engines/ultima/ultima4/game/menu.cpp
index 52524b4936..597647ec02 100644
--- a/engines/ultima/ultima4/game/menu.cpp
+++ b/engines/ultima/ultima4/game/menu.cpp
@@ -275,52 +275,5 @@ void Menu::setTitle(const Common::String &text, int x, int y) {
_titleY = y;
}
-MenuController::MenuController(Menu *menu, TextView *view) {
- this->_menu = menu;
- this->_view = view;
-}
-
-bool MenuController::keyPressed(int key) {
- bool handled = true;
- bool cursorOn = _view->getCursorEnabled();
-
- if (cursorOn)
- _view->disableCursor();
-
- switch (key) {
- case U4_UP:
- _menu->prev();
- break;
- case U4_DOWN:
- _menu->next();
- break;
- case U4_LEFT:
- case U4_RIGHT:
- case U4_ENTER: {
- MenuEvent::Type action = MenuEvent::ACTIVATE;
-
- if (key == U4_LEFT)
- action = MenuEvent::DECREMENT;
- else if (key == U4_RIGHT)
- action = MenuEvent::INCREMENT;
- _menu->activateItem(-1, action);
- }
- break;
- default:
- handled = _menu->activateItemByShortcut(key, MenuEvent::ACTIVATE);
- }
-
- _menu->show(_view);
-
- if (cursorOn)
- _view->enableCursor();
- _view->update();
-
- if (_menu->getClosed())
- doneWaiting();
-
- return handled;
-}
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/game/menu.h b/engines/ultima/ultima4/game/menu.h
index 57ab9f1ed5..be7df79d0a 100644
--- a/engines/ultima/ultima4/game/menu.h
+++ b/engines/ultima/ultima4/game/menu.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef ULTIMA4_MENU_H
-#define ULTIMA4_MENU_H
+#ifndef ULTIMA4_GAME_MENU_H
+#define ULTIMA4_GAME_MENU_H
#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/game/menuitem.h"
@@ -192,20 +192,6 @@ private:
int _titleX, _titleY;
};
-/**
- * This class controls a menu. The value field of WaitableController
- * isn't used.
- */
-class MenuController : public WaitableController<void *> {
-public:
- MenuController(Menu *menu, TextView *view);
- bool keyPressed(int key);
-
-protected:
- Menu *_menu;
- TextView *_view;
-};
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/game/player.cpp b/engines/ultima/ultima4/game/player.cpp
index 34d82ca352..d1a17c69ba 100644
--- a/engines/ultima/ultima4/game/player.cpp
+++ b/engines/ultima/ultima4/game/player.cpp
@@ -21,19 +21,19 @@
*/
#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/game/armor.h"
-#include "ultima/ultima4/map/combat.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/game.h"
+#include "ultima/ultima4/game/names.h"
+#include "ultima/ultima4/game/weapon.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
+#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/map/annotation.h"
#include "ultima/ultima4/map/location.h"
#include "ultima/ultima4/map/mapmgr.h"
-#include "ultima/ultima4/game/names.h"
#include "ultima/ultima4/map/tilemap.h"
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/core/types.h"
-#include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/game/weapon.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/game/script.cpp b/engines/ultima/ultima4/game/script.cpp
index 765bcdb055..f427655881 100644
--- a/engines/ultima/ultima4/game/script.cpp
+++ b/engines/ultima/ultima4/game/script.cpp
@@ -22,24 +22,24 @@
#include "ultima/ultima4/game/script.h"
#include "ultima/ultima4/game/armor.h"
-#include "ultima/ultima4/map/camp.h"
#include "ultima/ultima4/game/context.h"
+#include "ultima/ultima4/controllers/inn_controller.h"
#include "ultima/ultima4/conversation/conversation.h"
#include "ultima/ultima4/core/error.h"
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/filesys/filesystem.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/filesys/u4file.h"
#include "ultima/ultima4/game/game.h"
-#include "ultima/ultima4/sound/music.h"
#include "ultima/ultima4/game/player.h"
-#include "ultima/ultima4/filesys/savegame.h"
-#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/game/weapon.h"
#include "ultima/ultima4/game/spell.h"
#include "ultima/ultima4/game/stats.h"
+#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/filesys/u4file.h"
-#include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/game/weapon.h"
+#include "ultima/ultima4/sound/music.h"
#include "ultima/shared/conf/xml_tree.h"
namespace Ultima {
diff --git a/engines/ultima/ultima4/game/spell.cpp b/engines/ultima/ultima4/game/spell.cpp
index 968cd4c10d..226a71f1b7 100644
--- a/engines/ultima/ultima4/game/spell.cpp
+++ b/engines/ultima/ultima4/game/spell.cpp
@@ -20,20 +20,19 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/core/settings.h"
-#include "ultima/ultima4/core/debugger.h"
-#include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/game/game.h"
#include "ultima/ultima4/game/spell.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/creature.h"
#include "ultima/ultima4/game/moongate.h"
#include "ultima/ultima4/game/player.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/debugger.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/map/annotation.h"
-#include "ultima/ultima4/map/combat.h"
#include "ultima/ultima4/map/direction.h"
#include "ultima/ultima4/map/dungeon.h"
#include "ultima/ultima4/map/location.h"
@@ -41,6 +40,7 @@
#include "ultima/ultima4/map/mapmgr.h"
#include "ultima/ultima4/map/tile.h"
#include "ultima/ultima4/map/tileset.h"
+#include "ultima/ultima4/ultima4.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/game/stats.cpp b/engines/ultima/ultima4/game/stats.cpp
index 259d6f10d0..a107d1e6d3 100644
--- a/engines/ultima/ultima4/game/stats.cpp
+++ b/engines/ultima/ultima4/game/stats.cpp
@@ -409,54 +409,5 @@ void StatsArea::resetReagentsMenu() {
_reagentsMixMenu.reset(false);
}
-bool ReagentsMenuController::keyPressed(int key) {
- switch (key) {
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h': {
- /* select the corresponding reagent (if visible) */
- Menu::MenuItemList::iterator mi = _menu->getById(key - 'a');
- if ((*mi)->isVisible()) {
- _menu->setCurrent(_menu->getById(key - 'a'));
- keyPressed(U4_SPACE);
- }
- }
- break;
- case U4_LEFT:
- case U4_RIGHT:
- case U4_SPACE:
- if (_menu->isVisible()) {
- MenuItem *item = *_menu->getCurrent();
-
- /* change whether or not it's selected */
- item->setSelected(!item->isSelected());
-
- if (item->isSelected())
- _ingredients->addReagent((Reagent)item->getId());
- else
- _ingredients->removeReagent((Reagent)item->getId());
- }
- break;
- case U4_ENTER:
- eventHandler->setControllerDone();
- break;
-
- case U4_ESC:
- _ingredients->revert();
- eventHandler->setControllerDone();
- break;
-
- default:
- return MenuController::keyPressed(key);
- }
-
- return true;
-}
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/game/stats.h b/engines/ultima/ultima4/game/stats.h
index aa04c1951c..8dbabe3a4d 100644
--- a/engines/ultima/ultima4/game/stats.h
+++ b/engines/ultima/ultima4/game/stats.h
@@ -164,23 +164,6 @@ private:
Menu _reagentsMixMenu;
};
-/**
- * Controller for the reagents menu used when mixing spells. Fills
- * the passed in Ingredients with the selected reagents.
- */
-class ReagentsMenuController : public MenuController {
-public:
- ReagentsMenuController(Menu *menu, Ingredients *i, TextView *view) : MenuController(menu, view), _ingredients(i) { }
-
- /**
- * Handles spell mixing for the Ultima V-style menu-system
- */
- bool keyPressed(int key) override;
-
-private:
- Ingredients *_ingredients;
-};
-
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/gfx/screen.cpp b/engines/ultima/ultima4/gfx/screen.cpp
index 0d3282b9ed..47ce06dc65 100644
--- a/engines/ultima/ultima4/gfx/screen.cpp
+++ b/engines/ultima/ultima4/gfx/screen.cpp
@@ -20,8 +20,7 @@
*
*/
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/gfx/screen.h"
+#include "ultima/ultima4/controllers/intro_controller.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/error.h"
#include "ultima/ultima4/core/utils.h"
@@ -29,11 +28,11 @@
#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/game/intro.h"
#include "ultima/ultima4/game/names.h"
#include "ultima/ultima4/game/object.h"
#include "ultima/ultima4/game/player.h"
#include "ultima/ultima4/gfx/imagemgr.h"
+#include "ultima/ultima4/gfx/screen.h"
#include "ultima/ultima4/gfx/textcolor.h"
#include "ultima/ultima4/map/dungeonview.h"
#include "ultima/ultima4/map/location.h"
@@ -41,6 +40,7 @@
#include "ultima/ultima4/map/tileset.h"
#include "ultima/ultima4/map/tileview.h"
#include "ultima/ultima4/map/annotation.h"
+#include "ultima/ultima4/ultima4.h"
#include "common/system.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
diff --git a/engines/ultima/ultima4/gfx/screen_scummvm.cpp b/engines/ultima/ultima4/gfx/screen_scummvm.cpp
index d88637f00b..b96bb804b6 100644
--- a/engines/ultima/ultima4/gfx/screen_scummvm.cpp
+++ b/engines/ultima/ultima4/gfx/screen_scummvm.cpp
@@ -20,24 +20,24 @@
*
*/
+#include "ultima/ultima4/controllers/intro_controller.h"
#include "ultima/ultima4/core/config.h"
-#include "ultima/ultima4/game/context.h"
-#include "ultima/ultima4/map/dungeonview.h"
#include "ultima/ultima4/core/error.h"
-#include "ultima/ultima4/game/intro.h"
-#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/events/event.h"
+#include "ultima/ultima4/filesys/savegame.h"
+#include "ultima/ultima4/filesys/u4file.h"
+#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/gfx/scale.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/gfx/image.h"
#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/map/tileanim.h"
#include "ultima/ultima4/map/tileset.h"
-#include "ultima/ultima4/ultima4.h"
-#include "ultima/ultima4/filesys/u4file.h"
-#include "ultima/ultima4/core/utils.h"
+#include "ultima/ultima4/map/dungeonview.h"
#include "ultima/shared/core/file.h"
+#include "ultima/ultima4/ultima4.h"
#include "common/system.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
diff --git a/engines/ultima/ultima4/map/dungeon.h b/engines/ultima/ultima4/map/dungeon.h
index 9c3625c633..4597008b1f 100644
--- a/engines/ultima/ultima4/map/dungeon.h
+++ b/engines/ultima/ultima4/map/dungeon.h
@@ -23,9 +23,9 @@
#ifndef ULTIMA4_DUNGEON_H
#define ULTIMA4_DUNGEON_H
-#include "ultima/ultima4/map/combat.h"
-#include "ultima/ultima4/map/map.h"
+#include "ultima/ultima4/controllers/combat_controller.h"
#include "ultima/ultima4/core/types.h"
+#include "ultima/ultima4/map/map.h"
namespace Ultima {
namespace Ultima4 {
diff --git a/engines/ultima/ultima4/ultima4.cpp b/engines/ultima/ultima4/ultima4.cpp
index 1168dcb5f2..cbc3385cc4 100644
--- a/engines/ultima/ultima4/ultima4.cpp
+++ b/engines/ultima/ultima4/ultima4.cpp
@@ -21,24 +21,24 @@
*/
#include "ultima/ultima4/ultima4.h"
+#include "ultima/ultima4/controllers/intro_controller.h"
#include "ultima/ultima4/conversation/dialogueloader.h"
#include "ultima/ultima4/core/config.h"
#include "ultima/ultima4/core/debugger.h"
#include "ultima/ultima4/core/error.h"
+#include "ultima/ultima4/core/settings.h"
+#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/events/event.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/game.h"
-#include "ultima/ultima4/game/intro.h"
-#include "ultima/ultima4/sound/music.h"
#include "ultima/ultima4/game/person.h"
#include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/core/settings.h"
-#include "ultima/ultima4/sound/sound.h"
-#include "ultima/ultima4/core/utils.h"
#include "ultima/ultima4/gfx/imageloader.h"
#include "ultima/ultima4/gfx/imagemgr.h"
#include "ultima/ultima4/map/tileset.h"
+#include "ultima/ultima4/sound/music.h"
+#include "ultima/ultima4/sound/sound.h"
#include "common/debug.h"
#include "common/system.h"
More information about the Scummvm-git-logs
mailing list