[Scummvm-git-logs] scummvm master -> d48275970aa78866349f20f44bacdc0aff83e57b
dreammaster
dreammaster at scummvm.org
Mon Mar 5 04:44:20 CET 2018
This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
50630efde6 XEEN: Fix loading saves from main menus and launcher
f2b574d647 XEEN: Move all the dialog classes to their own sub-folder
67d4de1bb8 XEEN: Move Credits and Please Wait classes into their own files
b6b9714ec0 XEEN: Fix scroll effect for Clouds of Xeen main menu
badbeda5e2 XEEN: Implemented Dark Side of Xeen menu
66bd71f6f3 XEEN: Finish World of Xeen main menu
59fc48501c XEEN: Fix game credits text in create_xeen
546059408f XEEN: Added Other Options dialog for Dark Side and World
d48275970a XEEN: Regenerate xeen.ccs and remove accidentally committed dark.cc
Commit: 50630efde6d0f42f4d5f371d6818afac64ba86f5
https://github.com/scummvm/scummvm/commit/50630efde6d0f42f4d5f371d6818afac64ba86f5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:42-05:00
Commit Message:
XEEN: Fix loading saves from main menus and launcher
Changed paths:
devtools/create_xeen/constants.cpp
engines/xeen/dialogs.cpp
engines/xeen/dialogs.h
engines/xeen/resources.cpp
engines/xeen/resources.h
engines/xeen/scripts.cpp
engines/xeen/worldofxeen/worldofxeen.cpp
engines/xeen/worldofxeen/worldofxeen_menu.cpp
engines/xeen/worldofxeen/worldofxeen_menu.h
engines/xeen/xeen.cpp
engines/xeen/xeen.h
diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp
index cf59918..2df74e2 100644
--- a/devtools/create_xeen/constants.cpp
+++ b/devtools/create_xeen/constants.cpp
@@ -60,7 +60,42 @@ enum MagicSpell {
NO_SPELL = 76
};
-const char *const CREDITS =
+const char *const CLOUDS_CREDITS =
+ "\v012\t000\x3""c\f35Designed and Directed By:\n"
+ "\f17Jon Van Caneghem\x3""l\n"
+ "\n"
+ "\t025\f35Programming:\n"
+ "\t035\f17Mark Caldwell\n"
+ "\t035Dave Hathaway\n"
+ "\n"
+ "\t025\f35Sound System & FX:\n"
+ "\t035\f17Todd Hendrix\n"
+ "\n"
+ "\t025\f35Music & Speech:\n"
+ "\t035\f17Tim Tully\n"
+ "\n"
+ "\t025\f35Writing:\n"
+ "\t035\f17Paul Rattner\n"
+ "\t035Debbie Murphy\n"
+ "\t035Jon Van Caneghem\v012\n"
+ "\n"
+ "\n"
+ "\t180\f35Graphics:\n"
+ "\t190\f17Louis Johnson\n"
+ "\t190Jonathan P. Gwyn\n"
+ "\t190Bonita Long-Hemsath\n"
+ "\t190Julia Ulano\n"
+ "\t190Ricardo Barrera\n"
+ "\n"
+ "\t180\f35Testing:\n"
+ "\t190\f17Benjamin Bent\n"
+ "\t190Mario Escamilla\n"
+ "\t190Richard Espy\n"
+ "\t190Scott McDaniel\n"
+ "\t190Clayton Retzer\n"
+ "\t190Michael Suarez\x3""c";
+
+const char *const DARK_SIDE_CREDITS =
"\013""012\010""000\003""c\014""35Designed and Directed By:\n"
"\014""17Jon Van Caneghem\003""l\n"
"\n"
@@ -94,10 +129,47 @@ const char *const CREDITS =
"\t190Robert J. Lupo\n"
"\t190Clayton Retzer\n"
"\t190David Vela\003""c";
-
-const char *const OPTIONS_TITLE =
- "\x0D\x01\003""c\014""dMight and Magic Options\n"
- "World of Xeen\x02\n"
+const char *const SWORDS_CREDITS1 =
+ "\v012\x3""c35Published By New World Computing, Inc.\f17\n"
+ "Developed By CATware, Inc.\x3l\n"
+ "\f01Design and Direction\t180Series Created by\n"
+ "\t020Bill Fawcett\t190John Van Caneghem\n"
+ "\n"
+ "\t010Story Contributions\t180Producer & Manual\n"
+ "\t020Ellen Guon\t190Dean Rettig\n"
+ "\n"
+ "\t010Programming & Ideas\t180Original Programming\n"
+ "\t020David Potter\t190Mark Caldwell\n"
+ "\t020Rod Retterath\t190Dave Hathaway\n"
+ "\n"
+ "\t010Manual Illustrations\t180Graphic Artists\n"
+ "\t020Todd Cameron Hamilton\t190Jonathan P. Gwyn\n"
+ "\t020James Clouse\t190Bonnie Long-Hemsath\n"
+ "\t190Julia Ulano\n"
+ "\t190Ricardo Barrera\n";
+const char *const SWORDS_CREDITS2 =
+ "\f05v012\t000\x3l\n"
+ "\t100Sound Programming\n"
+ "\t110Todd Hendrix\n"
+ "\n"
+ "\t100Music\n"
+ "\t110Tim Tully\n"
+ "\t110Quality Assurance Manager\n"
+ "\t110Peter Ryu\n"
+ "\t100Testers\n"
+ "\t110Walter Johnson\n"
+ "\t110Bryan Farina\n"
+ "\t110David Baton\n"
+ "\t110Jack Nalls\n";
+
+const char *const CLOUDS_MAIN_MENU =
+ "\r\x1\x3""c\fdMight and Magic Options\n"
+ "Clouds of Xeen\x2\n"
+ "\v%03dCopyright (c) 1992 NWC, Inc.\n"
+ "All Rights Reserved\x1";
+const char *const WORLD_MAIN_MENU =
+ "\r\x1\x3""c\fdMight and Magic Options\n"
+ "World of Xeen\x2\n"
"\v117Copyright (c) 1993 NWC, Inc.\n"
"All Rights Reserved\x01";
@@ -1771,8 +1843,12 @@ const char *const DIFFICULTY_TEXT = "\v000\t000\x3""cSelect Game Preference";
void writeConstants(CCArchive &cc) {
Common::MemFile file;
- file.syncString(CREDITS);
- file.syncString(OPTIONS_TITLE);
+ file.syncString(CLOUDS_CREDITS);
+ file.syncString(DARK_SIDE_CREDITS);
+ file.syncString(SWORDS_CREDITS1);
+ file.syncString(SWORDS_CREDITS2);
+ file.syncString(CLOUDS_MAIN_MENU);
+ file.syncString(WORLD_MAIN_MENU);
file.syncString(THE_PARTY_NEEDS_REST);
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 276d9a7..4ca69ec 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -191,11 +191,24 @@ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
void CreditsScreen::show(XeenEngine *vm) {
CreditsScreen *dlg = new CreditsScreen(vm);
- dlg->execute();
+
+ switch (vm->getGameID()) {
+ case GType_Clouds:
+ dlg->execute(Res.CLOUDS_CREDITS);
+ break;
+ case GType_Swords:
+ dlg->execute(Res.SWORDS_CREDITS1);
+ dlg->execute(Res.SWORDS_CREDITS2);
+ break;
+ default:
+ dlg->execute(Res.DARK_SIDE_CREDITS);
+ break;
+ }
+
delete dlg;
}
-void CreditsScreen::execute() {
+void CreditsScreen::execute(const char *content) {
Screen &screen = *_vm->_screen;
Windows &windows = *_vm->_windows;
EventsManager &events = *_vm->_events;
@@ -205,7 +218,7 @@ void CreditsScreen::execute() {
windows[GAME_WINDOW].close();
screen.loadBackground("marb.raw");
- windows[0].writeString(Res.CREDITS);
+ windows[0].writeString(content);
doScroll(false, false);
events.setCursor(0);
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index b4ad772..cabc921 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -117,7 +117,7 @@ class CreditsScreen: public ButtonContainer {
private:
CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
- void execute();
+ void execute(const char *content);
public:
static void show(XeenEngine *vm);
};
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 0aa7d8a..6ea4252 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -62,8 +62,12 @@ Resources::Resources() {
void Resources::loadData() {
ResFile file(_buffer);
- file.syncString(CREDITS);
- file.syncString(OPTIONS_TITLE);
+ file.syncString(CLOUDS_CREDITS);
+ file.syncString(DARK_SIDE_CREDITS);
+ file.syncString(SWORDS_CREDITS1);
+ file.syncString(SWORDS_CREDITS2);
+ file.syncString(CLOUDS_MAIN_MENU);
+ file.syncString(WORLD_MAIN_MENU);
file.syncString(THE_PARTY_NEEDS_REST);
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 67ac992..b14b9f5 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -116,8 +116,12 @@ public:
const char **ITEM_NAMES[4];
// Data loaded from xeen.ccs
- const char *CREDITS;
- const char *OPTIONS_TITLE;
+ const char *CLOUDS_CREDITS;
+ const char *DARK_SIDE_CREDITS;
+ const char *SWORDS_CREDITS1;
+ const char *SWORDS_CREDITS2;
+ const char *CLOUDS_MAIN_MENU;
+ const char *WORLD_MAIN_MENU;
const char *THE_PARTY_NEEDS_REST;
const char *WHO_WILL;
const char *HOW_MUCH;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index e08fd1b..679e48c 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1084,6 +1084,10 @@ bool Scripts::cmdCutsceneEndClouds(ParamsIterator ¶ms) {
party._mazeId = 28;
party._mazePosition = Common::Point(18, 4);
+ g_vm->_gameWon[0] = true;
+ g_vm->_finalScore[0] = party.getScore();
+ g_vm->saveSettings();
+
doCloudsEnding();
return false;
}
@@ -1416,6 +1420,10 @@ bool Scripts::cmdCutsceneEndDarkside(ParamsIterator ¶ms) {
party._mazeDirection = DIR_NORTH;
party._mazePosition = Common::Point(25, 21);
+ g_vm->_gameWon[1] = true;
+ g_vm->_finalScore[1] = party.getScore();
+ g_vm->saveSettings();
+
doDarkSideEnding();
return false;
}
diff --git a/engines/xeen/worldofxeen/worldofxeen.cpp b/engines/xeen/worldofxeen/worldofxeen.cpp
index 20fa7be..962bdfe 100644
--- a/engines/xeen/worldofxeen/worldofxeen.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen.cpp
@@ -186,14 +186,7 @@ void WorldOfXeenEngine::showStartup() {
}
void WorldOfXeenEngine::showMainMenu() {
- // TODO: Remove this as the game main menus are properly implemented
- if (getGameID() == GType_Clouds) {
- _saves->newGame();
- _gameMode = GMODE_PLAY_GAME;
- return;
- }
-
- WorldOfXeenMenu::show(this);
+ WorldOfXeenMainMenuContainer::show();
}
} // End of namespace WorldOfXeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 7f5e7f3..a91a711 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -29,236 +29,249 @@
namespace Xeen {
namespace WorldOfXeen {
-void WorldOfXeenMenu::show(XeenEngine *vm) {
- WorldOfXeenMenu *menu;
+void MainMenuContainer::show() {
+ MainMenuContainer *menu;
- switch (vm->getGameID()) {
+ switch (g_vm->getGameID()) {
case GType_Clouds:
- menu = new CloudsOptionsMenu(vm);
+ menu = new CloudsMainMenuContainer();
break;
case GType_DarkSide:
- menu = new DarkSideOptionsMenu(vm);
+ menu = new DarkSideMainMenuContainer();
break;
case GType_WorldOfXeen:
- menu = new WorldOptionsMenu(vm);
+ menu = new WorldOfXeenMainMenuContainer();
break;
default:
- error("Unsupported game");
- break;
+ error("Invalid game");
}
menu->execute();
delete menu;
}
-void WorldOfXeenMenu::execute() {
- _vm->_files->setGameCc(1);
- SpriteResource special("special.icn");
- Windows &windows = *_vm->_windows;
- EventsManager &events = *_vm->_events;
-
- File newBright("newbrigh.m");
- _vm->_sound->playSong(newBright);
-
- windows[GAME_WINDOW].setBounds(Common::Rect(72, 25, 248, 175));
+MainMenuContainer::MainMenuContainer(const Common::String &spritesName) : _animateCtr(0), _dialog(nullptr) {
+ _backgroundSprites.load(spritesName);
+}
- Common::String title1, title2;
- startup(title1, title2);
- SpriteResource title1Sprites(title1), title2Sprites(title2);
+MainMenuContainer::~MainMenuContainer() {
+ delete _dialog;
+ g_vm->_windows->closeAll();
+ g_vm->_sound->stopAllAudio();
+ g_vm->_events->clearEvents();
+}
- bool firstTime = true, doFade = true;
- while (!_vm->shouldExit()) {
- setBackground(doFade);
+void MainMenuContainer::draw() {
+ g_vm->_screen->restoreBackground();
+ _animateCtr = (_animateCtr + 1) % 9;
+ _backgroundSprites.draw(0, _animateCtr);
+}
- if (firstTime) {
- firstTime = false;
- events.setCursor(0);
- events.showCursor();
+void MainMenuContainer::execute() {
+ EventsManager &events = *g_vm->_events;
+ bool showFlag = false;
+
+ // Show the cursor
+ events.clearEvents();
+ events.setCursor(0);
+ events.showCursor();
+
+ while (!g_vm->shouldExit() && g_vm->_gameMode == GMODE_NONE) {
+ // Draw the menu
+ draw();
+ if (_dialog)
+ _dialog->draw();
+
+ // Fade/scroll in screen if first frame
+ if (!showFlag) {
+ loadBackground();
+ // TODO: doScroll(false, false);
+ showFlag = true;
}
- showTitles1(title1Sprites);
- showTitles2();
-
- clearButtons();
- setupButtons(&title2Sprites);
- openWindow();
-
- while (!_vm->shouldExit()) {
- // Show the dialog with a continually animating background
- while (!_vm->shouldExit() && !_buttonValue)
- showContents(title1Sprites, true);
- if (_vm->shouldExit())
- return;
-
- // Handle keypress
- int key = toupper(_buttonValue);
- _buttonValue = 0;
-
- if (key == Common::KEYCODE_ESCAPE) {
- // Hide the options menu
- closeWindow();
- break;
- } else if (key == 'C' || key == 'V') {
- // Show credits
- closeWindow();
- CreditsScreen::show(_vm);
- break;
- } else if (key == 'S') {
- // Start new game
- int result = DifficultyDialog::show(_vm);
- if (result == -1)
- break;
-
- // Load a new game state and set the difficulty
- _vm->_saves->newGame();
- _vm->_party->_difficulty = (Difficulty)result;
- _vm->_gameMode = GMODE_PLAY_GAME;
- closeWindow();
- return;
- } else if (key == 'L') {
- _vm->_saves->newGame();
- if (_vm->_saves->loadGame()) {
- _vm->_gameMode = GMODE_PLAY_GAME;
- break;
+ // Check for events
+ events.updateGameCounter();
+
+ if (events.wait(4, true)) {
+ if (_dialog) {
+ // There's a dialog active, so let it handle the event
+ _dialog->handleEvents();
+
+ // If dialog was removed as a result of the event, flag screen for re-showing
+ // if the menu screen isn't being left
+ if (!_dialog)
+ showFlag = false;
+ } else {
+ // No active dialog. If Escape pressed, exit game entirely. Otherwise,
+ // open up the main menu dialog
+ if (events.isKeyPending()) {
+ Common::KeyState key;
+ if (events.getKey(key) && key.keycode == Common::KEYCODE_ESCAPE)
+ g_vm->_gameMode = GMODE_QUIT;
}
+
+ events.clearEvents();
+ showMenuDialog();
}
}
}
}
-void WorldOfXeenMenu::showTitles1(SpriteResource &sprites) {
- Screen &screen = *_vm->_screen;
- EventsManager &events = *_vm->_events;
-
- int frameNum = 0;
- while (!_vm->shouldExit() && !events.isKeyMousePressed()) {
- events.updateGameCounter();
-
- frameNum = (frameNum + 1) % (_vm->getGameID() == GType_WorldOfXeen ? 5 : 10);
- screen.restoreBackground();
- sprites.draw(0, frameNum);
+/*------------------------------------------------------------------------*/
- events.wait(4);
- }
+CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga") {
+ g_vm->_sound->playSong("inn.m");
}
-void WorldOfXeenMenu::showTitles2() {
- Screen &screen = *_vm->_screen;
- EventsManager &events = *_vm->_events;
- Sound &sound = *_vm->_sound;
- Windows &windows = *_vm->_windows;
-
- SpriteResource titleSprites("title2b.raw");
- SpriteResource kludgeSprites("kludge.int");
- SpriteResource title2Sprites[8] = {
- SpriteResource("title2b.int"), SpriteResource("title2c.int"),
- SpriteResource("title2d.int"), SpriteResource("title2e.int"),
- SpriteResource("title2f.int"), SpriteResource("title2g.int"),
- SpriteResource("title2h.int"), SpriteResource("title2i.int"),
- };
-
- kludgeSprites.draw(0, 0);
+void CloudsMainMenuContainer::loadBackground() {
+ Screen &screen = *g_vm->_screen;
+ screen.loadPalette("mm4.pal");
+ screen.loadBackground("intro.raw");
screen.saveBackground();
- sound.playSound("elect.voc");
-
- for (int i = 0; i < 30 && !_vm->shouldExit(); ++i) {
- events.updateGameCounter();
- screen.restoreBackground();
- title2Sprites[i / 4].draw(0, i % 4);
- windows[0].update();
+}
- if (i == 19)
- sound.stopSound();
+void CloudsMainMenuContainer::showMenuDialog() {
+ setOwner(new CloudsMenuDialog(this));
+}
- while (!_vm->shouldExit() && events.timeElapsed() < 2)
- events.pollEventsAndWait();
- }
+/*------------------------------------------------------------------------*/
- screen.restoreBackground();
- windows[0].update();
+DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("intro.vga") {
+ g_vm->_sound->playSong("inn.m");
}
-void WorldOfXeenMenu::setupButtons(SpriteResource *buttons) {
- addButton(Common::Rect(124, 87, 124 + 53, 87 + 10), 'S');
- addButton(Common::Rect(126, 98, 126 + 47, 98 + 10), 'L');
- addButton(Common::Rect(91, 110, 91 + 118, 110 + 10), 'C');
- addButton(Common::Rect(85, 121, 85 + 131, 121 + 10), 'O');
+void DarkSideMainMenuContainer::loadBackground() {
+ Screen &screen = *g_vm->_screen;
+ screen.loadPalette("mm4.pal");
+ screen.loadBackground("intro.raw");
+ screen.saveBackground();
}
-void WorldOptionsMenu::setupButtons(SpriteResource *buttons) {
- addButton(Common::Rect(93, 53, 93 + 134, 53 + 20), 'S', buttons);
- addButton(Common::Rect(93, 78, 93 + 134, 78 + 20), 'L', buttons);
- addButton(Common::Rect(93, 103, 93 + 134, 103 + 20), 'C', buttons);
- addButton(Common::Rect(93, 128, 93 + 134, 128 + 20), 'O', buttons);
+void DarkSideMainMenuContainer::showMenuDialog() {
+ setOwner(new CloudsMenuDialog(this));
}
/*------------------------------------------------------------------------*/
-void CloudsOptionsMenu::startup(Common::String &title1, Common::String &title2) {
- title1 = "title1.int";
- title2 = "title1a.int";
+WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("intro.vga") {
+ g_vm->_sound->playSong("inn.m");
}
-/*------------------------------------------------------------------------*/
+void WorldOfXeenMainMenuContainer::loadBackground() {
+ Screen &screen = *g_vm->_screen;
+ screen.loadPalette("mm4.pal");
+ screen.loadBackground("intro.raw");
+ screen.saveBackground();
+}
-void DarkSideOptionsMenu::startup(Common::String &title1, Common::String &title2) {
- title1 = "title2.int";
- title2 = "title2a.int";
+void WorldOfXeenMainMenuContainer::showMenuDialog() {
+ setOwner(new CloudsMenuDialog(this));
}
-void WorldOptionsMenu::startup(Common::String &title1, Common::String &title2) {
- title1 = "world.int";
- title2 = "start.icn";
+/*------------------------------------------------------------------------*/
- Screen &screen = *_vm->_screen;
- screen.fadeOut();
- screen.loadPalette("dark.pal");
- _vm->_events->clearEvents();
-}
+bool MainMenuDialog::handleEvents() {
+ checkEvents(g_vm);
+ int difficulty;
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_s:
+ // Start new game
+ difficulty = DifficultyDialog::show(g_vm);
+ if (difficulty == -1)
+ return true;
+
+ // Load a new game state and set the difficulty
+ g_vm->_saves->newGame();
+ g_vm->_party->_difficulty = (Difficulty)difficulty;
+ g_vm->_gameMode = GMODE_PLAY_GAME;
+ break;
-void WorldOptionsMenu::setBackground(bool doFade) {
- Screen &screen = *_vm->_screen;
- screen.loadBackground("world.raw");
- screen.saveBackground();
+ case Common::KEYCODE_l:
+ // Load existing game
+ g_vm->_saves->newGame();
+ if (!g_vm->_saves->loadGame())
+ return true;
+
+ g_vm->_gameMode = GMODE_PLAY_GAME;
+ break;
+
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_v:
+ // Show credits
+ CreditsScreen::show(g_vm);
+ break;
+
+ default:
+ return false;
+ }
- if (doFade)
- screen.fadeIn();
+ // If this point is reached, delete the dialog itself, which will return the main menu
+ // to it's default "No dialog showing" state
+ delete this;
+ return true;
}
-void WorldOptionsMenu::openWindow() {
- Windows &windows = *_vm->_windows;
- windows[GAME_WINDOW].open();
+/*------------------------------------------------------------------------*/
+
+CloudsMenuDialog::CloudsMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner) {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.setBounds(Common::Rect(72, 25, 248, g_vm->_gameWon[0] ? 175 : 150));
+ w.open();
+
+ loadButtons();
}
-void WorldOptionsMenu::closeWindow() {
- Windows &windows = *_vm->_windows;
- windows[GAME_WINDOW].close();
+CloudsMenuDialog::~CloudsMenuDialog() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.close();
}
-void WorldOptionsMenu::showContents(SpriteResource &title1, bool waitFlag) {
- EventsManager &events = *_vm->_events;
- Screen &screen = *_vm->_screen;
- Windows &windows = *_vm->_windows;
- events.updateGameCounter();
+void CloudsMenuDialog::loadButtons() {
+ _buttonSprites.load("start.icn");
+ addButton(Common::Rect(93, 53, 227, 73), Common::KEYCODE_s, &_buttonSprites);
+ addButton(Common::Rect(93, 78, 227, 98), Common::KEYCODE_l, &_buttonSprites);
+ addButton(Common::Rect(93, 103, 227, 123), Common::KEYCODE_c, &_buttonSprites);
+ if (g_vm->_gameWon[0])
+ addButton(Common::Rect(93, 128, 227, 148), Common::KEYCODE_e, &_buttonSprites);
+}
- // Draw the background frame in a continous cycle
- _bgFrame = (_bgFrame + 1) % 5;
- title1.draw(windows[0], _bgFrame);
+void CloudsMenuDialog::draw() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+
+ w.frame();
+ w.writeString(Common::String::format(Res.CLOUDS_MAIN_MENU, g_vm->_gameWon[0] ? 117 : 92));
+ drawButtons(&w);
+}
- // Draw the basic frame for the optitons menu and title text
- windows[GAME_WINDOW].frame();
- windows[GAME_WINDOW].writeString(Res.OPTIONS_TITLE);
+bool CloudsMenuDialog::handleEvents() {
+ if (MainMenuDialog::handleEvents())
+ return true;
- drawButtons(&windows[0]);
- screen.update();
+ switch (_buttonValue) {
+ case Common::KEYCODE_e:
+ if (g_vm->_gameWon[0]) {
+ // Close the window
+ delete this;
- if (waitFlag) {
- while (!_vm->shouldExit() && !_buttonValue && events.timeElapsed() < 3) {
- events.pollEventsAndWait();
- checkEvents(_vm);
+ // Show clouds ending
+ WOX_VM.showCloudsEnding(g_vm->_finalScore[0]);
+ return true;
}
+ break;
+
+ default:
+ break;
}
+
+ return false;
}
+/*------------------------------------------------------------------------*/
+
+
} // End of namespace WorldOfXeen
} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.h b/engines/xeen/worldofxeen/worldofxeen_menu.h
index 39d309c..3495f08 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.h
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.h
@@ -29,82 +29,181 @@
namespace Xeen {
namespace WorldOfXeen {
-class WorldOfXeenMenu : public SettingsBaseDialog {
+class MainMenuDialog;
+
+class MainMenuContainer {
private:
- void execute();
-protected:
- WorldOfXeenMenu(XeenEngine *vm) : SettingsBaseDialog(vm) {}
+ int _animateCtr;
+ SpriteResource _backgroundSprites;
+ MainMenuDialog *_dialog;
protected:
- virtual void startup(Common::String &title1, Common::String &title2) = 0;
+ /**
+ * Draws the main menu background
+ */
+ void draw();
- virtual void setBackground(bool doFade) {}
+ /**
+ * Load the background
+ */
+ virtual void loadBackground() = 0;
- virtual void showTitles1(SpriteResource &sprites);
+ /**
+ * Shows the main menu dialog
+ */
+ virtual void showMenuDialog() = 0;
+public:
+ /**
+ * Show the main menu for the correct game
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ MainMenuContainer(const Common::String &spritesName);
- virtual void showTitles2();
+ /**
+ * Destructor
+ */
+ virtual ~MainMenuContainer();
- virtual void setupButtons(SpriteResource *buttons);
+ /**
+ * Execute the menu
+ */
+ void execute();
/**
- * Opens the menu window
+ * Sets the dialog being displayed in the menu
*/
- virtual void openWindow() {}
+ void setOwner(MainMenuDialog *dlalog) {
+ _dialog = dlalog;
+ }
+};
+class CloudsMainMenuContainer : public MainMenuContainer {
+protected:
/**
- * Closes the menu window
+ * Load the background
*/
- virtual void closeWindow() {}
-public:
- virtual ~WorldOfXeenMenu() {}
+ virtual void loadBackground();
- static void show(XeenEngine *vm);
+ /**
+ * Shows the main menu dialog
+ */
+ virtual void showMenuDialog();
+public:
+ CloudsMainMenuContainer();
};
-class CloudsOptionsMenu : public WorldOfXeenMenu {
+class DarkSideMainMenuContainer : public MainMenuContainer {
protected:
- virtual void startup(Common::String &title1, Common::String &title2);
-public:
- CloudsOptionsMenu(XeenEngine *vm) : WorldOfXeenMenu(vm) {}
+ /**
+ * Load the background
+ */
+ virtual void loadBackground();
- virtual ~CloudsOptionsMenu() {}
+ /**
+ * Shows the main menu dialog
+ */
+ virtual void showMenuDialog();
+public:
+ DarkSideMainMenuContainer();
};
-class DarkSideOptionsMenu : public WorldOfXeenMenu {
+class WorldOfXeenMainMenuContainer : public MainMenuContainer {
protected:
- virtual void startup(Common::String &title1, Common::String &title2);
-public:
- DarkSideOptionsMenu(XeenEngine *vm) : WorldOfXeenMenu(vm) {}
+ /**
+ * Load the background
+ */
+ virtual void loadBackground();
- virtual ~DarkSideOptionsMenu() {}
+ /**
+ * Shows the main menu dialog
+ */
+ virtual void showMenuDialog();
+public:
+ WorldOfXeenMainMenuContainer();
};
-class WorldOptionsMenu : public DarkSideOptionsMenu {
+class MenuContainerDialog : public ButtonContainer {
private:
- int _bgFrame;
-protected:
- virtual void startup(Common::String &title1, Common::String &title2);
+ MainMenuContainer *_owner;
+public:
+ /**
+ * Constructor
+ */
+ MenuContainerDialog(MainMenuContainer *owner) : ButtonContainer(g_vm), _owner(owner) {}
- virtual void setBackground(bool doFade);
+ /**
+ * Destructor
+ */
+ virtual ~MenuContainerDialog() {
+ _owner->setOwner(nullptr);
+ }
+
+ /**
+ * Draws the dialog
+ */
+ virtual void draw() = 0;
- virtual void showTitles2() {}
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents() = 0;
+};
- virtual void setupButtons(SpriteResource *buttons);
+class MainMenuDialog : public MenuContainerDialog {
+public:
+ /**
+ * Constructor
+ */
+ MainMenuDialog(MainMenuContainer *owner) : MenuContainerDialog(owner) {}
/**
- * Opens the menu window
+ * Destructor
*/
- virtual void openWindow();
+ virtual ~MainMenuDialog() {}
/**
- * Closes the menu window
+ * Draws the dialog
*/
- virtual void closeWindow();
+ virtual void draw() = 0;
- virtual void showContents(SpriteResource &title1, bool mode);
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents();
+
+};
+
+class CloudsMenuDialog : public MainMenuDialog {
+private:
+ SpriteResource _buttonSprites;
+private:
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
public:
- WorldOptionsMenu(XeenEngine *vm) : DarkSideOptionsMenu(vm), _bgFrame(0) {}
+ /**
+ * Constructor
+ */
+ CloudsMenuDialog(MainMenuContainer *owner);
- virtual ~WorldOptionsMenu() {}
+ /**
+ * Destructor
+ */
+ virtual ~CloudsMenuDialog();
+
+ /**
+ * Draws the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents();
};
} // End of namespace WorldOfXeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 21db8b2..6122f4d 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -62,6 +62,8 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
_mode = MODE_0;
_endingScore = 0;
_loadSaveSlot = -1;
+ _gameWon[0] = _gameWon[1] = false;
+ _finalScore[0] = _finalScore[1] = 0;
g_vm = this;
}
@@ -111,6 +113,12 @@ bool XeenEngine::initialize() {
// Setup mixer
syncSoundSettings();
+ // Load settings
+ _gameWon[0] = ConfMan.hasKey("game_won") && ConfMan.getBool("game_won");
+ _gameWon[1] = ConfMan.hasKey("game_won2") && ConfMan.getBool("game_won2");
+ _finalScore[0] = ConfMan.hasKey("final_score") ? ConfMan.getInt("final_score") : 0;
+ _finalScore[1] = ConfMan.hasKey("final_score2") ? ConfMan.getInt("final_score2") : 0;
+
// If requested, load a savegame instead of showing the intro
if (ConfMan.hasKey("save_slot")) {
int saveSlot = ConfMan.getInt("save_slot");
@@ -294,4 +302,15 @@ void XeenEngine::GUIError(const char *msg, ...) {
GUIErrorMessage(buffer);
}
+void XeenEngine::saveSettings() {
+ if (_gameWon[0])
+ ConfMan.setBool("game_won", true);
+ if (_gameWon[1])
+ ConfMan.setBool("game_won2", true);
+
+ ConfMan.setInt("final_score", _finalScore[0]);
+ ConfMan.setInt("final_score2", _finalScore[1]);
+ ConfMan.flushToDisk();
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 5031f1f..98ba00b 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -183,6 +183,8 @@ public:
bool _noDirectionSense;
bool _startupWindowActive;
uint _endingScore;
+ bool _gameWon[2];
+ uint _finalScore[2];
public:
XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
virtual ~XeenEngine();
@@ -251,6 +253,11 @@ public:
static Common::String printK(uint value);
static Common::String printK2(uint value);
+
+ /**
+ * Saves engine settings
+ */
+ void saveSettings();
};
extern XeenEngine *g_vm;
Commit: f2b574d64762d23a83cc682da0e622be99080688
https://github.com/scummvm/scummvm/commit/f2b574d64762d23a83cc682da0e622be99080688
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:42-05:00
Commit Message:
XEEN: Move all the dialog classes to their own sub-folder
Changed paths:
A engines/xeen/dialogs/dialogs.cpp
A engines/xeen/dialogs/dialogs.h
A engines/xeen/dialogs/dialogs_awards.cpp
A engines/xeen/dialogs/dialogs_awards.h
A engines/xeen/dialogs/dialogs_char_info.cpp
A engines/xeen/dialogs/dialogs_char_info.h
A engines/xeen/dialogs/dialogs_control_panel.cpp
A engines/xeen/dialogs/dialogs_control_panel.h
A engines/xeen/dialogs/dialogs_create_char.cpp
A engines/xeen/dialogs/dialogs_create_char.h
A engines/xeen/dialogs/dialogs_difficulty.cpp
A engines/xeen/dialogs/dialogs_difficulty.h
A engines/xeen/dialogs/dialogs_dismiss.cpp
A engines/xeen/dialogs/dialogs_dismiss.h
A engines/xeen/dialogs/dialogs_exchange.cpp
A engines/xeen/dialogs/dialogs_exchange.h
A engines/xeen/dialogs/dialogs_info.cpp
A engines/xeen/dialogs/dialogs_info.h
A engines/xeen/dialogs/dialogs_input.cpp
A engines/xeen/dialogs/dialogs_input.h
A engines/xeen/dialogs/dialogs_items.cpp
A engines/xeen/dialogs/dialogs_items.h
A engines/xeen/dialogs/dialogs_map.cpp
A engines/xeen/dialogs/dialogs_map.h
A engines/xeen/dialogs/dialogs_message.cpp
A engines/xeen/dialogs/dialogs_message.h
A engines/xeen/dialogs/dialogs_party.cpp
A engines/xeen/dialogs/dialogs_party.h
A engines/xeen/dialogs/dialogs_query.cpp
A engines/xeen/dialogs/dialogs_query.h
A engines/xeen/dialogs/dialogs_quests.cpp
A engines/xeen/dialogs/dialogs_quests.h
A engines/xeen/dialogs/dialogs_quick_fight.cpp
A engines/xeen/dialogs/dialogs_quick_fight.h
A engines/xeen/dialogs/dialogs_quick_ref.cpp
A engines/xeen/dialogs/dialogs_quick_ref.h
A engines/xeen/dialogs/dialogs_spells.cpp
A engines/xeen/dialogs/dialogs_spells.h
A engines/xeen/dialogs/dialogs_whowill.cpp
A engines/xeen/dialogs/dialogs_whowill.h
R engines/xeen/dialogs.cpp
R engines/xeen/dialogs.h
R engines/xeen/dialogs_awards.cpp
R engines/xeen/dialogs_awards.h
R engines/xeen/dialogs_char_info.cpp
R engines/xeen/dialogs_char_info.h
R engines/xeen/dialogs_control_panel.cpp
R engines/xeen/dialogs_control_panel.h
R engines/xeen/dialogs_create_char.cpp
R engines/xeen/dialogs_create_char.h
R engines/xeen/dialogs_difficulty.cpp
R engines/xeen/dialogs_difficulty.h
R engines/xeen/dialogs_dismiss.cpp
R engines/xeen/dialogs_dismiss.h
R engines/xeen/dialogs_exchange.cpp
R engines/xeen/dialogs_exchange.h
R engines/xeen/dialogs_info.cpp
R engines/xeen/dialogs_info.h
R engines/xeen/dialogs_input.cpp
R engines/xeen/dialogs_input.h
R engines/xeen/dialogs_items.cpp
R engines/xeen/dialogs_items.h
R engines/xeen/dialogs_map.cpp
R engines/xeen/dialogs_map.h
R engines/xeen/dialogs_message.cpp
R engines/xeen/dialogs_message.h
R engines/xeen/dialogs_party.cpp
R engines/xeen/dialogs_party.h
R engines/xeen/dialogs_query.cpp
R engines/xeen/dialogs_query.h
R engines/xeen/dialogs_quests.cpp
R engines/xeen/dialogs_quests.h
R engines/xeen/dialogs_quick_fight.cpp
R engines/xeen/dialogs_quick_fight.h
R engines/xeen/dialogs_quick_ref.cpp
R engines/xeen/dialogs_quick_ref.h
R engines/xeen/dialogs_spells.cpp
R engines/xeen/dialogs_spells.h
R engines/xeen/dialogs_whowill.cpp
R engines/xeen/dialogs_whowill.h
engines/xeen/character.cpp
engines/xeen/interface.cpp
engines/xeen/interface.h
engines/xeen/interface_scene.cpp
engines/xeen/locations.cpp
engines/xeen/locations.h
engines/xeen/module.mk
engines/xeen/party.cpp
engines/xeen/party.h
engines/xeen/scripts.cpp
engines/xeen/spells.cpp
engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
engines/xeen/swordsofxeen/swordsofxeen_menu.h
engines/xeen/worldofxeen/worldofxeen_menu.cpp
engines/xeen/worldofxeen/worldofxeen_menu.h
engines/xeen/xeen.h
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 69fbc16..c6ebde8 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -21,8 +21,8 @@
*/
#include "xeen/character.h"
-#include "xeen/dialogs_query.h"
-#include "xeen/dialogs_message.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/dialogs/dialogs_message.h"
#include "xeen/resources.h"
#include "xeen/xeen.h"
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
deleted file mode 100644
index 4ca69ec..0000000
--- a/engines/xeen/dialogs.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/* 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 "common/scummsys.h"
-#include "xeen/dialogs.h"
-#include "xeen/events.h"
-#include "xeen/resources.h"
-#include "xeen/screen.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-void ButtonContainer::saveButtons() {
- _savedButtons.push(_buttons);
- clearButtons();
-}
-
-/*
- * Clears the current list of defined buttons
- */
-void ButtonContainer::clearButtons() {
- _buttons.clear();
-}
-
-void ButtonContainer::restoreButtons() {
- _buttons = _savedButtons.pop();
-}
-
-void ButtonContainer::addButton(const Common::Rect &bounds, int val,
- SpriteResource *sprites) {
- _buttons.push_back(UIButton(bounds, val, _buttons.size() * 2, sprites, sprites != nullptr));
-}
-
-void ButtonContainer::addButton(const Common::Rect &bounds, int val,
- int frameNum, SpriteResource *sprites) {
- _buttons.push_back(UIButton(bounds, val, frameNum, sprites, sprites != nullptr));
-}
-
-void ButtonContainer::addPartyButtons(XeenEngine *vm) {
- for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) {
- addButton(Common::Rect(Res.CHAR_FACES_X[idx], 150, Res.CHAR_FACES_X[idx] + 32, 182),
- Common::KEYCODE_F1 + idx);
- }
-}
-
-bool ButtonContainer::checkEvents(XeenEngine *vm) {
- EventsManager &events = *vm->_events;
- Party &party = *vm->_party;
- Windows &windows = *_vm->_windows;
- _buttonValue = 0;
-
- if (events._leftButton) {
- Common::Point pt = events._mousePos;
-
- // Check for party member glyphs being clicked
- Common::Rect r(0, 0, 32, 32);
- for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
- r.moveTo(Res.CHAR_FACES_X[idx], 150);
- if (r.contains(pt)) {
- _buttonValue = Common::KEYCODE_F1 + idx;
- break;
- }
- }
-
- // Check whether any button is selected
- for (uint i = 0; i < _buttons.size(); ++i) {
- if (_buttons[i]._bounds.contains(pt)) {
- events.debounceMouse();
-
- _buttonValue = _buttons[i]._value;
- break;
- }
- }
-
- if (!_buttonValue && Common::Rect(8, 8, 224, 135).contains(pt)) {
- _buttonValue = 1;
- return true;
- }
- } else if (events.isKeyPending()) {
- Common::KeyState keyState;
- events.getKey(keyState);
-
- _buttonValue = keyState.keycode;
- if (_buttonValue == Common::KEYCODE_KP8)
- _buttonValue = Common::KEYCODE_UP;
- else if (_buttonValue == Common::KEYCODE_KP2)
- _buttonValue = Common::KEYCODE_DOWN;
- else if (_buttonValue == Common::KEYCODE_KP_ENTER)
- _buttonValue = Common::KEYCODE_RETURN;
-
- _buttonValue |= (keyState.flags & ~Common::KBD_STICKY) << 16;
- }
-
- if (_buttonValue) {
- // Check for a button matching the selected _buttonValue
- Window &win = windows[39];
- for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
- UIButton &btn = _buttons[btnIndex];
- if (btn._draw && btn._value == _buttonValue) {
- // Found the correct button
- // Draw button depressed
- btn._sprites->draw(0, btn._frameNum + 1,
- Common::Point(btn._bounds.left, btn._bounds.top));
- win.setBounds(btn._bounds);
- win.update();
-
- // Slight delay
- events.updateGameCounter();
- events.wait(2);
-
- // Redraw button in it's original non-depressed form
- btn._sprites->draw(0, btn._frameNum,
- Common::Point(btn._bounds.left, btn._bounds.top));
- win.setBounds(btn._bounds);
- win.update();
- break;
- }
- }
-
- return true;
- }
-
- return false;
-}
-
-void ButtonContainer::drawButtons(XSurface *surface) {
- for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
- UIButton &btn = _buttons[btnIndex];
- if (btn._draw) {
- btn._sprites->draw(*surface, btn._frameNum,
- Common::Point(btn._bounds.left, btn._bounds.top));
- }
- }
-}
-
-bool ButtonContainer::doScroll(bool rollUp, bool fadeIn) {
- if (_vm->_files->_isDarkCc) {
- return Cutscenes::doScroll(rollUp, fadeIn);
- } else {
- saveButtons();
- clearButtons();
- bool result = Cutscenes::doScroll(rollUp, fadeIn);
- restoreButtons();
- return result;
- }
-}
-
-void ButtonContainer::loadStrings(const Common::String &name) {
- File f(name);
- _textStrings.clear();
- while (f.pos() < f.size())
- _textStrings.push_back(f.readString());
- f.close();
-}
-
-void ButtonContainer::loadStrings(const Common::String &name, int ccMode) {
- File f(name, ccMode);
- _textStrings.clear();
- while (f.pos() < f.size())
- _textStrings.push_back(f.readString());
- f.close();
-}
-
-/*------------------------------------------------------------------------*/
-
-void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
- _vm->_events->pollEventsAndWait();
- checkEvents(_vm);
-}
-
-/*------------------------------------------------------------------------*/
-
-void CreditsScreen::show(XeenEngine *vm) {
- CreditsScreen *dlg = new CreditsScreen(vm);
-
- switch (vm->getGameID()) {
- case GType_Clouds:
- dlg->execute(Res.CLOUDS_CREDITS);
- break;
- case GType_Swords:
- dlg->execute(Res.SWORDS_CREDITS1);
- dlg->execute(Res.SWORDS_CREDITS2);
- break;
- default:
- dlg->execute(Res.DARK_SIDE_CREDITS);
- break;
- }
-
- delete dlg;
-}
-
-void CreditsScreen::execute(const char *content) {
- Screen &screen = *_vm->_screen;
- Windows &windows = *_vm->_windows;
- EventsManager &events = *_vm->_events;
-
- // Handle drawing the credits screen
- doScroll(true, false);
- windows[GAME_WINDOW].close();
-
- screen.loadBackground("marb.raw");
- windows[0].writeString(content);
- doScroll(false, false);
-
- events.setCursor(0);
- windows[0].update();
- clearButtons();
-
- // Wait for keypress
- while (!events.isKeyMousePressed())
- events.pollEventsAndWait();
-
- doScroll(true, false);
-}
-
-/*------------------------------------------------------------------------*/
-
-PleaseWait::PleaseWait(bool isOops) {
- _msg = isOops ? Res.OOPS : Res.PLEASE_WAIT;
-}
-
-PleaseWait::~PleaseWait() {
- Windows &windows = *g_vm->_windows;
- windows[9].close();
-}
-
-void PleaseWait::show() {
- Windows &windows = *g_vm->_windows;
- Window &w = windows[9];
-
- if (g_vm->_mode != MODE_0) {
- w.open();
- w.writeString(_msg);
- w.update();
- }
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
deleted file mode 100644
index cabc921..0000000
--- a/engines/xeen/dialogs.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* 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 XEEN_DIALOGS_H
-#define XEEN_DIALOGS_H
-
-#include "common/array.h"
-#include "common/stack.h"
-#include "common/rect.h"
-#include "xeen/cutscenes.h"
-#include "xeen/sprites.h"
-#include "xeen/xsurface.h"
-
-namespace Xeen {
-
-class XeenEngine;
-
-class UIButton {
-public:
- Common::Rect _bounds;
- SpriteResource *_sprites;
- int _value;
- uint _frameNum;
- bool _draw;
-
- UIButton(const Common::Rect &bounds, int value, uint frameNum, SpriteResource *sprites, bool draw) :
- _bounds(bounds), _value(value), _frameNum(frameNum),
- _sprites(sprites), _draw(draw) {}
-
- UIButton() : _value(0), _frameNum(0), _sprites(nullptr), _draw(false) {}
-};
-
-class ButtonContainer : public Cutscenes {
-private:
- Common::Stack< Common::Array<UIButton> > _savedButtons;
-protected:
- Common::Array<UIButton> _buttons;
- Common::StringArray _textStrings;
- int _buttonValue;
-
- bool checkEvents(XeenEngine *vm);
-
- /**
- * Draws the scroll in the background
- * @param rollUp If true, rolls up the scroll. If false, unrolls.
- * @param fadeIn If true, does an initial fade in
- * @returns True if key or mouse pressed
- */
- virtual bool doScroll(bool rollUp, bool fadeIn);
-
- /**
- * Load a set of text strings from the given resource
- * @param name Name of resource containing strings
- */
- void loadStrings(const Common::String &name);
-
- /**
- * Load a set of text strings from the given resource
- * @param name Name of resource containing strings
- * @param ccMode Optional cc file number to explicitly use
- */
- void loadStrings(const Common::String &name, int ccMode);
-public:
- ButtonContainer(XeenEngine *vm) : Cutscenes(vm), _buttonValue(0) {}
-
- /**
- * Saves the current list of buttons
- */
- void saveButtons();
-
- void clearButtons();
-
- void restoreButtons();
-
- void addButton(const Common::Rect &bounds, int val,
- SpriteResource *sprites = nullptr);
- void addButton(const Common::Rect &bounds, int val,
- int frameNum, SpriteResource *sprites = nullptr);
-
- void addPartyButtons(XeenEngine *vm);
-
- /**
- * Draws the buttons onto the passed surface
- */
- void drawButtons(XSurface *surface);
-};
-
-class SettingsBaseDialog : public ButtonContainer {
-protected:
- virtual void showContents(SpriteResource &title1, bool mode);
-public:
- SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(vm) {}
-
- virtual ~SettingsBaseDialog() {}
-};
-
-class CreditsScreen: public ButtonContainer {
-private:
- CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
-
- void execute(const char *content);
-public:
- static void show(XeenEngine *vm);
-};
-
-class PleaseWait {
-private:
- Common::String _msg;
-public:
- PleaseWait(bool isOops = false);
- ~PleaseWait();
-
- void show();
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs/dialogs.cpp b/engines/xeen/dialogs/dialogs.cpp
new file mode 100644
index 0000000..c9b5658
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs.cpp
@@ -0,0 +1,257 @@
+/* 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 "common/scummsys.h"
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/events.h"
+#include "xeen/resources.h"
+#include "xeen/screen.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void ButtonContainer::saveButtons() {
+ _savedButtons.push(_buttons);
+ clearButtons();
+}
+
+/*
+ * Clears the current list of defined buttons
+ */
+void ButtonContainer::clearButtons() {
+ _buttons.clear();
+}
+
+void ButtonContainer::restoreButtons() {
+ _buttons = _savedButtons.pop();
+}
+
+void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+ SpriteResource *sprites) {
+ _buttons.push_back(UIButton(bounds, val, _buttons.size() * 2, sprites, sprites != nullptr));
+}
+
+void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+ int frameNum, SpriteResource *sprites) {
+ _buttons.push_back(UIButton(bounds, val, frameNum, sprites, sprites != nullptr));
+}
+
+void ButtonContainer::addPartyButtons(XeenEngine *vm) {
+ for (uint idx = 0; idx < MAX_ACTIVE_PARTY; ++idx) {
+ addButton(Common::Rect(Res.CHAR_FACES_X[idx], 150, Res.CHAR_FACES_X[idx] + 32, 182),
+ Common::KEYCODE_F1 + idx);
+ }
+}
+
+bool ButtonContainer::checkEvents(XeenEngine *vm) {
+ EventsManager &events = *vm->_events;
+ Party &party = *vm->_party;
+ Windows &windows = *_vm->_windows;
+ _buttonValue = 0;
+
+ if (events._leftButton) {
+ Common::Point pt = events._mousePos;
+
+ // Check for party member glyphs being clicked
+ Common::Rect r(0, 0, 32, 32);
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ r.moveTo(Res.CHAR_FACES_X[idx], 150);
+ if (r.contains(pt)) {
+ _buttonValue = Common::KEYCODE_F1 + idx;
+ break;
+ }
+ }
+
+ // Check whether any button is selected
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ if (_buttons[i]._bounds.contains(pt)) {
+ events.debounceMouse();
+
+ _buttonValue = _buttons[i]._value;
+ break;
+ }
+ }
+
+ if (!_buttonValue && Common::Rect(8, 8, 224, 135).contains(pt)) {
+ _buttonValue = 1;
+ return true;
+ }
+ } else if (events.isKeyPending()) {
+ Common::KeyState keyState;
+ events.getKey(keyState);
+
+ _buttonValue = keyState.keycode;
+ if (_buttonValue == Common::KEYCODE_KP8)
+ _buttonValue = Common::KEYCODE_UP;
+ else if (_buttonValue == Common::KEYCODE_KP2)
+ _buttonValue = Common::KEYCODE_DOWN;
+ else if (_buttonValue == Common::KEYCODE_KP_ENTER)
+ _buttonValue = Common::KEYCODE_RETURN;
+
+ _buttonValue |= (keyState.flags & ~Common::KBD_STICKY) << 16;
+ }
+
+ if (_buttonValue) {
+ // Check for a button matching the selected _buttonValue
+ Window &win = windows[39];
+ for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+ UIButton &btn = _buttons[btnIndex];
+ if (btn._draw && btn._value == _buttonValue) {
+ // Found the correct button
+ // Draw button depressed
+ btn._sprites->draw(0, btn._frameNum + 1,
+ Common::Point(btn._bounds.left, btn._bounds.top));
+ win.setBounds(btn._bounds);
+ win.update();
+
+ // Slight delay
+ events.updateGameCounter();
+ events.wait(2);
+
+ // Redraw button in it's original non-depressed form
+ btn._sprites->draw(0, btn._frameNum,
+ Common::Point(btn._bounds.left, btn._bounds.top));
+ win.setBounds(btn._bounds);
+ win.update();
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void ButtonContainer::drawButtons(XSurface *surface) {
+ for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+ UIButton &btn = _buttons[btnIndex];
+ if (btn._draw) {
+ btn._sprites->draw(*surface, btn._frameNum,
+ Common::Point(btn._bounds.left, btn._bounds.top));
+ }
+ }
+}
+
+bool ButtonContainer::doScroll(bool rollUp, bool fadeIn) {
+ if (_vm->_files->_isDarkCc) {
+ return Cutscenes::doScroll(rollUp, fadeIn);
+ } else {
+ saveButtons();
+ clearButtons();
+ bool result = Cutscenes::doScroll(rollUp, fadeIn);
+ restoreButtons();
+ return result;
+ }
+}
+
+void ButtonContainer::loadStrings(const Common::String &name) {
+ File f(name);
+ _textStrings.clear();
+ while (f.pos() < f.size())
+ _textStrings.push_back(f.readString());
+ f.close();
+}
+
+void ButtonContainer::loadStrings(const Common::String &name, int ccMode) {
+ File f(name, ccMode);
+ _textStrings.clear();
+ while (f.pos() < f.size())
+ _textStrings.push_back(f.readString());
+ f.close();
+}
+
+/*------------------------------------------------------------------------*/
+
+void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
+ _vm->_events->pollEventsAndWait();
+ checkEvents(_vm);
+}
+
+/*------------------------------------------------------------------------*/
+
+void CreditsScreen::show(XeenEngine *vm) {
+ CreditsScreen *dlg = new CreditsScreen(vm);
+
+ switch (vm->getGameID()) {
+ case GType_Clouds:
+ dlg->execute(Res.CLOUDS_CREDITS);
+ break;
+ case GType_Swords:
+ dlg->execute(Res.SWORDS_CREDITS1);
+ dlg->execute(Res.SWORDS_CREDITS2);
+ break;
+ default:
+ dlg->execute(Res.DARK_SIDE_CREDITS);
+ break;
+ }
+
+ delete dlg;
+}
+
+void CreditsScreen::execute(const char *content) {
+ Screen &screen = *_vm->_screen;
+ Windows &windows = *_vm->_windows;
+ EventsManager &events = *_vm->_events;
+
+ // Handle drawing the credits screen
+ doScroll(true, false);
+ windows[GAME_WINDOW].close();
+
+ screen.loadBackground("marb.raw");
+ windows[0].writeString(content);
+ doScroll(false, false);
+
+ events.setCursor(0);
+ windows[0].update();
+ clearButtons();
+
+ // Wait for keypress
+ while (!events.isKeyMousePressed())
+ events.pollEventsAndWait();
+
+ doScroll(true, false);
+}
+
+/*------------------------------------------------------------------------*/
+
+PleaseWait::PleaseWait(bool isOops) {
+ _msg = isOops ? Res.OOPS : Res.PLEASE_WAIT;
+}
+
+PleaseWait::~PleaseWait() {
+ Windows &windows = *g_vm->_windows;
+ windows[9].close();
+}
+
+void PleaseWait::show() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[9];
+
+ if (g_vm->_mode != MODE_0) {
+ w.open();
+ w.writeString(_msg);
+ w.update();
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs.h b/engines/xeen/dialogs/dialogs.h
new file mode 100644
index 0000000..cabc921
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs.h
@@ -0,0 +1,137 @@
+/* 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 XEEN_DIALOGS_H
+#define XEEN_DIALOGS_H
+
+#include "common/array.h"
+#include "common/stack.h"
+#include "common/rect.h"
+#include "xeen/cutscenes.h"
+#include "xeen/sprites.h"
+#include "xeen/xsurface.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class UIButton {
+public:
+ Common::Rect _bounds;
+ SpriteResource *_sprites;
+ int _value;
+ uint _frameNum;
+ bool _draw;
+
+ UIButton(const Common::Rect &bounds, int value, uint frameNum, SpriteResource *sprites, bool draw) :
+ _bounds(bounds), _value(value), _frameNum(frameNum),
+ _sprites(sprites), _draw(draw) {}
+
+ UIButton() : _value(0), _frameNum(0), _sprites(nullptr), _draw(false) {}
+};
+
+class ButtonContainer : public Cutscenes {
+private:
+ Common::Stack< Common::Array<UIButton> > _savedButtons;
+protected:
+ Common::Array<UIButton> _buttons;
+ Common::StringArray _textStrings;
+ int _buttonValue;
+
+ bool checkEvents(XeenEngine *vm);
+
+ /**
+ * Draws the scroll in the background
+ * @param rollUp If true, rolls up the scroll. If false, unrolls.
+ * @param fadeIn If true, does an initial fade in
+ * @returns True if key or mouse pressed
+ */
+ virtual bool doScroll(bool rollUp, bool fadeIn);
+
+ /**
+ * Load a set of text strings from the given resource
+ * @param name Name of resource containing strings
+ */
+ void loadStrings(const Common::String &name);
+
+ /**
+ * Load a set of text strings from the given resource
+ * @param name Name of resource containing strings
+ * @param ccMode Optional cc file number to explicitly use
+ */
+ void loadStrings(const Common::String &name, int ccMode);
+public:
+ ButtonContainer(XeenEngine *vm) : Cutscenes(vm), _buttonValue(0) {}
+
+ /**
+ * Saves the current list of buttons
+ */
+ void saveButtons();
+
+ void clearButtons();
+
+ void restoreButtons();
+
+ void addButton(const Common::Rect &bounds, int val,
+ SpriteResource *sprites = nullptr);
+ void addButton(const Common::Rect &bounds, int val,
+ int frameNum, SpriteResource *sprites = nullptr);
+
+ void addPartyButtons(XeenEngine *vm);
+
+ /**
+ * Draws the buttons onto the passed surface
+ */
+ void drawButtons(XSurface *surface);
+};
+
+class SettingsBaseDialog : public ButtonContainer {
+protected:
+ virtual void showContents(SpriteResource &title1, bool mode);
+public:
+ SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ virtual ~SettingsBaseDialog() {}
+};
+
+class CreditsScreen: public ButtonContainer {
+private:
+ CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(const char *content);
+public:
+ static void show(XeenEngine *vm);
+};
+
+class PleaseWait {
+private:
+ Common::String _msg;
+public:
+ PleaseWait(bool isOops = false);
+ ~PleaseWait();
+
+ void show();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs/dialogs_awards.cpp b/engines/xeen/dialogs/dialogs_awards.cpp
new file mode 100644
index 0000000..8e8bfcf
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_awards.cpp
@@ -0,0 +1,131 @@
+/* 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 "xeen/dialogs/dialogs_awards.h"
+#include "xeen/party.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void Awards::show(XeenEngine *vm, const Character *ch) {
+ Awards *dlg = new Awards(vm);
+ dlg->execute(ch);
+ delete dlg;
+}
+
+void Awards::execute(const Character *ch) {
+ EventsManager &events = *g_vm->_events;
+ Windows &windows = *g_vm->_windows;
+ Common::StringArray awards;
+ int numAwards;
+ Mode oldMode = g_vm->_mode;
+ int topIndex = 0;
+
+ loadStrings("award.bin", 1);
+ addButtons();
+
+ // Open the window and draw contents
+ bool win29Open = windows[29]._enabled;
+ if (!win29Open) {
+ windows[29].open();
+ windows[30].open();
+ }
+
+ windows[29].writeString(Res.AWARDS_TEXT);
+ drawButtons(&windows[0]);
+
+ while (!_vm->shouldExit()) {
+ // Build up a list of awards the character has
+ awards.clear();
+ awards.resize(AWARDS_TOTAL);
+ numAwards = 0;
+
+ for (int awardNum = 0; awardNum < AWARDS_TOTAL; ++awardNum) {
+ if (ch->hasAward(awardNum)) {
+ if (awardNum == 9) {
+ // # Warzone Wins
+ awards[numAwards] = Common::String::format(_textStrings[9].c_str(), 28);
+ } else if (awardNum == 17) {
+ // Legendary Race
+ awards[numAwards] = Common::String::format(_textStrings[17].c_str(),
+ Res.RACE_NAMES[ch->_race]);
+ } else {
+ awards[numAwards] = _textStrings[awardNum];
+ }
+ ++numAwards;
+ }
+ }
+
+ // If no awards, add in a message indicating so
+ if (numAwards == 0) {
+ awards[1] = Res.NO_AWARDS;
+ }
+
+ Common::String msg = Common::String::format(Res.AWARDS_FOR,
+ ch->_name.c_str(), Res.CLASS_NAMES[ch->_class],
+ awards[topIndex].c_str(),
+ awards[topIndex + 1].c_str(),
+ awards[topIndex + 2].c_str(),
+ awards[topIndex + 3].c_str(),
+ awards[topIndex + 4].c_str(),
+ awards[topIndex + 5].c_str(),
+ awards[topIndex + 6].c_str(),
+ awards[topIndex + 7].c_str(),
+ awards[topIndex + 8].c_str()
+ );
+ windows[30].writeString(msg);
+ windows[24].update();
+
+ // Wait for keypress
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!g_vm->shouldExit() && !_buttonValue);
+
+ if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ break;
+ } else if (_buttonValue == Common::KEYCODE_u) {
+ topIndex = MAX(topIndex - 1, 0);
+ } else if (_buttonValue == Common::KEYCODE_d) {
+ if ((++topIndex + 9) > numAwards)
+ --topIndex;
+ }
+ }
+
+ // Close the window
+ if (win29Open) {
+ windows[30].close();
+ windows[29].close();
+ }
+
+ g_vm->_mode = oldMode;
+}
+
+void Awards::addButtons() {
+ _iconSprites.load("award.icn");
+ addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_u, &_iconSprites);
+ addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_d, &_iconSprites);
+ addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_awards.h b/engines/xeen/dialogs/dialogs_awards.h
new file mode 100644
index 0000000..2ca6817
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_awards.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 XEEN_DIALOGS_AWARDS_H
+#define XEEN_DIALOGS_AWARDS_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/character.h"
+
+namespace Xeen {
+
+class Awards : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+private:
+ Awards(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ /**
+ * Executes the dialog
+ */
+ void execute(const Character *ch);
+
+ /**
+ * Add buttons for the dialog
+ */
+ void addButtons();
+public:
+ static void show(XeenEngine *vm, const Character *ch);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_AWARDS_H */
diff --git a/engines/xeen/dialogs/dialogs_char_info.cpp b/engines/xeen/dialogs/dialogs_char_info.cpp
new file mode 100644
index 0000000..0ae64ed
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_char_info.cpp
@@ -0,0 +1,571 @@
+/* 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 "xeen/dialogs/dialogs_awards.h"
+#include "xeen/dialogs/dialogs_char_info.h"
+#include "xeen/dialogs/dialogs_exchange.h"
+#include "xeen/dialogs/dialogs_items.h"
+#include "xeen/dialogs/dialogs_quick_ref.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void CharacterInfo::show(XeenEngine *vm, int charIndex) {
+ CharacterInfo *dlg = new CharacterInfo(vm);
+ dlg->execute(charIndex);
+ delete dlg;
+}
+
+void CharacterInfo::execute(int charIndex) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+
+ bool redrawFlag = true;
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_CHARACTER_INFO;
+ loadDrawStructs();
+ addButtons();
+
+ Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
+ intf.highlightChar(charIndex);
+ Window &w = windows[24];
+ w.open();
+
+ do {
+ if (redrawFlag) {
+ Common::String charDetails = loadCharacterDetails(*c);
+ w.writeString(Common::String::format(Res.CHARACTER_TEMPLATE, charDetails.c_str()));
+ w.drawList(_drawList, 24);
+ w.update();
+ redrawFlag = false;
+ }
+
+ // Wait for keypress, showing a blinking cursor
+ events.updateGameCounter();
+ bool cursorFlag = false;
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue) {
+ events.pollEventsAndWait();
+ if (events.timeElapsed() > 4) {
+ cursorFlag = !cursorFlag;
+ events.updateGameCounter();
+ }
+
+ showCursor(cursorFlag);
+ w.update();
+ checkEvents(_vm);
+ }
+ events.clearEvents();
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)(oldMode == MODE_COMBAT ? combat._combatParty.size() : party._activeParty.size())) {
+ charIndex = _buttonValue;
+ c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
+ } else {
+ _vm->_mode = MODE_CHARACTER_INFO;
+ }
+
+ intf.highlightChar(_buttonValue);
+ redrawFlag = true;
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ if (_cursorCell > 0) {
+ showCursor(false);
+ --_cursorCell;
+ showCursor(true);
+ }
+ w.update();
+ break;
+
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ if (_cursorCell < 20) {
+ showCursor(false);
+ ++_cursorCell;
+ showCursor(true);
+ }
+ w.update();
+ break;
+
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_KP4:
+ if (_cursorCell >= 5) {
+ showCursor(false);
+ _cursorCell -= 5;
+ showCursor(true);
+ }
+ w.update();
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_KP6:
+ if (_cursorCell <= 15) {
+ showCursor(false);
+ _cursorCell += 5;
+ showCursor(true);
+ }
+ w.update();
+ break;
+
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ _buttonValue = _cursorCell + Common::KEYCODE_a;
+ // Deliberate fall-through
+
+ case 1001:
+ case 1002:
+ case 1003:
+ case 1004:
+ case 1005:
+ case 1006:
+ case 1007:
+ case 1008:
+ case 1009:
+ case 1010:
+ case 1011:
+ case 1012:
+ case 1013:
+ case 1014:
+ case 1015:
+ case 1016:
+ case 1017:
+ case 1018:
+ case 1019:
+ case 1020: {
+ showCursor(false);
+ _cursorCell = _buttonValue - 1001;
+ showCursor(true);
+ w.update();
+
+ bool result = expandStat(_cursorCell, *c);
+ _vm->_mode = MODE_COMBAT;
+ if (result)
+ redrawFlag = true;
+ break;
+ }
+
+ case Common::KEYCODE_e:
+ if (oldMode == MODE_COMBAT) {
+ ErrorScroll::show(_vm, Res.EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT);
+ } else {
+ _vm->_mode = oldMode;
+ ExchangeDialog::show(_vm, c, charIndex);
+ _vm->_mode = MODE_CHARACTER_INFO;
+ redrawFlag = true;
+ }
+ break;
+
+ case Common::KEYCODE_i:
+ _vm->_mode = oldMode;
+ _vm->_combat->_itemFlag = _vm->_mode == MODE_COMBAT;
+ c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO);
+
+ if (!c) {
+ party._stepped = true;
+ goto exit;
+ }
+
+ _vm->_mode = MODE_CHARACTER_INFO;
+ break;
+
+ case Common::KEYCODE_q:
+ QuickReferenceDialog::show(_vm);
+ redrawFlag = true;
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ goto exit;
+ }
+ } while (!_vm->shouldExit());
+exit:
+ w.close();
+ intf.unhighlightChar();
+ _vm->_mode = oldMode;
+ _vm->_combat->_itemFlag = false;
+}
+
+void CharacterInfo::loadDrawStructs() {
+ _drawList[0] = DrawStruct(0, 2, 16);
+ _drawList[1] = DrawStruct(2, 2, 39);
+ _drawList[2] = DrawStruct(4, 2, 62);
+ _drawList[3] = DrawStruct(6, 2, 85);
+ _drawList[4] = DrawStruct(8, 2, 108);
+ _drawList[5] = DrawStruct(10, 53, 16);
+ _drawList[6] = DrawStruct(12, 53, 39);
+ _drawList[7] = DrawStruct(14, 53, 62);
+ _drawList[8] = DrawStruct(16, 53, 85);
+ _drawList[9] = DrawStruct(18, 53, 108);
+ _drawList[10] = DrawStruct(20, 104, 16);
+ _drawList[11] = DrawStruct(22, 104, 39);
+ _drawList[12] = DrawStruct(24, 104, 62);
+ _drawList[13] = DrawStruct(26, 104, 85);
+ _drawList[14] = DrawStruct(28, 104, 108);
+ _drawList[15] = DrawStruct(30, 169, 16);
+ _drawList[16] = DrawStruct(32, 169, 39);
+ _drawList[17] = DrawStruct(34, 169, 62);
+ _drawList[18] = DrawStruct(36, 169, 85);
+ _drawList[19] = DrawStruct(38, 169, 108);
+ _drawList[20] = DrawStruct(40, 277, 3);
+ _drawList[21] = DrawStruct(42, 277, 35);
+ _drawList[22] = DrawStruct(44, 277, 67);
+ _drawList[23] = DrawStruct(46, 277, 99);
+
+ _iconSprites.load("view.icn");
+ for (int idx = 0; idx < 24; ++idx)
+ _drawList[idx]._sprites = &_iconSprites;
+}
+
+void CharacterInfo::addButtons() {
+ addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites);
+ addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites);
+ addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites);
+ addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites);
+ addButton(Common::Rect(10, 116, 34, 136), 1005, &_iconSprites);
+ addButton(Common::Rect(61, 24, 85, 44), 1006, &_iconSprites);
+ addButton(Common::Rect(61, 47, 85, 67), 1007, &_iconSprites);
+ addButton(Common::Rect(61, 70, 85, 90), 1008, &_iconSprites);
+ addButton(Common::Rect(61, 93, 85, 113), 1009, &_iconSprites);
+ addButton(Common::Rect(61, 116, 85, 136), 1010, &_iconSprites);
+ addButton(Common::Rect(112, 24, 136, 44), 1011, &_iconSprites);
+ addButton(Common::Rect(112, 47, 136, 67), 1012, &_iconSprites);
+ addButton(Common::Rect(112, 70, 136, 90), 1013, &_iconSprites);
+ addButton(Common::Rect(112, 93, 136, 113), 1014, &_iconSprites);
+ addButton(Common::Rect(112, 116, 136, 136), 1015, &_iconSprites);
+ addButton(Common::Rect(177, 24, 201, 44), 1016, &_iconSprites);
+ addButton(Common::Rect(177, 47, 201, 67), 1017, &_iconSprites);
+ addButton(Common::Rect(177, 70, 201, 90), 1018, &_iconSprites);
+ addButton(Common::Rect(177, 93, 201, 113), 1019, &_iconSprites);
+ addButton(Common::Rect(177, 116, 201, 136), 1020, &_iconSprites);
+ addButton(Common::Rect(285, 11, 309, 31), Common::KEYCODE_i, &_iconSprites);
+ addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites);
+ addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addPartyButtons(_vm);
+}
+
+Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
+ Condition condition = c.worstCondition();
+ Party &party = *_vm->_party;
+ int foodVal = party._food / party._activeParty.size() / 3;
+
+ int totalResist =
+ c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary +
+ c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary +
+ c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary +
+ c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary +
+ c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary +
+ c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary;
+
+ return Common::String::format(Res.CHARACTER_DETAILS,
+ Res.PARTY_GOLD, c._name.c_str(), Res.SEX_NAMES[c._sex],
+ Res.RACE_NAMES[c._race], Res.CLASS_NAMES[c._class],
+ c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT),
+ c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY),
+ c.statColor(c._currentHp, c.getMaxHP()), c._currentHp,
+ c.getCurrentExperience(),
+ c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT),
+ c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK),
+ c.statColor(c._currentSp, c.getMaxSP()), c._currentSp,
+ party._gold,
+ c.statColor(c.getStat(PERSONALITY), c.getStat(PERSONALITY, true)), c.getStat(PERSONALITY),
+ c.statColor(c.getAge(), c.getAge(true)), c.getAge(),
+ totalResist,
+ party._gems,
+ c.statColor(c.getStat(ENDURANCE), c.getStat(ENDURANCE, true)), c.getStat(ENDURANCE),
+ c.statColor(c.getCurrentLevel(), c._level._permanent), c.getCurrentLevel(),
+ c.getNumSkills(),
+ foodVal, (foodVal == 1) ? ' ' : 's',
+ c.statColor(c.getStat(SPEED), c.getStat(SPEED, true)), c.getStat(SPEED),
+ c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(),
+ c.getNumAwards(),
+ Res.CONDITION_COLORS[condition], Res.CONDITION_NAMES[condition],
+ condition == NO_CONDITION && party._blessed ? Res.PLUS_14 : "",
+ condition == NO_CONDITION && party._powerShield ? Res.PLUS_14 : "",
+ condition == NO_CONDITION && party._holyBonus ? Res.PLUS_14 : "",
+ condition == NO_CONDITION && party._heroism ? Res.PLUS_14 : ""
+ );
+}
+
+void CharacterInfo::showCursor(bool flag) {
+ const int CURSOR_X[5] = { 9, 60, 111, 176, 0 };
+ const int CURSOR_Y[5] = { 23, 46, 69, 92, 115 };
+
+ if (_cursorCell < 20) {
+ _iconSprites.draw(0, flag ? 49 : 48,
+ Common::Point(CURSOR_X[_cursorCell / 5], CURSOR_Y[_cursorCell % 5]));
+ }
+}
+
+bool CharacterInfo::expandStat(int attrib, const Character &c) {
+ const int STAT_POS[2][20] = {
+ {
+ 61, 61, 61, 61, 61, 112, 112, 112, 112, 112,
+ 177, 177, 177, 177, 177, 34, 34, 34, 34, 34
+ }, {
+ 24, 47, 70, 93, 116, 24, 47, 70, 93, 116,
+ 24, 47, 70, 93, 116, 24, 47, 70, 93, 116
+ }
+ };
+ assert(attrib < 20);
+ Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
+ STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ uint stat1, stat2;
+ uint idx;
+ Common::String msg;
+
+ switch (attrib) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ // Basic attributes
+ stat1 = c.getStat((Attribute)attrib, false);
+ stat2 = c.getStat((Attribute)attrib, true);
+ idx = 0;
+ while (Res.STAT_VALUES[idx] <= (int)stat1)
+ ++idx;
+
+ msg = Common::String::format(Res.CURRENT_MAXIMUM_RATING_TEXT, Res.STAT_NAMES[attrib],
+ stat1, stat2, Res.RATING_TEXT[idx]);
+ break;
+
+ case 7:
+ // Age
+ stat1 = c.getAge(false);
+ stat2 = c.getAge(true);
+ msg = Common::String::format(Res.AGE_TEXT, Res.STAT_NAMES[attrib],
+ stat1, stat2, c._birthDay, c._birthYear);
+ break;
+
+ case 8: {
+ // Level
+ const int CLASS_ATTACK_GAINS[10] = { 5, 6, 6, 7, 8, 6, 5, 4, 7, 6 };
+ idx = c.getCurrentLevel() / CLASS_ATTACK_GAINS[c._class] + 1;
+
+ msg = Common::String::format(Res.LEVEL_TEXT, Res.STAT_NAMES[attrib],
+ c.getCurrentLevel(), c._level._permanent,
+ idx, idx > 1 ? "s" : "",
+ c._level._permanent);
+ break;
+ }
+
+ case 9:
+ // Armor Class
+ stat1 = c.getArmorClass(false);
+ stat2 = c.getArmorClass(true);
+ msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
+ stat1, stat2);
+ bounds.setHeight(42);
+ break;
+
+ case 10:
+ // Hit Points
+ stat1 = c._currentHp;
+ stat2 = c.getMaxHP();
+ msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
+ stat1, stat2);
+ bounds.setHeight(42);
+ break;
+
+ case 11:
+ // Spell Points
+ stat1 = c._currentSp;
+ stat2 = c.getMaxSP();
+ msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
+ stat1, stat2);
+ bounds.setHeight(42);
+ break;
+
+ case 12:
+ // Resistences
+ msg = Common::String::format(Res.RESISTENCES_TEXT, Res.STAT_NAMES[attrib],
+ c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary,
+ c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary,
+ c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary,
+ c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary,
+ c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary,
+ c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary);
+ bounds.setHeight(80);
+ break;
+
+ case 13: {
+ // Skills
+ Common::String lines[20];
+ int numLines = c.getNumSkills();
+ if (numLines > 0) {
+ for (int skill = THIEVERY; skill <= DANGER_SENSE; ++skill) {
+ if (c._skills[skill]) {
+ if (skill == THIEVERY) {
+ lines[0] = Common::String::format("\n\t020%s%u",
+ Res.SKILL_NAMES[THIEVERY], c.getThievery());
+ } else {
+ lines[skill] = Common::String::format("\n\t020%s", Res.SKILL_NAMES[skill]);
+ }
+ }
+ }
+ } else {
+ lines[0] = Res.NONE;
+ numLines = 1;
+ }
+
+ msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ Res.STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(),
+ lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
+ lines[17].c_str(), lines[6].c_str(), lines[7].c_str(), lines[8].c_str(),
+ lines[9].c_str(), lines[10].c_str(), lines[11].c_str(), lines[12].c_str(),
+ lines[13].c_str(), lines[16].c_str(), lines[14].c_str(), lines[15].c_str());
+
+ bounds.top -= (numLines / 2) * 8;
+ bounds.setHeight(numLines * 9 + 26);
+ if (bounds.bottom >= SCREEN_HEIGHT)
+ bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
+ break;
+ }
+
+ case 14:
+ // Awards
+ Awards::show(_vm, &c);
+ return false;
+
+ case 15:
+ // Experience
+ stat1 = c.getCurrentExperience();
+ stat2 = c.experienceToNextLevel();
+ msg = Common::String::format(Res.EXPERIENCE_TEXT,
+ Res.STAT_NAMES[attrib], stat1,
+ stat2 == 0 ? Res.ELIGIBLE : Common::String::format("%d", stat2).c_str()
+ );
+ bounds.setHeight(43);
+ break;
+
+ case 16:
+ // Gold
+ msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[0],
+ party._gold, party._bankGold);
+ bounds.setHeight(43);
+ break;
+
+ case 17:
+ // Gems
+ msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[1],
+ party._gems, party._bankGems);
+ bounds.setHeight(43);
+ break;
+
+ case 18: {
+ // Food
+ int food = (party._food / party._activeParty.size()) / 3;
+ msg = Common::String::format(Res.FOOD_TEXT, Res.CONSUMABLE_NAMES[2],
+ party._food, food, food != 1 ? "s" : "");
+ break;
+ }
+
+ case 19: {
+ // Conditions
+ Common::String lines[20];
+ int total = 0;
+ for (int condition = CURSED; condition <= ERADICATED; ++condition) {
+ if (c._conditions[condition]) {
+ if (condition >= UNCONSCIOUS) {
+ lines[condition] = Common::String::format("\n\t020%s",
+ Res.CONDITION_NAMES[condition]);
+ } else {
+ lines[condition] = Common::String::format("\n\t020%s\t095-%d",
+ Res.CONDITION_NAMES[condition], c._conditions[condition]);
+ }
+
+ ++total;
+ }
+ }
+
+ Condition condition = c.worstCondition();
+ if (condition == NO_CONDITION) {
+ lines[0] = Common::String::format("\n\t020%s", Res.GOOD);
+ ++total;
+ }
+
+ if (party._blessed)
+ lines[16] = Common::String::format(Res.BLESSED, party._blessed);
+ if (party._powerShield)
+ lines[17] = Common::String::format(Res.POWER_SHIELD, party._powerShield);
+ if (party._holyBonus)
+ lines[18] = Common::String::format(Res.HOLY_BONUS, party._holyBonus);
+ if (party._heroism)
+ lines[19] = Common::String::format(Res.HEROISM, party._heroism);
+
+ msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1",
+ Res.CONSUMABLE_NAMES[3], lines[0].c_str(), lines[1].c_str(),
+ lines[2].c_str(), lines[3].c_str(), lines[4].c_str(),
+ lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str(), lines[9].c_str(), lines[10].c_str(),
+ lines[11].c_str(), lines[12].c_str(), lines[13].c_str(),
+ lines[14].c_str(), lines[15].c_str(), lines[16].c_str(),
+ lines[17].c_str(), lines[18].c_str(), lines[19].c_str()
+ );
+
+ bounds.top -= ((total - 1) / 2) * 8;
+ bounds.setHeight(total * 9 + 26);
+ if (bounds.bottom >= SCREEN_HEIGHT)
+ bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // Write the data for the stat display
+ Window &w = windows[28];
+ w.setBounds(bounds);
+ w.open();
+ w.writeString(msg);
+ w.update();
+
+ // Wait for a user key/click
+ EventsManager &events = *_vm->_events;
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ events.clearEvents();
+
+ w.close();
+ return false;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_char_info.h b/engines/xeen/dialogs/dialogs_char_info.h
new file mode 100644
index 0000000..6dc7eaa
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_char_info.h
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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 XEEN_DIALOGS_CHAR_INFO_H
+#define XEEN_DIALOGS_CHAR_INFO_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+#include "xeen/window.h"
+
+namespace Xeen {
+
+class CharacterInfo : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ DrawStruct _drawList[24];
+ int _cursorCell;
+
+ CharacterInfo(XeenEngine *vm) : ButtonContainer(vm), _cursorCell(0) {}
+
+ void execute(int charIndex);
+
+ /**
+ * Load the draw structure list with frame numbers and positions
+ */
+ void loadDrawStructs();
+
+ /**
+ * Set up the button list for the dialog
+ */
+ void addButtons();
+
+ /**
+ * Return a string containing the details of the character
+ */
+ Common::String loadCharacterDetails(const Character &c);
+
+ /**
+ * Cursor display handling
+ */
+ void showCursor(bool flag);
+
+ bool expandStat(int attrib, const Character &c);
+public:
+ static void show(XeenEngine *vm, int charIndex);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CHAR_INFO_H */
diff --git a/engines/xeen/dialogs/dialogs_control_panel.cpp b/engines/xeen/dialogs/dialogs_control_panel.cpp
new file mode 100644
index 0000000..9c933b3
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_control_panel.cpp
@@ -0,0 +1,220 @@
+/* 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 "xeen/dialogs/dialogs_control_panel.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/party.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int ControlPanel::show(XeenEngine *vm) {
+ ControlPanel *dlg = new ControlPanel(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+int ControlPanel::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ SavesManager &saves = *_vm->_saves;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[23];
+ Window &w3 = windows[3];
+
+ loadButtons();
+
+ int result = 0, debugCtr = 0;
+ w.open();
+
+ do {
+ Common::String btnText = getButtonText();
+ Common::String text = Common::String::format(Res.CONTROL_PANEL_TEXT, btnText.c_str());
+
+ drawButtons(&w);
+ w.writeString(text);
+ w.writeString("\xB""000\t000\x1");
+ w.update();
+
+ do {
+ events.updateGameCounter();
+ intf.draw3d(false, false);
+ w.writeString("\r");
+ drawButtons(&w);
+ w.writeString(text);
+ w.writeString("\v000\t000");
+ w.frame();
+
+ if (_debugFlag)
+ w.writeString(getTimeText());
+
+ w3.update();
+ w.update();
+
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ if (_vm->shouldExit())
+ return 0;
+ } while (!_buttonValue && !events.timeElapsed());
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_q:
+ if (Confirm::show(g_vm, Res.CONFIRM_QUIT)) {
+ g_vm->_gameMode = GMODE_QUIT;
+ result = 1;
+ }
+ break;
+
+ case Common::KEYCODE_w:
+ if (Confirm::show(g_vm, Res.MR_WIZARD)) {
+ w.close();
+ if (!windows[2]._enabled) {
+ sound.playFX(51);
+
+ if (g_vm->getGameID() == GType_WorldOfXeen) {
+ map._loadDarkSide = false;
+ map.load(28);
+ party._mazeDirection = DIR_EAST;
+ } else {
+ map._loadDarkSide = true;
+ map.load(29);
+ party._mazeDirection = DIR_SOUTH;
+ }
+ party.moveToRunLocation();
+ }
+
+ party._gems = 0;
+ result = 2;
+ }
+ break;
+
+ case Common::KEYCODE_l:
+ if (_vm->_mode == MODE_COMBAT) {
+ ErrorScroll::show(_vm, Res.NO_LOADING_IN_COMBAT);
+ } else {
+ // Close dialog and show loading dialog
+ result = 3;
+ }
+ break;
+
+ case Common::KEYCODE_s:
+ if (_vm->_mode == MODE_COMBAT) {
+ ErrorScroll::show(_vm, Res.NO_SAVING_IN_COMBAT);
+ } else {
+ // Close dialog and show saving dialog
+ result = 4;
+ }
+ break;
+
+ case Common::KEYCODE_e:
+ sound.setEffectsOn(!sound._soundOn);
+ break;
+
+ case Common::KEYCODE_m:
+ sound.setMusicOn(!sound._musicOn);
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ result = 1;
+ break;
+
+ // Goober cheat sequence
+ case Common::KEYCODE_g:
+ debugCtr = 1;
+ break;
+ case Common::KEYCODE_o:
+ debugCtr = (debugCtr == 1 || debugCtr == 2) ? 2 : 0;
+ break;
+ case Common::KEYCODE_b:
+ debugCtr = (debugCtr == 2) ? 3 : 0;
+ break;
+ case Common::KEYCODE_r:
+ if (debugCtr == 3)
+ _debugFlag = true;
+ else
+ debugCtr = 0;
+ break;
+
+ default:
+ break;
+ }
+ } while (!result);
+
+ w.close();
+ intf.drawParty(true);
+
+ if (result == 3) {
+ saves.loadGame();
+ } else if (result == 4) {
+ saves.saveGame();
+ }
+
+ return result;
+}
+
+void ControlPanel::loadButtons() {
+ _iconSprites.load("cpanel.icn");
+
+ addButton(Common::Rect(214, 56, 244, 69), Common::KEYCODE_e, 0, &_iconSprites);
+ addButton(Common::Rect(214, 75, 244, 88), Common::KEYCODE_m, 0, &_iconSprites);
+ addButton(Common::Rect(135, 56, 165, 69), Common::KEYCODE_l, 0, &_iconSprites);
+ addButton(Common::Rect(135, 75, 165, 88), Common::KEYCODE_s, 0, &_iconSprites);
+
+ // For ScummVM we've merged both Save and Save As into a single
+ // save item, so we don't need this one
+ addButton(Common::Rect(), 0);
+
+ addButton(Common::Rect(135, 94, 165, 107), Common::KEYCODE_q, 0, &_iconSprites);
+ addButton(Common::Rect(175, 113, 205, 126), Common::KEYCODE_w, 0, &_iconSprites);
+}
+
+Common::String ControlPanel::getButtonText() {
+ Sound &sound = *g_vm->_sound;
+ _btnSoundText = sound._soundOn ? Res.ON : Res.OFF;
+ _btnMusicText = sound._musicOn ? Res.ON : Res.OFF;
+
+ return Common::String::format(Res.CONTROL_PANEL_BUTTONS,
+ _btnSoundText.c_str(), _btnMusicText.c_str());
+}
+
+Common::String ControlPanel::getTimeText() const {
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ Common::String timeStr = Common::String::format("%d:%.2d:%.2d%c",
+ td.tm_hour == 0 || td.tm_hour == 12 ? 12 : (td.tm_hour % 12),
+ td.tm_min, td.tm_sec, (td.tm_hour >= 12) ? 'p' : 'c');
+
+ uint32 playtime = g_vm->_events->playTime() / GAME_FRAME_RATE;
+ Common::String playtimeStr = Common::String::format("%d:%.2d:%.2d",
+ playtime / 3600, (playtime / 60) % 60, playtime % 60);
+ return Common::String::format(
+ "\x2\x3l\xB""000\t000\x4""160%s\x3r\xB""000\t000%s\x1",
+ timeStr.c_str(), playtimeStr.c_str());
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_control_panel.h b/engines/xeen/dialogs/dialogs_control_panel.h
new file mode 100644
index 0000000..5181825
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_control_panel.h
@@ -0,0 +1,66 @@
+/* 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 XEEN_DIALOGS_CONTROL_PANEL_H
+#define XEEN_DIALOGS_CONTROL_PANEL_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class ControlPanel : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ Common::String _btnSoundText, _btnMusicText;
+ bool _debugFlag;
+private:
+ ControlPanel(XeenEngine *vm) : ButtonContainer(vm), _debugFlag(false) {}
+
+ /**
+ * Inner handler for showing the dialog
+ */
+ int execute();
+
+ /**
+ * Loads the buttons for the dialog
+ */
+ void loadButtons();
+
+ /**
+ * Gets the text for the dialog buttons
+ */
+ Common::String getButtonText();
+
+ /**
+ * Gets the current time
+ */
+ Common::String getTimeText() const;
+public:
+ /**
+ * Show the control panel
+ */
+ static int show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */
diff --git a/engines/xeen/dialogs/dialogs_create_char.cpp b/engines/xeen/dialogs/dialogs_create_char.cpp
new file mode 100644
index 0000000..577ae53
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_create_char.cpp
@@ -0,0 +1,648 @@
+/* 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 "xeen/dialogs/dialogs_create_char.h"
+#include "xeen/dialogs/dialogs_input.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void CreateCharacterDialog::show(XeenEngine *vm) {
+ CreateCharacterDialog *dlg = new CreateCharacterDialog(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+CreateCharacterDialog::CreateCharacterDialog(XeenEngine *vm) : ButtonContainer(vm) {
+ Common::fill(&_attribs[0], &_attribs[TOTAL_ATTRIBUTES], 0);
+ Common::fill(&_allowedClasses[0], &_allowedClasses[TOTAL_CLASSES], false);
+ _dicePos[0] = Common::Point(20, 17);
+ _dicePos[1] = Common::Point(112, 35);
+ _dicePos[2] = Common::Point(61, 50);
+ _diceFrame[0] = 0;
+ _diceFrame[1] = 2;
+ _diceFrame[2] = 4;
+ _diceInc[0] = Common::Point(10, -10);
+ _diceInc[1] = Common::Point(-10, -10);
+ _diceInc[2] = Common::Point(-10, 10);
+
+ _dice.load("dice.vga");
+ _diceSize = _dice.getFrameSize(0);
+
+ loadButtons();
+}
+
+void CreateCharacterDialog::execute() {
+ EventsManager &events = *_vm->_events;
+ Party &party = *_vm->_party;
+ Screen &screen = *_vm->_screen;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[0];
+ Common::Array<int> freeCharList;
+ int classId = -1;
+ int selectedClass = 0;
+ bool hasFadedIn = false;
+ bool restartFlag = true;
+ Race race = HUMAN;
+ Sex sex = MALE;
+ Common::String msg, details;
+ int charIndex = 0;
+
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_4;
+
+ // Load the background
+ screen.loadBackground("create.raw");
+ events.setCursor(0);
+
+ while (!_vm->shouldExit()) {
+ if (restartFlag) {
+ // Build up list of roster slot indexes that are free
+ freeCharList.clear();
+ for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
+ if (party._roster[idx]._name.empty())
+ freeCharList.push_back(idx);
+ }
+ charIndex = 0;
+
+ if (freeCharList.size() == XEEN_TOTAL_CHARACTERS)
+ break;
+
+ // Get and race and sex for the given character
+ race = (Race)((freeCharList[charIndex] / 4) % 5);
+ sex = (Sex)(freeCharList[charIndex] & 1);
+
+ // Randomly determine attributes, and which classes they allow
+ rollAttributes();
+
+ // Get the display of the rolled character details
+ selectedClass = newCharDetails(race, sex, classId, selectedClass, details);
+ msg = Common::String::format(Res.CREATE_CHAR_DETAILS,
+ details.c_str());
+
+ // Draw the icons and the currently selected headshot
+ drawIcons();
+ party._roster[freeCharList[charIndex]]._faceSprites->draw(
+ w, 0, Common::Point(27, 102));
+
+ // Render all on-screen text
+ w.writeString(msg);
+ w.update();
+
+ // Draw the arrow for the selected class, if applicable
+ if (selectedClass != -1)
+ printSelectionArrow(selectedClass);
+
+ // Draw the dice
+ drawDice();
+ if (!hasFadedIn) {
+ screen.fadeIn();
+ hasFadedIn = true;
+ }
+
+ restartFlag = false;
+ }
+
+ // Animate the dice until a user action occurs
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue)
+ drawDice();
+
+ // Handling for different actions
+ if (_buttonValue == Common::KEYCODE_ESCAPE)
+ break;
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_UP:
+ if (charIndex == 0)
+ continue;
+
+ --charIndex;
+ race = (Race)((freeCharList[charIndex] / 4) % 5);
+ sex = (Sex)(freeCharList[charIndex] & 1);
+ break;
+
+ case Common::KEYCODE_DOWN:
+ if (++charIndex == (int)freeCharList.size()) {
+ --charIndex;
+ continue;
+ } else {
+ race = (Race)((freeCharList[charIndex] / 4) % 5);
+ sex = (Sex)(freeCharList[charIndex] & 1);
+ }
+ break;
+
+ case Common::KEYCODE_PAGEUP:
+ for (int tempClass = selectedClass - 1; tempClass >= 0; --tempClass) {
+ if (_allowedClasses[tempClass]) {
+ selectedClass = tempClass;
+ break;
+ }
+ }
+
+ printSelectionArrow(selectedClass);
+ continue;
+
+ case Common::KEYCODE_PAGEDOWN:
+ break;
+
+ case Common::KEYCODE_m:
+ case Common::KEYCODE_i:
+ case Common::KEYCODE_p:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_s:
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_l:
+ if (swapAttributes(_buttonValue)) {
+ checkClass();
+ classId = -1;
+ selectedClass = newCharDetails(race, sex, classId, selectedClass, msg);
+ }
+ break;
+
+ case 1000:
+ case 1001:
+ case 1002:
+ case 1003:
+ case 1004:
+ case 1005:
+ case 1006:
+ case 1007:
+ case 1008:
+ case 1009:
+ if (_allowedClasses[_buttonValue - 1000]) {
+ selectedClass = classId = _buttonValue - 1000;
+ }
+ break;
+
+ case Common::KEYCODE_c: {
+ _vm->_mode = MODE_FF;
+ bool result = saveCharacter(party._roster[freeCharList[charIndex]],
+ classId, race, sex);
+ _vm->_mode = MODE_4;
+
+ if (result)
+ restartFlag = true;
+ continue;
+ }
+
+ case Common::KEYCODE_RETURN:
+ classId = selectedClass;
+ break;
+
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_r:
+ // Re-roll the attributes
+ rollAttributes();
+ classId = -1;
+ break;
+
+ default:
+ // For all other keypresses, skip the code below the switch
+ // statement, and go to wait for the next key
+ continue;
+ }
+
+ if (_buttonValue != Common::KEYCODE_PAGEDOWN) {
+ selectedClass = newCharDetails(race, sex, classId, selectedClass, msg);
+
+ drawIcons2();
+ party._roster[freeCharList[charIndex]]._faceSprites->draw(w, 0,
+ Common::Point(27, 102));
+
+ w.writeString(msg);
+ w.update();
+
+ if (selectedClass != -1) {
+ printSelectionArrow(selectedClass);
+ continue;
+ }
+ }
+
+ // Move to next available class, or if the code block above resulted in
+ // selectedClass being -1, move to select the first available class
+ for (int tempClass = selectedClass + 1; tempClass <= CLASS_RANGER; ++tempClass) {
+ if (_allowedClasses[tempClass]) {
+ selectedClass = tempClass;
+ break;
+ }
+ }
+
+ printSelectionArrow(selectedClass);
+ } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ _vm->_mode = oldMode;
+}
+
+void CreateCharacterDialog::loadButtons() {
+ _icons.load("create.icn");
+
+ // Add buttons
+ addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &_icons);
+ addButton(Common::Rect(132, 128, 156, 148), Common::KEYCODE_c, &_icons);
+ addButton(Common::Rect(132, 158, 156, 178), Common::KEYCODE_ESCAPE, &_icons);
+ addButton(Common::Rect(86, 98, 110, 118), Common::KEYCODE_UP, &_icons);
+ addButton(Common::Rect(86, 120, 110, 140), Common::KEYCODE_DOWN, &_icons);
+ addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_n, nullptr);
+ addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i, nullptr);
+ addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p, nullptr);
+ addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e, nullptr);
+ addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s, nullptr);
+ addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a, nullptr);
+ addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l, nullptr);
+ addButton(Common::Rect(227, 19, 239, 29), 1000, nullptr);
+ addButton(Common::Rect(227, 30, 239, 40), 1001, nullptr);
+ addButton(Common::Rect(227, 41, 239, 51), 1002, nullptr);
+ addButton(Common::Rect(227, 52, 239, 62), 1003, nullptr);
+ addButton(Common::Rect(227, 63, 239, 73), 1004, nullptr);
+ addButton(Common::Rect(227, 74, 239, 84), 1005, nullptr);
+ addButton(Common::Rect(227, 85, 239, 95), 1006, nullptr);
+ addButton(Common::Rect(227, 96, 239, 106), 1007, nullptr);
+ addButton(Common::Rect(227, 107, 239, 117), 1008, nullptr);
+ addButton(Common::Rect(227, 118, 239, 128), 1009, nullptr);
+}
+
+void CreateCharacterDialog::drawIcons() {
+ // Draw the screen
+ _icons.draw(0, 10, Common::Point(168, 19));
+ _icons.draw(0, 12, Common::Point(168, 43));
+ _icons.draw(0, 14, Common::Point(168, 67));
+ _icons.draw(0, 16, Common::Point(168, 91));
+ _icons.draw(0, 18, Common::Point(168, 115));
+ _icons.draw(0, 20, Common::Point(168, 139));
+ _icons.draw(0, 22, Common::Point(168, 163));
+ for (int idx = 0; idx < 9; ++idx)
+ _icons.draw(0, 24 + idx * 2, Common::Point(227, 19 + 11 * idx));
+
+ for (int idx = 0; idx < 7; ++idx)
+ _icons.draw(0, 50 + idx, Common::Point(195, 31 + 24 * idx));
+
+ _icons.draw(0, 57, Common::Point(62, 148));
+ _icons.draw(0, 58, Common::Point(62, 158));
+ _icons.draw(0, 59, Common::Point(62, 168));
+ _icons.draw(0, 61, Common::Point(220, 19));
+ _icons.draw(0, 64, Common::Point(220, 155));
+ _icons.draw(0, 65, Common::Point(220, 170));
+
+ _icons.draw(0, 0, Common::Point(132, 98));
+ _icons.draw(0, 2, Common::Point(132, 128));
+ _icons.draw(0, 4, Common::Point(132, 158));
+ _icons.draw(0, 6, Common::Point(86, 98));
+ _icons.draw(0, 8, Common::Point(86, 120));
+}
+
+void CreateCharacterDialog::drawIcons2() {
+ for (int idx = 0; idx < 7; ++idx)
+ _icons.draw(0, 10 + idx * 2, Common::Point(168, 19 + idx * 24));
+ for (int idx = 0; idx < 10; ++idx)
+ _icons.draw(0, 24 + idx * 2, Common::Point(227, 19 + idx * 11));
+ for (int idx = 0; idx < 8; ++idx)
+ _icons.draw(0, 50 + idx, Common::Point(195, 31 + idx * 24));
+
+ _icons.draw(0, 57, Common::Point(62, 148));
+ _icons.draw(0, 58, Common::Point(62, 158));
+ _icons.draw(0, 59, Common::Point(62, 168));
+ _icons.draw(0, 61, Common::Point(220, 19));
+ _icons.draw(0, 64, Common::Point(220, 155));
+ _icons.draw(0, 65, Common::Point(220, 170));
+
+ _icons.draw(0, 0, Common::Point(132, 98));
+ _icons.draw(0, 2, Common::Point(132, 128));
+ _icons.draw(0, 4, Common::Point(132, 158));
+ _icons.draw(0, 6, Common::Point(86, 98));
+ _icons.draw(0, 8, Common::Point(86, 120));
+}
+
+void CreateCharacterDialog::rollAttributes() {
+ bool repeat = true;
+ do {
+ // Default all the attributes to zero
+ Common::fill(&_attribs[0], &_attribs[TOTAL_ATTRIBUTES], 0);
+
+ // Assign random amounts to each attribute
+ for (int idx1 = 0; idx1 < 3; ++idx1) {
+ for (int idx2 = 0; idx2 < TOTAL_ATTRIBUTES; ++idx2) {
+ _attribs[idx2] += _vm->getRandomNumber(10, 79) / 10;
+ }
+ }
+
+ // Check which classes are allowed based on the rolled attributes
+ checkClass();
+
+ // Only exit if the attributes allow for at least one class
+ for (int idx = 0; idx < TOTAL_CLASSES; ++idx) {
+ if (_allowedClasses[idx])
+ repeat = false;
+ }
+ } while (repeat);
+}
+
+void CreateCharacterDialog::checkClass() {
+ _allowedClasses[CLASS_KNIGHT] = _attribs[MIGHT] >= 15;
+ _allowedClasses[CLASS_PALADIN] = _attribs[MIGHT] >= 13
+ && _attribs[PERSONALITY] >= 13 && _attribs[ENDURANCE] >= 13;
+ _allowedClasses[CLASS_ARCHER] = _attribs[INTELLECT] >= 13 && _attribs[ACCURACY] >= 13;
+ _allowedClasses[CLASS_CLERIC] = _attribs[PERSONALITY] >= 13;
+ _allowedClasses[CLASS_SORCERER] = _attribs[INTELLECT] >= 13;
+ _allowedClasses[CLASS_ROBBER] = _attribs[LUCK] >= 13;
+ _allowedClasses[CLASS_NINJA] = _attribs[SPEED] >= 13 && _attribs[ACCURACY] >= 13;
+ _allowedClasses[CLASS_BARBARIAN] = _attribs[ENDURANCE] >= 15;
+ _allowedClasses[CLASS_DRUID] = _attribs[INTELLECT] >= 15 && _attribs[PERSONALITY] >= 15;
+ _allowedClasses[CLASS_RANGER] = _attribs[INTELLECT] >= 12 && _attribs[PERSONALITY] >= 12
+ && _attribs[ENDURANCE] >= 12 && _attribs[SPEED] >= 12;
+}
+
+int CreateCharacterDialog::newCharDetails(Race race, Sex sex, int classId,
+ int selectedClass, Common::String &msg) {
+ int foundClass = -1;
+ Common::String skillStr, classStr, raceSkillStr;
+
+ // If a selected class is provided, set the default skill for that class
+ if (classId != -1 && Res.NEW_CHAR_SKILLS[classId] != -1) {
+ const char *skillP = Res.SKILL_NAMES[Res.NEW_CHAR_SKILLS[classId]];
+ skillStr = Common::String(skillP, skillP + Res.NEW_CHAR_SKILLS_LEN[classId]);
+ }
+
+ // If a class is provided, set the class name
+ if (classId != -1) {
+ classStr = Common::String::format("\t062\v168%s", Res.CLASS_NAMES[classId]);
+ }
+
+ // Set up default skill for the race, if any
+ if (Res.NEW_CHAR_RACE_SKILLS[race] != -1) {
+ raceSkillStr = Res.SKILL_NAMES[Res.NEW_CHAR_RACE_SKILLS[race]];
+ }
+
+ // Set up color to use for each skill string to be displayed, based
+ // on whether each class is allowed or not for the given attributes
+ int classColors[TOTAL_CLASSES];
+ Common::fill(&classColors[0], &classColors[TOTAL_CLASSES], 0);
+ for (int classNum = CLASS_KNIGHT; classNum <= CLASS_RANGER; ++classNum) {
+ if (_allowedClasses[classNum]) {
+ if (classId == -1 && (foundClass == -1 || foundClass < classNum))
+ foundClass = classNum;
+ classColors[classNum] = 4;
+ }
+ }
+ if (classId != -1)
+ classColors[selectedClass] = 12;
+
+ // Return stats details and character class
+ msg = Common::String::format(Res.NEW_CHAR_STATS, Res.RACE_NAMES[race], Res.SEX_NAMES[sex],
+ _attribs[MIGHT], _attribs[INTELLECT], _attribs[PERSONALITY],
+ _attribs[ENDURANCE], _attribs[SPEED], _attribs[ACCURACY], _attribs[LUCK],
+ classColors[CLASS_KNIGHT], classColors[CLASS_PALADIN],
+ classColors[CLASS_ARCHER], classColors[CLASS_CLERIC],
+ classColors[CLASS_SORCERER], classColors[CLASS_ROBBER],
+ classColors[CLASS_NINJA], classColors[CLASS_BARBARIAN],
+ classColors[CLASS_DRUID], classColors[CLASS_RANGER],
+ skillStr.c_str(), raceSkillStr.c_str(), classStr.c_str()
+ );
+ return classId == -1 ? foundClass : selectedClass;
+}
+
+void CreateCharacterDialog::printSelectionArrow(int selectedClass) {
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[0];
+
+ _icons.draw(0, 61, Common::Point(220, 19));
+ _icons.draw(0, 63, Common::Point(220, selectedClass * 11 + 21));
+ w.update();
+}
+
+void CreateCharacterDialog::drawDice() {
+ EventsManager &events = *_vm->_events;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[32];
+
+ // Draw the dice area background
+ events.updateGameCounter();
+ _dice.draw(w, 7, Common::Point(12, 11));
+
+ // Iterate through each of the three dice
+ for (int diceNum = 0; diceNum < 3; ++diceNum) {
+ _diceFrame[diceNum] = (_diceFrame[diceNum] + 1) % 7;
+ _dicePos[diceNum] += _diceInc[diceNum];
+
+ if (_dicePos[diceNum].x < 13) {
+ _dicePos[diceNum].x = 13;
+ _diceInc[diceNum].x *= -1;
+ } else if (_dicePos[diceNum].x >= (163 - _diceSize.x)) {
+ _dicePos[diceNum].x = 163 - _diceSize.x;
+ _diceInc[diceNum].x *= -1;
+ }
+
+ if (_dicePos[diceNum].y < 12) {
+ _dicePos[diceNum].y = 12;
+ _diceInc[diceNum].y *= -1;
+ } else if (_dicePos[diceNum].y >= (93 - _diceSize.y)) {
+ _dicePos[diceNum].y = 93 - _diceSize.y;
+ _diceInc[diceNum].y *= -1;
+ }
+
+ _dice.draw(w, _diceFrame[diceNum], _dicePos[diceNum]);
+ }
+
+ // Wait for a single frame, checking for any events
+ w.update();
+ events.wait(1);
+ checkEvents(_vm);
+}
+
+int CreateCharacterDialog::getAttribFromKeycode(int keycode) const {
+ switch (keycode) {
+ case Common::KEYCODE_m:
+ return MIGHT;
+ case Common::KEYCODE_i:
+ return INTELLECT;
+ case Common::KEYCODE_p:
+ return PERSONALITY;
+ case Common::KEYCODE_e:
+ return ENDURANCE;
+ case Common::KEYCODE_s:
+ return SPEED;
+ case Common::KEYCODE_a:
+ return ACCURACY;
+ case Common::KEYCODE_l:
+ return LUCK;
+ default:
+ return -1;
+ }
+}
+
+bool CreateCharacterDialog::swapAttributes(int keycode) {
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[0];
+
+ int srcAttrib = getAttribFromKeycode(keycode);
+ assert(srcAttrib >= 0);
+
+ _vm->_mode = MODE_86;
+ _icons.draw(w, srcAttrib * 2 + 11, Common::Point(
+ _buttons[srcAttrib + 5]._bounds.left, _buttons[srcAttrib + 5]._bounds.top));
+ w.update();
+
+ int destAttrib = exchangeAttribute(srcAttrib);
+ if (destAttrib != -1) {
+ _icons.draw(w, destAttrib * 2 + 11, Common::Point(
+ _buttons[destAttrib + 5]._bounds.left,
+ _buttons[destAttrib + 5]._bounds.top));
+
+ SWAP(_attribs[srcAttrib], _attribs[destAttrib]);
+ return true;
+
+ } else {
+ _icons.draw(w, srcAttrib * 2 + 10, Common::Point(
+ _buttons[srcAttrib + 5]._bounds.left,
+ _buttons[srcAttrib + 5]._bounds.top));
+ w.update();
+ _vm->_mode = MODE_SLEEPING;
+ return false;
+ }
+}
+
+int CreateCharacterDialog::exchangeAttribute(int srcAttr) {
+ EventsManager &events = *_vm->_events;
+ Windows &windows = *_vm->_windows;
+ SpriteResource icons;
+ icons.load("create2.icn");
+
+ saveButtons();
+ addButton(Common::Rect(118, 58, 142, 78), Common::KEYCODE_ESCAPE, &_icons);
+ addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_m);
+ addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i);
+ addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p);
+ addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e);
+ addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s);
+ addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a);
+ addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l);
+
+ Window &w = windows[26];
+ w.open();
+ w.writeString(Common::String::format(Res.EXCHANGE_ATTR_WITH, Res.STAT_NAMES[srcAttr]));
+ icons.draw(w, 0, Common::Point(118, 58));
+ w.update();
+
+ int result = -1;
+ bool breakFlag = false;
+ while (!_vm->shouldExit() && !breakFlag) {
+ // Wait for an action
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && !_buttonValue);
+ if (_buttonValue == Common::KEYCODE_ESCAPE)
+ break;
+
+ int destAttr = getAttribFromKeycode(_buttonValue);
+
+ if (destAttr != -1 && srcAttr != destAttr) {
+ result = destAttr;
+ break;
+ }
+ }
+
+ w.close();
+ restoreButtons();
+ _buttonValue = 0;
+ return result;
+}
+
+bool CreateCharacterDialog::saveCharacter(Character &c, int classId, Race race, Sex sex) {
+ if (classId == -1) {
+ ErrorScroll::show(_vm, Res.SELECT_CLASS_BEFORE_SAVING);
+ return false;
+ }
+
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Common::String name;
+ int result;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+
+ // Prompt for a character name
+ w.open();
+ w.writeString(Res.NAME_FOR_NEW_CHARACTER);
+ saveButtons();
+ result = Input::show(_vm, &w, name, 10, 200);
+ restoreButtons();
+ w.close();
+
+ if (!result)
+ // Name aborted, so exit
+ return false;
+
+ // Save new character details
+ c.clear();
+ c._name = name;
+ c._savedMazeId = party._priorMazeId;
+ c._xeenSide = map._loadDarkSide;
+ c._sex = sex;
+ c._race = race;
+ c._class = (CharacterClass)classId;
+ c._level._permanent = isDarkCc ? 5 : 1;
+
+ c._might._permanent = _attribs[MIGHT];
+ c._intellect._permanent = _attribs[INTELLECT];
+ c._personality._permanent = _attribs[PERSONALITY];
+ c._endurance._permanent = _attribs[ENDURANCE];
+ c._speed._permanent = _attribs[SPEED];
+ c._accuracy._permanent = _attribs[ACCURACY];
+ c._luck._permanent = _attribs[LUCK];
+
+ c._magicResistence._permanent = Res.RACE_MAGIC_RESISTENCES[race];
+ c._fireResistence._permanent = Res.RACE_FIRE_RESISTENCES[race];
+ c._electricityResistence._permanent = Res.RACE_ELECTRIC_RESISTENCES[race];
+ c._coldResistence._permanent = Res.RACE_COLD_RESISTENCES[race];
+ c._energyResistence._permanent = Res.RACE_ENERGY_RESISTENCES[race];
+ c._poisonResistence._permanent = Res.RACE_POISON_RESISTENCES[race];
+
+ c._birthYear = party._year - 18;
+ c._birthDay = party._day;
+ c._hasSpells = false;
+ c._currentSpell = -1;
+
+ // Set up any default spells for the character's class
+ for (int idx = 0; idx < 4; ++idx) {
+ if (Res.NEW_CHARACTER_SPELLS[c._class][idx] != -1) {
+ c._hasSpells = true;
+ c._currentSpell = Res.NEW_CHARACTER_SPELLS[c._class][idx];
+ c._spells[c._currentSpell] = true;
+ }
+ }
+
+ int classSkill = Res.NEW_CHAR_SKILLS[c._class];
+ if (classSkill != -1)
+ c._skills[classSkill] = 1;
+
+ int raceSkill = Res.NEW_CHAR_RACE_SKILLS[c._race];
+ if (raceSkill != -1)
+ c._skills[raceSkill] = 1;
+
+ c._currentHp = c.getMaxHP();
+ c._currentSp = c.getMaxSP();
+ return true;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_create_char.h b/engines/xeen/dialogs/dialogs_create_char.h
new file mode 100644
index 0000000..dc1422e
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_create_char.h
@@ -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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_CREATE_CHAR_H
+#define XEEN_DIALOGS_CREATE_CHAR_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/character.h"
+
+namespace Xeen {
+
+class CreateCharacterDialog : public ButtonContainer {
+private:
+ SpriteResource _icons;
+ SpriteResource _dice;
+ Common::Point _diceSize;
+ int _diceFrame[3];
+ Common::Point _dicePos[3];
+ Common::Point _diceInc[3];
+ uint _attribs[TOTAL_ATTRIBUTES];
+ bool _allowedClasses[TOTAL_CLASSES];
+private:
+ /**
+ * Constructor
+ */
+ CreateCharacterDialog(XeenEngine *vm);
+
+ /**
+ * Loads the buttons for the dialog
+ */
+ void loadButtons();
+
+ /**
+ * Draws on-screen icons
+ */
+ void drawIcons();
+
+ /**
+ * Draws on-screen icons
+ */
+ void drawIcons2();
+
+ /**
+ * Animate the dice rolling around
+ */
+ void drawDice();
+
+ /**
+ * Executes the dialog
+ */
+ void execute();
+
+ /**
+ * Returns the attribute that a given keycode represents
+ */
+ int getAttribFromKeycode(int keycode) const;
+
+ /**
+ * Handles the logic for swapping attributes
+ * @param keycode Key pressed representing one of the attributes
+ * @returns True if swap occurred
+ */
+ bool swapAttributes(int keycode);
+
+ /**
+ * Exchanging two attributes for the character being rolled
+ */
+ int exchangeAttribute(int srcAttr);
+
+ /**
+ * Set a list of flags for which classes the passed attribute set meet the
+ * minimum requirements of
+ */
+ void checkClass();
+
+ /**
+ * Return details of the generated character
+ */
+ int newCharDetails(Race race, Sex sex, int classId, int selectedClass, Common::String &msg);
+
+ /**
+ * Print the selection arrow to indicate the selected class
+ */
+ void printSelectionArrow(int selectedClass);
+
+ /**
+ * Saves the rolled character into the roster
+ */
+ bool saveCharacter(Character &c, int classId, Race race, Sex sex);
+
+ /**
+ * Roll up some random values for the attributes, and return both them as
+ * well as a list of classes that the attributes meet the requirements for
+ */
+ void rollAttributes();
+public:
+ /**
+ * Shows the Create Character dialog
+ */
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CREATE_CHAR_H */
diff --git a/engines/xeen/dialogs/dialogs_difficulty.cpp b/engines/xeen/dialogs/dialogs_difficulty.cpp
new file mode 100644
index 0000000..0b024e1
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_difficulty.cpp
@@ -0,0 +1,75 @@
+/* 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 "xeen/dialogs/dialogs_difficulty.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int DifficultyDialog::show(XeenEngine *vm) {
+ DifficultyDialog *dlg = new DifficultyDialog(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+DifficultyDialog::DifficultyDialog(XeenEngine *vm) : ButtonContainer(vm) {
+ loadButtons();
+}
+
+int DifficultyDialog::execute() {
+ EventsManager &events = *_vm->_events;
+ Windows &windows = *_vm->_windows;
+
+ Window &w = windows[6];
+ w.open();
+ w.writeString(Res.DIFFICULTY_TEXT);
+ drawButtons(&w);
+
+ int result = -1;
+ while (!_vm->shouldExit()) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+
+ if (_buttonValue == Common::KEYCODE_a)
+ result = ADVENTURER;
+ else if (_buttonValue == Common::KEYCODE_w)
+ result = WARRIOR;
+ else if (_buttonValue != Common::KEYCODE_ESCAPE)
+ continue;
+
+ break;
+ }
+
+ w.close();
+ return result;
+}
+
+void DifficultyDialog::loadButtons() {
+ _sprites.load("choice.icn");
+ addButton(Common::Rect(68, 167, 158, 187), Common::KEYCODE_a, &_sprites);
+ addButton(Common::Rect(166, 167, 256, 187), Common::KEYCODE_w, &_sprites);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_difficulty.h b/engines/xeen/dialogs/dialogs_difficulty.h
new file mode 100644
index 0000000..5ff2c93
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_difficulty.h
@@ -0,0 +1,60 @@
+/* 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 XEEN_DIALOGS_DIFFICULTY_H
+#define XEEN_DIALOGS_DIFFICULTY_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class DifficultyDialog : public ButtonContainer {
+private:
+ SpriteResource _sprites;
+
+ /**
+ * Constructor
+ */
+ DifficultyDialog(XeenEngine *vm);
+
+ /**
+ * Shows the dialog
+ */
+ int execute();
+
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
+public:
+ /**
+ * Shows the difficulty selection dialog
+ * @param vm Engine reference
+ * @returns 0=Adventurer, 1=Warrior, -1 exit
+ */
+ static int show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_DIFFICULTY_H */
diff --git a/engines/xeen/dialogs/dialogs_dismiss.cpp b/engines/xeen/dialogs/dialogs_dismiss.cpp
new file mode 100644
index 0000000..716f8f0
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_dismiss.cpp
@@ -0,0 +1,95 @@
+/* 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 "xeen/dialogs/dialogs_dismiss.h"
+#include "xeen/party.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void Dismiss::show(XeenEngine *vm) {
+ Dismiss *dlg = new Dismiss(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void Dismiss::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ loadButtons();
+
+ Window &w = windows[31];
+ w.open();
+ _iconSprites.draw(w, 0, Common::Point(225, 120));
+ w.update();
+
+ bool breakFlag = false;
+ while (!_vm->shouldExit() && !breakFlag) {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(false);
+ w.frame();
+ w.writeString("\r");
+ _iconSprites.draw(w, 0, Common::Point(225, 120));
+ windows[3].update();
+ w.update();
+
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && !_buttonValue && events.timeElapsed() == 0);
+ } while (!_vm->shouldExit() && !_buttonValue);
+
+ if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+ _buttonValue -= Common::KEYCODE_F1;
+
+ if (_buttonValue < (int)party._activeParty.size()) {
+ if (party._activeParty.size() == 1) {
+ w.close();
+ ErrorScroll::show(_vm, Res.CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT);
+ w.open();
+ } else {
+ // Remove the character from the party
+ party._activeParty.remove_at(_buttonValue);
+ breakFlag = true;
+ }
+ break;
+ }
+ } else if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ breakFlag = true;
+ }
+ }
+}
+
+void Dismiss::loadButtons() {
+ _iconSprites.load("esc.icn");
+ addButton(Common::Rect(225, 120, 249, 140), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+ addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+ addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+ addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_dismiss.h b/engines/xeen/dialogs/dialogs_dismiss.h
new file mode 100644
index 0000000..832f779
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_dismiss.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 XEEN_DIALOGS_DISMISS_H
+#define XEEN_DIALOGS_DISMISS_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class Dismiss : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ Dismiss(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+
+ void loadButtons();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_DISMISS_H */
diff --git a/engines/xeen/dialogs/dialogs_exchange.cpp b/engines/xeen/dialogs/dialogs_exchange.cpp
new file mode 100644
index 0000000..87dde1b
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_exchange.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 "xeen/dialogs/dialogs_exchange.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void ExchangeDialog::show(XeenEngine *vm, Character *&c, int &charIndex) {
+ ExchangeDialog *dlg = new ExchangeDialog(vm);
+ dlg->execute(c, charIndex);
+ delete dlg;
+}
+
+void ExchangeDialog::execute(Character *&c, int &charIndex) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ loadButtons();
+
+ Window &w = windows[31];
+ w.open();
+ w.writeString(Res.EXCHANGE_WITH_WHOM);
+ _iconSprites.draw(w, 0, Common::Point(225, 120));
+ w.update();
+
+ while (!_vm->shouldExit()) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+
+ if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ SWAP(party._activeParty[charIndex], party._activeParty[_buttonValue]);
+
+ charIndex = _buttonValue;
+ c = &party._activeParty[charIndex];
+ break;
+ }
+ } else if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ break;
+ }
+ }
+
+ w.close();
+ intf.drawParty(true);
+ intf.highlightChar(charIndex);
+}
+
+void ExchangeDialog::loadButtons() {
+ _iconSprites.load("esc.icn");
+ addButton(Common::Rect(225, 120, 249, 245), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+ addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+ addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+ addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_exchange.h b/engines/xeen/dialogs/dialogs_exchange.h
new file mode 100644
index 0000000..ff7e214
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_exchange.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 XEEN_DIALOGS_EXCHANGE_H
+#define XEEN_DIALOGS_EXCHANGE_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+class ExchangeDialog : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ ExchangeDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(Character *&c, int &charIndex);
+
+ void loadButtons();
+public:
+ static void show(XeenEngine *vm, Character *&c, int &charIndex);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_EXCHANGE_H */
diff --git a/engines/xeen/dialogs/dialogs_info.cpp b/engines/xeen/dialogs/dialogs_info.cpp
new file mode 100644
index 0000000..5055853
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_info.cpp
@@ -0,0 +1,129 @@
+/* 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 "xeen/dialogs/dialogs_info.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void InfoDialog::show(XeenEngine *vm) {
+ InfoDialog *dlg = new InfoDialog(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void InfoDialog::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+
+ protectionText();
+ Common::String statusText = "";
+ for (uint idx = 0; idx < _lines.size(); ++idx)
+ statusText += _lines[idx];
+
+ Common::String gameName;
+ if (_vm->getGameID() == GType_Swords)
+ gameName = Res.SWORDS_GAME_TEXT;
+ else if (_vm->getGameID() == GType_Clouds)
+ gameName = Res.CLOUDS_GAME_TEXT;
+ else if (_vm->getGameID() == GType_DarkSide)
+ gameName = Res.DARKSIDE_GAME_TEXT;
+ else
+ gameName = Res.WORLD_GAME_TEXT;
+
+ // Form the display message
+ int hour = party._minutes / 60;
+ Common::String details = Common::String::format(Res.GAME_INFORMATION,
+ gameName.c_str(), Res.WEEK_DAY_STRINGS[party._day % 10],
+ (hour > 12) ? hour - 12 : (!hour ? 12 : hour),
+ party._minutes % 60, (hour > 11) ? 'p' : 'a',
+ party._day, party._year, statusText.c_str());
+
+ Window &w = windows[28];
+ w.setBounds(Common::Rect(88, 20, 248, 112 + (_lines.empty() ? 0 : _lines.size() * 9 + 13)));
+ w.open();
+ w.writeString(details);
+
+ do {
+ events.updateGameCounter();
+ intf.draw3d(false, false);
+ w.frame();
+ w.writeString(details);
+ w.update();
+
+ events.wait(1);
+ } while (!_vm->shouldExit() && !events.isKeyMousePressed());
+
+ events.clearEvents();
+ w.close();
+}
+
+void InfoDialog::protectionText() {
+ Party &party = *_vm->_party;
+// Common::StringArray _lines;
+ const char *const AA_L024 = "\x3l\n\x9""024";
+ const char *const AA_R124 = "\x3r\x9""124";
+
+ if (party._lightCount) {
+ _lines.push_back(Common::String::format(Res.LIGHT_COUNT_TEXT, party._lightCount));
+ }
+
+ if (party._fireResistence) {
+ _lines.push_back(Common::String::format(Res.FIRE_RESISTENCE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._fireResistence));
+ }
+
+ if (party._electricityResistence) {
+ _lines.push_back(Common::String::format(Res.ELECRICITY_RESISTENCE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._electricityResistence));
+ }
+
+ if (party._coldResistence) {
+ _lines.push_back(Common::String::format(Res.COLD_RESISTENCE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._coldResistence));
+ }
+
+ if (party._poisonResistence) {
+ _lines.push_back(Common::String::format(Res.POISON_RESISTENCE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._poisonResistence));
+ }
+
+ if (party._clairvoyanceActive) {
+ _lines.push_back(Common::String::format(Res.CLAIRVOYANCE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+ }
+
+ if (party._levitateCount) {
+ _lines.push_back(Common::String::format(Res.LEVITATE_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+ }
+
+ if (party._walkOnWaterActive) {
+ _lines.push_back(Common::String::format(Res.WALK_ON_WATER_TEXT,
+ _lines.size() == 0 ? 10 : 1, AA_L024, AA_R124));
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_info.h b/engines/xeen/dialogs/dialogs_info.h
new file mode 100644
index 0000000..fdbbc22
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_info.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 XEEN_DIALOGS_INFO_H
+#define XEEN_DIALOGS_INFO_H
+
+#include "common/str-array.h"
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class InfoDialog : public ButtonContainer {
+private:
+ Common::StringArray _lines;
+
+ InfoDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+
+ void protectionText();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_INFO_H */
diff --git a/engines/xeen/dialogs/dialogs_input.cpp b/engines/xeen/dialogs/dialogs_input.cpp
new file mode 100644
index 0000000..1d05c81
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_input.cpp
@@ -0,0 +1,323 @@
+/* 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 "xeen/dialogs/dialogs_input.h"
+#include "xeen/scripts.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int Input::show(XeenEngine *vm, Window *window, Common::String &line,
+ uint maxLen, int maxWidth, bool isNumeric) {
+ Input *dlg = new Input(vm, window);
+ int result = dlg->getString(line, maxLen, maxWidth, isNumeric);
+ delete dlg;
+
+ return result;
+}
+
+int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
+ _vm->_noDirectionSense = true;
+ Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x3""c", maxWidth);
+ _window->writeString(msg);
+ _window->update();
+
+ while (!_vm->shouldExit()) {
+ Common::KeyState keyState = waitForKey(msg);
+ const Common::KeyCode keyCode = keyState.keycode;
+
+ bool refresh = false;
+ if ((keyCode == Common::KEYCODE_BACKSPACE || keyCode == Common::KEYCODE_DELETE)
+ && line.size() > 0) {
+ line.deleteLastChar();
+ refresh = true;
+ } else if (line.size() < maxLen && (line.size() > 0 || keyCode != Common::KEYCODE_SPACE)
+ && ((isNumeric && keyState.ascii >= '0' && keyState.ascii <= '9') ||
+ (!isNumeric && keyState.ascii >= ' ' && keyState.ascii <= (char)127))) {
+ line += keyState.ascii;
+ refresh = true;
+ } else if (keyCode == Common::KEYCODE_RETURN || keyCode == Common::KEYCODE_KP_ENTER) {
+ break;
+ } else if (keyCode == Common::KEYCODE_ESCAPE) {
+ line = "";
+ break;
+ }
+
+ if (refresh) {
+ msg = Common::String::format("\x3""l\t000\x4%03d\x3""c%s", maxWidth, line.c_str());
+ _window->writeString(msg);
+ _window->update();
+ }
+ }
+
+ _vm->_noDirectionSense = false;
+ return line.size();
+}
+
+Common::KeyState Input::waitForKey(const Common::String &msg) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Windows &windows = *_vm->_windows;
+
+ bool oldUpDoorText = intf._upDoorText;
+ byte oldTillMove = intf._tillMove;
+ intf._upDoorText = false;
+ intf._tillMove = 0;
+
+ bool flag = !_vm->_startupWindowActive && !windows[25]._enabled
+ && _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
+
+ Common::KeyState ks;
+ while (!_vm->shouldExit()) {
+ events.updateGameCounter();
+
+ if (flag)
+ intf.draw3d(false);
+ _window->writeString(msg);
+ animateCursor();
+ _window->update();
+
+ if (flag)
+ windows[3].update();
+
+ events.wait(1);
+
+ if (events.isKeyPending()) {
+ events.getKey(ks);
+ break;
+ }
+ }
+
+ _window->writeString("");
+ _window->update();
+
+ intf._tillMove = oldTillMove;
+ intf._upDoorText = oldUpDoorText;
+
+ return ks;
+}
+
+void Input::animateCursor() {
+ // Iterate through each frame
+ _cursorAnimIndex = _cursorAnimIndex ? _cursorAnimIndex - 1 : 5;
+ static const char CURSOR_ANIMATION_IDS[] = { 32, 124, 126, 127, 126, 124 };
+
+ // Form a string for the cursor and write it out
+ Common::Point writePos = _window->_writePos;
+ _window->writeCharacter(CURSOR_ANIMATION_IDS[_cursorAnimIndex]);
+ _window->_writePos = writePos;
+}
+
+/*------------------------------------------------------------------------*/
+
+StringInput::StringInput(XeenEngine *vm): Input(vm, &(*vm->_windows)[6]) {
+}
+
+int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
+ const Common::String &msg2, int opcode) {
+ StringInput *dlg = new StringInput(vm);
+ int result = dlg->execute(type, msg1, msg2, opcode);
+ delete dlg;
+
+ return result;
+}
+
+int StringInput::execute(bool type, const Common::String &expected,
+ const Common::String &title, int opcode) {
+ FileManager &files = *_vm->_files;
+ Interface &intf = *_vm->_interface;
+ Scripts &scripts = *_vm->_scripts;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Sound &sound = *_vm->_sound;
+ int result = 0;
+
+ w.open();
+ w.writeString(Common::String::format("\r\x03""c%s\v024\t000", title.c_str()));
+ w.update();
+
+ Common::String line;
+ if (getString(line, 30, 200, false)) {
+ if (type) {
+ if (line == intf._interfaceText) {
+ result = true;
+ } else if (line == expected) {
+ result = (opcode == 55) ? -1 : 1;
+ }
+ } else {
+ // Load in the mirror list
+ MirrorEntry me;
+ scripts._mirror.clear();
+
+ File f(Common::String::format("%smirr.txt", files._isDarkCc ? "dark" : "xeen"), 1);
+ while (me.synchronize(f))
+ scripts._mirror.push_back(me);
+ f.close();
+
+ // Load in any extended mirror entries
+ Common::File f2;
+ if (f2.open(Common::String::format("%smirr.ext", files._isDarkCc ? "dark" : "xeen"))) {
+ while (me.synchronize(f2))
+ scripts._mirror.push_back(me);
+ f2.close();
+ }
+
+ for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
+ if (!line.compareToIgnoreCase(scripts._mirror[idx]._name)) {
+ result = idx + 1;
+ sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
+ break;
+ }
+ }
+ }
+ }
+
+ w.close();
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+NumericInput::NumericInput(XeenEngine *vm, int window) : Input(vm, &(*vm->_windows)[window]) {
+}
+
+int NumericInput::show(XeenEngine *vm, int window, int maxLength, int maxWidth) {
+ NumericInput *dlg = new NumericInput(vm, window);
+ int result = dlg->execute(maxLength, maxWidth);
+ delete dlg;
+
+ return result;
+}
+
+int NumericInput::execute(int maxLength, int maxWidth) {
+ Common::String line;
+
+ if (getString(line, maxLength, maxWidth, true))
+ return atoi(line.c_str());
+ else
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+int Choose123::show(XeenEngine *vm, int numOptions) {
+ assert(numOptions <= 3);
+ Choose123 *dlg = new Choose123(vm);
+ int result = dlg->execute(numOptions);
+ delete dlg;
+
+ return result;
+}
+
+int Choose123::execute(int numOptions) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ LocationManager &loc = *_vm->_locations;
+ Windows &windows = *_vm->_windows;
+
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_DIALOG_123;
+
+ loadButtons(numOptions);
+ _iconSprites.draw(0, 7, Common::Point(232, 74));
+ drawButtons(&windows[0]);
+ windows[34].update();
+
+ int result = -1;
+ while (result == -1) {
+ do {
+ events.updateGameCounter();
+ int delay;
+ if (loc.isActive()) {
+ loc.drawAnim(true);
+ delay = 3;
+ } else {
+ intf.draw3d(true);
+ delay = 1;
+ }
+
+ events.wait(delay);
+ if (_vm->shouldExit())
+ return 0;
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = 0;
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3: {
+ int v = _buttonValue - Common::KEYCODE_1 + 1;
+ if (v <= numOptions)
+ result = v;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ _vm->_mode = oldMode;
+ intf.mainIconsPrint();
+
+ return result;
+}
+
+void Choose123::loadButtons(int numOptions) {
+ _iconSprites.load("choose.icn");
+
+ if (numOptions >= 1)
+ addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_1, &_iconSprites);
+ if (numOptions >= 2)
+ addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_2, &_iconSprites);
+ if (numOptions >= 3)
+ addButton(Common::Rect(286, 75, 311, 95), Common::KEYCODE_3, &_iconSprites);
+}
+
+/*------------------------------------------------------------------------*/
+
+int HowMuch::show(XeenEngine *vm) {
+ HowMuch *dlg = new HowMuch(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+int HowMuch::execute() {
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Common::String num;
+
+ w.open();
+ w.writeString(Res.HOW_MUCH);
+ w.update();
+ int lineSize = Input::show(_vm, &w, num, 8, 70, true);
+ w.close();
+
+ if (!lineSize)
+ return -1;
+ return atoi(num.c_str());
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_input.h b/engines/xeen/dialogs/dialogs_input.h
new file mode 100644
index 0000000..270495f
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_input.h
@@ -0,0 +1,105 @@
+/* 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 XEEN_DIALOGS_STRING_INPUT_H
+#define XEEN_DIALOGS_STRING_INPUT_H
+
+#include "common/keyboard.h"
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/screen.h"
+
+namespace Xeen {
+
+class Input : public ButtonContainer {
+private:
+ /**
+ * Draws the text input and cursor and waits until the user presses a key
+ */
+ Common::KeyState waitForKey(const Common::String &msg);
+
+ /**
+ * Animates the box text cursor
+ */
+ void animateCursor();
+protected:
+ Window *_window;
+ int _cursorAnimIndex;
+
+ /**
+ * Allows the user to enter a string
+ */
+ int getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric);
+
+ Input(XeenEngine *vm, Window *window) : ButtonContainer(vm),
+ _window(window), _cursorAnimIndex(0) {}
+public:
+ static int show(XeenEngine *vm, Window *window, Common::String &line,
+ uint maxLen, int maxWidth, bool isNumeric = false);
+};
+
+class StringInput : public Input {
+protected:
+ StringInput(XeenEngine *vm);
+
+ int execute(bool type, const Common::String &expected,
+ const Common::String &title, int opcode);
+public:
+ static int show(XeenEngine *vm, bool type, const Common::String &msg1,
+ const Common::String &msg2, int opcode);
+};
+
+class NumericInput : public Input {
+private:
+ NumericInput(XeenEngine *vm, int window);
+
+ int execute(int maxLength, int maxWidth);
+public:
+ static int show(XeenEngine *vm, int window, int maxLength, int maxWidth);
+};
+
+class Choose123 : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ Choose123(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute(int numOptions);
+
+ void loadButtons(int numOptions);
+public:
+ static int show(XeenEngine *vm, int numOptions);
+};
+
+class HowMuch : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ HowMuch(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute();
+public:
+ static int show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_STRING_INPUT_H */
diff --git a/engines/xeen/dialogs/dialogs_items.cpp b/engines/xeen/dialogs/dialogs_items.cpp
new file mode 100644
index 0000000..0ca0fd2
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_items.cpp
@@ -0,0 +1,1066 @@
+/* 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 "xeen/dialogs/dialogs_items.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/dialogs/dialogs_quests.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) {
+ ItemsDialog *dlg = new ItemsDialog(vm);
+ Character *result = dlg->execute(c, mode);
+ delete dlg;
+
+ return result;
+}
+
+Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+
+ Character *startingChar = c;
+ ItemCategory category = mode == ITEMMODE_RECHARGE || mode == ITEMMODE_COMBAT ?
+ CATEGORY_MISC : CATEGORY_WEAPON;
+ int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
+ if (varA != 0)
+ mode = ITEMMODE_CHAR_INFO;
+ bool updateStock = mode == ITEMMODE_BLACKSMITH;
+ int itemIndex = -1;
+ Common::StringArray lines;
+ uint arr[40];
+ int actionIndex = -1;
+
+ events.setCursor(0);
+ loadButtons(mode, c);
+
+ windows[29].open();
+ windows[30].open();
+
+ enum { REDRAW_NONE, REDRAW_TEXT, REDRAW_FULL } redrawFlag = REDRAW_FULL;
+ for (;;) {
+ if (redrawFlag == REDRAW_FULL) {
+ if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
+ && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ _buttons[4]._bounds.moveTo(148, _buttons[4]._bounds.top);
+ _buttons[9]._draw = false;
+ } else if (mode == ITEMMODE_RECHARGE) {
+ _buttons[4]._value = Common::KEYCODE_r;
+ } else if (mode == ITEMMODE_ENCHANT) {
+ _buttons[4]._value = Common::KEYCODE_e;
+ } else if (mode == ITEMMODE_TO_GOLD) {
+ _buttons[4]._value = Common::KEYCODE_g;
+ } else {
+ _buttons[4]._bounds.moveTo(0, _buttons[4]._bounds.top);
+ _buttons[9]._draw = true;
+ _buttons[9]._value = Common::KEYCODE_u;
+ }
+
+ // Write text for the dialog
+ Common::String msg;
+ if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_ENCHANT
+ && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ msg = Common::String::format(Res.ITEMS_DIALOG_TEXT1,
+ Res.BTN_BUY, Res.BTN_SELL, Res.BTN_IDENTIFY, Res.BTN_FIX);
+ } else if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ msg = Common::String::format(Res.ITEMS_DIALOG_TEXT1,
+ category == 3 ? Res.BTN_USE : Res.BTN_EQUIP,
+ Res.BTN_REMOVE, Res.BTN_DISCARD, Res.BTN_QUEST);
+ } else if (mode == ITEMMODE_ENCHANT) {
+ msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_ENCHANT);
+ } else if (mode == ITEMMODE_RECHARGE) {
+ msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_RECHARGE);
+ } else {
+ msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_GOLD);
+ }
+
+ windows[29].writeString(msg);
+ drawButtons(&windows[0]);
+
+ Common::fill(&arr[0], &arr[40], 0);
+ itemIndex = -1;
+ }
+
+ if (redrawFlag == REDRAW_TEXT || redrawFlag == REDRAW_FULL) {
+ lines.clear();
+
+ if (mode == ITEMMODE_CHAR_INFO || category != 3) {
+ _iconSprites.draw(0, 8, Common::Point(148, 109));
+ }
+ if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ _iconSprites.draw(0, 10, Common::Point(182, 109));
+ _iconSprites.draw(0, 12, Common::Point(216, 109));
+ _iconSprites.draw(0, 14, Common::Point(250, 109));
+ }
+
+ switch (mode) {
+ case ITEMMODE_CHAR_INFO:
+ _iconSprites.draw(0, 9, Common::Point(148, 109));
+ break;
+ case ITEMMODE_BLACKSMITH:
+ _iconSprites.draw(0, 11, Common::Point(182, 109));
+ break;
+ case ITEMMODE_REPAIR:
+ _iconSprites.draw(0, 15, Common::Point(250, 109));
+ break;
+ case ITEMMODE_IDENTIFY:
+ _iconSprites.draw(0, 13, Common::Point(216, 109));
+ break;
+ default:
+ break;
+ }
+
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ DrawStruct &ds = _itemsDrawList[idx];
+ XeenItem &i = c->_items[category][idx];
+
+ ds._sprites = nullptr;
+ ds._x = 8;
+ ds._y = 18 + idx * 9;
+
+ switch (category) {
+ case CATEGORY_WEAPON:
+ case CATEGORY_ARMOR:
+ case CATEGORY_ACCESSORY:
+ if (i._id) {
+ if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+ || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+ lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE1,
+ arr[idx], idx + 1,
+ c->_items[category].getFullDescription(idx, arr[idx]).c_str()));
+ } else {
+ lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE2,
+ arr[idx], idx + 1,
+ c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
+ calcItemCost(c, idx, mode,
+ mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
+ category)
+ ));
+ }
+
+ ds._sprites = &_equipSprites;
+ if (c->_weapons.passRestrictions(i._id, true))
+ ds._frame = i._frame;
+ else
+ ds._frame = 14;
+ } else if (ds._sprites == nullptr && idx == 0) {
+ lines.push_back(Res.NO_ITEMS_AVAILABLE);
+ }
+ break;
+
+ case CATEGORY_MISC:
+ if (i._material == 0) {
+ // No item
+ if (idx == 0) {
+ lines.push_back(Res.NO_ITEMS_AVAILABLE);
+ }
+ } else {
+ ItemsMode tempMode = mode;
+ int skill = startingChar->_skills[MERCHANT];
+
+ if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
+ || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+ tempMode = ITEMMODE_ENCHANT;
+ } else if (mode == ITEMMODE_TO_GOLD) {
+ skill = 1;
+ }
+
+ lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE2,
+ arr[idx], idx + 1,
+ c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
+ calcItemCost(c, idx, tempMode, skill, category)
+ ));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ while (lines.size() < INV_ITEMS_TOTAL)
+ lines.push_back("");
+
+ // Draw out overall text and the list of items
+ switch (mode) {
+ case ITEMMODE_CHAR_INFO:
+ case ITEMMODE_8:
+ windows[30].writeString(Common::String::format(Res.X_FOR_THE_Y,
+ category == CATEGORY_MISC ? "\x3l" : "\x3c",
+ Res.CATEGORY_NAMES[category], c->_name.c_str(), Res.CLASS_NAMES[c->_class],
+ category == CATEGORY_MISC ? Res.FMT_CHARGES : " ",
+ lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+ lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str()
+ ));
+ break;
+
+ case ITEMMODE_BLACKSMITH:
+ windows[30].writeString(Common::String::format(Res.AVAILABLE_GOLD_COST,
+ Res.CATEGORY_NAMES[category], party._gold,
+ lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+ lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str()
+ ));
+ break;
+
+ case ITEMMODE_2:
+ case ITEMMODE_RECHARGE:
+ case ITEMMODE_ENCHANT:
+ case ITEMMODE_REPAIR:
+ case ITEMMODE_IDENTIFY:
+ case ITEMMODE_TO_GOLD:
+ windows[30].writeString(Common::String::format(Res.X_FOR_Y,
+ Res.CATEGORY_NAMES[category], startingChar->_name.c_str(),
+ (mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? Res.CHARGES : Res.COST,
+ lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+ lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str()
+ ));
+ break;
+
+ case ITEMMODE_3:
+ case ITEMMODE_5:
+ windows[30].writeString(Common::String::format(Res.X_FOR_Y_GOLD,
+ Res.CATEGORY_NAMES[category], c->_name.c_str(), party._gold, Res.CHARGES,
+ lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
+ lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str()
+ ));
+ break;
+
+ default:
+ break;
+ }
+
+ // Draw the glyphs for the items
+ windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL);
+ windows[0].update();
+ }
+
+ redrawFlag = REDRAW_NONE;
+
+ if (itemIndex != -1) {
+ switch (mode) {
+ case ITEMMODE_BLACKSMITH:
+ actionIndex = 0;
+ break;
+ case ITEMMODE_2:
+ actionIndex = 1;
+ break;
+ case ITEMMODE_REPAIR:
+ actionIndex = 3;
+ break;
+ case ITEMMODE_IDENTIFY:
+ actionIndex = 2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // If it's time to do an item action, take care of it
+ if (actionIndex >= 0) {
+ int result = doItemOptions(*c, actionIndex, itemIndex, category, mode);
+ if (result == 1) {
+ // Finish dialog with no selected character
+ c = nullptr;
+ break;
+ } else if (result == 2) {
+ // Close dialogs and finish dialog with original starting character
+ windows[30].close();
+ windows[29].close();
+ c = startingChar;
+ break;
+ }
+
+ // Otherwise, result and continue showing dialog
+ actionIndex = -1;
+ }
+
+ // Wait for a selection
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ }
+ if (_vm->shouldExit())
+ return nullptr;
+
+ // Handle escaping out of dialog
+ if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ if (mode == ITEMMODE_8)
+ continue;
+ c = startingChar;
+ break;
+ }
+
+ // Handle other selections
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ if (!varA && mode != ITEMMODE_3 && mode != ITEMMODE_ENCHANT
+ && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD
+ && party._mazeId != 0) {
+ _buttonValue -= Common::KEYCODE_F1;
+
+ if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ?
+ combat._combatParty.size() : party._activeParty.size())) {
+ // Character number is valid
+ redrawFlag = REDRAW_TEXT;
+ Character *newChar = _vm->_mode == MODE_COMBAT ?
+ combat._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
+
+ if (mode == ITEMMODE_BLACKSMITH) {
+ _oldCharacter = newChar;
+ startingChar = newChar;
+ c = &_itemsCharacter;
+ } else if (mode != ITEMMODE_2 && mode != ITEMMODE_REPAIR
+ && mode != ITEMMODE_IDENTIFY && itemIndex != -1) {
+ InventoryItems &destItems = newChar->_items[category];
+ XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1];
+ InventoryItems &srcItems = c->_items[category];
+ XeenItem &srcItem = srcItems[itemIndex];
+
+ if (srcItem._bonusFlags & ITEMFLAG_CURSED)
+ ErrorScroll::show(_vm, Res.CANNOT_REMOVE_CURSED_ITEM);
+ else if (destItems[INV_ITEMS_TOTAL - 1]._id)
+ ErrorScroll::show(_vm, Common::String::format(
+ Res.CATEGORY_BACKPACK_IS_FULL[category], c->_name.c_str()));
+ else {
+ destItem = srcItem;
+ srcItem.clear();
+ destItem._frame = 0;
+
+ srcItems.sort();
+ destItems.sort();
+ }
+
+ continue;
+ }
+
+ c = newChar;
+ startingChar = newChar;
+ intf.highlightChar(_buttonValue);
+ }
+ }
+ break;
+
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ // Select an item
+ if (mode == ITEMMODE_3)
+ break;
+
+ _buttonValue -= Common::KEYCODE_1;
+ if (_buttonValue != itemIndex) {
+ // Check whether the new selection has an associated item
+ if (!c->_items[category][_buttonValue].empty()) {
+ itemIndex = _buttonValue;
+ Common::fill(&arr[0], &arr[40], 0);
+ arr[itemIndex] = 15;
+ }
+
+ redrawFlag = REDRAW_TEXT;
+ }
+ break;
+
+ case Common::KEYCODE_a:
+ // Armor category
+ category = CATEGORY_ARMOR;
+ redrawFlag = REDRAW_FULL;
+ break;
+
+ case Common::KEYCODE_b:
+ // Buy
+ if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+ mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+ mode = ITEMMODE_BLACKSMITH;
+ c = &_itemsCharacter;
+ redrawFlag = REDRAW_FULL;
+ }
+ break;
+
+ case Common::KEYCODE_c:
+ // Accessories category
+ category = CATEGORY_ACCESSORY;
+ redrawFlag = REDRAW_FULL;
+ break;
+
+ case Common::KEYCODE_d:
+ if (mode == ITEMMODE_CHAR_INFO)
+ actionIndex = 3;
+ break;
+
+ case Common::KEYCODE_e:
+ if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_ENCHANT ||
+ mode == ITEMMODE_TO_GOLD) {
+ if (category != CATEGORY_MISC) {
+ actionIndex = mode == ITEMMODE_ENCHANT ? 4 : 0;
+ }
+ }
+ break;
+
+ case Common::KEYCODE_f:
+ if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+ mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+ mode = ITEMMODE_REPAIR;
+ c = startingChar;
+ redrawFlag = REDRAW_TEXT;
+ }
+ break;
+
+ case Common::KEYCODE_g:
+ if (mode == ITEMMODE_TO_GOLD)
+ actionIndex = 6;
+ break;
+
+ case Common::KEYCODE_i:
+ if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+ mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+ mode = ITEMMODE_IDENTIFY;
+ c = startingChar;
+ redrawFlag = REDRAW_TEXT;
+ }
+ break;
+
+ case Common::KEYCODE_m:
+ // Misc
+ category = CATEGORY_MISC;
+ redrawFlag = REDRAW_TEXT;
+ break;
+
+ case Common::KEYCODE_q:
+ // Quests
+ if (mode == ITEMMODE_CHAR_INFO) {
+ Quests::show(_vm);
+ redrawFlag = REDRAW_FULL;
+ }
+ break;
+
+ case Common::KEYCODE_r:
+ if (mode == ITEMMODE_CHAR_INFO)
+ actionIndex = 1;
+ else if (mode == ITEMMODE_RECHARGE)
+ actionIndex = 5;
+ break;
+
+ case Common::KEYCODE_s:
+ if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
+ mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
+ mode = ITEMMODE_2;
+ c = startingChar;
+ redrawFlag = REDRAW_TEXT;
+ }
+ break;
+
+ case Common::KEYCODE_u:
+ if (mode == ITEMMODE_CHAR_INFO && category == CATEGORY_MISC)
+ actionIndex = 2;
+ break;
+
+ case Common::KEYCODE_w:
+ // Weapons category
+ category = CATEGORY_WEAPON;
+ redrawFlag = REDRAW_TEXT;
+ break;
+ }
+ }
+
+ windows[30].close();
+ windows[29].close();
+
+ intf.drawParty(true);
+ if (updateStock)
+ charData2BlackData();
+
+ return c;
+}
+
+void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
+ _iconSprites.load(Common::String::format("%s.icn",
+ (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
+ _equipSprites.load("equip.icn");
+
+ if (mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE || mode == ITEMMODE_TO_GOLD) {
+ // Enchant button list
+ addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
+ addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
+ addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_m, &_iconSprites);
+ addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_u, &_iconSprites);
+ addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+ addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+ addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+ addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+ addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+ addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+ addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+ addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+ addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
+ } else {
+ addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
+ addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
+ addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_m, &_iconSprites);
+ addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(182, 109, 206, 129), Common::KEYCODE_r, &_iconSprites);
+ addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites);
+ addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites);
+ addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+ addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+ addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+ addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+ addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+ addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+ addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+ addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+ addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
+ addPartyButtons(_vm);
+ }
+
+ if (mode == ITEMMODE_BLACKSMITH) {
+ _oldCharacter = c;
+ c = &_itemsCharacter;
+ blackData2CharData();
+
+ _buttons[4]._value = Common::KEYCODE_b;
+ _buttons[5]._value = Common::KEYCODE_s;
+ _buttons[6]._value = Common::KEYCODE_i;
+ _buttons[7]._value = Common::KEYCODE_f;
+
+ setEquipmentIcons();
+ } else {
+ _buttons[4]._value = Common::KEYCODE_e;
+ _buttons[5]._value = Common::KEYCODE_r;
+ _buttons[6]._value = Common::KEYCODE_d;
+ _buttons[7]._value = Common::KEYCODE_q;
+ }
+}
+
+void ItemsDialog::blackData2CharData() {
+ Party &party = *_vm->_party;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int slotIndex = 0;
+ while (slotIndex < 4 && party._mazeId != (int)Res.BLACKSMITH_MAP_IDS[isDarkCc][slotIndex])
+ ++slotIndex;
+ if (slotIndex == 4)
+ slotIndex = 0;
+
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ _itemsCharacter._weapons[idx] = party._blacksmithWeapons[isDarkCc][idx];
+ _itemsCharacter._armor[idx] = party._blacksmithArmor[isDarkCc][idx];
+ _itemsCharacter._accessories[idx] = party._blacksmithAccessories[isDarkCc][idx];
+ _itemsCharacter._misc[idx] = party._blacksmithMisc[isDarkCc][idx];
+ }
+}
+
+void ItemsDialog::charData2BlackData() {
+ Party &party = *_vm->_party;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int slotIndex = 0;
+ while (slotIndex < 4 && party._mazeId != (int)Res.BLACKSMITH_MAP_IDS[isDarkCc][slotIndex])
+ ++slotIndex;
+ if (slotIndex == 4)
+ slotIndex = 0;
+
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ party._blacksmithWeapons[isDarkCc][idx] = _itemsCharacter._weapons[idx];
+ party._blacksmithArmor[isDarkCc][idx] = _itemsCharacter._armor[idx];
+ party._blacksmithAccessories[isDarkCc][idx] = _itemsCharacter._accessories[idx];
+ party._blacksmithMisc[isDarkCc][idx] = _itemsCharacter._misc[idx];
+ }
+}
+
+void ItemsDialog::setEquipmentIcons() {
+ for (int typeIndex = 0; typeIndex < 4; ++typeIndex) {
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ switch (typeIndex) {
+ case CATEGORY_WEAPON: {
+ XeenItem &i = _itemsCharacter._weapons[idx];
+ if (i._id <= 17)
+ i._frame = 1;
+ else if (i._id <= 29 || i._id > 33)
+ i._frame = 13;
+ else
+ i._frame = 4;
+ break;
+ }
+
+ case CATEGORY_ARMOR: {
+ XeenItem &i = _itemsCharacter._armor[idx];
+ if (i._id <= 7)
+ i._frame = 3;
+ else if (i._id == 9)
+ i._frame = 5;
+ else if (i._id == 10)
+ i._frame = 9;
+ else if (i._id <= 12)
+ i._frame = 10;
+ else
+ i._frame = 6;
+ break;
+ }
+
+ case CATEGORY_ACCESSORY: {
+ XeenItem &i = _itemsCharacter._accessories[idx];
+ if (i._id == 1)
+ i._id = 8;
+ else if (i._id == 2)
+ i._frame = 12;
+ else if (i._id <= 7)
+ i._frame = 7;
+ else
+ i._frame = 11;
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
+ int skillLevel, ItemCategory category) {
+ int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
+ int result = 0;
+ int level = skillLevel & 0x7f;
+
+ InventoryItems *invGroups[4] = {
+ &c->_weapons, &c->_armor, &c->_accessories, &c->_misc
+ };
+ const int *BASE_COSTS[4] = {
+ Res.WEAPON_BASE_COSTS, Res.ARMOR_BASE_COSTS, Res.ACCESSORY_BASE_COSTS, Res.MISC_BASE_COSTS
+ };
+
+ switch (mode) {
+ case ITEMMODE_BLACKSMITH:
+ level = 0;
+ break;
+ case ITEMMODE_2:
+ case ITEMMODE_TO_GOLD:
+ level = level == 0 ? 1 : 0;
+ break;
+ case ITEMMODE_IDENTIFY:
+ level = 2;
+ break;
+ case ITEMMODE_REPAIR:
+ level = 3;
+ break;
+ default:
+ break;
+ }
+
+ switch (category) {
+ case CATEGORY_WEAPON:
+ case CATEGORY_ARMOR:
+ case CATEGORY_ACCESSORY: {
+ XeenItem &i = (*invGroups[category])[itemIndex];
+ amount1 = (BASE_COSTS[category])[i._id];
+
+ if (i._material > 36 && i._material < 59) {
+ switch (i._material) {
+ case 37:
+ amount1 /= 10;
+ break;
+ case 38:
+ amount1 /= 4;
+ break;
+ case 39:
+ amount1 /= 2;
+ break;
+ case 40:
+ amount1 /= 4;
+ break;
+ default:
+ amount1 *= Res.METAL_BASE_MULTIPLIERS[i._material - 37];
+ break;
+ }
+ }
+
+ if (i._material < 37)
+ amount2 = Res.ELEMENTAL_DAMAGE[i._material] * 100;
+ else if (i._material > 58)
+ amount3 = Res.ELEMENTAL_DAMAGE[i._material - 59 + 7] * 100;
+
+ switch (mode) {
+ case ITEMMODE_BLACKSMITH:
+ case ITEMMODE_2:
+ case ITEMMODE_REPAIR:
+ case ITEMMODE_IDENTIFY:
+ case ITEMMODE_TO_GOLD:
+ result = (amount1 + amount2 + amount3 + amount4) / Res.ITEM_SKILL_DIVISORS[level];
+ if (!result)
+ result = 1;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case CATEGORY_MISC: {
+ // Misc
+ XeenItem &i = c->_misc[itemIndex];
+ amount1 = Res.MISC_MATERIAL_COSTS[i._material];
+ amount4 = Res.MISC_BASE_COSTS[i._id];
+
+ switch (mode) {
+ case ITEMMODE_BLACKSMITH:
+ case ITEMMODE_2:
+ case ITEMMODE_REPAIR:
+ case ITEMMODE_IDENTIFY:
+ case ITEMMODE_TO_GOLD:
+ result = (amount1 + amount2 + amount3 + amount4) / Res.ITEM_SKILL_DIVISORS[level];
+ if (!result)
+ result = 1;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
+}
+
+int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
+ ItemsMode mode) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+
+ XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] };
+ XeenItem *items = itemCategories[category];
+ if (!items[0]._id)
+ // Inventory is empty
+ return category == CATEGORY_MISC ? 0 : 2;
+
+ Window &w = windows[11];
+ SpriteResource escSprites;
+ if (itemIndex < 0 || itemIndex > 8) {
+ saveButtons();
+
+ escSprites.load("esc.icn");
+ addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites);
+ addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+ addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+ addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+ addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+ addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+ addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+ addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+ addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+ addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
+
+ w.open();
+ w.writeString(Common::String::format(Res.WHICH_ITEM, Res.ITEM_ACTIONS[actionIndex]));
+ _iconSprites.draw(0, 0, Common::Point(235, 111));
+ w.update();
+
+ while (!_vm->shouldExit()) {
+ while (!_buttonValue) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ if (_vm->shouldExit())
+ return false;
+ }
+
+ if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ itemIndex = -1;
+ break;
+ } else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) {
+ // Check whether there's an item at the selected index
+ int selectedIndex = _buttonValue - Common::KEYCODE_1;
+ if (!items[selectedIndex]._id)
+ continue;
+
+ itemIndex = selectedIndex;
+ break;
+ }
+ }
+
+ w.close();
+ restoreButtons();
+ }
+
+ if (itemIndex != -1) {
+ XeenItem &item = c._items[category][itemIndex];
+
+ switch (mode) {
+ case ITEMMODE_CHAR_INFO:
+ case ITEMMODE_8:
+ switch (actionIndex) {
+ case 0:
+ c._items[category].equipItem(itemIndex);
+ break;
+ case 1:
+ c._items[category].removeItem(itemIndex);
+ break;
+ case 2:
+ if (!party._mazeId) {
+ ErrorScroll::show(_vm, Res.WHATS_YOUR_HURRY);
+ } else {
+ XeenItem &i = c._misc[itemIndex];
+
+ Condition condition = c.worstCondition();
+ switch (condition) {
+ case ASLEEP:
+ case PARALYZED:
+ case UNCONSCIOUS:
+ case DEAD:
+ case STONED:
+ case ERADICATED:
+ ErrorScroll::show(_vm, Common::String::format(Res.IN_NO_CONDITION, c._name.c_str()));
+ break;
+ default:
+ if (combat._itemFlag) {
+ ErrorScroll::show(_vm, Res.USE_ITEM_IN_COMBAT);
+ } else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK)
+ && !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
+ int charges = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
+ i._bonusFlags = charges;
+ _oldCharacter = &c;
+
+ windows[30].close();
+ windows[29].close();
+ windows[24].close();
+ spells.castItemSpell(i._id);
+
+ if (!charges) {
+ // Ran out of charges, so make item disappear
+ c._items[category][itemIndex].clear();
+ c._items[category].sort();
+ }
+ } else {
+ ErrorScroll::show(_vm, Common::String::format(Res.NO_SPECIAL_ABILITIES,
+ c._items[category].getFullDescription(itemIndex).c_str()
+ ));
+ }
+ }
+ }
+ break;
+ case 3:
+ c._items[category].discardItem(itemIndex);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case ITEMMODE_BLACKSMITH: {
+ InventoryItems &invItems = _oldCharacter->_items[category];
+ if (invItems[INV_ITEMS_TOTAL - 1]._id) {
+ // If the last slot is in use, it means the list is full
+ ErrorScroll::show(_vm, Common::String::format(Res.BACKPACK_IS_FULL,
+ _oldCharacter->_name.c_str()));
+ } else {
+ int cost = calcItemCost(_oldCharacter, itemIndex, mode, 0, category);
+ Common::String desc = c._items[category].getFullDescription(itemIndex);
+ if (Confirm::show(_vm, Common::String::format(Res.BUY_X_FOR_Y_GOLD,
+ desc.c_str(), cost))) {
+ if (party.subtract(CONS_GOLD, cost, WHERE_PARTY, WT_FREEZE_WAIT)) {
+ if (isDarkCc) {
+ sound.stopSound();
+ sound.playSound("choice2.voc");
+ }
+
+ // Add entry to the end of the list
+ _oldCharacter->_items[category][8] = c._items[category][itemIndex];
+ _oldCharacter->_items[category][8]._frame = 0;
+ c._items[category].clear();
+ c._items[category].sort();
+ _oldCharacter->_items[category].sort();
+ }
+ }
+ }
+ return 0;
+ }
+
+ case ITEMMODE_2: {
+ bool noNeed;
+ switch (category) {
+ case CATEGORY_WEAPON:
+ noNeed = (item._bonusFlags & ITEMFLAG_CURSED) || item._id == 34;
+ break;
+ default:
+ noNeed = item._bonusFlags & ITEMFLAG_CURSED;
+ break;
+ }
+
+ if (noNeed) {
+ ErrorScroll::show(_vm, Common::String::format(Res.NO_NEED_OF_THIS,
+ c._items[category].getFullDescription(itemIndex).c_str()));
+ } else {
+ int cost = calcItemCost(&c, itemIndex, mode, c._skills[MERCHANT], category);
+ Common::String desc = c._items[category].getFullDescription(itemIndex);
+ Common::String msg = Common::String::format(Res.SELL_X_FOR_Y_GOLD,
+ desc.c_str(), cost);
+
+ if (Confirm::show(_vm, msg)) {
+ // Remove the sold item and add gold to the party's total
+ item.clear();
+ c._items[category].sort();
+
+ party._gold += cost;
+ }
+ }
+ return 0;
+ }
+
+ case ITEMMODE_RECHARGE:
+ if (category != CATEGORY_MISC || c._misc[itemIndex]._material > 9
+ || c._misc[itemIndex]._id == 53 || c._misc[itemIndex]._id == 0) {
+ sound.playFX(21);
+ ErrorScroll::show(_vm, Common::String::format(Res.NOT_RECHARGABLE, Res.SPELL_FAILED));
+ } else {
+ int charges = MIN(63, _vm->getRandomNumber(1, 6) +
+ (c._misc[itemIndex]._bonusFlags & ITEMFLAG_BONUS_MASK));
+ sound.playFX(20);
+
+ c._misc[itemIndex]._bonusFlags = (c._misc[itemIndex]._bonusFlags
+ & ~ITEMFLAG_BONUS_MASK) | charges;
+ }
+ return 2;
+
+ case ITEMMODE_ENCHANT: {
+ int amount = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1);
+ amount = MIN(amount, 5);
+ _oldCharacter->_items[category].enchantItem(itemIndex, amount);
+ break;
+ }
+
+ case ITEMMODE_REPAIR:
+ if (!(item._bonusFlags & ITEMFLAG_BROKEN)) {
+ ErrorScroll::show(_vm, Res.ITEM_NOT_BROKEN);
+ } else {
+ int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
+ Common::String msg = Common::String::format(Res.FIX_IDENTIFY_GOLD,
+ Res.FIX_IDENTIFY[0],
+ c._items[category].getFullDescription(itemIndex).c_str(),
+ cost);
+
+ if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
+ item._bonusFlags &= ~ITEMFLAG_BROKEN;
+ }
+ }
+ break;
+
+ case ITEMMODE_IDENTIFY: {
+ int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
+ Common::String msg = Common::String::format(Res.FIX_IDENTIFY_GOLD,
+ Res.FIX_IDENTIFY[1],
+ c._items[category].getFullDescription(itemIndex).c_str(),
+ cost);
+
+ if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
+ Common::String details = c._items[category].getIdentifiedDetails(itemIndex);
+ Common::String desc = c._items[category].getFullDescription(itemIndex);
+ Common::String str = Common::String::format(Res.IDENTIFY_ITEM_MSG,
+ desc.c_str(), details.c_str());
+
+ Window &win = windows[14];
+ win.open();
+ win.writeString(str);
+ win.update();
+
+ saveButtons();
+ clearButtons();
+
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ events.clearEvents();
+
+ restoreButtons();
+ win.close();
+ }
+ break;
+ }
+
+ case ITEMMODE_TO_GOLD:
+ // Convert item in inventory to gold
+ itemToGold(c, itemIndex, category, mode);
+ return 2;
+
+ default:
+ break;
+ }
+ }
+
+ intf._charsShooting = false;
+ combat.moveMonsters();
+ combat._whosTurn = -1;
+ return true;
+}
+
+void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
+ ItemsMode mode) {
+ XeenItem &item = c._items[category][itemIndex];
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+
+ if (category == CATEGORY_WEAPON && item._id == 34) {
+ sound.playFX(21);
+ ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03""c%s",
+ Res.SPELL_FAILED));
+ } else if (item._id != 0) {
+ // There is a valid item present
+ // Calculate cost of item and add it to the party's total
+ int cost = calcItemCost(&c, itemIndex, mode, 1, category);
+ party._gold += cost;
+
+ // Remove the item from the inventory
+ item.clear();
+ c._items[category].sort();
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_items.h b/engines/xeen/dialogs/dialogs_items.h
new file mode 100644
index 0000000..b9af06e
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_items.h
@@ -0,0 +1,89 @@
+/* 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 XEEN_DIALOGS_ITEMS_H
+#define XEEN_DIALOGS_ITEMS_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+#include "xeen/window.h"
+
+namespace Xeen {
+
+enum ItemsMode {
+ ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3,
+ ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8,
+ ITEMMODE_REPAIR = 9, ITEMMODE_IDENTIFY = 10, ITEMMODE_TO_GOLD = 11
+};
+
+class ItemsDialog : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ SpriteResource _equipSprites;
+ Character _itemsCharacter;
+ Character *_oldCharacter;
+ DrawStruct _itemsDrawList[INV_ITEMS_TOTAL];
+
+ ItemsDialog(XeenEngine *vm) : ButtonContainer(vm), _oldCharacter(nullptr) {}
+
+ Character *execute(Character *c, ItemsMode mode);
+
+ /**
+ * Load the buttons for the dialog
+ */
+ void loadButtons(ItemsMode mode, Character *&c);
+
+ /**
+ * Loads the temporary _itemsCharacter character with the item set
+ * the given blacksmith has available, so the user can "view" the
+ * set as if it were a standard character's inventory
+ */
+ void blackData2CharData();
+
+ /**
+ * Saves the inventory from the temporary _itemsCharacter character back into the
+ * blacksmith storage, so changes in blacksmith inventory remain persistent
+ */
+ void charData2BlackData();
+
+ /**
+ * Sets the equipment icon to use for each item for display
+ */
+ void setEquipmentIcons();
+
+ /**
+ * Calculate the cost of an item
+ */
+ int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel,
+ ItemCategory category);
+
+ int doItemOptions(Character &c, int actionIndex, int itemIndex,
+ ItemCategory category, ItemsMode mode);
+
+ void itemToGold(Character &c, int itemIndex, ItemCategory category, ItemsMode mode);
+public:
+ static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_ITEMS_H */
diff --git a/engines/xeen/dialogs/dialogs_map.cpp b/engines/xeen/dialogs/dialogs_map.cpp
new file mode 100644
index 0000000..b822c71
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_map.cpp
@@ -0,0 +1,461 @@
+/* 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 "xeen/dialogs/dialogs_map.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+#define MAP_SIZE 16
+#define MAP_DIFF (MAP_SIZE / 2)
+#define MAP_XSTART 80
+#define MAP_YSTART 38
+#define TILE_WIDTH 10
+#define TILE_HEIGHT 8
+
+void MapDialog::show(XeenEngine *vm) {
+ MapDialog *dlg = new MapDialog(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void MapDialog::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+
+ _pt = party._mazePosition;
+ _globalSprites.load("global.icn");
+
+ if (_pt.x < 8 && map.mazeData()._surroundingMazes._west == 0) {
+ _arrowPt.x = _pt.x * 10 + 4;
+ _pt.x = 7;
+ } else if (_pt.x > 23) {
+ _arrowPt.x = (byte)(_pt.x * 10 + 100);
+ _pt.x = 23;
+ } else if (_pt.x > 8 && map.mazeData()._surroundingMazes._east == 0) {
+ _arrowPt.x = (byte)(_pt.x * 10 + 4);
+ _pt.x = 7;
+ } else {
+ _arrowPt.x = 74;
+ }
+
+ if (_pt.y < 8 && map.mazeData()._surroundingMazes._south == 0) {
+ _arrowPt.y = ((15 - _pt.y) << 3) + 13;
+ _pt.y = 8;
+ } else if (_pt.y > 24) {
+ _arrowPt.y = ((15 - (_pt.y - 16)) << 3) + 13;
+ _pt.y = 24;
+ } else if (_pt.y >= 8 && map.mazeData()._surroundingMazes._north == 0) {
+ _arrowPt.y = ((15 - _pt.y) << 3) + 13;
+ _pt.y = 8;
+ } else {
+ _arrowPt.y = 69;
+ }
+
+ windows[5].open();
+ bool drawFlag = true;
+
+ events.updateGameCounter();
+ do {
+ if (drawFlag)
+ intf.draw3d(false, false);
+ windows[5].writeString("\r");
+
+ if (map._isOutdoors)
+ drawOutdoors();
+ else
+ drawIndoors();
+
+ windows[5].frame();
+ if (!map._isOutdoors) {
+ map._tileSprites.draw(0, 52, Common::Point(76, 30));
+ } else if (_frameEndFlag) {
+ _globalSprites.draw(0, party._mazeDirection + 1,
+ Common::Point(_arrowPt.x + 76, _arrowPt.y + 25));
+ }
+
+ if (events.timeElapsed() > 5) {
+ // Set the flag to make the basic arrow blinking effect
+ _frameEndFlag = !_frameEndFlag;
+ events.updateGameCounter();
+ }
+
+ windows[5].writeString(Common::String::format(Res.MAP_TEXT,
+ map._mazeName.c_str(), party._mazePosition.x,
+ party._mazePosition.y, Res.DIRECTION_TEXT[party._mazeDirection]));
+ windows[5].update();
+ windows[3].update();
+
+ events.ipause5(2);
+ drawFlag = false;
+ } while (!_vm->shouldExit() && !events.isKeyMousePressed());
+
+ events.clearEvents();
+ windows[5].close();
+}
+
+void MapDialog::drawOutdoors() {
+ Map &map = *g_vm->_map;
+ int v, frame;
+
+ // Draw outdoors map
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ --mazeY, yp += TILE_HEIGHT) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 0);
+ assert(v != INVALID_CELL);
+ frame = map.mazeDataCurrent()._surfaceTypes[v];
+
+ if (map._currentSteppedOn) {
+ map._tileSprites.draw(0, frame, Common::Point(xp, yp));
+ }
+ }
+ }
+
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ --mazeY, yp += TILE_HEIGHT) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 4);
+ assert(v != INVALID_CELL);
+ frame = map.mazeDataCurrent()._wallTypes[v];
+
+ if (frame && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame + 16, Common::Point(xp, yp));
+ }
+ }
+
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ --mazeY, yp += TILE_HEIGHT) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ frame = map.mazeLookup(Common::Point(mazeX, mazeY), 8, 0xff);
+
+ if (frame && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame + 32, Common::Point(xp, yp));
+ }
+ }
+}
+
+void MapDialog::drawIndoors() {
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ int v, frame;
+ int frame2 = _animFrame;
+ _animFrame = (_animFrame + 2) % 8;
+
+ // Draw indoors map
+ frame2 = (frame2 + 2) % 8;
+
+ // Draw default ground for all the valid explored areas
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ yp += TILE_HEIGHT, --mazeY) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 0, 0xffff);
+
+ if (v != INVALID_CELL && map._currentSteppedOn)
+ map._tileSprites.draw(0, 0, Common::Point(xp, yp));
+ }
+ }
+
+ // Draw thinner ground tiles on the left edge of the map
+ for (int yp = MAP_YSTART + 5, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ yp += TILE_HEIGHT, --mazeY) {
+ v = map.mazeLookup(Common::Point(_pt.x - 8, mazeY), 0, 0xffff);
+
+ if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+ map._tileSprites.draw(0, 36 + map.mazeData()._surfaceTypes[
+ map._currentSurfaceId], Common::Point(75, yp));
+ }
+
+ // Draw thin tile portion on top-left corner of map
+ v = map.mazeLookup(Common::Point(_pt.x - 8, _pt.y + 8), 0, 0xffff);
+ if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+ map._tileSprites.draw(0, 36 + map.mazeData()._surfaceTypes[
+ map._currentSurfaceId], Common::Point(75, 35));
+
+ // Draw any thin tiles at the very top of the map
+ for (int xp = MAP_XSTART + 5, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, _pt.y + 8), 0, 0xffff);
+
+ if (v != INVALID_CELL && map._currentSurfaceId != 0 && map._currentSteppedOn)
+ map._tileSprites.draw(0, 36 + map.mazeData()._surfaceTypes[
+ map._currentSurfaceId], Common::Point(xp, 35));
+ }
+
+ // Draw the default ground tiles
+ for (int yp = MAP_YSTART + 5, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ yp += TILE_HEIGHT, --mazeY) {
+ for (int xp = MAP_XSTART + 5, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 0, 0xffff);
+
+ if (v != INVALID_CELL && map._currentSurfaceId && map._currentSteppedOn)
+ map._tileSprites.draw(0, 36 + map.mazeData()._surfaceTypes[
+ map._currentSurfaceId], Common::Point(xp, yp));
+ }
+ }
+
+ // Draw walls on left and top edges of map
+ for (int xp = MAP_XSTART, yp = MAP_YSTART + (MAP_SIZE - 1) * TILE_HEIGHT,
+ mazeX = _pt.x - (MAP_DIFF - 1), mazeY = _pt.y - MAP_DIFF;
+ mazeX < (_pt.x + MAP_DIFF); xp += TILE_WIDTH, yp -= TILE_HEIGHT, ++mazeX, ++mazeY) {
+ // Draw walls on left edge of map
+ v = map.mazeLookup(Common::Point(_pt.x - 8, mazeY), 12);
+
+ switch (v) {
+ case SURFTYPE_DIRT:
+ frame = 18;
+ break;
+ case SURFTYPE_SNOW:
+ frame = 22;
+ break;
+ case SURFTYPE_SWAMP:
+ case SURFTYPE_CLOUD:
+ frame = 16;
+ break;
+ case SURFTYPE_LAVA:
+ case SURFTYPE_DWATER:
+ frame = 2;
+ break;
+ case SURFTYPE_DESERT:
+ frame = 30;
+ break;
+ case SURFTYPE_ROAD:
+ frame = 32;
+ break;
+ case SURFTYPE_TFLR:
+ frame = 20;
+ break;
+ case SURFTYPE_SKY:
+ frame = 28;
+ break;
+ case SURFTYPE_CROAD:
+ frame = 14;
+ break;
+ case SURFTYPE_SEWER:
+ frame = frame2 + 4;
+ break;
+ case SURFTYPE_SCORCH:
+ frame = 24;
+ break;
+ case SURFTYPE_SPACE:
+ frame = 26;
+ break;
+ default:
+ frame = -1;
+ break;
+ }
+
+ if (frame != -1 && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame, Common::Point(70, yp));
+
+ // Draw walls on top edge of map
+ v = map.mazeLookup(Common::Point(mazeX, _pt.y + 8), 0);
+
+ switch (v) {
+ case SURFTYPE_DIRT:
+ frame = 19;
+ break;
+ case SURFTYPE_GRASS:
+ frame = 35;
+ break;
+ case SURFTYPE_SNOW:
+ frame = 23;
+ break;
+ case SURFTYPE_SWAMP:
+ case SURFTYPE_CLOUD:
+ frame = 17;
+ break;
+ case SURFTYPE_LAVA:
+ case SURFTYPE_DWATER:
+ frame = 3;
+ break;
+ case SURFTYPE_DESERT:
+ frame = 31;
+ break;
+ case SURFTYPE_ROAD:
+ frame = 33;
+ break;
+ case SURFTYPE_TFLR:
+ frame = 21;
+ break;
+ case SURFTYPE_SKY:
+ frame = 29;
+ break;
+ case SURFTYPE_CROAD:
+ frame = 15;
+ break;
+ case SURFTYPE_SEWER:
+ frame = frame2 + 5;
+ break;
+ case SURFTYPE_SCORCH:
+ frame = 25;
+ break;
+ case SURFTYPE_SPACE:
+ frame = 27;
+ break;
+ default:
+ frame = -1;
+ break;
+ }
+
+ if (frame != -1 && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame, Common::Point(xp, 30));
+ }
+
+ // Draw the walls for the remaining cells of the minimap
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1, yCtr = 0; yCtr < MAP_SIZE;
+ yp += TILE_HEIGHT, --mazeY, ++yCtr) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1), xCtr = 0; xCtr < MAP_SIZE;
+ xp += TILE_WIDTH, ++mazeX, ++xCtr) {
+ // Draw the arrow if at the correct position
+ if ((_arrowPt.x / 10) == xCtr && (14 - (_arrowPt.y / 10)) == yCtr && _frameEndFlag) {
+ _globalSprites.draw(0, party._mazeDirection + 1,
+ Common::Point(_arrowPt.x + 81, _arrowPt.y + 29));
+ }
+
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 12);
+ switch (v) {
+ case 1:
+ frame = 18;
+ break;
+ case 2:
+ frame = 34;
+ break;
+ case 3:
+ frame = 22;
+ break;
+ case 4:
+ case 13:
+ frame = 16;
+ break;
+ case 5:
+ case 8:
+ frame = 2;
+ break;
+ case 6:
+ frame = 30;
+ break;
+ case 7:
+ frame = 32;
+ break;
+ case 9:
+ frame = 20;
+ break;
+ case 10:
+ frame = 28;
+ break;
+ case 11:
+ frame = 14;
+ break;
+ case 12:
+ frame = frame2 + 4;
+ break;
+ case 14:
+ frame = 24;
+ break;
+ case 15:
+ frame = 26;
+ break;
+ default:
+ frame = -1;
+ break;
+ }
+
+ if (frame != -1 && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame, Common::Point(xp, yp));
+
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 0);
+ switch (v) {
+ case 1:
+ frame = 19;
+ break;
+ case 2:
+ frame = 35;
+ break;
+ case 3:
+ frame = 23;
+ break;
+ case 4:
+ case 13:
+ frame = 17;
+ break;
+ case 5:
+ case 8:
+ frame = 3;
+ break;
+ case 6:
+ frame = 31;
+ break;
+ case 7:
+ frame = 33;
+ break;
+ case 9:
+ frame = 21;
+ break;
+ case 10:
+ frame = 29;
+ break;
+ case 11:
+ frame = 15;
+ break;
+ case 12:
+ frame = frame2 + 5;
+ break;
+ case 14:
+ frame = 25;
+ break;
+ case 15:
+ frame = 27;
+ break;
+ default:
+ frame = -1;
+ break;
+ }
+
+ if (frame != -1 && map._currentSteppedOn)
+ map._tileSprites.draw(0, frame, Common::Point(xp, yp));
+ }
+ }
+
+ // Draw overlay on cells that haven't been stepped on yet
+ for (int yp = MAP_YSTART, mazeY = _pt.y + MAP_DIFF - 1; mazeY >= (_pt.y - MAP_DIFF);
+ yp += TILE_HEIGHT, --mazeY) {
+ for (int xp = MAP_XSTART, mazeX = _pt.x - (MAP_DIFF - 1); mazeX <= (_pt.x + MAP_DIFF);
+ xp += TILE_WIDTH, ++mazeX) {
+ v = map.mazeLookup(Common::Point(mazeX, mazeY), 0, 0xffff);
+
+ if (v == INVALID_CELL || !map._currentSteppedOn)
+ map._tileSprites.draw(0, 1, Common::Point(xp, yp));
+ }
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_map.h b/engines/xeen/dialogs/dialogs_map.h
new file mode 100644
index 0000000..5e22e52
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_map.h
@@ -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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_MAP_H
+#define XEEN_DIALOGS_MAP_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class XeenEngine;
+
+class MapDialog: public ButtonContainer {
+private:
+ int _animFrame;
+ SpriteResource _globalSprites;
+ Common::Point _pt, _arrowPt;
+ bool _frameEndFlag;
+private:
+ MapDialog(XeenEngine *vm) : ButtonContainer(vm),
+ _animFrame(0), _frameEndFlag(false) {}
+
+ /**
+ * Draws the map contents when outdoors
+ */
+ void drawOutdoors();
+
+ /**
+ * Draws the map contents when indoors
+ */
+ void drawIndoors();
+
+ /**
+ * Handles the display of the dialog
+ */
+ void execute();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_AUTOMAP_H */
diff --git a/engines/xeen/dialogs/dialogs_message.cpp b/engines/xeen/dialogs/dialogs_message.cpp
new file mode 100644
index 0000000..df8afea
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_message.cpp
@@ -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.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "xeen/dialogs/dialogs_message.h"
+#include "xeen/events.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void MessageDialog::show(XeenEngine *vm, const Common::String &msg, MessageWaitType waitType) {
+ MessageDialog *dlg = new MessageDialog(vm);
+ dlg->execute(msg, waitType);
+ delete dlg;
+}
+
+void MessageDialog::execute(const Common::String &msg, MessageWaitType waitType) {
+ EventsManager &events = *_vm->_events;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+
+ w.open();
+ w.writeString(msg);
+ w.update();
+
+ switch (waitType) {
+ case WT_FREEZE_WAIT:
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+
+ events.clearEvents();
+ break;
+
+ case WT_ANIMATED_WAIT:
+ if (windows[11]._enabled || _vm->_mode == MODE_17) {
+ g_vm->_locations->wait();
+ break;
+ }
+ // fall through
+
+ case WT_NONFREEZED_WAIT:
+ do {
+ events.updateGameCounter();
+ _vm->_interface->draw3d(true);
+
+ events.wait(1);
+ if (checkEvents(_vm))
+ break;
+ } while (!_vm->shouldExit() && !_buttonValue);
+ break;
+
+ case WT_LOC_WAIT:
+ g_vm->_locations->wait();
+ break;
+
+ default:
+ break;
+ }
+
+ w.close();
+}
+
+/*------------------------------------------------------------------------*/
+
+void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, MessageWaitType waitType) {
+ Common::String s = Common::String::format("\x3""c\v010\t000%s", msg.c_str());
+ MessageDialog::show(vm, s, waitType);
+}
+
+/*------------------------------------------------------------------------*/
+
+void CantCast::show(XeenEngine *vm, int spellId, int componentNum) {
+ CantCast *dlg = new CantCast(vm);
+ dlg->execute(spellId, componentNum);
+ delete dlg;
+}
+
+void CantCast::execute(int spellId, int componentNum) {
+ EventsManager &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_FF;
+
+ sound.playFX(21);
+ w.open();
+ w.writeString(Common::String::format(Res.NOT_ENOUGH_TO_CAST,
+ Res.SPELL_CAST_COMPONENTS[componentNum - 1],
+ spells._spellNames[spellId].c_str()
+ ));
+ w.update();
+
+ do {
+ events.pollEventsAndWait();
+ } while (!_vm->shouldExit() && !events.isKeyMousePressed());
+ events.clearEvents();
+
+ w.close();
+ _vm->_mode = oldMode;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_message.h b/engines/xeen/dialogs/dialogs_message.h
new file mode 100644
index 0000000..95d9428
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_message.h
@@ -0,0 +1,61 @@
+/* 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 XEEN_dialogs_message_H
+#define XEEN_dialogs_message_H
+
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/character.h"
+
+namespace Xeen {
+
+enum MessageWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1,
+ WT_LOC_WAIT = 2, WT_ANIMATED_WAIT = 3 };
+
+class MessageDialog : public ButtonContainer {
+private:
+ MessageDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(const Common::String &msg, MessageWaitType waitType);
+public:
+ static void show(XeenEngine *vm, const Common::String &msg,
+ MessageWaitType waitType = WT_FREEZE_WAIT);
+};
+
+class ErrorScroll {
+public:
+ static void show(XeenEngine *vm, const Common::String &msg,
+ MessageWaitType waitType = WT_FREEZE_WAIT);
+};
+
+class CantCast: public ButtonContainer {
+private:
+ CantCast(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(int spellId, int componentNum);
+public:
+ static void show(XeenEngine *vm, int spellId, int componentNum);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_dialogs_message_H */
diff --git a/engines/xeen/dialogs/dialogs_party.cpp b/engines/xeen/dialogs/dialogs_party.cpp
new file mode 100644
index 0000000..33e138b
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_party.cpp
@@ -0,0 +1,451 @@
+/* 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 "xeen/dialogs/dialogs_char_info.h"
+#include "xeen/dialogs/dialogs_create_char.h"
+#include "xeen/dialogs/dialogs_party.h"
+#include "xeen/dialogs/dialogs_input.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/character.h"
+#include "xeen/events.h"
+#include "xeen/party.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(vm),
+ PartyDrawer(vm), _vm(vm) {
+ initDrawStructs();
+}
+
+void PartyDialog::show(XeenEngine *vm) {
+ PartyDialog *dlg = new PartyDialog(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void PartyDialog::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Screen &screen = *_vm->_screen;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ bool modeFlag = false;
+ int startingChar = 0;
+
+ loadButtons();
+ setupBackground();
+
+ while (!_vm->shouldExit()) {
+ _vm->_mode = MODE_1;
+
+ // Build up a list of available characters in the Roster that are on the
+ // same side of Xeen as the player is currently on
+ _charList.clear();
+ for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
+ Character &player = party._roster[i];
+ if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
+ continue;
+
+ _charList.push_back(i);
+ }
+
+ Window &w = windows[11];
+ w.open();
+ setupFaces(startingChar, false);
+ w.writeString(Common::String::format(Res.PARTY_DIALOG_TEXT, _partyDetails.c_str()));
+ w.drawList(&_faceDrawStructs[0], 4);
+
+ _uiSprites.draw(w, 0, Common::Point(16, 100));
+ _uiSprites.draw(w, 2, Common::Point(52, 100));
+ _uiSprites.draw(w, 4, Common::Point(87, 100));
+ _uiSprites.draw(w, 6, Common::Point(122, 100));
+ _uiSprites.draw(w, 8, Common::Point(157, 100));
+ _uiSprites.draw(w, 10, Common::Point(192, 100));
+ if (g_vm->getGameID() == GType_Swords)
+ Res._logoSprites.draw(1, 0, Common::Point(232, 9));
+
+ screen.loadPalette("mm4.pal");
+
+ if (modeFlag) {
+ windows[0].update();
+ events.setCursor(0);
+ screen.fadeIn();
+ } else {
+ if (_vm->getGameID() == GType_DarkSide) {
+ screen.fadeOut();
+ windows[0].update();
+ }
+
+ doScroll(false, false);
+ events.setCursor(0);
+
+ if (_vm->getGameID() == GType_DarkSide) {
+ screen.fadeIn();
+ }
+ }
+
+ bool breakFlag = false;
+ while (!_vm->shouldExit() && !breakFlag) {
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && !_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_x:
+ if (party._activeParty.size() == 0) {
+ ErrorScroll::show(_vm, Res.NO_ONE_TO_ADVENTURE_WITH);
+ } else {
+ if (_vm->_mode != MODE_0) {
+ for (int idx = OBSCURITY_NONE; idx >= OBSCURITY_BLACK; --idx) {
+ events.updateGameCounter();
+ intf.obscureScene((Obscurity)idx);
+ w.update();
+
+ while (events.timeElapsed() < 1)
+ events.pollEventsAndWait();
+ }
+ }
+
+ w.close();
+ party._mazeId = party._priorMazeId;
+
+ party.copyPartyToRoster();
+ //_vm->_saves->writeCharFile();
+ return;
+ }
+ break;
+
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ // Show character info
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size())
+ CharacterInfo::show(_vm, _buttonValue);
+ break;
+
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ _buttonValue -= Common::KEYCODE_1 - 7;
+ if ((_buttonValue - 7 + startingChar) < (int)_charList.size()) {
+ // Check if the selected character is already in the party
+ uint idx = 0;
+ for (; idx < party._activeParty.size(); ++idx) {
+ if (_charList[_buttonValue - 7 + startingChar] ==
+ party._activeParty[idx]._rosterId)
+ break;
+ }
+
+ // Only add the character if they're not already in the party
+ if (idx == party._activeParty.size()) {
+ if (party._activeParty.size() == MAX_ACTIVE_PARTY) {
+ sound.playFX(21);
+ ErrorScroll::show(_vm, Res.YOUR_PARTY_IS_FULL);
+ } else {
+ // Add the character to the active party
+ party._activeParty.push_back(party._roster[
+ _charList[_buttonValue - 7 + startingChar]]);
+ startingCharChanged(startingChar);
+ }
+ }
+ }
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ // Up arrow
+ if (startingChar > 0) {
+ startingChar -= 4;
+ startingCharChanged(startingChar);
+ }
+ break;
+
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ // Down arrow
+ if (startingChar < ((int)_charList.size() - 4)) {
+ startingChar += 4;
+ startingCharChanged(startingChar);
+ }
+ break;
+
+ case Common::KEYCODE_c:
+ // Create
+ if (_charList.size() == XEEN_TOTAL_CHARACTERS) {
+ ErrorScroll::show(_vm, Res.YOUR_ROSTER_IS_FULL);
+ } else {
+ screen.fadeOut();
+ w.close();
+
+ // Show the create character dialog
+ CreateCharacterDialog::show(_vm);
+
+ party.copyPartyToRoster();
+ //_vm->_saves->writeCharFile();
+ screen.fadeOut();
+ modeFlag = true;
+ breakFlag = true;
+ }
+ break;
+
+ case Common::KEYCODE_d:
+ // Delete character
+ if (_charList.size() > 0) {
+ int charButtonValue = selectCharacter(true, startingChar);
+ if (charButtonValue != 0) {
+ int charIndex = charButtonValue - Common::KEYCODE_1 + startingChar;
+ Character &c = party._roster[_charList[charIndex]];
+ if (c.hasSlayerSword()) {
+ ErrorScroll::show(_vm, Res.HAS_SLAYER_SWORD);
+ } else {
+ Common::String msg = Common::String::format(Res.SURE_TO_DELETE_CHAR,
+ c._name.c_str(), Res.CLASS_NAMES[c._class]);
+ if (Confirm::show(_vm, msg)) {
+ // If the character is in the party, remove it
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ if (party._activeParty[idx]._rosterId == c._rosterId) {
+ party._activeParty.remove_at(idx);
+ break;
+ }
+ }
+
+ // Empty the character in the roster
+ c.clear();
+
+ // Rebuild the character list
+ _charList.clear();
+ for (int idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
+ Character &ch = party._roster[idx];
+ if (!ch._name.empty() && ch._savedMazeId == party._priorMazeId) {
+ _charList.push_back(idx);
+ }
+ }
+
+ startingCharChanged(startingChar);
+ }
+ }
+ }
+ }
+ break;
+
+ case Common::KEYCODE_r:
+ // Remove character
+ if (party._activeParty.size() > 0) {
+ int charButtonValue = selectCharacter(false, startingChar);
+ if (charButtonValue != 0) {
+ party.copyPartyToRoster();
+ party._activeParty.remove_at(charButtonValue - Common::KEYCODE_F1);
+ }
+ startingCharChanged(startingChar);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void PartyDialog::loadButtons() {
+ _uiSprites.load("inn.icn");
+ addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_uiSprites);
+ addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_uiSprites);
+ addButton(Common::Rect(87, 100, 111, 120), Common::KEYCODE_d, &_uiSprites);
+ addButton(Common::Rect(122, 100, 146, 120), Common::KEYCODE_r, &_uiSprites);
+ addButton(Common::Rect(157, 100, 181, 120), Common::KEYCODE_c, &_uiSprites);
+ addButton(Common::Rect(192, 100, 216, 120), Common::KEYCODE_x, &_uiSprites);
+ addButton(Common::Rect(0, 0, 0, 0), Common::KEYCODE_ESCAPE);
+}
+
+void PartyDialog::initDrawStructs() {
+ _faceDrawStructs[0] = DrawStruct(0, 0, 0);
+ _faceDrawStructs[1] = DrawStruct(0, 101, 0);
+ _faceDrawStructs[2] = DrawStruct(0, 0, 43);
+ _faceDrawStructs[3] = DrawStruct(0, 101, 43);
+}
+
+void PartyDialog::setupBackground() {
+ _vm->_screen->loadBackground("back.raw");
+ _vm->_interface->assembleBorder();
+}
+
+void PartyDialog::setupFaces(int firstDisplayChar, bool updateFlag) {
+ Party &party = *_vm->_party;
+ Common::String charNames[4];
+ Common::String charRaces[4];
+ Common::String charSex[4];
+ Common::String charClasses[4];
+ int posIndex;
+ int charId;
+
+ // Reset the button areas for the display character images
+ while (_buttons.size() > 7)
+ _buttons.remove_at(7);
+ addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+ addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+ addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3);
+ addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4);
+
+
+ for (posIndex = 0; posIndex < 4; ++posIndex) {
+ charId = (firstDisplayChar + posIndex) >= (int)_charList.size() ? -1 :
+ _charList[firstDisplayChar + posIndex];
+ bool isInParty = party.isInParty(charId);
+
+ if (charId == -1) {
+ while ((int)_buttons.size() >(7 + posIndex))
+ _buttons.remove_at(_buttons.size() - 1);
+ break;
+ }
+
+ Common::Rect &b = _buttons[7 + posIndex]._bounds;
+ b.moveTo((posIndex & 1) ? 117 : 16, b.top);
+ Character &ps = party._roster[_charList[firstDisplayChar + posIndex]];
+ charNames[posIndex] = isInParty ? Res.IN_PARTY : ps._name;
+ charRaces[posIndex] = Res.RACE_NAMES[ps._race];
+ charSex[posIndex] = Res.SEX_NAMES[ps._sex];
+ charClasses[posIndex] = Res.CLASS_NAMES[ps._class];
+ }
+
+ drawParty(updateFlag);
+
+ // Set up the sprite set to use for each face
+ for (posIndex = 0; posIndex < 4; ++posIndex) {
+ if ((firstDisplayChar + posIndex) >= (int)_charList.size())
+ _faceDrawStructs[posIndex]._sprites = nullptr;
+ else
+ _faceDrawStructs[posIndex]._sprites = party._roster[
+ _charList[firstDisplayChar + posIndex]]._faceSprites;
+ }
+
+ _partyDetails = Common::String::format(Res.PARTY_DETAILS,
+ charNames[0].c_str(), charRaces[0].c_str(), charSex[0].c_str(), charClasses[0].c_str(),
+ charNames[1].c_str(), charRaces[1].c_str(), charSex[1].c_str(), charClasses[1].c_str(),
+ charNames[2].c_str(), charRaces[2].c_str(), charSex[2].c_str(), charClasses[2].c_str(),
+ charNames[3].c_str(), charRaces[3].c_str(), charSex[3].c_str(), charClasses[3].c_str()
+ );
+}
+
+void PartyDialog::startingCharChanged(int firstDisplayChar) {
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[11];
+
+ setupFaces(firstDisplayChar, true);
+ w.writeString(Common::String::format(Res.PARTY_DIALOG_TEXT, _partyDetails.c_str()));
+ w.drawList(_faceDrawStructs, 4);
+
+ _uiSprites.draw(w, 0, Common::Point(16, 100));
+ _uiSprites.draw(w, 2, Common::Point(52, 100));
+ _uiSprites.draw(w, 4, Common::Point(87, 100));
+ _uiSprites.draw(w, 6, Common::Point(122, 100));
+ _uiSprites.draw(w, 8, Common::Point(157, 100));
+ _uiSprites.draw(w, 10, Common::Point(192, 100));
+
+ w.update();
+}
+
+int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
+ EventsManager &events = *_vm->_events;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[28];
+
+ SpriteResource iconSprites;
+ iconSprites.load("esc.icn");
+
+ w.setBounds(Common::Rect(50, isDelete ? 112 : 76, 266, isDelete ? 148 : 112));
+ w.open();
+ w.writeString(Common::String::format(Res.REMOVE_OR_DELETE_WHICH,
+ Res.REMOVE_DELETE[isDelete ? 1 : 0]));
+ iconSprites.draw(w, 0, Common::Point(225, isDelete ? 120 : 84));
+ w.update();
+
+ saveButtons();
+ addButton(Common::Rect(225, isDelete ? 120 : 84, 249, isDelete ? 140 : 104),
+ Common::KEYCODE_ESCAPE, &iconSprites);
+ addButton(Common::Rect(16, 16, 48, 48), Common::KEYCODE_1);
+ addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2);
+ addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3);
+ addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4);
+ addPartyButtons(_vm);
+
+ int result = -1, v;
+ while (!_vm->shouldExit() && result == -1) {
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ }
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = 0;
+ break;
+
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ if (!isDelete) {
+ v = _buttonValue - Common::KEYCODE_F1;
+ if (v < (int)party._activeParty.size())
+ result = _buttonValue;
+ }
+ break;
+
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ if (isDelete) {
+ v = _buttonValue - Common::KEYCODE_1;
+ if ((firstDisplayChar + v) < (int)_charList.size())
+ result = _buttonValue;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ w.close();
+ restoreButtons();
+ return result == -1 ? 0 : result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_party.h b/engines/xeen/dialogs/dialogs_party.h
new file mode 100644
index 0000000..8f87ca3
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_party.h
@@ -0,0 +1,87 @@
+/* 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 XEEN_DIALOGS_PARTY_H
+#define XEEN_DIALOGS_PARTY_H
+
+#include "common/array.h"
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/interface.h"
+#include "xeen/screen.h"
+#include "xeen/sprites.h"
+
+namespace Xeen {
+
+/**
+ * Shows the Party dialog that's shown when signing into an inn
+ */
+class PartyDialog : public ButtonContainer, public PartyDrawer {
+private:
+ XeenEngine *_vm;
+ SpriteResource _uiSprites;
+ DrawStruct _faceDrawStructs[4];
+ Common::String _partyDetails;
+ Common::Array<int> _charList;
+
+ /**
+ * Constructor
+ */
+ PartyDialog(XeenEngine *vm);
+
+ /**
+ * Executes the dialog
+ */
+ void execute();
+
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
+
+ /**
+ * Initialises a list of elements to draw
+ */
+ void initDrawStructs();
+
+ /**
+ * Sets up the background
+ */
+ void setupBackground();
+
+ /**
+ * Sets up the faces from the avaialble roster for display in the party dialog
+ */
+ void setupFaces(int firstDisplayChar, bool updateFlag);
+
+ void startingCharChanged(int firstDisplayChar);
+
+ int selectCharacter(bool isDelete, int firstDisplayChar);
+public:
+ /**
+ * Show the Party dialog
+ */
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_PARTY_H */
diff --git a/engines/xeen/dialogs/dialogs_query.cpp b/engines/xeen/dialogs/dialogs_query.cpp
new file mode 100644
index 0000000..79f4682
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_query.cpp
@@ -0,0 +1,158 @@
+/* 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 "xeen/dialogs/dialogs_query.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool Confirm::show(XeenEngine *vm, const Common::String &msg, int mode) {
+ Confirm *dlg = new Confirm(vm);
+ bool result = dlg->execute(msg, mode);
+ delete dlg;
+
+ return result;
+}
+
+bool Confirm::execute(const Common::String &msg, int mode) {
+ EventsManager &events = *_vm->_events;
+ Windows &windows = *_vm->_windows;
+ SpriteResource confirmSprites;
+
+ confirmSprites.load("confirm.icn");
+ addButton(Common::Rect(129, 112, 153, 122), Common::KEYCODE_y, &confirmSprites);
+ addButton(Common::Rect(185, 112, 209, 122), Common::KEYCODE_n, &confirmSprites);
+
+ Window &w = windows[mode ? 22 : 21];
+ w.open();
+
+ if (!mode) {
+ confirmSprites.draw(w, 0, Common::Point(129, 112));
+ confirmSprites.draw(w, 2, Common::Point(185, 112));
+ _buttons[0]._bounds.moveTo(129, 112);
+ _buttons[1]._bounds.moveTo(185, 112);
+ } else {
+ if (mode & 0x80) {
+ clearButtons();
+ } else {
+ confirmSprites.draw(w, 0, Common::Point(120, 133));
+ confirmSprites.draw(w, 2, Common::Point(176, 133));
+ _buttons[0]._bounds.moveTo(120, 133);
+ _buttons[1]._bounds.moveTo(176, 133);
+ }
+ }
+
+ w.writeString(msg);
+ w.update();
+
+ events.clearEvents();
+ bool result = false;
+
+ while (!_vm->shouldExit()) {
+ events.pollEvents();
+ checkEvents(_vm);
+
+ if ((mode & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE
+ || _buttonValue == Common::KEYCODE_n)
+ break;
+
+ if (_buttonValue == Common::KEYCODE_y) {
+ result = true;
+ break;
+ }
+ }
+
+ w.close();
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
+ YesNo *dlg = new YesNo(vm);
+ bool result = dlg->execute(type, townFlag);
+ delete dlg;
+
+ return result;
+}
+
+bool YesNo::execute(bool type, bool townFlag) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Resources &res = *_vm->_resources;
+ LocationManager &loc = *_vm->_locations;
+ Windows &windows = *_vm->_windows;
+ SpriteResource confirmSprites;
+ bool result = false;
+
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
+
+ if (!type) {
+ confirmSprites.load("confirm.icn");
+ res._globalSprites.draw(0, 7, Common::Point(232, 74));
+ confirmSprites.draw(0, 0, Common::Point(235, 75));
+ confirmSprites.draw(0, 2, Common::Point(260, 75));
+ windows[34].update();
+
+ addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &confirmSprites);
+ addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &confirmSprites);
+
+ intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+ intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+ }
+
+ while (!_vm->shouldExit()) {
+ events.updateGameCounter();
+
+ if (loc.isActive()) {
+ loc.drawAnim(townFlag);
+ //numFrames = 3;
+ } else {
+ intf.draw3d(true);
+ //numFrames = 1;
+ }
+
+ events.wait(3);
+ checkEvents(_vm);
+ if (!_buttonValue)
+ continue;
+
+ if (type || _buttonValue == Common::KEYCODE_y) {
+ result = true;
+ break;
+ } else if (_buttonValue == Common::KEYCODE_n || _buttonValue == Common::KEYCODE_ESCAPE)
+ break;
+ }
+
+ intf._face1State = intf._face2State = 2;
+ _vm->_mode = oldMode;
+
+ if (!type)
+ intf.mainIconsPrint();
+
+ return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_query.h b/engines/xeen/dialogs/dialogs_query.h
new file mode 100644
index 0000000..911de3d
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_query.h
@@ -0,0 +1,50 @@
+/* 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 XEEN_DIALOGS_QUERY_H
+#define XEEN_DIALOGS_QUERY_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class Confirm : public ButtonContainer {
+private:
+ Confirm(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ bool execute(const Common::String &msg, int mode);
+public:
+ static bool show(XeenEngine *vm, const Common::String &msg, int mode = 0);
+};
+
+class YesNo : public ButtonContainer {
+private:
+ YesNo(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ bool execute(bool type, bool townFlag);
+public:
+ static bool show(XeenEngine *vm, bool type, bool townFlag = false);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUERY_H */
diff --git a/engines/xeen/dialogs/dialogs_quests.cpp b/engines/xeen/dialogs/dialogs_quests.cpp
new file mode 100644
index 0000000..e4f6227
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quests.cpp
@@ -0,0 +1,254 @@
+/* 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 "common/scummsys.h"
+#include "xeen/dialogs/dialogs_quests.h"
+#include "xeen/events.h"
+#include "xeen/party.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+#define MAX_DIALOG_LINES 128
+
+void Quests::show(XeenEngine *vm) {
+ Quests *dlg = new Quests(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void Quests::execute() {
+ EventsManager &events = *_vm->_events;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Mode oldMode = _vm->_mode;
+ int count = 0;
+ bool headerShown = false;
+ int topRow = 0;
+
+ addButtons();
+ loadQuestNotes();
+
+ enum { QUEST_ITEMS, CURRENT_QUESTS, AUTO_NOTES } mode = QUEST_ITEMS;
+ bool windowFlag;
+ if (windows[29]._enabled) {
+ windowFlag = false;
+ } else {
+ windows[29].open();
+ windows[30].open();
+ windowFlag = true;
+ }
+
+ windows[29].writeString(Res.QUESTS_DIALOG_TEXT);
+ drawButtons(&windows[0]);
+
+ while (!_vm->shouldExit()) {
+ Common::String lines[MAX_DIALOG_LINES];
+
+ switch (mode) {
+ case QUEST_ITEMS:
+ for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+ lines[idx] = "\b \b*";
+
+ count = 0;
+ headerShown = false;
+ for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) {
+ if (party._questItems[idx]) {
+ if (!count && !headerShown && idx < 35) {
+ lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ }
+ if (idx >= 35 && !headerShown) {
+ lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
+ headerShown = true;
+ }
+
+ switch (idx) {
+ case 17:
+ case 26:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ lines[count++] = Common::String::format("%d %s%c",
+ party._questItems[idx], Res.QUEST_ITEM_NAMES[idx],
+ party._questItems[idx] == 1 ? ' ' : 's');
+ break;
+ default:
+ lines[count++] = Res.QUEST_ITEM_NAMES[idx];
+ break;
+ }
+ }
+ }
+
+ if (count == 0) {
+ windows[30].writeString(Res.NO_QUEST_ITEMS);
+ } else {
+ windows[30].writeString(Common::String::format(Res.QUEST_ITEMS_DATA,
+ lines[topRow].c_str(), lines[topRow + 1].c_str(),
+ lines[topRow + 2].c_str(), lines[topRow + 3].c_str(),
+ lines[topRow + 4].c_str(), lines[topRow + 5].c_str(),
+ lines[topRow + 6].c_str(), lines[topRow + 7].c_str(),
+ lines[topRow + 8].c_str()
+ ));
+ }
+ break;
+
+ case CURRENT_QUESTS:
+ for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+ lines[idx] = "";
+
+ count = 0;
+ headerShown = false;
+ for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) {
+ if (party._questFlags[(idx + 1) / 30][(idx + 1) % 30]) {
+ if (!count && !headerShown && idx < 29) {
+ lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ }
+ if (idx > 28 && !headerShown) {
+ lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
+ headerShown = true;
+ }
+
+ lines[count++] = _questNotes[idx];
+ }
+ }
+
+ if (count == 0)
+ lines[1] = Res.NO_CURRENT_QUESTS;
+
+ windows[30].writeString(Common::String::format(Res.CURRENT_QUESTS_DATA,
+ lines[topRow].c_str(), lines[topRow + 1].c_str(), lines[topRow + 2].c_str()));
+ break;
+
+ case AUTO_NOTES:
+ for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx)
+ lines[idx] = "";
+
+ count = 0;
+ headerShown = false;
+ for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) {
+ if (party._worldFlags[idx]) {
+ if (!count && !headerShown && idx < 72) {
+ lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ }
+ if (idx >= 72 && !headerShown) {
+ lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
+ headerShown = true;
+ }
+
+ lines[count++] = _questNotes[idx + 56];
+ }
+ }
+
+ if (count == 0)
+ lines[1] = Res.NO_AUTO_NOTES;
+
+ windows[30].writeString(Common::String::format(Res.AUTO_NOTES_DATA,
+ lines[topRow].c_str(), lines[topRow + 1].c_str(),
+ lines[topRow + 2].c_str(), lines[topRow + 3].c_str(),
+ lines[topRow + 4].c_str(), lines[topRow + 5].c_str(),
+ lines[topRow + 6].c_str(), lines[topRow + 7].c_str(),
+ lines[topRow + 8].c_str()
+ ));
+ break;
+ }
+
+ windows[30].writeString("\v000\t000");
+ windows[24].update();
+
+ // Key handling
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ }
+
+ if (_buttonValue == Common::KEYCODE_ESCAPE)
+ break;
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_a:
+ mode = AUTO_NOTES;
+ topRow = 0;
+ break;
+ case Common::KEYCODE_i:
+ mode = QUEST_ITEMS;
+ topRow = 0;
+ break;
+ case Common::KEYCODE_q:
+ mode = CURRENT_QUESTS;
+ topRow = 0;
+ break;
+ case Common::KEYCODE_HOME:
+ topRow = 0;
+ break;
+ case Common::KEYCODE_END:
+ topRow = MAX(count - 1, 0);
+ break;
+ case Common::KEYCODE_PAGEUP:
+ topRow = MAX(topRow - 3, 0);
+ break;
+ case Common::KEYCODE_PAGEDOWN:
+ topRow = CLIP(topRow + 3, 0, MAX(count - 1, 0));
+ break;
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ topRow = MAX(topRow - 1, 0);
+ break;
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ topRow = CLIP(topRow + 1, 0, MAX(count - 1, 0));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (windowFlag) {
+ windows[30].close();
+ windows[29].close();
+ }
+ _vm->_mode = oldMode;
+}
+
+void Quests::addButtons() {
+ _iconSprites.load("quest.icn");
+
+
+ addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_i, &_iconSprites);
+ addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_q, &_iconSprites);
+ addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_a, &_iconSprites);
+ addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_UP, &_iconSprites);
+ addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_DOWN, &_iconSprites);
+ addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
+}
+
+void Quests::loadQuestNotes() {
+ File f("qnotes.bin");
+ while (f.pos() < f.size())
+ _questNotes.push_back(f.readString());
+ f.close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_quests.h b/engines/xeen/dialogs/dialogs_quests.h
new file mode 100644
index 0000000..a3f1980
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quests.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 XEEN_DIALOGS_QUESTS_H
+#define XEEN_DIALOGS_QUESTS_H
+
+#include "common/str-array.h"
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class Quests : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ Common::StringArray _questNotes;
+
+ Quests(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+
+ void addButtons();
+
+ void loadQuestNotes();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUESTS_H */
diff --git a/engines/xeen/dialogs/dialogs_quick_fight.cpp b/engines/xeen/dialogs/dialogs_quick_fight.cpp
new file mode 100644
index 0000000..63acf55
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quick_fight.cpp
@@ -0,0 +1,105 @@
+/* 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 "xeen/dialogs/dialogs_quick_fight.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void QuickFight::show(XeenEngine *vm, Character *currentChar) {
+ QuickFight *dlg = new QuickFight(vm, currentChar);
+ dlg->execute();
+ delete dlg;
+}
+
+QuickFight::QuickFight(XeenEngine *vm, Character *currentChar) : ButtonContainer(vm),
+ _currentChar(currentChar) {
+ loadButtons();
+}
+
+void QuickFight::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[10];
+ w.open();
+
+ do {
+ // Draw the dialog text and buttons
+ Common::String msg = Common::String::format(Res.QUICK_FIGHT_TEXT,
+ _currentChar->_name.c_str(),
+ Res.QUICK_FIGHT_OPTIONS[_currentChar->_quickOption]);
+ w.writeString(msg);
+ drawButtons(&w);
+
+ // Wait for selection
+ _buttonValue = 0;
+ events.updateGameCounter();
+ do {
+ intf.draw3d(false, false);
+
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ if (_vm->shouldExit())
+ return;
+ } while (!_buttonValue && !events.timeElapsed());
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_n:
+ case Common::KEYCODE_t:
+ _currentChar->_quickOption = (QuickAction)(((int)_currentChar->_quickOption + 1) % 4);
+ break;
+
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6: {
+ int charIdx = _buttonValue - Common::KEYCODE_F1;
+ if (charIdx < (int)combat._combatParty.size()) {
+ // Highlight new character
+ _currentChar = &party._activeParty[charIdx];
+ intf.highlightChar(charIdx);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ } while (_buttonValue != Common::KEYCODE_RETURN && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ w.close();
+ events.clearEvents();
+}
+
+void QuickFight::loadButtons() {
+ _icons.load("train.icn");
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_quick_fight.h b/engines/xeen/dialogs/dialogs_quick_fight.h
new file mode 100644
index 0000000..e3662c9
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quick_fight.h
@@ -0,0 +1,60 @@
+/* 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 XEEN_DIALOGS_QUICK_FIGHT_H
+#define XEEN_DIALOGS_QUICK_FIGHT_H
+
+#include "xeen/character.h"
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/sprites.h"
+
+namespace Xeen {
+
+class QuickFight : public ButtonContainer {
+private:
+ SpriteResource _icons;
+ Character *_currentChar;
+private:
+ /**
+ * Constructor
+ */
+ QuickFight(XeenEngine *vm, Character *currentChar);
+
+ /**
+ * Executes the display of the dialog
+ */
+ void execute();
+
+ /**
+ * Load butons for the dialog
+ */
+ void loadButtons();
+public:
+ /**
+ * Show the dialog
+ */
+ static void show(XeenEngine *vm, Character *currentChar);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUICK_FIGHT_H */
diff --git a/engines/xeen/dialogs/dialogs_quick_ref.cpp b/engines/xeen/dialogs/dialogs_quick_ref.cpp
new file mode 100644
index 0000000..0c8a63b
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quick_ref.cpp
@@ -0,0 +1,88 @@
+/* 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 "xeen/dialogs/dialogs_quick_ref.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void QuickReferenceDialog::show(XeenEngine *vm) {
+ QuickReferenceDialog *dlg = new QuickReferenceDialog(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void QuickReferenceDialog::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Common::String lines[8];
+
+ events.setCursor(0);
+
+ for (uint idx = 0; idx < (combat._globalCombat == 2 ? combat._combatParty.size() :
+ party._activeParty.size()); ++idx) {
+ Character &c = combat._globalCombat == 2 ? *combat._combatParty[idx] :
+ party._activeParty[idx];
+ Condition condition = c.worstCondition();
+ lines[idx] = Common::String::format(Res.QUICK_REF_LINE,
+ idx * 10 + 24, idx + 1, c._name.c_str(),
+ Res.CLASS_NAMES[c._class][0], Res.CLASS_NAMES[c._class][1], Res.CLASS_NAMES[c._class][2],
+ c.statColor(c.getCurrentLevel(), c._level._permanent), c._level._permanent,
+ c.statColor(c._currentHp, c.getMaxHP()), c._currentHp,
+ c.statColor(c._currentSp, c.getMaxSP()), c._currentSp,
+ c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(),
+ Res.CONDITION_COLORS[condition],
+ Res.CONDITION_NAMES[condition][0], Res.CONDITION_NAMES[condition][1],
+ Res.CONDITION_NAMES[condition][2], Res.CONDITION_NAMES[condition][3]
+ );
+ }
+
+ int food = (party._food / party._activeParty.size()) / 3;
+ Common::String msg = Common::String::format(Res.QUICK_REFERENCE,
+ lines[0].c_str(), lines[1].c_str(), lines[2].c_str(),
+ lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
+ lines[6].c_str(), lines[7].c_str(),
+ party._gold, party._gems,
+ food, food == 1 ? "" : "s"
+ );
+
+ Window &w = windows[24];
+ bool windowOpen = w._enabled;
+ if (!windowOpen)
+ w.open();
+ w.writeString(msg);
+ w.update();
+
+ // Wait for a key/mouse press
+ events.clearEvents();
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ events.clearEvents();
+
+ if (!windowOpen)
+ w.close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_quick_ref.h b/engines/xeen/dialogs/dialogs_quick_ref.h
new file mode 100644
index 0000000..4630043
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_quick_ref.h
@@ -0,0 +1,41 @@
+/* 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 XEEN_DIALOGS_QUICK_REF_H
+#define XEEN_DIALOGS_QUICK_REF_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class QuickReferenceDialog : public ButtonContainer {
+private:
+ QuickReferenceDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_QUICK_REF_H */
diff --git a/engines/xeen/dialogs/dialogs_spells.cpp b/engines/xeen/dialogs/dialogs_spells.cpp
new file mode 100644
index 0000000..3da5a51
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_spells.cpp
@@ -0,0 +1,1045 @@
+/* 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 "xeen/dialogs/dialogs_spells.h"
+#include "xeen/dialogs/dialogs_input.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/resources.h"
+#include "xeen/spells.h"
+#include "xeen/sprites.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog,
+ Character *c, int isCasting) {
+ SpellsDialog *dlg = new SpellsDialog(vm);
+ Character *result = dlg->execute(priorDialog, c, isCasting);
+ delete dlg;
+
+ return result;
+}
+
+Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int isCasting) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ loadButtons();
+
+ int castingCopy = isCasting;
+ isCasting &= 0x7f;
+ int selection = -1;
+ int topIndex = 0;
+ int newSelection;
+ windows[25].open();
+
+ do {
+ if (!isCasting) {
+ if (!c->guildMember()) {
+ sound.stopSound();
+ intf._overallFrame = 5;
+ sound.playSound(isDarkCc ? "skull1.voc" : "guild11.voc", 1);
+ break;
+ }
+
+ Common::String title = Common::String::format(Res.BUY_SPELLS, c->_name.c_str());
+ Common::String msg = Common::String::format(Res.GUILD_OPTIONS,
+ title.c_str(), XeenEngine::printMil(party._gold).c_str());
+ windows[10].writeString(msg);
+
+ warning("TODO: Sprite draw using previously used button sprites");
+ }
+
+ _spells.clear();
+ const char *errorMsg = setSpellText(c, castingCopy);
+ windows[25].writeString(Common::String::format(Res.SPELLS_FOR,
+ errorMsg == nullptr ? Res.SPELL_LINES_0_TO_9 : "",
+ c->_name.c_str()));
+
+ // Setup and write out spell list
+ const char *names[10];
+ int colors[10];
+ Common::String emptyStr = "";
+ Common::fill(&names[0], &names[10], emptyStr.c_str());
+ Common::fill(&colors[0], &colors[10], 9);
+
+ for (int idx = 0; idx < 10; ++idx) {
+ if ((topIndex + idx) < (int)_spells.size()) {
+ names[idx] = _spells[topIndex + idx]._name.c_str();
+ colors[idx] = _spells[topIndex + idx]._color;
+ }
+ }
+
+ if (selection >= topIndex && selection < (topIndex + 10))
+ colors[selection - topIndex] = 15;
+ if (_spells.size() == 0)
+ names[0] = errorMsg;
+
+ windows[37].writeString(Common::String::format(Res.SPELLS_DIALOG_SPELLS,
+ colors[0], names[0], colors[1], names[1], colors[2], names[2],
+ colors[3], names[3], colors[4], names[4], colors[5], names[5],
+ colors[6], names[6], colors[7], names[7], colors[8], names[8],
+ colors[9], names[9],
+ isCasting ? Res.SPELL_PTS : Res.GOLD,
+ isCasting ? c->_currentSp : party._gold
+ ));
+
+ _scrollSprites.draw(0, 4, Common::Point(39, 26));
+ _scrollSprites.draw(0, 0, Common::Point(187, 26));
+ _scrollSprites.draw(0, 2, Common::Point(187, 111));
+ if (isCasting)
+ _scrollSprites.draw(windows[25], 5, Common::Point(132, 123));
+
+ windows[25].update();
+
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && !_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ if (_vm->_mode != MODE_COMBAT) {
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ spells._lastCaster = _buttonValue;
+ intf.highlightChar(_buttonValue);
+
+ if (_vm->_mode == MODE_17) {
+ windows[10].writeString(Common::String::format(Res.GUILD_OPTIONS,
+ XeenEngine::printMil(party._gold).c_str(), Res.GUILD_TEXT, c->_name.c_str()));
+ } else {
+ int category;
+ switch (c->_class) {
+ case CLASS_ARCHER:
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ case CLASS_RANGER:
+ category = 2;
+ break;
+ default:
+ category = 0;
+ break;
+ }
+
+ int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell;
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ windows[10].writeString(Common::String::format(Res.CAST_SPELL_DETAILS,
+ c->_name.c_str(), spells._spellNames[spellId].c_str(),
+ spells.calcSpellPoints(spellId, c->getCurrentLevel()),
+ Res.SPELL_GEM_COST[spellId], c->_currentSp));
+ }
+
+ if (priorDialog != nullptr)
+ priorDialog->drawButtons(&windows[0]);
+ windows[10].update();
+ }
+ }
+ break;
+
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_s:
+ if (selection != -1)
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ selection = -1;
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_0:
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ newSelection = topIndex + ((_buttonValue == Common::KEYCODE_0) ? 9 :
+ (_buttonValue - Common::KEYCODE_1));
+
+ if (newSelection < (int)_spells.size()) {
+ int expenseFactor = 0;
+ int category = 0;
+
+ switch (c->_class) {
+ case CLASS_PALADIN:
+ expenseFactor = 1;
+ category = 0;
+ break;
+ case CLASS_ARCHER:
+ expenseFactor = 1;
+ category = 1;
+ break;
+ case CLASS_CLERIC:
+ category = 0;
+ break;
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ category = 2;
+ break;
+ case CLASS_RANGER:
+ expenseFactor = 1;
+ category = 2;
+ break;
+ default:
+ break;
+ }
+
+ int spellIndex = _spells[newSelection]._spellIndex;
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int spellCost = spells.calcSpellCost(spellId, expenseFactor);
+
+ if (isCasting) {
+ selection = newSelection;
+ } else {
+ Common::String spellName = _spells[newSelection]._name;
+ Common::String msg = (castingCopy & 0x80) ?
+ Common::String::format(Res.SPELLS_PRESS_A_KEY, spellName.c_str()) :
+ Common::String::format(Res.SPELLS_PURCHASE, spellName.c_str(), spellCost);
+
+ if (Confirm::show(_vm, msg, castingCopy + 1)) {
+ if (party.subtract(CONS_GOLD, spellCost, WHERE_PARTY, WT_FREEZE_WAIT)) {
+ c->_spells[spellIndex] = true;
+ sound.stopSound();
+ intf._overallFrame = 0;
+ sound.playSound(isDarkCc ? "guild12.voc" : "parrot2.voc", 1);
+ } else {
+ sound.playFX(21);
+ }
+ }
+ }
+ }
+ break;
+
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_KP9:
+ topIndex = MAX((int)topIndex - 10, 0);
+ break;
+
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_KP3:
+ topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ if (topIndex > 0)
+ --topIndex;
+ break;
+
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ if (topIndex < ((int)_spells.size() - 10))
+ ++topIndex;
+ break;
+ }
+ } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ windows[25].close();
+
+ if (_vm->shouldExit())
+ selection = -1;
+ if (isCasting && selection != -1)
+ c->_currentSpell = _spells[selection]._spellIndex;
+
+ return c;
+}
+
+void SpellsDialog::loadButtons() {
+ _iconSprites.load("main.icn");
+ _scrollSprites.load("scroll.icn");
+ addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites);
+ addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites);
+ addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1);
+ addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2);
+ addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3);
+ addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4);
+ addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5);
+ addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6);
+ addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7);
+ addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8);
+ addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9);
+ addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0);
+ addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE);
+ addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP);
+ addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN);
+ addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s);
+ addPartyButtons(_vm);
+}
+
+const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int expenseFactor = 0;
+ int currLevel = c->getCurrentLevel();
+ int category;
+
+ if ((isCasting & 0x7f) == 0) {
+ switch (c->_class) {
+ case CLASS_PALADIN:
+ expenseFactor = 1;
+ category = 0;
+ break;
+ case CLASS_ARCHER:
+ expenseFactor = 1;
+ category = 1;
+ break;
+ case CLASS_CLERIC:
+ category = 0;
+ break;
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ category = 2;
+ break;
+ case CLASS_RANGER:
+ expenseFactor = 1;
+ category = 2;
+ break;
+ default:
+ category = -1;
+ break;
+ }
+
+ if (category != -1) {
+ if (party._mazeId == 49 || party._mazeId == 37) {
+ for (uint spellId = 0; spellId < 76; ++spellId) {
+ int idx = 0;
+ while (idx < MAX_SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != (int)spellId)
+ ++idx;
+
+ // Handling if the spell is appropriate for the character's class
+ if (idx < MAX_SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else if (isDarkCc) {
+ int groupIndex = (party._mazeId - 29) / 2;
+ for (int spellId = Res.DARK_SPELL_RANGES[groupIndex][0];
+ spellId < Res.DARK_SPELL_RANGES[groupIndex][1]; ++spellId) {
+ int idx = 0;
+ while (idx < 40 && Res.SPELLS_ALLOWED[category][idx] ==
+ Res.DARK_SPELL_OFFSETS[category][spellId]);
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else {
+ for (int spellId = 0; spellId < 20; ++spellId) {
+ int idx = 0;
+ while (Res.CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
+ (int)Res.SPELLS_ALLOWED[category][idx] && idx < 40) ;
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ }
+ }
+
+ if (c->getMaxSP() == 0)
+ return Res.NOT_A_SPELL_CASTER;
+
+ } else if ((isCasting & 0x7f) == 1) {
+ switch (c->_class) {
+ case CLASS_ARCHER:
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ case CLASS_RANGER:
+ category = 2;
+ break;
+ case CLASS_PALADIN:
+ case CLASS_CLERIC:
+ default:
+ category = 0;
+ break;
+ }
+
+ if (c->getMaxSP() == 0) {
+ return Res.NOT_A_SPELL_CASTER;
+ } else {
+ for (int spellIndex = 0; spellIndex < MAX_SPELLS_PER_CLASS; ++spellIndex) {
+ if (c->_spells[spellIndex]) {
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int gemCost = Res.SPELL_GEM_COST[spellId];
+ int spCost = spells.calcSpellPoints(spellId, currLevel);
+
+ Common::String msg = Common::String::format("\x3l%s\x3r\x9""000%u/%u",
+ spells._spellNames[spellId].c_str(), spCost, gemCost);
+ _spells.push_back(SpellEntry(msg, spellIndex, spellId));
+ }
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+/*------------------------------------------------------------------------*/
+
+CastSpell::CastSpell(XeenEngine *vm) : ButtonContainer(vm) {
+ Windows &windows = *_vm->_windows;
+ _oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+
+ windows[10].open();
+ loadButtons();
+}
+
+CastSpell::~CastSpell() {
+ Interface &intf = *_vm->_interface;
+ Windows &windows = *_vm->_windows;
+
+ windows[10].close();
+ intf.unhighlightChar();
+
+ _vm->_mode = (Mode)_oldMode;
+}
+
+
+int CastSpell::show(XeenEngine *vm) {
+ Combat &combat = *vm->_combat;
+ Interface &intf = *vm->_interface;
+ Party &party = *vm->_party;
+ Spells &spells = *vm->_spells;
+ int charNum;
+
+ // Get which character is doing the casting
+ if (vm->_mode == MODE_COMBAT) {
+ charNum = combat._whosTurn;
+ } else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) {
+ charNum = spells._lastCaster;
+ } else {
+ for (charNum = (int)party._activeParty.size() - 1; charNum >= 0; --charNum) {
+ if (party._activeParty[charNum]._hasSpells) {
+ spells._lastCaster = charNum;
+ break;
+ }
+ }
+ }
+
+ Character *c = &party._activeParty[charNum];
+ intf.highlightChar(charNum);
+
+ return show(vm, c);
+}
+
+int CastSpell::show(XeenEngine *vm, Character *&c) {
+ Spells &spells = *vm->_spells;
+ CastSpell *dlg = new CastSpell(vm);
+ int spellId;
+ int result = -1;
+
+ do {
+ spellId = dlg->execute(c);
+
+ if (g_vm->shouldExit() || spellId == -1) {
+ result = 0;
+ } else {
+ result = spells.castSpell(c, (MagicSpell)spellId);
+ }
+ } while (result == -1);
+
+ delete dlg;
+ return result;
+}
+
+int CastSpell::execute(Character *&c) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[10];
+
+ int spellId = -1;
+ bool redrawFlag = true;
+ do {
+ if (redrawFlag) {
+ int category = c->getClassCategory();
+ int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39;
+ spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int gemCost = Res.SPELL_GEM_COST[spellId];
+ int spCost = spells.calcSpellPoints(spellId, c->getCurrentLevel());
+
+ w.writeString(Common::String::format(Res.CAST_SPELL_DETAILS,
+ c->_name.c_str(), spells._spellNames[spellId].c_str(),
+ spCost, gemCost, c->_currentSp));
+ drawButtons(&windows[0]);
+ w.update();
+
+ redrawFlag = false;
+ }
+
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ // Wait for event or time expiry
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && events.timeElapsed() < 1 && !_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ // Only allow changing character if the party is not in combat
+ if (_oldMode != MODE_COMBAT) {
+ _vm->_mode = (Mode)_oldMode;
+ _buttonValue -= Common::KEYCODE_F1;
+
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ redrawFlag = true;
+ break;
+ }
+ }
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ spellId = -1;
+ break;
+
+ case Common::KEYCODE_c:
+ // Cast spell - return the selected spell Id to be cast
+ if (c->_currentSpell != -1 && !c->noActions())
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_n:
+ // Select new spell
+ _vm->_mode = (Mode)_oldMode;
+ c = SpellsDialog::show(_vm, this, c, 1);
+ redrawFlag = true;
+ break;
+
+ default:
+ break;
+ }
+ } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ if (_vm->shouldExit())
+ spellId = -1;
+ return spellId;
+}
+
+void CastSpell::loadButtons() {
+ _iconSprites.load("cast.icn");
+ addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_n, &_iconSprites);
+ addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addPartyButtons(_vm);
+}
+
+/*------------------------------------------------------------------------*/
+
+Character *SpellOnWho::show(XeenEngine *vm, int spellId) {
+ SpellOnWho *dlg = new SpellOnWho(vm);
+ int result = dlg->execute(spellId);
+ delete dlg;
+
+ if (result == -1)
+ return nullptr;
+
+ Combat &combat = *vm->_combat;
+ Party &party = *vm->_party;
+ return combat._combatMode == 2 ? combat._combatParty[result] :
+ &party._activeParty[result];
+}
+
+int SpellOnWho::execute(int spellId) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[16];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+ int result = 999;
+
+ w.open();
+ w.writeString(Res.ON_WHO);
+ w.update();
+ addPartyButtons(_vm);
+
+ while (result == 999) {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return -1;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = -1;
+ spells.addSpellCost(*combat._oldCharacter, spellId);
+ break;
+
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)(combat._combatMode == 2 ? combat._combatParty.size() :
+ party._activeParty.size())) {
+ result = _buttonValue;
+ }
+ break;
+ }
+ }
+
+ w.close();
+ _vm->_mode = oldMode;
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+int SelectElement::show(XeenEngine *vm, int spellId) {
+ SelectElement *dlg = new SelectElement(vm);
+ int result = dlg->execute(spellId);
+ delete dlg;
+
+ return result;
+}
+
+int SelectElement::execute(int spellId) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[15];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+ int result = 999;
+
+ loadButtons();
+
+ w.open();
+ w.writeString(Res.WHICH_ELEMENT1);
+ drawButtons(&windows[0]);
+ w.update();
+
+ while (result == 999) {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+ w.frame();
+ w.writeString(Res.WHICH_ELEMENT2);
+ drawButtons(&windows[0]);
+ w.update();
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return -1;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = -1;
+ spells.addSpellCost(*combat._oldCharacter, spellId);
+ break;
+
+ case Common::KEYCODE_a:
+ result = DT_POISON;
+ break;
+ case Common::KEYCODE_c:
+ result = DT_COLD;
+ break;
+ case Common::KEYCODE_e:
+ result = DT_ELECTRICAL;
+ break;
+ case Common::KEYCODE_f:
+ result = DT_FIRE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ w.close();
+ _vm->_mode = oldMode;
+ return result;
+}
+
+void SelectElement::loadButtons() {
+ _iconSprites.load("element.icn");
+ addButton(Common::Rect(60, 92, 84, 112), Common::KEYCODE_f, &_iconSprites);
+ addButton(Common::Rect(90, 92, 114, 112), Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(120, 92, 144, 112), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites);
+}
+
+/*------------------------------------------------------------------------*/
+
+void NotWhileEngaged::show(XeenEngine *vm, int spellId) {
+ NotWhileEngaged *dlg = new NotWhileEngaged(vm);
+ dlg->execute(spellId);
+ delete dlg;
+}
+
+void NotWhileEngaged::execute(int spellId) {
+ EventsManager &events = *_vm->_events;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+
+ w.open();
+ w.writeString(Common::String::format(Res.CANT_CAST_WHILE_ENGAGED,
+ spells._spellNames[spellId].c_str()));
+ w.update();
+
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ events.clearEvents();
+
+ w.close();
+ _vm->_mode = oldMode;
+}
+
+/*------------------------------------------------------------------------*/
+
+bool LloydsBeacon::show(XeenEngine *vm) {
+ LloydsBeacon *dlg = new LloydsBeacon(vm);
+ bool result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+bool LloydsBeacon::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[10];
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ Character &c = *combat._oldCharacter;
+
+ loadButtons();
+
+ if (!c._lloydMap) {
+ // No destination previously set, so have a default ready
+ if (isDarkCc) {
+ c._lloydSide = 1;
+ c._lloydPosition = Common::Point(25, 21);
+ c._lloydMap = 29;
+ } else {
+ c._lloydSide = 0;
+ c._lloydPosition = Common::Point(18, 4);
+ c._lloydMap = 28;
+ }
+ }
+
+ // Open up the text file for the destination map and read in it's name
+ File textFile(Common::String::format("%s%c%03d.txt",
+ c._lloydSide == 0 ? "xeen" : "dark",
+ c._lloydMap >= 100 ? 'x' : '0',
+ c._lloydMap));
+ Common::String mapName = textFile.readString();
+ textFile.close();
+
+ // Display the dialog
+ w.open();
+ w.writeString(Common::String::format(Res.LLOYDS_BEACON,
+ mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y));
+ drawButtons(&windows[0]);
+ w.update();
+
+ bool result = true;
+ do {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return true;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_r:
+ if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) {
+ result = false;
+ } else {
+ sound.playFX(51);
+ map._loadDarkSide = isDarkCc;
+ if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) {
+ map.load(c._lloydMap);
+ }
+
+ party._mazePosition = c._lloydPosition;
+ }
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_s:
+ case Common::KEYCODE_t:
+ sound.playFX(20);
+ c._lloydMap = party._mazeId;
+ c._lloydPosition = party._mazePosition;
+ c._lloydSide = isDarkCc ? 1 : 0;
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+ }
+ } while (_buttonValue != Common::KEYCODE_ESCAPE);
+
+ w.close();
+ return result;
+}
+
+void LloydsBeacon::loadButtons() {
+ _iconSprites.load("lloyds.icn");
+
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_r, &_iconSprites);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites);
+}
+
+/*------------------------------------------------------------------------*/
+
+int Teleport::show(XeenEngine *vm) {
+ Teleport *dlg = new Teleport(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+int Teleport::execute() {
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Common::String num;
+
+ w.open();
+ w.writeString(Common::String::format(Res.HOW_MANY_SQUARES,
+ Res.DIRECTION_TEXT[party._mazeDirection]));
+ w.update();
+ int lineSize = Input::show(_vm, &w, num, 1, 200, true);
+ w.close();
+
+ if (!lineSize)
+ return -1;
+ int numSquares = atoi(num.c_str());
+ Common::Point pt = party._mazePosition;
+ int v;
+
+ switch (party._mazeDirection) {
+ case DIR_NORTH:
+ pt.y += numSquares;
+ break;
+ case DIR_EAST:
+ pt.x += numSquares;
+ break;
+ case DIR_SOUTH:
+ pt.y -= numSquares;
+ break;
+ case DIR_WEST:
+ pt.x -= numSquares;
+ break;
+ default:
+ break;
+ }
+
+ v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0);
+
+ if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) &&
+ (!map._isOutdoors || v == SURFTYPE_DWATER)) {
+ party._mazePosition = pt;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+int TownPortal::show(XeenEngine *vm) {
+ TownPortal *dlg = new TownPortal(vm);
+ int townNumber = dlg->execute();
+ delete dlg;
+
+ return townNumber;
+}
+
+int TownPortal::execute() {
+ Map &map = *_vm->_map;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[20];
+ Common::String townNames[5];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_FF;
+
+ // Build up a lsit of the names of the towns on the current side of Xeen
+ for (int idx = 0; idx < 5; ++idx) {
+ File f(Common::String::format("%s%04d.txt",
+ map._sideTownPortal ? "dark" : "xeen",
+ Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]));
+ townNames[idx] = f.readString();
+ f.close();
+ }
+
+ w.open();
+ w.writeString(Common::String::format(Res.TOWN_PORTAL,
+ townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(),
+ townNames[3].c_str(), townNames[4].c_str()
+ ));
+ w.update();
+
+ // Get the town number
+ int townNumber;
+ Common::String num;
+ do {
+ int result = Input::show(_vm, &w, num, 1, 160, true);
+ townNumber = !result ? 0 : atoi(num.c_str());
+ } while (townNumber > 5);
+
+ w.close();
+ _vm->_mode = oldMode;
+
+ return townNumber;
+}
+
+/*------------------------------------------------------------------------*/
+
+void IdentifyMonster::show(XeenEngine *vm) {
+ IdentifyMonster *dlg = new IdentifyMonster(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void IdentifyMonster::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[17];
+ Common::String monsterDesc[3];
+
+ for (int monIndex = 0; monIndex < 3; ++monIndex) {
+ if (combat._attackMonsters[monIndex] == -1)
+ continue;
+
+ MazeMonster &monster = map._mobData._monsters[combat._attackMonsters[monIndex]];
+ MonsterStruct &monsterData = *monster._monsterData;
+
+ monsterDesc[monIndex] = Common::String::format(Res.MONSTER_DETAILS,
+ monsterData._name.c_str(),
+ _vm->printK2(monster._hp).c_str(),
+ monsterData._armorClass, monsterData._numberOfAttacks,
+ Res.MONSTER_SPECIAL_ATTACKS[monsterData._specialAttack]
+ );
+ }
+
+ sound.playFX(20);
+ w.open();
+ w.writeString(Common::String::format(Res.IDENTIFY_MONSTERS,
+ monsterDesc[0].c_str(), monsterDesc[1].c_str(), monsterDesc[2].c_str()));
+ w.update();
+
+ do {
+ events.updateGameCounter();
+ intf.draw3d(false);
+ w.frame();
+ windows[3].update();
+
+ events.wait(1, false);
+ } while (!events.isKeyMousePressed());
+
+ w.close();
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_spells.h b/engines/xeen/dialogs/dialogs_spells.h
new file mode 100644
index 0000000..2bcaef4
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_spells.h
@@ -0,0 +1,151 @@
+/* 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 XEEN_DIALOGS_SPELLS_H
+#define XEEN_DIALOGS_SPELLS_H
+
+#include "common/array.h"
+#include "xeen/dialogs/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+struct SpellEntry {
+ Common::String _name;
+ int _spellIndex;
+ int _spellId;
+ int _color;
+
+ SpellEntry(const Common::String &name, int spellIndex, int spellId) :
+ _name(name), _spellIndex(spellIndex), _spellId(spellId), _color(9) {}
+};
+
+class SpellsDialog : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ SpriteResource _scrollSprites;
+ Common::Array<SpellEntry> _spells;
+
+ SpellsDialog(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ Character *execute(ButtonContainer *priorDialog, Character *c, int isCasting);
+
+ void loadButtons();
+
+ const char *setSpellText(Character *c, int isCasting);
+public:
+ static Character *show(XeenEngine *vm, ButtonContainer *priorDialog,
+ Character *c, int isCasting);
+};
+
+class CastSpell : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+ int _oldMode;
+private:
+ CastSpell(XeenEngine *vm);
+ ~CastSpell();
+
+ int execute(Character *&c);
+
+ void loadButtons();
+public:
+ static int show(XeenEngine *vm);
+ static int show(XeenEngine *vm, Character *&c);
+};
+
+class SpellOnWho : public ButtonContainer {
+private:
+ SpellOnWho(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute(int spellId);
+public:
+ static Character *show(XeenEngine *vm, int spellId);
+};
+
+class SelectElement : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ SelectElement(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute(int spellId);
+
+ void loadButtons();
+public:
+ static int show(XeenEngine *vm, int spellId);
+};
+
+class NotWhileEngaged : public ButtonContainer {
+private:
+ NotWhileEngaged(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(int spellId);
+public:
+ static void show(XeenEngine *vm, int spellId);
+};
+
+class LloydsBeacon : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ LloydsBeacon(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ bool execute();
+
+ void loadButtons();
+public:
+ static bool show(XeenEngine *vm);
+};
+
+class Teleport : public ButtonContainer {
+private:
+ SpriteResource _iconSprites;
+
+ Teleport(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute();
+public:
+ static int show(XeenEngine *vm);
+};
+
+class TownPortal : public ButtonContainer {
+private:
+ TownPortal(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute();
+public:
+ static int show(XeenEngine *vm);
+};
+
+class IdentifyMonster : public ButtonContainer {
+private:
+ IdentifyMonster(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/dialogs/dialogs_whowill.cpp b/engines/xeen/dialogs/dialogs_whowill.cpp
new file mode 100644
index 0000000..8428042
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_whowill.cpp
@@ -0,0 +1,105 @@
+/* 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 "xeen/dialogs/dialogs_whowill.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+int WhoWill::show(XeenEngine *vm, int message, int action, bool type) {
+ WhoWill *dlg = new WhoWill(vm);
+ int result = dlg->execute(message, action, type);
+ delete dlg;
+
+ return result;
+}
+
+int WhoWill::execute(int message, int action, bool type) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Scripts &scripts = *_vm->_scripts;
+ LocationManager &loc = *_vm->_locations;
+ Windows &windows = *_vm->_windows;
+ int numFrames;
+
+ if (party._activeParty.size() <= 1)
+ // Unless there's at least two characters, just return the first one
+ return 1;
+
+ windows[38].close();
+ windows[12].close();
+
+ Common::String actionStr = type ? map._events._text[action] : Res.WHO_WILL_ACTIONS[action];
+ Common::String msg = Common::String::format(Res.WHO_WILL, actionStr.c_str(),
+ Res.WHO_ACTIONS[message], party._activeParty.size());
+
+ windows[36].open();
+ windows[36].writeString(msg);
+ windows[36].update();
+
+ intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+ intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+
+ while (!_vm->shouldExit()) {
+ events.updateGameCounter();
+
+ if (windows[11]._enabled) {
+ loc.drawAnim(false);
+ windows[36].frame();
+ numFrames = 3;
+ } else {
+ intf.draw3d(false);
+ windows[36].frame();
+ windows[3].update();
+ numFrames = 1;
+ }
+
+ events.wait(numFrames);
+ checkEvents(_vm);
+ if (!_buttonValue)
+ continue;
+
+ if (_buttonValue == 27) {
+ _buttonValue = 0;
+ break;
+ } else if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+ _buttonValue -= Common::KEYCODE_F1 - 1;
+ if (_buttonValue > (int)party._activeParty.size())
+ continue;
+
+ if (party._activeParty[_buttonValue - 1].noActions())
+ continue;
+
+ scripts._whoWill = _buttonValue;
+ break;
+ }
+ }
+
+ intf._face1State = intf._face2State = 2;
+ windows[36].close();
+ return _buttonValue;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_whowill.h b/engines/xeen/dialogs/dialogs_whowill.h
new file mode 100644
index 0000000..5303bdb
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_whowill.h
@@ -0,0 +1,41 @@
+/* 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 XEEN_DIALOGS_WHOWHILL_H
+#define XEEN_DIALOGS_WHOWHILL_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class WhoWill : public ButtonContainer {
+private:
+ WhoWill(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ int execute(int message, int action, bool type);
+public:
+ static int show(XeenEngine *vm, int message, int action, bool type);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_WHOWHILL_H */
diff --git a/engines/xeen/dialogs_awards.cpp b/engines/xeen/dialogs_awards.cpp
deleted file mode 100644
index 242539c..0000000
--- a/engines/xeen/dialogs_awards.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 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 "xeen/dialogs_awards.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-void Awards::show(XeenEngine *vm, const Character *ch) {
- Awards *dlg = new Awards(vm);
- dlg->execute(ch);
- delete dlg;
-}
-
-void Awards::execute(const Character *ch) {
- EventsManager &events = *g_vm->_events;
- Windows &windows = *g_vm->_windows;
- Common::StringArray awards;
- int numAwards;
- Mode oldMode = g_vm->_mode;
- int topIndex = 0;
-
- loadStrings("award.bin", 1);
- addButtons();
-
- // Open the window and draw contents
- bool win29Open = windows[29]._enabled;
- if (!win29Open) {
- windows[29].open();
- windows[30].open();
- }
-
- windows[29].writeString(Res.AWARDS_TEXT);
- drawButtons(&windows[0]);
-
- while (!_vm->shouldExit()) {
- // Build up a list of awards the character has
- awards.clear();
- awards.resize(AWARDS_TOTAL);
- numAwards = 0;
-
- for (int awardNum = 0; awardNum < AWARDS_TOTAL; ++awardNum) {
- if (ch->hasAward(awardNum)) {
- if (awardNum == 9) {
- // # Warzone Wins
- awards[numAwards] = Common::String::format(_textStrings[9].c_str(), 28);
- } else if (awardNum == 17) {
- // Legendary Race
- awards[numAwards] = Common::String::format(_textStrings[17].c_str(),
- Res.RACE_NAMES[ch->_race]);
- } else {
- awards[numAwards] = _textStrings[awardNum];
- }
- ++numAwards;
- }
- }
-
- // If no awards, add in a message indicating so
- if (numAwards == 0) {
- awards[1] = Res.NO_AWARDS;
- }
-
- Common::String msg = Common::String::format(Res.AWARDS_FOR,
- ch->_name.c_str(), Res.CLASS_NAMES[ch->_class],
- awards[topIndex].c_str(),
- awards[topIndex + 1].c_str(),
- awards[topIndex + 2].c_str(),
- awards[topIndex + 3].c_str(),
- awards[topIndex + 4].c_str(),
- awards[topIndex + 5].c_str(),
- awards[topIndex + 6].c_str(),
- awards[topIndex + 7].c_str(),
- awards[topIndex + 8].c_str()
- );
- windows[30].writeString(msg);
- windows[24].update();
-
- // Wait for keypress
- do {
- events.pollEventsAndWait();
- checkEvents(_vm);
- } while (!g_vm->shouldExit() && !_buttonValue);
-
- if (_buttonValue == Common::KEYCODE_ESCAPE) {
- break;
- } else if (_buttonValue == Common::KEYCODE_u) {
- topIndex = MAX(topIndex - 1, 0);
- } else if (_buttonValue == Common::KEYCODE_d) {
- if ((++topIndex + 9) > numAwards)
- --topIndex;
- }
- }
-
- // Close the window
- if (win29Open) {
- windows[30].close();
- windows[29].close();
- }
-
- g_vm->_mode = oldMode;
-}
-
-void Awards::addButtons() {
- _iconSprites.load("award.icn");
- addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_u, &_iconSprites);
- addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_d, &_iconSprites);
- addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_awards.h b/engines/xeen/dialogs_awards.h
deleted file mode 100644
index 6ce3a05..0000000
--- a/engines/xeen/dialogs_awards.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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 XEEN_DIALOGS_AWARDS_H
-#define XEEN_DIALOGS_AWARDS_H
-
-#include "xeen/dialogs.h"
-#include "xeen/character.h"
-
-namespace Xeen {
-
-class Awards : public ButtonContainer {
-private:
- SpriteResource _iconSprites;
-private:
- Awards(XeenEngine *vm) : ButtonContainer(vm) {}
-
- /**
- * Executes the dialog
- */
- void execute(const Character *ch);
-
- /**
- * Add buttons for the dialog
- */
- void addButtons();
-public:
- static void show(XeenEngine *vm, const Character *ch);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_AWARDS_H */
diff --git a/engines/xeen/dialogs_char_info.cpp b/engines/xeen/dialogs_char_info.cpp
deleted file mode 100644
index 3d9ebfb..0000000
--- a/engines/xeen/dialogs_char_info.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/* 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 "xeen/dialogs_awards.h"
-#include "xeen/dialogs_char_info.h"
-#include "xeen/dialogs_exchange.h"
-#include "xeen/dialogs_items.h"
-#include "xeen/dialogs_quick_ref.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-void CharacterInfo::show(XeenEngine *vm, int charIndex) {
- CharacterInfo *dlg = new CharacterInfo(vm);
- dlg->execute(charIndex);
- delete dlg;
-}
-
-void CharacterInfo::execute(int charIndex) {
- Combat &combat = *_vm->_combat;
- EventsManager &events = *_vm->_events;
- Interface &intf = *_vm->_interface;
- Party &party = *_vm->_party;
- Windows &windows = *_vm->_windows;
-
- bool redrawFlag = true;
- Mode oldMode = _vm->_mode;
- _vm->_mode = MODE_CHARACTER_INFO;
- loadDrawStructs();
- addButtons();
-
- Character *c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
- intf.highlightChar(charIndex);
- Window &w = windows[24];
- w.open();
-
- do {
- if (redrawFlag) {
- Common::String charDetails = loadCharacterDetails(*c);
- w.writeString(Common::String::format(Res.CHARACTER_TEMPLATE, charDetails.c_str()));
- w.drawList(_drawList, 24);
- w.update();
- redrawFlag = false;
- }
-
- // Wait for keypress, showing a blinking cursor
- events.updateGameCounter();
- bool cursorFlag = false;
- _buttonValue = 0;
- while (!_vm->shouldExit() && !_buttonValue) {
- events.pollEventsAndWait();
- if (events.timeElapsed() > 4) {
- cursorFlag = !cursorFlag;
- events.updateGameCounter();
- }
-
- showCursor(cursorFlag);
- w.update();
- checkEvents(_vm);
- }
- events.clearEvents();
-
- switch (_buttonValue) {
- case Common::KEYCODE_F1:
- case Common::KEYCODE_F2:
- case Common::KEYCODE_F3:
- case Common::KEYCODE_F4:
- case Common::KEYCODE_F5:
- case Common::KEYCODE_F6:
- _buttonValue -= Common::KEYCODE_F1;
- if (_buttonValue < (int)(oldMode == MODE_COMBAT ? combat._combatParty.size() : party._activeParty.size())) {
- charIndex = _buttonValue;
- c = (oldMode != MODE_COMBAT) ? &party._activeParty[charIndex] : combat._combatParty[charIndex];
- } else {
- _vm->_mode = MODE_CHARACTER_INFO;
- }
-
- intf.highlightChar(_buttonValue);
- redrawFlag = true;
- break;
-
- case Common::KEYCODE_UP:
- case Common::KEYCODE_KP8:
- if (_cursorCell > 0) {
- showCursor(false);
- --_cursorCell;
- showCursor(true);
- }
- w.update();
- break;
-
- case Common::KEYCODE_DOWN:
- case Common::KEYCODE_KP2:
- if (_cursorCell < 20) {
- showCursor(false);
- ++_cursorCell;
- showCursor(true);
- }
- w.update();
- break;
-
- case Common::KEYCODE_LEFT:
- case Common::KEYCODE_KP4:
- if (_cursorCell >= 5) {
- showCursor(false);
- _cursorCell -= 5;
- showCursor(true);
- }
- w.update();
- break;
-
- case Common::KEYCODE_RIGHT:
- case Common::KEYCODE_KP6:
- if (_cursorCell <= 15) {
- showCursor(false);
- _cursorCell += 5;
- showCursor(true);
- }
- w.update();
- break;
-
- case Common::KEYCODE_RETURN:
- case Common::KEYCODE_KP_ENTER:
- _buttonValue = _cursorCell + Common::KEYCODE_a;
- // Deliberate fall-through
-
- case 1001:
- case 1002:
- case 1003:
- case 1004:
- case 1005:
- case 1006:
- case 1007:
- case 1008:
- case 1009:
- case 1010:
- case 1011:
- case 1012:
- case 1013:
- case 1014:
- case 1015:
- case 1016:
- case 1017:
- case 1018:
- case 1019:
- case 1020: {
- showCursor(false);
- _cursorCell = _buttonValue - 1001;
- showCursor(true);
- w.update();
-
- bool result = expandStat(_cursorCell, *c);
- _vm->_mode = MODE_COMBAT;
- if (result)
- redrawFlag = true;
- break;
- }
-
- case Common::KEYCODE_e:
- if (oldMode == MODE_COMBAT) {
- ErrorScroll::show(_vm, Res.EXCHANGING_IN_COMBAT, WT_FREEZE_WAIT);
- } else {
- _vm->_mode = oldMode;
- ExchangeDialog::show(_vm, c, charIndex);
- _vm->_mode = MODE_CHARACTER_INFO;
- redrawFlag = true;
- }
- break;
-
- case Common::KEYCODE_i:
- _vm->_mode = oldMode;
- _vm->_combat->_itemFlag = _vm->_mode == MODE_COMBAT;
- c = ItemsDialog::show(_vm, c, ITEMMODE_CHAR_INFO);
-
- if (!c) {
- party._stepped = true;
- goto exit;
- }
-
- _vm->_mode = MODE_CHARACTER_INFO;
- break;
-
- case Common::KEYCODE_q:
- QuickReferenceDialog::show(_vm);
- redrawFlag = true;
- break;
-
- case Common::KEYCODE_ESCAPE:
- goto exit;
- }
- } while (!_vm->shouldExit());
-exit:
- w.close();
- intf.unhighlightChar();
- _vm->_mode = oldMode;
- _vm->_combat->_itemFlag = false;
-}
-
-void CharacterInfo::loadDrawStructs() {
- _drawList[0] = DrawStruct(0, 2, 16);
- _drawList[1] = DrawStruct(2, 2, 39);
- _drawList[2] = DrawStruct(4, 2, 62);
- _drawList[3] = DrawStruct(6, 2, 85);
- _drawList[4] = DrawStruct(8, 2, 108);
- _drawList[5] = DrawStruct(10, 53, 16);
- _drawList[6] = DrawStruct(12, 53, 39);
- _drawList[7] = DrawStruct(14, 53, 62);
- _drawList[8] = DrawStruct(16, 53, 85);
- _drawList[9] = DrawStruct(18, 53, 108);
- _drawList[10] = DrawStruct(20, 104, 16);
- _drawList[11] = DrawStruct(22, 104, 39);
- _drawList[12] = DrawStruct(24, 104, 62);
- _drawList[13] = DrawStruct(26, 104, 85);
- _drawList[14] = DrawStruct(28, 104, 108);
- _drawList[15] = DrawStruct(30, 169, 16);
- _drawList[16] = DrawStruct(32, 169, 39);
- _drawList[17] = DrawStruct(34, 169, 62);
- _drawList[18] = DrawStruct(36, 169, 85);
- _drawList[19] = DrawStruct(38, 169, 108);
- _drawList[20] = DrawStruct(40, 277, 3);
- _drawList[21] = DrawStruct(42, 277, 35);
- _drawList[22] = DrawStruct(44, 277, 67);
- _drawList[23] = DrawStruct(46, 277, 99);
-
- _iconSprites.load("view.icn");
- for (int idx = 0; idx < 24; ++idx)
- _drawList[idx]._sprites = &_iconSprites;
-}
-
-void CharacterInfo::addButtons() {
- addButton(Common::Rect(10, 24, 34, 44), 1001, &_iconSprites);
- addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites);
- addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites);
- addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites);
- addButton(Common::Rect(10, 116, 34, 136), 1005, &_iconSprites);
- addButton(Common::Rect(61, 24, 85, 44), 1006, &_iconSprites);
- addButton(Common::Rect(61, 47, 85, 67), 1007, &_iconSprites);
- addButton(Common::Rect(61, 70, 85, 90), 1008, &_iconSprites);
- addButton(Common::Rect(61, 93, 85, 113), 1009, &_iconSprites);
- addButton(Common::Rect(61, 116, 85, 136), 1010, &_iconSprites);
- addButton(Common::Rect(112, 24, 136, 44), 1011, &_iconSprites);
- addButton(Common::Rect(112, 47, 136, 67), 1012, &_iconSprites);
- addButton(Common::Rect(112, 70, 136, 90), 1013, &_iconSprites);
- addButton(Common::Rect(112, 93, 136, 113), 1014, &_iconSprites);
- addButton(Common::Rect(112, 116, 136, 136), 1015, &_iconSprites);
- addButton(Common::Rect(177, 24, 201, 44), 1016, &_iconSprites);
- addButton(Common::Rect(177, 47, 201, 67), 1017, &_iconSprites);
- addButton(Common::Rect(177, 70, 201, 90), 1018, &_iconSprites);
- addButton(Common::Rect(177, 93, 201, 113), 1019, &_iconSprites);
- addButton(Common::Rect(177, 116, 201, 136), 1020, &_iconSprites);
- addButton(Common::Rect(285, 11, 309, 31), Common::KEYCODE_i, &_iconSprites);
- addButton(Common::Rect(285, 43, 309, 63), Common::KEYCODE_q, &_iconSprites);
- addButton(Common::Rect(285, 75, 309, 95), Common::KEYCODE_e, &_iconSprites);
- addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites);
- addPartyButtons(_vm);
-}
-
-Common::String CharacterInfo::loadCharacterDetails(const Character &c) {
- Condition condition = c.worstCondition();
- Party &party = *_vm->_party;
- int foodVal = party._food / party._activeParty.size() / 3;
-
- int totalResist =
- c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary +
- c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary +
- c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary +
- c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary +
- c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary +
- c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary;
-
- return Common::String::format(Res.CHARACTER_DETAILS,
- Res.PARTY_GOLD, c._name.c_str(), Res.SEX_NAMES[c._sex],
- Res.RACE_NAMES[c._race], Res.CLASS_NAMES[c._class],
- c.statColor(c.getStat(MIGHT), c.getStat(MIGHT, true)), c.getStat(MIGHT),
- c.statColor(c.getStat(ACCURACY), c.getStat(ACCURACY, true)), c.getStat(ACCURACY),
- c.statColor(c._currentHp, c.getMaxHP()), c._currentHp,
- c.getCurrentExperience(),
- c.statColor(c.getStat(INTELLECT), c.getStat(INTELLECT, true)), c.getStat(INTELLECT),
- c.statColor(c.getStat(LUCK), c.getStat(LUCK, true)), c.getStat(LUCK),
- c.statColor(c._currentSp, c.getMaxSP()), c._currentSp,
- party._gold,
- c.statColor(c.getStat(PERSONALITY), c.getStat(PERSONALITY, true)), c.getStat(PERSONALITY),
- c.statColor(c.getAge(), c.getAge(true)), c.getAge(),
- totalResist,
- party._gems,
- c.statColor(c.getStat(ENDURANCE), c.getStat(ENDURANCE, true)), c.getStat(ENDURANCE),
- c.statColor(c.getCurrentLevel(), c._level._permanent), c.getCurrentLevel(),
- c.getNumSkills(),
- foodVal, (foodVal == 1) ? ' ' : 's',
- c.statColor(c.getStat(SPEED), c.getStat(SPEED, true)), c.getStat(SPEED),
- c.statColor(c.getArmorClass(), c.getArmorClass(true)), c.getArmorClass(),
- c.getNumAwards(),
- Res.CONDITION_COLORS[condition], Res.CONDITION_NAMES[condition],
- condition == NO_CONDITION && party._blessed ? Res.PLUS_14 : "",
- condition == NO_CONDITION && party._powerShield ? Res.PLUS_14 : "",
- condition == NO_CONDITION && party._holyBonus ? Res.PLUS_14 : "",
- condition == NO_CONDITION && party._heroism ? Res.PLUS_14 : ""
- );
-}
-
-void CharacterInfo::showCursor(bool flag) {
- const int CURSOR_X[5] = { 9, 60, 111, 176, 0 };
- const int CURSOR_Y[5] = { 23, 46, 69, 92, 115 };
-
- if (_cursorCell < 20) {
- _iconSprites.draw(0, flag ? 49 : 48,
- Common::Point(CURSOR_X[_cursorCell / 5], CURSOR_Y[_cursorCell % 5]));
- }
-}
-
-bool CharacterInfo::expandStat(int attrib, const Character &c) {
- const int STAT_POS[2][20] = {
- {
- 61, 61, 61, 61, 61, 112, 112, 112, 112, 112,
- 177, 177, 177, 177, 177, 34, 34, 34, 34, 34
- }, {
- 24, 47, 70, 93, 116, 24, 47, 70, 93, 116,
- 24, 47, 70, 93, 116, 24, 47, 70, 93, 116
- }
- };
- assert(attrib < 20);
- Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
- STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
- Party &party = *_vm->_party;
- Windows &windows = *_vm->_windows;
- uint stat1, stat2;
- uint idx;
- Common::String msg;
-
- switch (attrib) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- // Basic attributes
- stat1 = c.getStat((Attribute)attrib, false);
- stat2 = c.getStat((Attribute)attrib, true);
- idx = 0;
- while (Res.STAT_VALUES[idx] <= (int)stat1)
- ++idx;
-
- msg = Common::String::format(Res.CURRENT_MAXIMUM_RATING_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2, Res.RATING_TEXT[idx]);
- break;
-
- case 7:
- // Age
- stat1 = c.getAge(false);
- stat2 = c.getAge(true);
- msg = Common::String::format(Res.AGE_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2, c._birthDay, c._birthYear);
- break;
-
- case 8: {
- // Level
- const int CLASS_ATTACK_GAINS[10] = { 5, 6, 6, 7, 8, 6, 5, 4, 7, 6 };
- idx = c.getCurrentLevel() / CLASS_ATTACK_GAINS[c._class] + 1;
-
- msg = Common::String::format(Res.LEVEL_TEXT, Res.STAT_NAMES[attrib],
- c.getCurrentLevel(), c._level._permanent,
- idx, idx > 1 ? "s" : "",
- c._level._permanent);
- break;
- }
-
- case 9:
- // Armor Class
- stat1 = c.getArmorClass(false);
- stat2 = c.getArmorClass(true);
- msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2);
- bounds.setHeight(42);
- break;
-
- case 10:
- // Hit Points
- stat1 = c._currentHp;
- stat2 = c.getMaxHP();
- msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2);
- bounds.setHeight(42);
- break;
-
- case 11:
- // Spell Points
- stat1 = c._currentSp;
- stat2 = c.getMaxSP();
- msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2);
- bounds.setHeight(42);
- break;
-
- case 12:
- // Resistences
- msg = Common::String::format(Res.RESISTENCES_TEXT, Res.STAT_NAMES[attrib],
- c._fireResistence._permanent + c.itemScan(11) + c._fireResistence._temporary,
- c._coldResistence._permanent + c.itemScan(13) + c._coldResistence._temporary,
- c._electricityResistence._permanent + c.itemScan(12) + c._electricityResistence._temporary,
- c._poisonResistence._permanent + c.itemScan(14) + c._poisonResistence._temporary,
- c._energyResistence._permanent + c.itemScan(15) + c._energyResistence._temporary,
- c._magicResistence._permanent + c.itemScan(16) + c._magicResistence._temporary);
- bounds.setHeight(80);
- break;
-
- case 13: {
- // Skills
- Common::String lines[20];
- int numLines = c.getNumSkills();
- if (numLines > 0) {
- for (int skill = THIEVERY; skill <= DANGER_SENSE; ++skill) {
- if (c._skills[skill]) {
- if (skill == THIEVERY) {
- lines[0] = Common::String::format("\n\t020%s%u",
- Res.SKILL_NAMES[THIEVERY], c.getThievery());
- } else {
- lines[skill] = Common::String::format("\n\t020%s", Res.SKILL_NAMES[skill]);
- }
- }
- }
- } else {
- lines[0] = Res.NONE;
- numLines = 1;
- }
-
- msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
- Res.STAT_NAMES[attrib], lines[0].c_str(), lines[1].c_str(),
- lines[2].c_str(), lines[3].c_str(), lines[4].c_str(), lines[5].c_str(),
- lines[17].c_str(), lines[6].c_str(), lines[7].c_str(), lines[8].c_str(),
- lines[9].c_str(), lines[10].c_str(), lines[11].c_str(), lines[12].c_str(),
- lines[13].c_str(), lines[16].c_str(), lines[14].c_str(), lines[15].c_str());
-
- bounds.top -= (numLines / 2) * 8;
- bounds.setHeight(numLines * 9 + 26);
- if (bounds.bottom >= SCREEN_HEIGHT)
- bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
- break;
- }
-
- case 14:
- // Awards
- Awards::show(_vm, &c);
- return false;
-
- case 15:
- // Experience
- stat1 = c.getCurrentExperience();
- stat2 = c.experienceToNextLevel();
- msg = Common::String::format(Res.EXPERIENCE_TEXT,
- Res.STAT_NAMES[attrib], stat1,
- stat2 == 0 ? Res.ELIGIBLE : Common::String::format("%d", stat2).c_str()
- );
- bounds.setHeight(43);
- break;
-
- case 16:
- // Gold
- msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[0],
- party._gold, party._bankGold);
- bounds.setHeight(43);
- break;
-
- case 17:
- // Gems
- msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[1],
- party._gems, party._bankGems);
- bounds.setHeight(43);
- break;
-
- case 18: {
- // Food
- int food = (party._food / party._activeParty.size()) / 3;
- msg = Common::String::format(Res.FOOD_TEXT, Res.CONSUMABLE_NAMES[2],
- party._food, food, food != 1 ? "s" : "");
- break;
- }
-
- case 19: {
- // Conditions
- Common::String lines[20];
- int total = 0;
- for (int condition = CURSED; condition <= ERADICATED; ++condition) {
- if (c._conditions[condition]) {
- if (condition >= UNCONSCIOUS) {
- lines[condition] = Common::String::format("\n\t020%s",
- Res.CONDITION_NAMES[condition]);
- } else {
- lines[condition] = Common::String::format("\n\t020%s\t095-%d",
- Res.CONDITION_NAMES[condition], c._conditions[condition]);
- }
-
- ++total;
- }
- }
-
- Condition condition = c.worstCondition();
- if (condition == NO_CONDITION) {
- lines[0] = Common::String::format("\n\t020%s", Res.GOOD);
- ++total;
- }
-
- if (party._blessed)
- lines[16] = Common::String::format(Res.BLESSED, party._blessed);
- if (party._powerShield)
- lines[17] = Common::String::format(Res.POWER_SHIELD, party._powerShield);
- if (party._holyBonus)
- lines[18] = Common::String::format(Res.HOLY_BONUS, party._holyBonus);
- if (party._heroism)
- lines[19] = Common::String::format(Res.HEROISM, party._heroism);
-
- msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1",
- Res.CONSUMABLE_NAMES[3], lines[0].c_str(), lines[1].c_str(),
- lines[2].c_str(), lines[3].c_str(), lines[4].c_str(),
- lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
- lines[8].c_str(), lines[9].c_str(), lines[10].c_str(),
- lines[11].c_str(), lines[12].c_str(), lines[13].c_str(),
- lines[14].c_str(), lines[15].c_str(), lines[16].c_str(),
- lines[17].c_str(), lines[18].c_str(), lines[19].c_str()
- );
-
- bounds.top -= ((total - 1) / 2) * 8;
- bounds.setHeight(total * 9 + 26);
- if (bounds.bottom >= SCREEN_HEIGHT)
- bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
- break;
- }
-
- default:
- break;
- }
-
- // Write the data for the stat display
- Window &w = windows[28];
- w.setBounds(bounds);
- w.open();
- w.writeString(msg);
- w.update();
-
- // Wait for a user key/click
- EventsManager &events = *_vm->_events;
- while (!_vm->shouldExit() && !events.isKeyMousePressed())
- events.pollEventsAndWait();
- events.clearEvents();
-
- w.close();
- return false;
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_char_info.h b/engines/xeen/dialogs_char_info.h
deleted file mode 100644
index 5f53870..0000000
--- a/engines/xeen/dialogs_char_info.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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 XEEN_DIALOGS_CHAR_INFO_H
-#define XEEN_DIALOGS_CHAR_INFO_H
-
-#include "xeen/dialogs.h"
-#include "xeen/party.h"
-#include "xeen/window.h"
-
-namespace Xeen {
-
-class CharacterInfo : public ButtonContainer {
-private:
- SpriteResource _iconSprites;
- DrawStruct _drawList[24];
- int _cursorCell;
-
- CharacterInfo(XeenEngine *vm) : ButtonContainer(vm), _cursorCell(0) {}
-
- void execute(int charIndex);
-
- /**
- * Load the draw structure list with frame numbers and positions
- */
- void loadDrawStructs();
-
- /**
- * Set up the button list for the dialog
- */
- void addButtons();
-
- /**
- * Return a string containing the details of the character
- */
- Common::String loadCharacterDetails(const Character &c);
-
- /**
- * Cursor display handling
- */
- void showCursor(bool flag);
-
- bool expandStat(int attrib, const Character &c);
-public:
- static void show(XeenEngine *vm, int charIndex);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_CHAR_INFO_H */
diff --git a/engines/xeen/dialogs_control_panel.cpp b/engines/xeen/dialogs_control_panel.cpp
deleted file mode 100644
index d2129e4..0000000
--- a/engines/xeen/dialogs_control_panel.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/* 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 "xeen/dialogs_control_panel.h"
-#include "xeen/dialogs_query.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-int ControlPanel::show(XeenEngine *vm) {
- ControlPanel *dlg = new ControlPanel(vm);
- int result = dlg->execute();
- delete dlg;
-
- return result;
-}
-
-int ControlPanel::execute() {
- EventsManager &events = *_vm->_events;
- Interface &intf = *_vm->_interface;
- Map &map = *_vm->_map;
- Party &party = *_vm->_party;
- SavesManager &saves = *_vm->_saves;
- Sound &sound = *_vm->_sound;
- Windows &windows = *_vm->_windows;
- Window &w = windows[23];
- Window &w3 = windows[3];
-
- loadButtons();
-
- int result = 0, debugCtr = 0;
- w.open();
-
- do {
- Common::String btnText = getButtonText();
- Common::String text = Common::String::format(Res.CONTROL_PANEL_TEXT, btnText.c_str());
-
- drawButtons(&w);
- w.writeString(text);
- w.writeString("\xB""000\t000\x1");
- w.update();
-
- do {
- events.updateGameCounter();
- intf.draw3d(false, false);
- w.writeString("\r");
- drawButtons(&w);
- w.writeString(text);
- w.writeString("\v000\t000");
- w.frame();
-
- if (_debugFlag)
- w.writeString(getTimeText());
-
- w3.update();
- w.update();
-
- events.pollEventsAndWait();
- checkEvents(_vm);
- if (_vm->shouldExit())
- return 0;
- } while (!_buttonValue && !events.timeElapsed());
-
- switch (_buttonValue) {
- case Common::KEYCODE_q:
- if (Confirm::show(g_vm, Res.CONFIRM_QUIT)) {
- g_vm->_gameMode = GMODE_QUIT;
- result = 1;
- }
- break;
-
- case Common::KEYCODE_w:
- if (Confirm::show(g_vm, Res.MR_WIZARD)) {
- w.close();
- if (!windows[2]._enabled) {
- sound.playFX(51);
-
- if (g_vm->getGameID() == GType_WorldOfXeen) {
- map._loadDarkSide = false;
- map.load(28);
- party._mazeDirection = DIR_EAST;
- } else {
- map._loadDarkSide = true;
- map.load(29);
- party._mazeDirection = DIR_SOUTH;
- }
- party.moveToRunLocation();
- }
-
- party._gems = 0;
- result = 2;
- }
- break;
-
- case Common::KEYCODE_l:
- if (_vm->_mode == MODE_COMBAT) {
- ErrorScroll::show(_vm, Res.NO_LOADING_IN_COMBAT);
- } else {
- // Close dialog and show loading dialog
- result = 3;
- }
- break;
-
- case Common::KEYCODE_s:
- if (_vm->_mode == MODE_COMBAT) {
- ErrorScroll::show(_vm, Res.NO_SAVING_IN_COMBAT);
- } else {
- // Close dialog and show saving dialog
- result = 4;
- }
- break;
-
- case Common::KEYCODE_e:
- sound.setEffectsOn(!sound._soundOn);
- break;
-
- case Common::KEYCODE_m:
- sound.setMusicOn(!sound._musicOn);
- break;
-
- case Common::KEYCODE_ESCAPE:
- result = 1;
- break;
-
- // Goober cheat sequence
- case Common::KEYCODE_g:
- debugCtr = 1;
- break;
- case Common::KEYCODE_o:
- debugCtr = (debugCtr == 1 || debugCtr == 2) ? 2 : 0;
- break;
- case Common::KEYCODE_b:
- debugCtr = (debugCtr == 2) ? 3 : 0;
- break;
- case Common::KEYCODE_r:
- if (debugCtr == 3)
- _debugFlag = true;
- else
- debugCtr = 0;
- break;
-
- default:
- break;
- }
- } while (!result);
-
- w.close();
- intf.drawParty(true);
-
- if (result == 3) {
- saves.loadGame();
- } else if (result == 4) {
- saves.saveGame();
- }
-
- return result;
-}
-
-void ControlPanel::loadButtons() {
- _iconSprites.load("cpanel.icn");
-
- addButton(Common::Rect(214, 56, 244, 69), Common::KEYCODE_e, 0, &_iconSprites);
- addButton(Common::Rect(214, 75, 244, 88), Common::KEYCODE_m, 0, &_iconSprites);
- addButton(Common::Rect(135, 56, 165, 69), Common::KEYCODE_l, 0, &_iconSprites);
- addButton(Common::Rect(135, 75, 165, 88), Common::KEYCODE_s, 0, &_iconSprites);
-
- // For ScummVM we've merged both Save and Save As into a single
- // save item, so we don't need this one
- addButton(Common::Rect(), 0);
-
- addButton(Common::Rect(135, 94, 165, 107), Common::KEYCODE_q, 0, &_iconSprites);
- addButton(Common::Rect(175, 113, 205, 126), Common::KEYCODE_w, 0, &_iconSprites);
-}
-
-Common::String ControlPanel::getButtonText() {
- Sound &sound = *g_vm->_sound;
- _btnSoundText = sound._soundOn ? Res.ON : Res.OFF;
- _btnMusicText = sound._musicOn ? Res.ON : Res.OFF;
-
- return Common::String::format(Res.CONTROL_PANEL_BUTTONS,
- _btnSoundText.c_str(), _btnMusicText.c_str());
-}
-
-Common::String ControlPanel::getTimeText() const {
- TimeDate td;
- g_system->getTimeAndDate(td);
- Common::String timeStr = Common::String::format("%d:%.2d:%.2d%c",
- td.tm_hour == 0 || td.tm_hour == 12 ? 12 : (td.tm_hour % 12),
- td.tm_min, td.tm_sec, (td.tm_hour >= 12) ? 'p' : 'c');
-
- uint32 playtime = g_vm->_events->playTime() / GAME_FRAME_RATE;
- Common::String playtimeStr = Common::String::format("%d:%.2d:%.2d",
- playtime / 3600, (playtime / 60) % 60, playtime % 60);
- return Common::String::format(
- "\x2\x3l\xB""000\t000\x4""160%s\x3r\xB""000\t000%s\x1",
- timeStr.c_str(), playtimeStr.c_str());
-}
-
-} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_control_panel.h b/engines/xeen/dialogs_control_panel.h
deleted file mode 100644
index b87e78d..0000000
--- a/engines/xeen/dialogs_control_panel.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* 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 XEEN_DIALOGS_CONTROL_PANEL_H
-#define XEEN_DIALOGS_CONTROL_PANEL_H
-
-#include "xeen/dialogs.h"
-
-namespace Xeen {
-
-class ControlPanel : public ButtonContainer {
-private:
- SpriteResource _iconSprites;
- Common::String _btnSoundText, _btnMusicText;
- bool _debugFlag;
-private:
- ControlPanel(XeenEngine *vm) : ButtonContainer(vm), _debugFlag(false) {}
-
- /**
- * Inner handler for showing the dialog
- */
- int execute();
-
- /**
- * Loads the buttons for the dialog
- */
- void loadButtons();
-
- /**
- * Gets the text for the dialog buttons
- */
- Common::String getButtonText();
-
- /**
- * Gets the current time
- */
- Common::String getTimeText() const;
-public:
- /**
- * Show the control panel
- */
- static int show(XeenEngine *vm);
-};
-
-} // End of namespace Xeen
-
-#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */
diff --git a/engines/xeen/dialogs_create_char.cpp b/engines/xeen/dialogs_create_char.cpp
deleted file mode 100644
index 73aa4b3..0000000
--- a/engines/xeen/dialogs_create_char.cpp
+++ /dev/null
@@ -1,648 +0,0 @@
-/* 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 "xeen/dialogs_create_char.h"
-#include "xeen/dialogs_input.h"
-#include "xeen/xeen.h"
-
-namespace Xeen {
-
-void CreateCharacterDialog::show(XeenEngine *vm) {
- CreateCharacterDialog *dlg = new CreateCharacterDialog(vm);
- dlg->execute();
- delete dlg;
-}
-
-CreateCharacterDialog::CreateCharacterDialog(XeenEngine *vm) : ButtonContainer(vm) {
- Common::fill(&_attribs[0], &_attribs[TOTAL_ATTRIBUTES], 0);
- Common::fill(&_allowedClasses[0], &_allowedClasses[TOTAL_CLASSES], false);
- _dicePos[0] = Common::Point(20, 17);
- _dicePos[1] = Common::Point(112, 35);
- _dicePos[2] = Common::Point(61, 50);
- _diceFrame[0] = 0;
- _diceFrame[1] = 2;
- _diceFrame[2] = 4;
- _diceInc[0] = Common::Point(10, -10);
- _diceInc[1] = Common::Point(-10, -10);
- _diceInc[2] = Common::Point(-10, 10);
-
- _dice.load("dice.vga");
- _diceSize = _dice.getFrameSize(0);
-
- loadButtons();
-}
-
-void CreateCharacterDialog::execute() {
- EventsManager &events = *_vm->_events;
- Party &party = *_vm->_party;
- Screen &screen = *_vm->_screen;
- Windows &windows = *_vm->_windows;
- Window &w = windows[0];
- Common::Array<int> freeCharList;
- int classId = -1;
- int selectedClass = 0;
- bool hasFadedIn = false;
- bool restartFlag = true;
- Race race = HUMAN;
- Sex sex = MALE;
- Common::String msg, details;
- int charIndex = 0;
-
- Mode oldMode = _vm->_mode;
- _vm->_mode = MODE_4;
-
- // Load the background
- screen.loadBackground("create.raw");
- events.setCursor(0);
-
- while (!_vm->shouldExit()) {
- if (restartFlag) {
- // Build up list of roster slot indexes that are free
- freeCharList.clear();
- for (uint idx = 0; idx < XEEN_TOTAL_CHARACTERS; ++idx) {
- if (party._roster[idx]._name.empty())
- freeCharList.push_back(idx);
- }
- charIndex = 0;
-
- if (freeCharList.size() == XEEN_TOTAL_CHARACTERS)
- break;
-
- // Get and race and sex for the given character
- race = (Race)((freeCharList[charIndex] / 4) % 5);
- sex = (Sex)(freeCharList[charIndex] & 1);
-
- // Randomly determine attributes, and which classes they allow
- rollAttributes();
-
- // Get the display of the rolled character details
- selectedClass = newCharDetails(race, sex, classId, selectedClass, details);
- msg = Common::String::format(Res.CREATE_CHAR_DETAILS,
- details.c_str());
-
- // Draw the icons and the currently selected headshot
- drawIcons();
- party._roster[freeCharList[charIndex]]._faceSprites->draw(
- w, 0, Common::Point(27, 102));
-
- // Render all on-screen text
- w.writeString(msg);
- w.update();
-
- // Draw the arrow for the selected class, if applicable
- if (selectedClass != -1)
- printSelectionArrow(selectedClass);
-
- // Draw the dice
- drawDice();
- if (!hasFadedIn) {
- screen.fadeIn();
- hasFadedIn = true;
- }
-
- restartFlag = false;
- }
-
- // Animate the dice until a user action occurs
- _buttonValue = 0;
- while (!_vm->shouldExit() && !_buttonValue)
- drawDice();
-
- // Handling for different actions
- if (_buttonValue == Common::KEYCODE_ESCAPE)
- break;
-
- switch (_buttonValue) {
- case Common::KEYCODE_UP:
- if (charIndex == 0)
- continue;
-
- --charIndex;
- race = (Race)((freeCharList[charIndex] / 4) % 5);
- sex = (Sex)(freeCharList[charIndex] & 1);
- break;
-
- case Common::KEYCODE_DOWN:
- if (++charIndex == (int)freeCharList.size()) {
- --charIndex;
- continue;
- } else {
- race = (Race)((freeCharList[charIndex] / 4) % 5);
- sex = (Sex)(freeCharList[charIndex] & 1);
- }
- break;
-
- case Common::KEYCODE_PAGEUP:
- for (int tempClass = selectedClass - 1; tempClass >= 0; --tempClass) {
- if (_allowedClasses[tempClass]) {
- selectedClass = tempClass;
- break;
- }
- }
-
- printSelectionArrow(selectedClass);
- continue;
-
- case Common::KEYCODE_PAGEDOWN:
- break;
-
- case Common::KEYCODE_m:
- case Common::KEYCODE_i:
- case Common::KEYCODE_p:
- case Common::KEYCODE_e:
- case Common::KEYCODE_s:
- case Common::KEYCODE_a:
- case Common::KEYCODE_l:
- if (swapAttributes(_buttonValue)) {
- checkClass();
- classId = -1;
- selectedClass = newCharDetails(race, sex, classId, selectedClass, msg);
- }
- break;
-
- case 1000:
- case 1001:
- case 1002:
- case 1003:
- case 1004:
- case 1005:
- case 1006:
- case 1007:
- case 1008:
- case 1009:
- if (_allowedClasses[_buttonValue - 1000]) {
- selectedClass = classId = _buttonValue - 1000;
- }
- break;
-
- case Common::KEYCODE_c: {
- _vm->_mode = MODE_FF;
- bool result = saveCharacter(party._roster[freeCharList[charIndex]],
- classId, race, sex);
- _vm->_mode = MODE_4;
-
- if (result)
- restartFlag = true;
- continue;
- }
-
- case Common::KEYCODE_RETURN:
- classId = selectedClass;
- break;
-
- case Common::KEYCODE_SPACE:
- case Common::KEYCODE_r:
- // Re-roll the attributes
- rollAttributes();
- classId = -1;
- break;
-
- default:
- // For all other keypresses, skip the code below the switch
- // statement, and go to wait for the next key
- continue;
- }
-
- if (_buttonValue != Common::KEYCODE_PAGEDOWN) {
- selectedClass = newCharDetails(race, sex, classId, selectedClass, msg);
-
- drawIcons2();
- party._roster[freeCharList[charIndex]]._faceSprites->draw(w, 0,
- Common::Point(27, 102));
-
- w.writeString(msg);
- w.update();
-
- if (selectedClass != -1) {
- printSelectionArrow(selectedClass);
- continue;
- }
- }
-
- // Move to next available class, or if the code block above resulted in
- // selectedClass being -1, move to select the first available class
- for (int tempClass = selectedClass + 1; tempClass <= CLASS_RANGER; ++tempClass) {
- if (_allowedClasses[tempClass]) {
- selectedClass = tempClass;
- break;
- }
- }
-
- printSelectionArrow(selectedClass);
- } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
-
- _vm->_mode = oldMode;
-}
-
-void CreateCharacterDialog::loadButtons() {
- _icons.load("create.icn");
-
- // Add buttons
- addButton(Common::Rect(132, 98, 156, 118), Common::KEYCODE_r, &_icons);
- addButton(Common::Rect(132, 128, 156, 148), Common::KEYCODE_c, &_icons);
- addButton(Common::Rect(132, 158, 156, 178), Common::KEYCODE_ESCAPE, &_icons);
- addButton(Common::Rect(86, 98, 110, 118), Common::KEYCODE_UP, &_icons);
- addButton(Common::Rect(86, 120, 110, 140), Common::KEYCODE_DOWN, &_icons);
- addButton(Common::Rect(168, 19, 192, 39), Common::KEYCODE_n, nullptr);
- addButton(Common::Rect(168, 43, 192, 63), Common::KEYCODE_i, nullptr);
- addButton(Common::Rect(168, 67, 192, 87), Common::KEYCODE_p, nullptr);
- addButton(Common::Rect(168, 91, 192, 111), Common::KEYCODE_e, nullptr);
- addButton(Common::Rect(168, 115, 192, 135), Common::KEYCODE_s, nullptr);
- addButton(Common::Rect(168, 139, 192, 159), Common::KEYCODE_a, nullptr);
- addButton(Common::Rect(168, 163, 192, 183), Common::KEYCODE_l, nullptr);
- addButton(Common::Rect(227, 19, 239, 29), 1000, nullptr);
- addButton(Common::Rect(227, 30, 239, 40), 1001, nullptr);
- addButton(Common::Rect(227, 41, 239, 51), 1002, nullptr);
- addButton(Common::Rect(227, 52, 239, 62), 1003, nullptr);
- addButton(Common::Rect(227, 63, 239, 73), 1004, nullptr);
- addButton(Common::Rect(227, 74, 239, 84), 1005, nullptr);
- addButton(Common::Rect(227, 85, 239, 95), 1006, nullptr);
- addButton(Common::Rect(227, 96, 239, 106), 1007, nullptr);
- addButton(Common::Rect(227, 107, 239, 117), 1008, nullptr);
- addButton(Common::Rect(227, 118, 239, 128), 1009, nullptr);
-}
-
-void CreateCharacterDialog::drawIcons() {
- // Draw the screen
- _icons.draw(0, 10, Common::Point(168, 19));
- _icons.draw(0, 12, Common::Point(168, 43));
- _icons.draw(0, 14, Common::Point(168, 67));
- _icons.draw(0, 16, Common::Point(168, 91));
- _icons.draw(0, 18, Common::Point(168, 115));
- _icons.draw(0, 20, Common::Point(168, 139));
- _icons.draw(0, 22, Common::Point(168, 163));
- for (int idx = 0; idx < 9; ++idx)
- _icons.draw(0, 24 + idx * 2, Common::Point(227, 19 + 11 * idx));
-
- for (int idx = 0; idx < 7; ++idx)
- _icons.draw(0, 50 + idx, Common::Point(195, 31 + 24 * idx));
-
- _icons.draw(0, 57, Common::Point(62, 148));
- _icons.draw(0, 58, Common::Point(62, 158));
- _icons.draw(0, 59, Common::Point(62, 168));
- _icons.draw(0, 61, Common::Point(220, 19));
- _icons.draw(0, 64, Common::Point(220, 155));
- _icons.draw(0, 65, Common::Point(220, 170));
-
- _icons.draw(0, 0, Common::Point(132, 98));
- _icons.draw(0, 2, Common::Point(132, 128));
- _icons.draw(0, 4, Common::Point(132, 158));
- _icons.draw(0, 6, Common::Point(86, 98));
- _icons.draw(0, 8, Common::Point(86, 120));
-}
-
-void CreateCharacterDialog::drawIcons2() {
- for (int idx = 0; idx < 7; ++idx)
- _icons.draw(0, 10 + idx * 2, Common::Point(168, 19 + idx * 24));
- for (int idx = 0; idx < 10; ++idx)
- _icons.draw(0, 24 + idx * 2, Common::Point(227, 19 + idx * 11));
- for (int idx = 0; idx < 8; ++idx)
- _icons.draw(0, 50 + idx, Common::Point(195, 31 + idx * 24));
-
- _icons.draw(0, 57, Common::Point(62, 148));
- _icons.draw(0, 58, Common::Point(62, 158));
- _icons.draw(0, 59, Common::Point(62, 168));
- _icons.draw(0, 61, Common::Point(220, 19));
- _icons.draw(0, 64, Common::Point(220, 155));
- _icons.draw(0, 65, Common::Point(220, 170));
-
- _icons.draw(0, 0, Common::Point(132, 98));
- _icons.draw(0, 2, Common::Point(132, 128));
- _icons.draw(0, 4, Common::Point(132, 158));
- _icons.draw(0, 6, Common::Point(86, 98));
- _icons.draw(0, 8, Common::Point(86, 120));
-}
-
-void CreateCharacterDialog::rollAttributes() {
- bool repeat = true;
- do {
- // Default all the attributes to zero
- Common::fill(&_attribs[0], &_attribs[TOTAL_ATTRIBUTES], 0);
-
- // Assign random amounts to each attribute
- for (int idx1 = 0; idx1 < 3; ++idx1) {
- for (int idx2 = 0; idx2 < TOTAL_ATTRIBUTES; ++idx2) {
- _attribs[idx2] += _vm->getRandomNumber(10, 79) / 10;
- }
- }
-
- // Check which classes are allowed based on the rolled attributes
- checkClass();
-
- // Only exit if the attributes allow for at least one class
- for (int idx = 0; idx < TOTAL_CLASSES; ++idx) {
- if (_allowedClasses[idx])
- repeat = false;
- }
- } while (repeat);
-}
-
-void CreateCharacterDialog::checkClass() {
- _allowedClasses[CLASS_KNIGHT] = _attribs[MIGHT] >= 15;
- _allowedClasses[CLASS_PALADIN] = _attribs[MIGHT] >= 13
Commit: 67d4de1bb818b2cfc628549ba38cc4f00b8236b2
https://github.com/scummvm/scummvm/commit/67d4de1bb818b2cfc628549ba38cc4f00b8236b2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Move Credits and Please Wait classes into their own files
Changed paths:
A engines/xeen/dialogs/credits_screen.cpp
A engines/xeen/dialogs/credits_screen.h
A engines/xeen/dialogs/please_wait.cpp
A engines/xeen/dialogs/please_wait.h
engines/xeen/dialogs/dialogs.cpp
engines/xeen/dialogs/dialogs.h
engines/xeen/map.cpp
engines/xeen/module.mk
engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
engines/xeen/worldofxeen/worldofxeen_menu.cpp
diff --git a/engines/xeen/dialogs/credits_screen.cpp b/engines/xeen/dialogs/credits_screen.cpp
new file mode 100644
index 0000000..8fe0387
--- /dev/null
+++ b/engines/xeen/dialogs/credits_screen.cpp
@@ -0,0 +1,72 @@
+/* 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 "xeen/dialogs/credits_screen.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void CreditsScreen::show(XeenEngine *vm) {
+ CreditsScreen *dlg = new CreditsScreen(vm);
+
+ switch (vm->getGameID()) {
+ case GType_Clouds:
+ dlg->execute(Res.CLOUDS_CREDITS);
+ break;
+ case GType_Swords:
+ dlg->execute(Res.SWORDS_CREDITS1);
+ dlg->execute(Res.SWORDS_CREDITS2);
+ break;
+ default:
+ dlg->execute(Res.DARK_SIDE_CREDITS);
+ break;
+ }
+
+ delete dlg;
+}
+
+void CreditsScreen::execute(const char *content) {
+ Screen &screen = *_vm->_screen;
+ Windows &windows = *_vm->_windows;
+ EventsManager &events = *_vm->_events;
+
+ // Handle drawing the credits screen
+ doScroll(true, false);
+ windows[GAME_WINDOW].close();
+
+ screen.loadBackground("marb.raw");
+ windows[0].writeString(content);
+ doScroll(false, false);
+
+ events.setCursor(0);
+ windows[0].update();
+ clearButtons();
+
+ // Wait for keypress
+ while (!events.isKeyMousePressed())
+ events.pollEventsAndWait();
+
+ doScroll(true, false);
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/credits_screen.h b/engines/xeen/dialogs/credits_screen.h
new file mode 100644
index 0000000..b52839d
--- /dev/null
+++ b/engines/xeen/dialogs/credits_screen.h
@@ -0,0 +1,41 @@
+/* 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 XEEN_DIALOGS_CREDITS_SCREEN_H
+#define XEEN_DIALOGS_CREDITS_SCREEN_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class CreditsScreen: public ButtonContainer {
+private:
+ CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute(const char *content);
+public:
+ static void show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CREDITS_SCREEN_H */
diff --git a/engines/xeen/dialogs/dialogs.cpp b/engines/xeen/dialogs/dialogs.cpp
index c9b5658..d7a696b 100644
--- a/engines/xeen/dialogs/dialogs.cpp
+++ b/engines/xeen/dialogs/dialogs.cpp
@@ -187,71 +187,4 @@ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
checkEvents(_vm);
}
-/*------------------------------------------------------------------------*/
-
-void CreditsScreen::show(XeenEngine *vm) {
- CreditsScreen *dlg = new CreditsScreen(vm);
-
- switch (vm->getGameID()) {
- case GType_Clouds:
- dlg->execute(Res.CLOUDS_CREDITS);
- break;
- case GType_Swords:
- dlg->execute(Res.SWORDS_CREDITS1);
- dlg->execute(Res.SWORDS_CREDITS2);
- break;
- default:
- dlg->execute(Res.DARK_SIDE_CREDITS);
- break;
- }
-
- delete dlg;
-}
-
-void CreditsScreen::execute(const char *content) {
- Screen &screen = *_vm->_screen;
- Windows &windows = *_vm->_windows;
- EventsManager &events = *_vm->_events;
-
- // Handle drawing the credits screen
- doScroll(true, false);
- windows[GAME_WINDOW].close();
-
- screen.loadBackground("marb.raw");
- windows[0].writeString(content);
- doScroll(false, false);
-
- events.setCursor(0);
- windows[0].update();
- clearButtons();
-
- // Wait for keypress
- while (!events.isKeyMousePressed())
- events.pollEventsAndWait();
-
- doScroll(true, false);
-}
-
-/*------------------------------------------------------------------------*/
-
-PleaseWait::PleaseWait(bool isOops) {
- _msg = isOops ? Res.OOPS : Res.PLEASE_WAIT;
-}
-
-PleaseWait::~PleaseWait() {
- Windows &windows = *g_vm->_windows;
- windows[9].close();
-}
-
-void PleaseWait::show() {
- Windows &windows = *g_vm->_windows;
- Window &w = windows[9];
-
- if (g_vm->_mode != MODE_0) {
- w.open();
- w.writeString(_msg);
- w.update();
- }
-}
-
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs.h b/engines/xeen/dialogs/dialogs.h
index cabc921..9038f75 100644
--- a/engines/xeen/dialogs/dialogs.h
+++ b/engines/xeen/dialogs/dialogs.h
@@ -113,25 +113,6 @@ public:
virtual ~SettingsBaseDialog() {}
};
-class CreditsScreen: public ButtonContainer {
-private:
- CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
-
- void execute(const char *content);
-public:
- static void show(XeenEngine *vm);
-};
-
-class PleaseWait {
-private:
- Common::String _msg;
-public:
- PleaseWait(bool isOops = false);
- ~PleaseWait();
-
- void show();
-};
-
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs/please_wait.cpp b/engines/xeen/dialogs/please_wait.cpp
new file mode 100644
index 0000000..749c6a8
--- /dev/null
+++ b/engines/xeen/dialogs/please_wait.cpp
@@ -0,0 +1,50 @@
+/* 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 "xeen/dialogs/please_wait.h"
+#include "xeen/resources.h"
+#include "xeen/window.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+PleaseWait::PleaseWait(bool isOops) {
+ _msg = isOops ? Res.OOPS : Res.PLEASE_WAIT;
+}
+
+PleaseWait::~PleaseWait() {
+ Windows &windows = *g_vm->_windows;
+ windows[9].close();
+}
+
+void PleaseWait::show() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[9];
+
+ if (g_vm->_mode != MODE_0) {
+ w.open();
+ w.writeString(_msg);
+ w.update();
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/please_wait.h b/engines/xeen/dialogs/please_wait.h
new file mode 100644
index 0000000..0432e55
--- /dev/null
+++ b/engines/xeen/dialogs/please_wait.h
@@ -0,0 +1,45 @@
+/* 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 XEEN_DIALOGS_PLEASE_WAIT_H
+#define XEEN_DIALOGS_PLEASE_WAIT_H
+
+#include "xeen/dialogs/dialogs.h"
+
+namespace Xeen {
+
+class PleaseWait {
+private:
+ Common::String _msg;
+public:
+ PleaseWait(bool isOops = false);
+ ~PleaseWait();
+
+ /**
+ * Show the dialog
+ */
+ void show();
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_PLEASE_WAIT_H */
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d57d258..63068cd 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -27,6 +27,7 @@
#include "xeen/saves.h"
#include "xeen/screen.h"
#include "xeen/xeen.h"
+#include "xeen/dialogs/please_wait.h"
namespace Xeen {
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a49d5a3..b3e0d9a 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -9,11 +9,7 @@ MODULE_OBJS := \
worldofxeen/worldofxeen_resources.o \
swordsofxeen/swordsofxeen.o \
swordsofxeen/swordsofxeen_menu.o \
- character.o \
- combat.o \
- cutscenes.o \
- debugger.o \
- detection.o \
+ dialogs/credits_screen.o \
dialogs/dialogs.o \
dialogs/dialogs_awards.o \
dialogs/dialogs_char_info.o \
@@ -34,6 +30,12 @@ MODULE_OBJS := \
dialogs/dialogs_quick_ref.o \
dialogs/dialogs_spells.o \
dialogs/dialogs_whowill.o \
+ dialogs/please_wait.o \
+ character.o \
+ combat.o \
+ cutscenes.o \
+ debugger.o \
+ detection.o \
events.o \
files.o \
font.o \
diff --git a/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp b/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
index 6eb6a64..14f2083 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
+++ b/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
@@ -21,6 +21,7 @@
*/
#include "xeen/swordsofxeen/swordsofxeen_menu.h"
+#include "xeen/dialogs/credits_screen.h"
#include "xeen/dialogs/dialogs_difficulty.h"
#include "xeen/xeen.h"
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index c0aa900..4797309 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -23,6 +23,7 @@
#include "common/scummsys.h"
#include "xeen/worldofxeen/worldofxeen_menu.h"
#include "xeen/worldofxeen/worldofxeen.h"
+#include "xeen/dialogs/credits_screen.h"
#include "xeen/dialogs/dialogs_difficulty.h"
#include "xeen/resources.h"
Commit: b6b9714ec02aa4b927ace42cb9699de899494f91
https://github.com/scummvm/scummvm/commit/b6b9714ec02aa4b927ace42cb9699de899494f91
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Fix scroll effect for Clouds of Xeen main menu
Changed paths:
engines/xeen/cutscenes.cpp
engines/xeen/screen.cpp
engines/xeen/screen.h
engines/xeen/worldofxeen/worldofxeen_menu.cpp
diff --git a/engines/xeen/cutscenes.cpp b/engines/xeen/cutscenes.cpp
index 05d9fa7..1be9cc3 100644
--- a/engines/xeen/cutscenes.cpp
+++ b/engines/xeen/cutscenes.cpp
@@ -116,99 +116,7 @@ uint Cutscenes::getSpeakingFrame(uint minFrame, uint maxFrame) {
}
bool Cutscenes::doScroll(bool rollUp, bool fadeIn) {
- Screen &screen = *_vm->_screen;
- EventsManager &events = *_vm->_events;
- const int SCROLL_L[8] = { 29, 23, 15, -5, -11, -23, -49, -71 };
- const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
-
- if (_vm->_files->_isDarkCc) {
- if (fadeIn)
- screen.fadeIn(2);
- return _vm->shouldExit();
- }
-
- screen.saveBackground();
-
- // Load hand sprites
- SpriteResource *hand[16];
- for (int i = 0; i < 16; ++i) {
- Common::String name = Common::String::format("hand%02d.vga", i);
- hand[i] = new SpriteResource(name);
- }
-
- // Load marb sprites
- SpriteResource *marb[5];
- for (int i = 0; i < 4; ++i) {
- Common::String name = Common::String::format("marb%02d.vga", i + 1);
- marb[i] = new SpriteResource(name);
- }
-
- if (rollUp) {
- for (int i = 22, ctr = 7; i > 0 && !events.isKeyMousePressed()
- && !_vm->shouldExit(); --i) {
- events.updateGameCounter();
- screen.restoreBackground();
-
- if (i > 14) {
- hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
- hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
- --ctr;
- } else if (i != 0) {
- hand[i - 1]->draw(0, 0);
- }
-
- if (i <= 20)
- marb[(i - 1) / 5]->draw(0, (i - 1) % 5);
- screen.update();
-
- while (!_vm->shouldExit() && events.timeElapsed() == 0)
- events.pollEventsAndWait();
-
- if (i == 0 && fadeIn)
- screen.fadeIn(2);
- }
- } else {
- for (int i = 0, ctr = 0; i < 22 && !events.isKeyMousePressed()
- && !_vm->shouldExit(); ++i) {
- events.updateGameCounter();
- screen.restoreBackground();
-
- if (i < 14) {
- hand[i]->draw(0, 0);
- } else {
- hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
- hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
- ++ctr;
- }
-
- if (i < 20) {
- marb[i / 5]->draw(0, i % 5);
- }
- screen.update();
-
- while (!_vm->shouldExit() && events.timeElapsed() == 0)
- events.pollEventsAndWait();
-
- if (i == 0 && fadeIn)
- screen.fadeIn(2);
- }
- }
-
- if (rollUp) {
- hand[0]->draw(0, 0);
- marb[0]->draw(0, 0);
- } else {
- screen.restoreBackground();
- }
- screen.update();
-
- // Free resources
- for (int i = 0; i < 4; ++i)
- delete marb[i];
- for (int i = 0; i < 16; ++i)
- delete hand[i];
-
- return _vm->shouldExit() || events.isKeyMousePressed();
+ return _vm->_screen->doScroll(rollUp, fadeIn);
}
} // End of namespace Xeen
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index 2c92ee1..8dc7ec8 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -163,4 +163,100 @@ void Screen::restoreBackground(int slot) {
blitFrom(_savedScreens[slot - 1]);
}
+bool Screen::doScroll(bool rollUp, bool fadeIn) {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ const int SCROLL_L[8] = { 29, 23, 15, -5, -11, -23, -49, -71 };
+ const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
+
+ if (_vm->_files->_isDarkCc) {
+ if (fadeIn)
+ screen.fadeIn(2);
+ return _vm->shouldExit();
+ }
+
+ screen.saveBackground();
+
+ // Load hand sprites
+ SpriteResource *hand[16];
+ for (int i = 0; i < 16; ++i) {
+ Common::String name = Common::String::format("hand%02d.vga", i);
+ hand[i] = new SpriteResource(name);
+ }
+
+ // Load marb sprites
+ SpriteResource *marb[5];
+ for (int i = 0; i < 4; ++i) {
+ Common::String name = Common::String::format("marb%02d.vga", i + 1);
+ marb[i] = new SpriteResource(name);
+ }
+
+ if (rollUp) {
+ for (int i = 22, ctr = 7; i > 0 && !events.isKeyMousePressed()
+ && !_vm->shouldExit(); --i) {
+ events.updateGameCounter();
+ screen.restoreBackground();
+
+ if (i > 14) {
+ hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
+ hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
+ --ctr;
+ } else if (i != 0) {
+ hand[i - 1]->draw(0, 0);
+ }
+
+ if (i <= 20)
+ marb[(i - 1) / 5]->draw(0, (i - 1) % 5);
+ screen.update();
+
+ while (!_vm->shouldExit() && events.timeElapsed() == 0)
+ events.pollEventsAndWait();
+
+ if (i == 0 && fadeIn)
+ screen.fadeIn(2);
+ }
+ } else {
+ for (int i = 0, ctr = 0; i < 22 && !events.isKeyMousePressed()
+ && !_vm->shouldExit(); ++i) {
+ events.updateGameCounter();
+ screen.restoreBackground();
+
+ if (i < 14) {
+ hand[i]->draw(0, 0);
+ } else {
+ hand[14]->draw(0, 0, Common::Point(SCROLL_L[ctr], 0), SPRFLAG_800);
+ hand[15]->draw(0, 0, Common::Point(SCROLL_R[ctr], 0), SPRFLAG_800);
+ ++ctr;
+ }
+
+ if (i < 20) {
+ marb[i / 5]->draw(0, i % 5);
+ }
+ screen.update();
+
+ while (!_vm->shouldExit() && events.timeElapsed() == 0)
+ events.pollEventsAndWait();
+
+ if (i == 0 && fadeIn)
+ screen.fadeIn(2);
+ }
+ }
+
+ if (rollUp) {
+ hand[0]->draw(0, 0);
+ marb[0]->draw(0, 0);
+ } else {
+ screen.restoreBackground();
+ }
+ screen.update();
+
+ // Free resources
+ for (int i = 0; i < 4; ++i)
+ delete marb[i];
+ for (int i = 0; i < 16; ++i)
+ delete hand[i];
+
+ return _vm->shouldExit() || events.isKeyMousePressed();
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index 5028b50..3e7f23e 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -112,6 +112,14 @@ public:
* Restores a previously saved screen
*/
void restoreBackground(int slot = 1);
+
+ /**
+ * Draws the scroll in the background
+ * @param rollUp If true, rolls up the scroll. If false, unrolls.
+ * @param fadeIn If true, does an initial fade in
+ * @returns True if key or mouse pressed
+ */
+ bool doScroll(bool rollUp, bool fadeIn);
};
} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 4797309..356bb8c 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -70,6 +70,7 @@ void MainMenuContainer::draw() {
void MainMenuContainer::execute() {
EventsManager &events = *g_vm->_events;
+ Screen &screen = *g_vm->_screen;
bool showFlag = false;
// Show the cursor
@@ -77,6 +78,8 @@ void MainMenuContainer::execute() {
events.setCursor(0);
events.showCursor();
+ screen.doScroll(true, false);
+
while (!g_vm->shouldExit() && g_vm->_gameMode == GMODE_NONE) {
// Draw the menu
draw();
@@ -86,7 +89,7 @@ void MainMenuContainer::execute() {
// Fade/scroll in screen if first frame
if (!showFlag) {
loadBackground();
- // TODO: doScroll(false, false);
+ screen.doScroll(false, false);
showFlag = true;
}
Commit: badbeda5e2e4bad22a3f15582f1d0d4801682df6
https://github.com/scummvm/scummvm/commit/badbeda5e2e4bad22a3f15582f1d0d4801682df6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Implemented Dark Side of Xeen menu
Changed paths:
engines/xeen/dialogs/credits_screen.cpp
engines/xeen/worldofxeen/worldofxeen_menu.cpp
engines/xeen/worldofxeen/worldofxeen_menu.h
diff --git a/engines/xeen/dialogs/credits_screen.cpp b/engines/xeen/dialogs/credits_screen.cpp
index 8fe0387..09547ba 100644
--- a/engines/xeen/dialogs/credits_screen.cpp
+++ b/engines/xeen/dialogs/credits_screen.cpp
@@ -63,7 +63,7 @@ void CreditsScreen::execute(const char *content) {
clearButtons();
// Wait for keypress
- while (!events.isKeyMousePressed())
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
events.pollEventsAndWait();
doScroll(true, false);
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 356bb8c..d1d6814 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -51,7 +51,8 @@ void MainMenuContainer::show() {
delete menu;
}
-MainMenuContainer::MainMenuContainer(const Common::String &spritesName) : _animateCtr(0), _dialog(nullptr) {
+MainMenuContainer::MainMenuContainer(const Common::String &spritesName, uint frameCount) :
+ _frameCount(frameCount), _animateCtr(0), _dialog(nullptr) {
_backgroundSprites.load(spritesName);
}
@@ -64,7 +65,7 @@ MainMenuContainer::~MainMenuContainer() {
void MainMenuContainer::draw() {
g_vm->_screen->restoreBackground();
- _animateCtr = (_animateCtr + 1) % 9;
+ _animateCtr = (_animateCtr + 1) % _frameCount;
_backgroundSprites.draw(0, _animateCtr);
}
@@ -86,7 +87,7 @@ void MainMenuContainer::execute() {
if (_dialog)
_dialog->draw();
- // Fade/scroll in screen if first frame
+ // Fade/scroll in screen if first frame showing screen
if (!showFlag) {
loadBackground();
screen.doScroll(false, false);
@@ -101,8 +102,8 @@ void MainMenuContainer::execute() {
// There's a dialog active, so let it handle the event
_dialog->handleEvents();
- // If dialog was removed as a result of the event, flag screen for re-showing
- // if the menu screen isn't being left
+ // If dialog was removed as a result of the event, flag screen for re-showing,
+ // such as returning to main menu from the Credits screen
if (!_dialog)
showFlag = false;
} else {
@@ -123,7 +124,7 @@ void MainMenuContainer::execute() {
/*------------------------------------------------------------------------*/
-CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga") {
+CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga", 9) {
g_vm->_sound->playSong("inn.m");
}
@@ -140,31 +141,40 @@ void CloudsMainMenuContainer::showMenuDialog() {
/*------------------------------------------------------------------------*/
-DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("intro.vga") {
- g_vm->_sound->playSong("inn.m");
+DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("title2a.int", 10) {
+ Screen &screen = *g_vm->_screen;
+ Sound &sound = *g_vm->_sound;
+ screen.loadPalette("dark.pal");
+ screen.fadeIn(0x81);
+ sound.playSong("newbrigh.m");
+
+ _background.load("title2.int");
}
void DarkSideMainMenuContainer::loadBackground() {
Screen &screen = *g_vm->_screen;
- screen.loadPalette("mm4.pal");
- screen.loadBackground("intro.raw");
+ _background.draw(0, 0, Common::Point(0, 0));
+ _background.draw(0, 1, Common::Point(160, 0));
+
+ screen.loadPalette("dark.pal");
screen.saveBackground();
}
void DarkSideMainMenuContainer::showMenuDialog() {
- setOwner(new CloudsMenuDialog(this));
+ setOwner(new DarkSideMenuDialog(this));
}
/*------------------------------------------------------------------------*/
-WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("intro.vga") {
- g_vm->_sound->playSong("inn.m");
+WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("world.int", 5) {
+ Sound &sound = *g_vm->_sound;
+ sound.playSong("newbrigh.m");
}
void WorldOfXeenMainMenuContainer::loadBackground() {
Screen &screen = *g_vm->_screen;
- screen.loadPalette("mm4.pal");
- screen.loadBackground("intro.raw");
+ screen.loadPalette("dark.pal");
+ screen.loadBackground("world.raw");
screen.saveBackground();
}
@@ -206,6 +216,10 @@ bool MainMenuDialog::handleEvents() {
CreditsScreen::show(g_vm);
break;
+ case Common::KEYCODE_ESCAPE:
+ // Exit dialog (returning to just the animated background)
+ break;
+
default:
return false;
}
@@ -276,6 +290,139 @@ bool CloudsMenuDialog::handleEvents() {
/*------------------------------------------------------------------------*/
+DarkSideMenuDialog::DarkSideMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner), _firstDraw(true) {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.setBounds(Common::Rect(72, 25, 248, 150));
+ w.open();
+
+ loadButtons();
+}
+
+DarkSideMenuDialog::~DarkSideMenuDialog() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.close();
+}
+
+void DarkSideMenuDialog::loadButtons() {
+ addButton(Common::Rect(124, 87, 177, 97), Common::KEYCODE_s);
+ addButton(Common::Rect(126, 98, 173, 108), Common::KEYCODE_l);
+ addButton(Common::Rect(91, 110, 209, 120), Common::KEYCODE_c);
+ addButton(Common::Rect(85, 121, 216, 131), Common::KEYCODE_o);
+}
+
+void DarkSideMenuDialog::draw() {
+ Screen &screen = *g_vm->_screen;
+ EventsManager &events = *g_vm->_events;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+
+ if (!_firstDraw)
+ return;
+
+ SpriteResource kludgeSprites("kludge.int");
+ SpriteResource title2Sprites[8] = {
+ SpriteResource("title2b.int"), SpriteResource("title2c.int"),
+ SpriteResource("title2d.int"), SpriteResource("title2e.int"),
+ SpriteResource("title2f.int"), SpriteResource("title2g.int"),
+ SpriteResource("title2h.int"), SpriteResource("title2i.int"),
+ };
+
+ screen.loadBackground("title2b.raw");
+ kludgeSprites.draw(0, 0, Common::Point(85, 86));
+ screen.saveBackground();
+ sound.playSound("elect.voc");
+
+ for (int i = 0; i < 30 && !g_vm->shouldExit(); ++i) {
+ events.updateGameCounter();
+ screen.restoreBackground();
+ title2Sprites[i / 4].draw(0, i % 4);
+ windows[0].update();
+
+ if (i == 19)
+ sound.stopSound();
+
+ if (events.wait(2))
+ break;
+ }
+
+ events.clearEvents();
+ sound.stopSound();
+
+ screen.restoreBackground();
+ windows[0].update();
+ _firstDraw = false;
+}
+
+bool DarkSideMenuDialog::handleEvents() {
+ if (MainMenuDialog::handleEvents())
+ return true;
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_o:
+ // Show other options dialog
+ // TODO
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/*------------------------------------------------------------------------*/
+
+WorldMenuDialog::WorldMenuDialog(MainMenuContainer *owner) : MainMenuDialog(owner) {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.setBounds(Common::Rect(72, 25, 248, 175));
+ w.open();
+
+ loadButtons();
+}
+
+WorldMenuDialog::~WorldMenuDialog() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.close();
+}
+
+void WorldMenuDialog::loadButtons() {
+ _buttonSprites.load("start.icn");
+ addButton(Common::Rect(93, 53, 227, 73), Common::KEYCODE_s, &_buttonSprites);
+ addButton(Common::Rect(93, 78, 227, 98), Common::KEYCODE_l, &_buttonSprites);
+ addButton(Common::Rect(93, 103, 227, 123), Common::KEYCODE_c, &_buttonSprites);
+ addButton(Common::Rect(93, 128, 227, 148), Common::KEYCODE_o, &_buttonSprites);
+}
+
+void WorldMenuDialog::draw() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+
+ w.frame();
+ w.writeString(Common::String::format(Res.CLOUDS_MAIN_MENU, g_vm->_gameWon[0] ? 117 : 92));
+ drawButtons(&w);
+}
+
+bool WorldMenuDialog::handleEvents() {
+ if (MainMenuDialog::handleEvents())
+ return true;
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_o:
+ // Show other options dialog
+ // TODO
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
} // End of namespace WorldOfXeen
} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.h b/engines/xeen/worldofxeen/worldofxeen_menu.h
index 92d770b..1db78b9 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.h
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.h
@@ -33,7 +33,8 @@ class MainMenuDialog;
class MainMenuContainer {
private:
- int _animateCtr;
+ uint _animateCtr;
+ uint _frameCount;
SpriteResource _backgroundSprites;
MainMenuDialog *_dialog;
protected:
@@ -60,7 +61,7 @@ public:
/**
* Constructor
*/
- MainMenuContainer(const Common::String &spritesName);
+ MainMenuContainer(const Common::String &spritesName, uint frameCount);
/**
* Destructor
@@ -96,6 +97,8 @@ public:
};
class DarkSideMainMenuContainer : public MainMenuContainer {
+private:
+ SpriteResource _background;
protected:
/**
* Load the background
@@ -206,6 +209,67 @@ public:
virtual bool handleEvents();
};
+class DarkSideMenuDialog : public MainMenuDialog {
+private:
+ SpriteResource _buttonSprites;
+ bool _firstDraw;
+private:
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
+public:
+ /**
+ * Constructor
+ */
+ DarkSideMenuDialog(MainMenuContainer *owner);
+
+ /**
+ * Destructor
+ */
+ virtual ~DarkSideMenuDialog();
+
+ /**
+ * Draws the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents();
+};
+
+class WorldMenuDialog : public MainMenuDialog {
+private:
+ SpriteResource _buttonSprites;
+private:
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
+public:
+ /**
+ * Constructor
+ */
+ WorldMenuDialog(MainMenuContainer *owner);
+
+ /**
+ * Destructor
+ */
+ virtual ~WorldMenuDialog();
+
+ /**
+ * Draws the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents();
+};
+
} // End of namespace WorldOfXeen
} // End of namespace Xeen
Commit: 66bd71f6f37b29b2b859052d8ebff7f3c3cc054e
https://github.com/scummvm/scummvm/commit/66bd71f6f37b29b2b859052d8ebff7f3c3cc054e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Finish World of Xeen main menu
Changed paths:
engines/xeen/sound.cpp
engines/xeen/worldofxeen/worldofxeen_menu.cpp
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index 2fb8807..95aabbe 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -173,8 +173,7 @@ void Sound::playSong(const Common::String &name, int param) {
Common::File mf;
if (mf.open(name)) {
playSong(mf);
- }
- else {
+ } else {
File f(name, _musicSide);
playSong(f);
}
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index d1d6814..7b60a70 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -146,6 +146,8 @@ DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("titl
Sound &sound = *g_vm->_sound;
screen.loadPalette("dark.pal");
screen.fadeIn(0x81);
+
+ sound._musicSide = 1;
sound.playSong("newbrigh.m");
_background.load("title2.int");
@@ -168,6 +170,7 @@ void DarkSideMainMenuContainer::showMenuDialog() {
WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("world.int", 5) {
Sound &sound = *g_vm->_sound;
+ sound._musicSide = 1;
sound.playSong("newbrigh.m");
}
@@ -179,7 +182,7 @@ void WorldOfXeenMainMenuContainer::loadBackground() {
}
void WorldOfXeenMainMenuContainer::showMenuDialog() {
- setOwner(new CloudsMenuDialog(this));
+ setOwner(new WorldMenuDialog(this));
}
/*------------------------------------------------------------------------*/
@@ -402,7 +405,7 @@ void WorldMenuDialog::draw() {
Window &w = windows[GAME_WINDOW];
w.frame();
- w.writeString(Common::String::format(Res.CLOUDS_MAIN_MENU, g_vm->_gameWon[0] ? 117 : 92));
+ w.writeString(Res.WORLD_MAIN_MENU);
drawButtons(&w);
}
Commit: 59fc48501cf395da1bf6cf1887e7f1f81160e64a
https://github.com/scummvm/scummvm/commit/59fc48501cf395da1bf6cf1887e7f1f81160e64a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Fix game credits text in create_xeen
Changed paths:
devtools/create_xeen/constants.cpp
diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp
index 2df74e2..a0cdb18 100644
--- a/devtools/create_xeen/constants.cpp
+++ b/devtools/create_xeen/constants.cpp
@@ -96,41 +96,41 @@ const char *const CLOUDS_CREDITS =
"\t190Michael Suarez\x3""c";
const char *const DARK_SIDE_CREDITS =
- "\013""012\010""000\003""c\014""35Designed and Directed By:\n"
- "\014""17Jon Van Caneghem\003""l\n"
+ "\v012\t000\x3""c\f35Designed and Directed By:\n"
+ "\f17Jon Van Caneghem\x3""l\n"
"\n"
- "\t025\014""35Programming:\n"
- "\t035\014""17Mark Caldwell\n"
+ "\t025\f35Programming:\n"
+ "\t035\f17Mark Caldwell\n"
"\t035Dave Hathaway\n"
"\n"
- "\t025\014""35Sound System & FX:\n"
- "\t035\014""17Mike Heilemann\n"
+ "\t025\f35Sound System & FX:\n"
+ "\t035\f17Mike Heilemann\n"
"\n"
- "\t025\014""35Music & Speech:\n"
- "\t035\014""17Tim Tully\n"
+ "\t025\f35Music & Speech:\n"
+ "\t035\f17Tim Tully\n"
"\n"
- "\t025\014""35Writing:\n"
- "\t035\014""17Paul Rattner\n"
+ "\t025\f35Writing:\n"
+ "\t035\f17Paul Rattner\n"
"\t035Debbie Van Caneghem\n"
- "\t035Jon Van Caneghem\013""012\n"
+ "\t035Jon Van Caneghem\v012\n"
"\n"
"\n"
- "\t180\014""35Graphics:\n"
- "\t190\014""17Jonathan P. Gwyn\n"
+ "\t180\f35Graphics:\n"
+ "\t190\f17Jonathan P. Gwyn\n"
"\t190Bonita Long-Hemsath\n"
"\t190Julia Ulano\n"
"\t190Ricardo Barrera\n"
"\n"
- "\t180\014""35Testing:\n"
- "\t190\014""17Benjamin Bent\n"
+ "\t180\f35Testing:\n"
+ "\t190\f17Benjamin Bent\n"
"\t190Christian Dailey\n"
"\t190Mario Escamilla\n"
"\t190Marco Hunter\n"
"\t190Robert J. Lupo\n"
"\t190Clayton Retzer\n"
- "\t190David Vela\003""c";
+ "\t190David Vela\x3""c";
const char *const SWORDS_CREDITS1 =
- "\v012\x3""c35Published By New World Computing, Inc.\f17\n"
+ "\v012\x3""c\f35Published By New World Computing, Inc.\f17\n"
"Developed By CATware, Inc.\x3l\n"
"\f01Design and Direction\t180Series Created by\n"
"\t020Bill Fawcett\t190John Van Caneghem\n"
@@ -148,7 +148,7 @@ const char *const SWORDS_CREDITS1 =
"\t190Julia Ulano\n"
"\t190Ricardo Barrera\n";
const char *const SWORDS_CREDITS2 =
- "\f05v012\t000\x3l\n"
+ "\f05\v012\t000\x3l\n"
"\t100Sound Programming\n"
"\t110Todd Hendrix\n"
"\n"
@@ -162,16 +162,12 @@ const char *const SWORDS_CREDITS2 =
"\t110David Baton\n"
"\t110Jack Nalls\n";
-const char *const CLOUDS_MAIN_MENU =
+const char *const OPTIONS_MENU =
"\r\x1\x3""c\fdMight and Magic Options\n"
- "Clouds of Xeen\x2\n"
- "\v%03dCopyright (c) 1992 NWC, Inc.\n"
+ "%s of Xeen\x2\n"
+ "\v%.3dCopyright (c) %d NWC, Inc.\n"
"All Rights Reserved\x1";
-const char *const WORLD_MAIN_MENU =
- "\r\x1\x3""c\fdMight and Magic Options\n"
- "World of Xeen\x2\n"
- "\v117Copyright (c) 1993 NWC, Inc.\n"
- "All Rights Reserved\x01";
+const char *const GAME_NAMES[3] = { "Clouds", "Darkside", "World" };
const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
@@ -1847,8 +1843,8 @@ void writeConstants(CCArchive &cc) {
file.syncString(DARK_SIDE_CREDITS);
file.syncString(SWORDS_CREDITS1);
file.syncString(SWORDS_CREDITS2);
- file.syncString(CLOUDS_MAIN_MENU);
- file.syncString(WORLD_MAIN_MENU);
+ file.syncString(OPTIONS_MENU);
+ file.syncStrings(GAME_NAMES, 3);
file.syncString(THE_PARTY_NEEDS_REST);
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
Commit: 546059408f7ff96997a35c9ae77d1122868d5b1d
https://github.com/scummvm/scummvm/commit/546059408f7ff96997a35c9ae77d1122868d5b1d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:40:43-05:00
Commit Message:
XEEN: Added Other Options dialog for Dark Side and World
Changed paths:
engines/xeen/resources.cpp
engines/xeen/resources.h
engines/xeen/scripts.cpp
engines/xeen/worldofxeen/worldofxeen_cutscenes.h
engines/xeen/worldofxeen/worldofxeen_menu.cpp
engines/xeen/worldofxeen/worldofxeen_menu.h
engines/xeen/xeen.cpp
engines/xeen/xeen.h
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 6ea4252..14c87d6 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -66,8 +66,8 @@ void Resources::loadData() {
file.syncString(DARK_SIDE_CREDITS);
file.syncString(SWORDS_CREDITS1);
file.syncString(SWORDS_CREDITS2);
- file.syncString(CLOUDS_MAIN_MENU);
- file.syncString(WORLD_MAIN_MENU);
+ file.syncString(OPTIONS_MENU);
+ file.syncStrings(GAME_NAMES, 3);
file.syncString(THE_PARTY_NEEDS_REST);
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index b14b9f5..6dff6a7 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -120,8 +120,8 @@ public:
const char *DARK_SIDE_CREDITS;
const char *SWORDS_CREDITS1;
const char *SWORDS_CREDITS2;
- const char *CLOUDS_MAIN_MENU;
- const char *WORLD_MAIN_MENU;
+ const char *OPTIONS_MENU;
+ const char *GAME_NAMES[3];
const char *THE_PARTY_NEEDS_REST;
const char *WHO_WILL;
const char *HOW_MUCH;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index a3aa67b..ffe4e2d 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1085,7 +1085,7 @@ bool Scripts::cmdCutsceneEndClouds(ParamsIterator ¶ms) {
party._mazePosition = Common::Point(18, 4);
g_vm->_gameWon[0] = true;
- g_vm->_finalScore[0] = party.getScore();
+ g_vm->_finalScore = party.getScore();
g_vm->saveSettings();
doCloudsEnding();
@@ -1421,7 +1421,7 @@ bool Scripts::cmdCutsceneEndDarkside(ParamsIterator ¶ms) {
party._mazePosition = Common::Point(25, 21);
g_vm->_gameWon[1] = true;
- g_vm->_finalScore[1] = party.getScore();
+ g_vm->_finalScore = party.getScore();
g_vm->saveSettings();
doDarkSideEnding();
@@ -1429,6 +1429,12 @@ bool Scripts::cmdCutsceneEndDarkside(ParamsIterator ¶ms) {
}
bool Scripts::cmdCutsceneEndWorld(ParamsIterator ¶ms) {
+ Party &party = *g_vm->_party;
+
+ g_vm->_gameWon[2] = true;
+ g_vm->_finalScore = party.getScore();
+ g_vm->saveSettings();
+
_vm->_saves->_wonWorld = true;
_vm->_party->_worldEnd = true;
diff --git a/engines/xeen/worldofxeen/worldofxeen_cutscenes.h b/engines/xeen/worldofxeen/worldofxeen_cutscenes.h
index bd78593..6fee060 100644
--- a/engines/xeen/worldofxeen/worldofxeen_cutscenes.h
+++ b/engines/xeen/worldofxeen/worldofxeen_cutscenes.h
@@ -70,14 +70,14 @@ private:
* Part 4 of World of Xeen ending
*/
void worldEnding4();
-protected:
+public:
+ WorldOfXeenCutscenes(XeenEngine *vm) : _vm(vm), CloudsCutscenes(vm),
+ DarkSideCutscenes(vm), _goober(NON_GOOBER), _finalScore(0) {}
+
/**
* Shows the World of Xeen ending sequence
*/
void showWorldOfXeenEnding(GooberState state, uint score);
-public:
- WorldOfXeenCutscenes(XeenEngine *vm) : _vm(vm), CloudsCutscenes(vm),
- DarkSideCutscenes(vm), _goober(NON_GOOBER), _finalScore(0) {}
};
} // End of namespace WorldOfXeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 7b60a70..36d6b7c 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -264,7 +264,7 @@ void CloudsMenuDialog::draw() {
Window &w = windows[GAME_WINDOW];
w.frame();
- w.writeString(Common::String::format(Res.CLOUDS_MAIN_MENU, g_vm->_gameWon[0] ? 117 : 92));
+ w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[0], g_vm->_gameWon[0] ? 117 : 92, 1992));
drawButtons(&w);
}
@@ -279,7 +279,8 @@ bool CloudsMenuDialog::handleEvents() {
delete this;
// Show clouds ending
- WOX_VM.showCloudsEnding(g_vm->_finalScore[0]);
+ WOX_VM._sound->stopAllAudio();
+ WOX_VM.showCloudsEnding(g_vm->_finalScore);
return true;
}
break;
@@ -363,10 +364,16 @@ bool DarkSideMenuDialog::handleEvents() {
return true;
switch (_buttonValue) {
- case Common::KEYCODE_o:
+ case Common::KEYCODE_o: {
// Show other options dialog
- // TODO
- break;
+ // Remove this dialog
+ MainMenuContainer *owner = _owner;
+ delete this;
+
+ // Set the new options dialog
+ owner->setOwner(new OtherOptionsDialog(owner));
+ return true;
+ }
default:
break;
@@ -405,7 +412,7 @@ void WorldMenuDialog::draw() {
Window &w = windows[GAME_WINDOW];
w.frame();
- w.writeString(Res.WORLD_MAIN_MENU);
+ w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[2], 117, 1993));
drawButtons(&w);
}
@@ -414,10 +421,16 @@ bool WorldMenuDialog::handleEvents() {
return true;
switch (_buttonValue) {
- case Common::KEYCODE_o:
+ case Common::KEYCODE_o: {
// Show other options dialog
- // TODO
- break;
+ // Remove this dialog
+ MainMenuContainer *owner = _owner;
+ delete this;
+
+ // Set the new options dialog
+ owner->setOwner(new OtherOptionsDialog(owner));
+ return true;
+ }
default:
break;
@@ -426,6 +439,135 @@ bool WorldMenuDialog::handleEvents() {
return false;
}
+/*------------------------------------------------------------------------*/
+
+OtherOptionsDialog::OtherOptionsDialog(MainMenuContainer *owner) : MenuContainerDialog(owner) {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+
+ int height = (g_vm->getGameID() == GType_WorldOfXeen ? 25 : 0)
+ + (g_vm->getGameID() == GType_WorldOfXeen && g_vm->_gameWon[0] ? 25 : 0)
+ + (g_vm->_gameWon[1] ? 25 : 0)
+ + (g_vm->_gameWon[2] ? 25 : 0)
+ + 75;
+
+ w.setBounds(Common::Rect(72, 25, 248, 25 + height));
+ w.open();
+
+ loadButtons();
+}
+
+OtherOptionsDialog::~OtherOptionsDialog() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+ w.close();
+}
+
+void OtherOptionsDialog::loadButtons() {
+ _buttonSprites.load("special.icn");
+ Common::Rect r(93, 53, 227, 73);
+
+ // View Darkside Intro
+ addButton(r, Common::KEYCODE_d, &_buttonSprites);
+ r.translate(0, 25);
+
+ // View Clouds Intro
+ if (g_vm->getGameID() == GType_WorldOfXeen) {
+ addButton(r, Common::KEYCODE_c, &_buttonSprites);
+ r.translate(0, 25);
+ } else {
+ addButton(Common::Rect(), Common::KEYCODE_INVALID);
+ }
+
+ // View Darkside End
+ if (g_vm->_gameWon[1]) {
+ addButton(r, Common::KEYCODE_e, &_buttonSprites);
+ r.translate(0, 25);
+ } else {
+ addButton(Common::Rect(), Common::KEYCODE_INVALID);
+ }
+
+ // View Clouds End
+ if (g_vm->_gameWon[0]) {
+ addButton(r, Common::KEYCODE_v, &_buttonSprites);
+ r.translate(0, 25);
+ } else {
+ addButton(Common::Rect(), Common::KEYCODE_INVALID);
+ }
+
+ // View World End
+ if (g_vm->_gameWon[2]) {
+ addButton(r, Common::KEYCODE_w, &_buttonSprites);
+ } else {
+ addButton(Common::Rect(), Common::KEYCODE_INVALID);
+ }
+}
+
+void OtherOptionsDialog::draw() {
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[GAME_WINDOW];
+
+ w.frame();
+ w.writeString(Common::String::format(Res.OPTIONS_MENU,
+ Res.GAME_NAMES[g_vm->getGameID() == GType_WorldOfXeen ? 2 : 1],
+ w.getBounds().height() - 33, 1993));
+ drawButtons(&w);
+}
+
+bool OtherOptionsDialog::handleEvents() {
+ Sound &sound = *g_vm->_sound;
+ checkEvents(g_vm);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_d:
+ delete this;
+ sound.stopAllAudio();
+ WOX_VM.showDarkSideIntro(false);
+ break;
+
+ case Common::KEYCODE_c:
+ if (g_vm->getGameID() == GType_WorldOfXeen) {
+ delete this;
+ sound.stopAllAudio();
+ WOX_VM.showCloudsIntro();
+ }
+ break;
+
+ case Common::KEYCODE_e:
+ if (g_vm->_gameWon[1]) {
+ delete this;
+ sound.stopAllAudio();
+ WOX_VM.showDarkSideEnding(g_vm->_finalScore);
+ }
+ break;
+
+ case Common::KEYCODE_v:
+ if (g_vm->_gameWon[0]) {
+ delete this;
+ sound.stopAllAudio();
+ WOX_VM.showCloudsEnding(g_vm->_finalScore);
+ }
+ break;
+
+ case Common::KEYCODE_w:
+ if (g_vm->_gameWon[2]) {
+ delete this;
+ sound.stopAllAudio();
+ WOX_VM.showWorldOfXeenEnding(NON_GOOBER, g_vm->_finalScore);
+ }
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ // Exit dialog
+ delete this;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
} // End of namespace WorldOfXeen
} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.h b/engines/xeen/worldofxeen/worldofxeen_menu.h
index 1db78b9..f3cee75 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.h
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.h
@@ -29,14 +29,14 @@
namespace Xeen {
namespace WorldOfXeen {
-class MainMenuDialog;
+class MenuContainerDialog;
class MainMenuContainer {
private:
uint _animateCtr;
uint _frameCount;
SpriteResource _backgroundSprites;
- MainMenuDialog *_dialog;
+ MenuContainerDialog *_dialog;
protected:
/**
* Draws the main menu background
@@ -76,7 +76,7 @@ public:
/**
* Sets the dialog being displayed in the menu
*/
- void setOwner(MainMenuDialog *dlalog) {
+ void setOwner(MenuContainerDialog *dlalog) {
_dialog = dlalog;
}
};
@@ -129,7 +129,7 @@ public:
};
class MenuContainerDialog : public ButtonContainer {
-private:
+protected:
MainMenuContainer *_owner;
public:
/**
@@ -270,6 +270,36 @@ public:
virtual bool handleEvents();
};
+class OtherOptionsDialog : public MenuContainerDialog {
+private:
+ SpriteResource _buttonSprites;
+private:
+ /**
+ * Loads buttons for the dialog
+ */
+ void loadButtons();
+public:
+ /**
+ * Constructor
+ */
+ OtherOptionsDialog(MainMenuContainer *owner);
+
+ /**
+ * Destructor
+ */
+ virtual ~OtherOptionsDialog();
+
+ /**
+ * Draws the dialog
+ */
+ virtual void draw();
+
+ /**
+ * Handles events
+ */
+ virtual bool handleEvents();
+};
+
} // End of namespace WorldOfXeen
} // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 6122f4d..c209420 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -62,8 +62,8 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
_mode = MODE_0;
_endingScore = 0;
_loadSaveSlot = -1;
- _gameWon[0] = _gameWon[1] = false;
- _finalScore[0] = _finalScore[1] = 0;
+ _gameWon[0] = _gameWon[1] = _gameWon[2] = false;
+ _finalScore = 0;
g_vm = this;
}
@@ -116,8 +116,8 @@ bool XeenEngine::initialize() {
// Load settings
_gameWon[0] = ConfMan.hasKey("game_won") && ConfMan.getBool("game_won");
_gameWon[1] = ConfMan.hasKey("game_won2") && ConfMan.getBool("game_won2");
- _finalScore[0] = ConfMan.hasKey("final_score") ? ConfMan.getInt("final_score") : 0;
- _finalScore[1] = ConfMan.hasKey("final_score2") ? ConfMan.getInt("final_score2") : 0;
+ _gameWon[2] = ConfMan.hasKey("game_won3") && ConfMan.getBool("game_won3");
+ _finalScore = ConfMan.hasKey("final_score") ? ConfMan.getInt("final_score") : 0;
// If requested, load a savegame instead of showing the intro
if (ConfMan.hasKey("save_slot")) {
@@ -307,9 +307,10 @@ void XeenEngine::saveSettings() {
ConfMan.setBool("game_won", true);
if (_gameWon[1])
ConfMan.setBool("game_won2", true);
+ if (_gameWon[2])
+ ConfMan.setBool("game_won3", true);
- ConfMan.setInt("final_score", _finalScore[0]);
- ConfMan.setInt("final_score2", _finalScore[1]);
+ ConfMan.setInt("final_score", _finalScore);
ConfMan.flushToDisk();
}
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index 62b3a7e..d26ffde 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -183,8 +183,8 @@ public:
bool _noDirectionSense;
bool _startupWindowActive;
uint _endingScore;
- bool _gameWon[2];
- uint _finalScore[2];
+ bool _gameWon[3];
+ uint _finalScore;
public:
XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
virtual ~XeenEngine();
Commit: d48275970aa78866349f20f44bacdc0aff83e57b
https://github.com/scummvm/scummvm/commit/d48275970aa78866349f20f44bacdc0aff83e57b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-03-04T22:43:20-05:00
Commit Message:
XEEN: Regenerate xeen.ccs and remove accidentally committed dark.cc
Changed paths:
R dists/engine-data/dark.cc
dists/engine-data/xeen.ccs
diff --git a/dists/engine-data/dark.cc b/dists/engine-data/dark.cc
deleted file mode 100644
index 875ed74..0000000
Binary files a/dists/engine-data/dark.cc and /dev/null differ
diff --git a/dists/engine-data/xeen.ccs b/dists/engine-data/xeen.ccs
index 46d09c3..6a1e106 100644
Binary files a/dists/engine-data/xeen.ccs and b/dists/engine-data/xeen.ccs differ
More information about the Scummvm-git-logs
mailing list