Initial commit
This commit is contained in:
130
engines/mm/xeen/dialogs/credits_screen.cpp
Normal file
130
engines/mm/xeen/dialogs/credits_screen.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/credits_screen.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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");
|
||||
Common::String ttsMessage;
|
||||
windows[0].writeString(content, false, &ttsMessage);
|
||||
doScroll(false, false);
|
||||
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, (_vm->getGameID() != GType_Swords || content == Res.SWORDS_CREDITS1));
|
||||
#endif
|
||||
|
||||
events.setCursor(0);
|
||||
windows[0].update();
|
||||
clearButtons();
|
||||
|
||||
// Wait for keypress
|
||||
while (!_vm->shouldExit() && !events.isKeyMousePressed())
|
||||
events.pollEventsAndWait();
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
doScroll(true, false);
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void CreditsScreen::speakText(const Common::String &text, bool firstCreditsScreen) const {
|
||||
if (_vm->getGameID() == GType_Swords && firstCreditsScreen) {
|
||||
uint index = 0;
|
||||
// Developed/published by
|
||||
_vm->sayText(getNextTextSection(text, index, 2));
|
||||
|
||||
// Next four headers are separate from their corresponding credits. First get the headers, then voice the person
|
||||
// for the first header, and then voice the second header and second person
|
||||
for (uint8 i = 0; i < 2; ++i) {
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
Common::String nextHeader = getNextTextSection(text, index);
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
_vm->sayText(nextHeader);
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
}
|
||||
|
||||
// Same as first four headers, but with two people at a time instead of one
|
||||
for (uint8 i = 0; i < 2; ++i) {
|
||||
// First two headers
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
Common::String nextHeader = getNextTextSection(text, index);
|
||||
|
||||
// First people listed
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
Common::String nextHeaderPerson = getNextTextSection(text, index);
|
||||
|
||||
// Second person listed under first header
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
|
||||
// Next header
|
||||
_vm->sayText(nextHeader);
|
||||
_vm->sayText(nextHeaderPerson);
|
||||
|
||||
// Second person for second header
|
||||
if (i == 0) {
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
} else { // Last header has more than two people
|
||||
_vm->sayText(text.substr(index));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_vm->sayText(text);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
46
engines/mm/xeen/dialogs/credits_screen.h
Normal file
46
engines/mm/xeen/dialogs/credits_screen.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_CREDITS_SCREEN_H
|
||||
#define XEEN_DIALOGS_CREDITS_SCREEN_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class CreditsScreen: public ButtonContainer {
|
||||
private:
|
||||
CreditsScreen(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
void execute(const char *content);
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text, bool firstCreditsScreen) const;
|
||||
#endif
|
||||
public:
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
343
engines/mm/xeen/dialogs/dialogs.cpp
Normal file
343
engines/mm/xeen/dialogs/dialogs.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/events.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/screen.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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, uint8 ttsIndex) {
|
||||
_buttons.push_back(UIButton(bounds, val, _buttons.size() * 2, sprites, sprites != nullptr, ttsIndex, ttsIndex < UINT8_MAX));
|
||||
}
|
||||
|
||||
void ButtonContainer::addButton(const Common::Rect &bounds, int val,
|
||||
int frameNum, SpriteResource *sprites, uint8 ttsIndex) {
|
||||
_buttons.push_back(UIButton(bounds, val, frameNum, sprites, sprites != nullptr, ttsIndex, ttsIndex < UINT8_MAX));
|
||||
}
|
||||
|
||||
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;
|
||||
PendingEvent event;
|
||||
_buttonValue = 0;
|
||||
|
||||
#ifdef USE_TTS
|
||||
bool buttonKeyboardPressed = false;
|
||||
checkHoverOverButton();
|
||||
#endif
|
||||
|
||||
if (events.getEvent(event)) {
|
||||
if (event._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) && _buttons[i]._value) {
|
||||
events.debounceMouse();
|
||||
|
||||
_buttonValue = _buttons[i]._value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_buttonValue && _waitBounds.contains(pt)) {
|
||||
_buttonValue = Common::KEYCODE_SPACE;
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (event.isKeyboard()) {
|
||||
const Common::KeyCode &keycode = event._keyState.keycode;
|
||||
|
||||
if (keycode == Common::KEYCODE_KP8)
|
||||
_buttonValue = Common::KEYCODE_UP;
|
||||
else if (keycode == Common::KEYCODE_KP2)
|
||||
_buttonValue = Common::KEYCODE_DOWN;
|
||||
else if (keycode == Common::KEYCODE_KP_ENTER)
|
||||
_buttonValue = Common::KEYCODE_RETURN;
|
||||
else if (keycode != Common::KEYCODE_LCTRL && keycode != Common::KEYCODE_RCTRL
|
||||
&& keycode != Common::KEYCODE_LALT && keycode != Common::KEYCODE_RALT)
|
||||
_buttonValue = keycode;
|
||||
|
||||
if (_buttonValue) {
|
||||
_buttonValue |= (event._keyState.flags & ~Common::KBD_STICKY) << 16;
|
||||
#ifdef USE_TTS
|
||||
buttonKeyboardPressed = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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._value == _buttonValue) {
|
||||
#ifdef USE_TTS
|
||||
// Only voice the button's text if it was activated by keyboard press, to avoid voicing it
|
||||
// every time the player clicks it
|
||||
if (buttonKeyboardPressed && btn._canVoice && btn._ttsIndex < _buttonTexts.size()) {
|
||||
_vm->sayText(_buttonTexts[btn._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (btn._draw) {
|
||||
// Found the correct button
|
||||
// Draw button depressed
|
||||
btn._sprites->draw(0, btn._selectedFrame, 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;
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void ButtonContainer::checkHoverOverButton() {
|
||||
if (g_vm->_mouseMoved) {
|
||||
bool hoveringOverButton = false;
|
||||
|
||||
Common::Point pt = g_vm->_events->_mousePos;
|
||||
|
||||
for (uint i = 0; i < _buttons.size(); ++i) {
|
||||
if (_buttons[i]._canVoice && _buttons[i]._ttsIndex < _buttonTexts.size() && _buttons[i]._bounds.contains(pt) && _buttons[i]._value) {
|
||||
hoveringOverButton = true;
|
||||
|
||||
if (_previousButton != (int)i) {
|
||||
_vm->sayText(_buttonTexts[_buttons[i]._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
_previousButton = (int)i;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hoveringOverButton) {
|
||||
_previousButton = -1;
|
||||
}
|
||||
|
||||
g_vm->_mouseMoved = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ButtonContainer::drawButtons(XSurface *surface) {
|
||||
for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
|
||||
UIButton &btn = _buttons[btnIndex];
|
||||
if (btn._draw) {
|
||||
assert(btn._sprites);
|
||||
btn._sprites->draw(*surface, btn._frameNum,
|
||||
Common::Point(btn._bounds.left, btn._bounds.top));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonContainer::doScroll(bool rollUp, bool fadeIn) {
|
||||
if (_vm->_files->_ccNum) {
|
||||
return Cutscenes::doScroll(rollUp, fadeIn);
|
||||
} else {
|
||||
saveButtons();
|
||||
clearButtons();
|
||||
bool result = Cutscenes::doScroll(rollUp, fadeIn);
|
||||
restoreButtons();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonContainer::loadStrings(const Common::Path &name) {
|
||||
File f(name);
|
||||
_textStrings.clear();
|
||||
while (f.pos() < f.size())
|
||||
_textStrings.push_back(f.readString());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void ButtonContainer::loadStrings(const Common::Path &name, int ccMode) {
|
||||
File f(name, ccMode);
|
||||
_textStrings.clear();
|
||||
while (f.pos() < f.size())
|
||||
_textStrings.push_back(f.readString());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void ButtonContainer::setWaitBounds() {
|
||||
_waitBounds = Common::Rect(8, 8, 224, 140);
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
Common::String ButtonContainer::getNextTextSection(const Common::String &text, uint &index, uint count, const char *separator) const {
|
||||
Common::String result;
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
result += getNextTextSection(text, index) + separator;
|
||||
|
||||
if (index == Common::String::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Common::String ButtonContainer::getNextTextSection(const Common::String &text, uint &index, uint count) const {
|
||||
return getNextTextSection(text, index, count, "\n");
|
||||
}
|
||||
|
||||
Common::String ButtonContainer::getNextTextSection(const Common::String &text, uint &index) const {
|
||||
Common::String result;
|
||||
|
||||
index = text.findFirstNotOf('\n', index);
|
||||
if (index == Common::String::npos) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint endIndex = text.find('\n', index + 1);
|
||||
|
||||
if (endIndex == Common::String::npos) {
|
||||
result = text.substr(index);
|
||||
index = endIndex;
|
||||
return result;
|
||||
}
|
||||
|
||||
result = text.substr(index, endIndex - index);
|
||||
index = endIndex + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
Common::String ButtonContainer::addNextTextToButtons(const Common::String &text, uint &index) {
|
||||
Common::String buttonText = getNextTextSection(text, index) + '\n';
|
||||
_buttonTexts.push_back(buttonText);
|
||||
return buttonText;
|
||||
}
|
||||
|
||||
Common::String ButtonContainer::addNextTextToButtons(const Common::String &text, uint &index, uint count) {
|
||||
Common::String result;
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
result += addNextTextToButtons(text, index);
|
||||
|
||||
if (index == Common::String::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ButtonContainer::setButtonTexts(const Common::String &text) {
|
||||
_buttonTexts.clear();
|
||||
|
||||
uint index = 0;
|
||||
for (uint i = 0; i < _buttons.size(); ++i) {
|
||||
if (_buttons[i]._value) {
|
||||
_buttonTexts.push_back(getNextTextSection(text, index));
|
||||
} else {
|
||||
_buttonTexts.push_back("");
|
||||
}
|
||||
|
||||
if (index == Common::String::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonContainer::disableButtonVoicing(uint startIndex, uint endIndex) {
|
||||
for (uint i = startIndex; i < endIndex; ++i) {
|
||||
if (i < _buttons.size()) {
|
||||
_buttons[i]._canVoice = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonContainer::enableButtonVoicing(uint startIndex, uint endIndex) {
|
||||
for (uint i = startIndex; i < endIndex; ++i) {
|
||||
if (i < _buttons.size()) {
|
||||
_buttons[i]._canVoice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
|
||||
_vm->_events->pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
248
engines/mm/xeen/dialogs/dialogs.h
Normal file
248
engines/mm/xeen/dialogs/dialogs.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_H
|
||||
#define XEEN_DIALOGS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stack.h"
|
||||
#include "common/rect.h"
|
||||
#include "mm/xeen/cutscenes.h"
|
||||
#include "mm/xeen/sprites.h"
|
||||
#include "mm/shared/xeen/xsurface.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class XeenEngine;
|
||||
|
||||
class UIButton {
|
||||
public:
|
||||
Common::Rect _bounds;
|
||||
SpriteResource *_sprites;
|
||||
int _value;
|
||||
uint _frameNum, _selectedFrame;
|
||||
bool _draw;
|
||||
#ifdef USE_TTS
|
||||
uint8 _ttsIndex;
|
||||
bool _canVoice;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
UIButton(const Common::Rect &bounds, int value, uint frameNum, SpriteResource *sprites, bool draw, uint8 ttsIndex, bool ttsCanVoice) :
|
||||
_bounds(bounds), _value(value), _frameNum(frameNum), _selectedFrame(frameNum | 1),
|
||||
_sprites(sprites), _draw(draw) {
|
||||
#ifdef USE_TTS
|
||||
_ttsIndex = ttsIndex;
|
||||
_canVoice = ttsCanVoice;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
UIButton() : _value(0), _frameNum(0), _selectedFrame(0), _sprites(nullptr), _draw(false) {
|
||||
#ifdef USE_TTS
|
||||
_ttsIndex = 0;
|
||||
_canVoice = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frame
|
||||
*/
|
||||
void setFrame(uint frameNum) {
|
||||
_frameNum = frameNum;
|
||||
_selectedFrame = frameNum | 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frame
|
||||
*/
|
||||
void setFrame(uint frameNum, uint selectedFrame) {
|
||||
_frameNum = frameNum;
|
||||
_selectedFrame = selectedFrame;
|
||||
}
|
||||
};
|
||||
|
||||
class ButtonContainer : public Cutscenes {
|
||||
private:
|
||||
Common::Stack< Common::Array<UIButton> > _savedButtons;
|
||||
protected:
|
||||
Common::Array<UIButton> _buttons;
|
||||
Common::StringArray _textStrings;
|
||||
Common::Rect _waitBounds;
|
||||
int _buttonValue;
|
||||
#ifdef USE_TTS
|
||||
Common::StringArray _buttonTexts;
|
||||
int _previousButton;
|
||||
#endif
|
||||
|
||||
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
|
||||
*/
|
||||
bool doScroll(bool rollUp, bool fadeIn) override;
|
||||
|
||||
/**
|
||||
* Load a set of text strings from the given resource
|
||||
* @param name Name of resource containing strings
|
||||
*/
|
||||
void loadStrings(const Common::Path &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::Path &name, int ccMode);
|
||||
|
||||
/**
|
||||
* Sets the wait bounds, the area where clicking with the mouse generates
|
||||
* the equivalent of a space bar press, to the main interface area
|
||||
*/
|
||||
void setWaitBounds();
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Reads one or more sections of text, then combines them
|
||||
* @param text Text to take the sections from. Each section should be separated by one or more newlines
|
||||
* @param index Starting index, which is moved to the start of the following section, or npos if no sections remain
|
||||
* @param count How many sections to read
|
||||
* @param separator What to separate sections with
|
||||
* @returns The text sections combined, each separated by the separator
|
||||
*/
|
||||
Common::String getNextTextSection(const Common::String &text, uint &index, uint count, const char *separator) const;
|
||||
|
||||
/**
|
||||
* Reads one or more sections of text, then combines them. Newlines are kept intact
|
||||
* @param text Text to take the sections from. Each section should be separated by one or more newlines
|
||||
* @param index Starting index, which is moved to the start of the following section, or npos if no sections remain
|
||||
* @param count How many sections to read
|
||||
* @returns The text sections combined
|
||||
*/
|
||||
Common::String getNextTextSection(const Common::String &text, uint &index, uint count) const;
|
||||
|
||||
/**
|
||||
* Reads one section of text
|
||||
* @param text Text to take the section from. Each section should be separated by one or more newlines
|
||||
* @param index Starting index, which is moved to the start of the following section, or npos if no sections remain
|
||||
* @returns The text section
|
||||
*/
|
||||
Common::String getNextTextSection(const Common::String &text, uint &index) const;
|
||||
|
||||
/**
|
||||
* Reads one section of text and adds it to the button texts
|
||||
* @param text Text to take the section from. Each section should be separated by one or more newlines
|
||||
* @param index Starting index, which is moved to the start of the following section, or npos if no sections remain
|
||||
* @returns The text section
|
||||
*/
|
||||
Common::String addNextTextToButtons(const Common::String &text, uint &index);
|
||||
|
||||
/**
|
||||
* Reads one or more sections of text and adds them to the button texts
|
||||
* @param text Text to take the sections from. Each section should be separated by one or more newlines
|
||||
* @param index Starting index, which is moved to the start of the following section, or npos if no sections remain
|
||||
* @param count How many sections to read
|
||||
* @returns The text sections combined
|
||||
*/
|
||||
Common::String addNextTextToButtons(const Common::String &text, uint &index, uint count);
|
||||
|
||||
/**
|
||||
* Sets the text of each button for use by TTS
|
||||
* @param text Text for buttons. Each button's text should be separated by newlines
|
||||
*/
|
||||
void setButtonTexts(const Common::String &text);
|
||||
|
||||
/**
|
||||
* Disables the voicing of buttons from the start index to the end index
|
||||
* @param startIndex Starting index
|
||||
* @param endIndex Ending index
|
||||
*/
|
||||
void disableButtonVoicing(uint startIndex, uint endIndex);
|
||||
|
||||
/**
|
||||
* Enables the voicing of buttons from the start index to the end index
|
||||
* @param startIndex Starting index
|
||||
* @param endIndex Ending index
|
||||
*/
|
||||
void enableButtonVoicing(uint startIndex, uint endIndex);
|
||||
#endif
|
||||
public:
|
||||
ButtonContainer(XeenEngine *vm) : Cutscenes(vm), _buttonValue(0) {
|
||||
#ifdef USE_TTS
|
||||
_previousButton = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current list of buttons
|
||||
*/
|
||||
void saveButtons();
|
||||
|
||||
void clearButtons();
|
||||
|
||||
void restoreButtons();
|
||||
|
||||
void addButton(const Common::Rect &bounds, int val,
|
||||
SpriteResource *sprites = nullptr, uint8 ttsIndex = UINT8_MAX);
|
||||
void addButton(const Common::Rect &bounds, int val,
|
||||
int frameNum, SpriteResource *sprites = nullptr, uint8 ttsIndex = UINT8_MAX);
|
||||
|
||||
void addPartyButtons(XeenEngine *vm);
|
||||
|
||||
/**
|
||||
* Draws the buttons onto the passed surface
|
||||
*/
|
||||
void drawButtons(XSurface *surface);
|
||||
|
||||
/**
|
||||
* Clears any currently set button value
|
||||
*/
|
||||
void clearEvents() { _buttonValue = 0; }
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Checks if a button is being hovered over and voices its text with TTS, if there is text
|
||||
*/
|
||||
void checkHoverOverButton();
|
||||
#endif
|
||||
};
|
||||
|
||||
class SettingsBaseDialog : public ButtonContainer {
|
||||
protected:
|
||||
virtual void showContents(SpriteResource &title1, bool mode);
|
||||
public:
|
||||
SettingsBaseDialog(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
~SettingsBaseDialog() override {}
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
145
engines/mm/xeen/dialogs/dialogs_awards.cpp
Normal file
145
engines/mm/xeen/dialogs/dialogs_awards.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_awards.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
enum AwardsButtonTTSTextIndex {
|
||||
kAwardsUp = 0,
|
||||
kAwardsDown = 1,
|
||||
kAwardsExit = 2
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
Common::String buttonText;
|
||||
windows[29].writeString(Res.AWARDS_TEXT, false, &buttonText);
|
||||
drawButtons(&windows[0]);
|
||||
#ifdef USE_TTS
|
||||
setButtonTexts(buttonText);
|
||||
#endif
|
||||
|
||||
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 == WARZONE_AWARD) {
|
||||
// # Warzone Wins
|
||||
awards[numAwards] = Common::String::format(_textStrings[9].c_str(), ch->getAwardCount(WARZONE_AWARD));
|
||||
} 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);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(buttonText);
|
||||
#endif
|
||||
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, kAwardsUp);
|
||||
addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_d, &_iconSprites, kAwardsDown);
|
||||
addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites, kAwardsExit);
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
53
engines/mm/xeen/dialogs/dialogs_awards.h
Normal file
53
engines/mm/xeen/dialogs/dialogs_awards.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_AWARDS_H
|
||||
#define XEEN_DIALOGS_AWARDS_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/character.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
735
engines/mm/xeen/dialogs/dialogs_char_info.cpp
Normal file
735
engines/mm/xeen/dialogs/dialogs_char_info.cpp
Normal file
@@ -0,0 +1,735 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_awards.h"
|
||||
#include "mm/xeen/dialogs/dialogs_char_info.h"
|
||||
#include "mm/xeen/dialogs/dialogs_exchange.h"
|
||||
#include "mm/xeen/dialogs/dialogs_items.h"
|
||||
#include "mm/xeen/dialogs/dialogs_quick_ref.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kCharacterInfoInformationCount = 20;
|
||||
static const uint8 kCharacterInfoSideButtonCount = 4;
|
||||
static const uint8 kCharacterInfoPartyGoldIndex = 7;
|
||||
static const uint8 kCharacterInfoRowCount = 5;
|
||||
static const uint8 kCharacterInfoColumnCount = 4;
|
||||
|
||||
#endif
|
||||
|
||||
enum CharacterInfoButtonTTSTextIndex {
|
||||
kCharacterInfoItem = 0,
|
||||
kCharacterInfoQuickRef = 1,
|
||||
kCharacterInfoExchange = 2,
|
||||
kCharacterInfoExit = 3,
|
||||
kCharacterInfoMight = 4,
|
||||
kCharacterInfoAccuracy = 5,
|
||||
kCharacterInfoHP = 6,
|
||||
kCharacterInfoExperience = 7,
|
||||
kCharacterInfoIntellect = 8,
|
||||
kCharacterInfoLuck = 9,
|
||||
kCharacterInfoSP = 10,
|
||||
kCharacterInfoPartyGold = 11,
|
||||
kCharacterInfoPersonality = 12,
|
||||
kCharacterInfoAge = 13,
|
||||
kCharacterInfoResistances = 14,
|
||||
kCharacterInfoPartyGems = 15,
|
||||
kCharacterInfoEndurance = 16,
|
||||
kCharacterInfoLevel = 17,
|
||||
kCharacterInfoSkills = 18,
|
||||
kCharacterInfoPartyFood = 19,
|
||||
kCharacterInfoSpeed = 20,
|
||||
kCharacterInfoAC = 21,
|
||||
kCharacterInfoAwards = 22,
|
||||
kCharacterInfoCondition = 23
|
||||
};
|
||||
|
||||
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);
|
||||
Common::String ttsMessage;
|
||||
w.writeString(Common::String::format(Res.CHARACTER_TEMPLATE, charDetails.c_str()), false, &ttsMessage);
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage);
|
||||
#endif
|
||||
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();
|
||||
|
||||
if (Common::KEYCODE_F1 == _buttonValue ||
|
||||
Common::KEYCODE_F2 == _buttonValue ||
|
||||
Common::KEYCODE_F3 == _buttonValue ||
|
||||
Common::KEYCODE_F4 == _buttonValue ||
|
||||
Common::KEYCODE_F5 == _buttonValue ||
|
||||
Common::KEYCODE_F6 == _buttonValue) {
|
||||
_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];
|
||||
|
||||
intf.highlightChar(_buttonValue);
|
||||
redrawFlag = true;
|
||||
} else {
|
||||
_vm->_mode = MODE_CHARACTER_INFO;
|
||||
}
|
||||
|
||||
} else if (Common::KEYCODE_UP == _buttonValue ||
|
||||
Common::KEYCODE_KP8 == _buttonValue) {
|
||||
if (_cursorCell > 0) {
|
||||
showCursor(false);
|
||||
--_cursorCell;
|
||||
showCursor(true);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_buttonTexts[_buttons[_cursorCell]._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
}
|
||||
w.update();
|
||||
|
||||
} else if (Common::KEYCODE_DOWN == _buttonValue ||
|
||||
Common::KEYCODE_KP2 == _buttonValue) {
|
||||
if (_cursorCell < 20) {
|
||||
showCursor(false);
|
||||
++_cursorCell;
|
||||
showCursor(true);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_buttonTexts[_buttons[_cursorCell]._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
}
|
||||
w.update();
|
||||
|
||||
} else if (Common::KEYCODE_LEFT == _buttonValue ||
|
||||
Common::KEYCODE_KP4 == _buttonValue) {
|
||||
if (_cursorCell >= 5) {
|
||||
showCursor(false);
|
||||
_cursorCell -= 5;
|
||||
showCursor(true);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_buttonTexts[_buttons[_cursorCell]._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
}
|
||||
w.update();
|
||||
|
||||
} else if (Common::KEYCODE_RIGHT == _buttonValue ||
|
||||
Common::KEYCODE_KP6 == _buttonValue) {
|
||||
if (_cursorCell <= 15) {
|
||||
showCursor(false);
|
||||
_cursorCell += 5;
|
||||
showCursor(true);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_buttonTexts[_buttons[_cursorCell]._ttsIndex], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
}
|
||||
w.update();
|
||||
|
||||
} else if (1001 == _buttonValue ||
|
||||
1002 == _buttonValue ||
|
||||
1003 == _buttonValue ||
|
||||
1004 == _buttonValue ||
|
||||
1005 == _buttonValue ||
|
||||
1006 == _buttonValue ||
|
||||
1007 == _buttonValue ||
|
||||
1008 == _buttonValue ||
|
||||
1009 == _buttonValue ||
|
||||
1010 == _buttonValue ||
|
||||
1011 == _buttonValue ||
|
||||
1012 == _buttonValue ||
|
||||
1013 == _buttonValue ||
|
||||
1014 == _buttonValue ||
|
||||
1015 == _buttonValue ||
|
||||
1016 == _buttonValue ||
|
||||
1017 == _buttonValue ||
|
||||
1018 == _buttonValue ||
|
||||
1019 == _buttonValue ||
|
||||
1020 == _buttonValue) {
|
||||
showCursor(false);
|
||||
_cursorCell = _buttonValue - 1001;
|
||||
showCursor(true);
|
||||
w.update();
|
||||
bool result = expandStat(_cursorCell, *c);
|
||||
_vm->_mode = MODE_COMBAT;
|
||||
if (result)
|
||||
redrawFlag = true;
|
||||
|
||||
} else if (Common::KEYCODE_RETURN == _buttonValue ||
|
||||
Common::KEYCODE_KP_ENTER == _buttonValue) {
|
||||
bool result = expandStat(_cursorCell, *c);
|
||||
_vm->_mode = MODE_COMBAT;
|
||||
if (result)
|
||||
redrawFlag = true;
|
||||
|
||||
} else if (Res.KeyConstants.DialogsCharInfo.KEY_EXCHANGE == _buttonValue) {
|
||||
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;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsCharInfo.KEY_ITEM == _buttonValue) {
|
||||
_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;
|
||||
redrawFlag = true;
|
||||
|
||||
} else if (Res.KeyConstants.DialogsCharInfo.KEY_QUICK == _buttonValue) {
|
||||
QuickReferenceDialog::show(_vm);
|
||||
redrawFlag = true;
|
||||
|
||||
} else if (Common::KEYCODE_ESCAPE == _buttonValue) {
|
||||
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, kCharacterInfoMight);
|
||||
addButton(Common::Rect(10, 47, 34, 67), 1002, &_iconSprites, kCharacterInfoIntellect);
|
||||
addButton(Common::Rect(10, 70, 34, 90), 1003, &_iconSprites, kCharacterInfoPersonality);
|
||||
addButton(Common::Rect(10, 93, 34, 113), 1004, &_iconSprites, kCharacterInfoEndurance);
|
||||
addButton(Common::Rect(10, 116, 34, 136), 1005, &_iconSprites, kCharacterInfoSpeed);
|
||||
addButton(Common::Rect(61, 24, 85, 44), 1006, &_iconSprites, kCharacterInfoAccuracy);
|
||||
addButton(Common::Rect(61, 47, 85, 67), 1007, &_iconSprites, kCharacterInfoLuck);
|
||||
addButton(Common::Rect(61, 70, 85, 90), 1008, &_iconSprites, kCharacterInfoAge);
|
||||
addButton(Common::Rect(61, 93, 85, 113), 1009, &_iconSprites, kCharacterInfoLevel);
|
||||
addButton(Common::Rect(61, 116, 85, 136), 1010, &_iconSprites, kCharacterInfoAC);
|
||||
addButton(Common::Rect(112, 24, 136, 44), 1011, &_iconSprites, kCharacterInfoHP);
|
||||
addButton(Common::Rect(112, 47, 136, 67), 1012, &_iconSprites, kCharacterInfoSP);
|
||||
addButton(Common::Rect(112, 70, 136, 90), 1013, &_iconSprites, kCharacterInfoResistances);
|
||||
addButton(Common::Rect(112, 93, 136, 113), 1014, &_iconSprites, kCharacterInfoSkills);
|
||||
addButton(Common::Rect(112, 116, 136, 136), 1015, &_iconSprites, kCharacterInfoAwards);
|
||||
addButton(Common::Rect(177, 24, 201, 44), 1016, &_iconSprites, kCharacterInfoExperience);
|
||||
addButton(Common::Rect(177, 47, 201, 67), 1017, &_iconSprites, kCharacterInfoPartyGold);
|
||||
addButton(Common::Rect(177, 70, 201, 90), 1018, &_iconSprites, kCharacterInfoPartyGems);
|
||||
addButton(Common::Rect(177, 93, 201, 113), 1019, &_iconSprites, kCharacterInfoPartyFood);
|
||||
addButton(Common::Rect(177, 116, 201, 136), 1020, &_iconSprites, kCharacterInfoCondition);
|
||||
|
||||
addButton(Common::Rect(285, 11, 309, 31), Res.KeyConstants.DialogsCharInfo.KEY_ITEM, &_iconSprites, kCharacterInfoItem);
|
||||
addButton(Common::Rect(285, 43, 309, 63), Res.KeyConstants.DialogsCharInfo.KEY_QUICK, &_iconSprites, kCharacterInfoQuickRef);
|
||||
addButton(Common::Rect(285, 75, 309, 95), Res.KeyConstants.DialogsCharInfo.KEY_EXCHANGE, &_iconSprites, kCharacterInfoExchange);
|
||||
|
||||
addButton(Common::Rect(285, 107, 309, 127), Common::KEYCODE_ESCAPE, &_iconSprites, kCharacterInfoExit);
|
||||
addPartyButtons(_vm);
|
||||
}
|
||||
|
||||
const char *CharacterInfo::getDaysPlurals(int val) {
|
||||
if (Common::RU_RUS == g_vm->getLanguage()) {
|
||||
int i = val % 100;
|
||||
if (i < 5 || i > 20)
|
||||
switch (val % 10) {
|
||||
case 1:
|
||||
return Res.DAYS[0];
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return Res.DAYS[1];
|
||||
}
|
||||
return Res.DAYS[2];
|
||||
} else {
|
||||
return Res.DAYS[val == 1 ? 0 : 1];
|
||||
}
|
||||
}
|
||||
|
||||
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._fireResistance._permanent + c.itemScan(11) + c._fireResistance._temporary +
|
||||
c._coldResistance._permanent + c.itemScan(13) + c._coldResistance._temporary +
|
||||
c._electricityResistance._permanent + c.itemScan(12) + c._electricityResistance._temporary +
|
||||
c._poisonResistance._permanent + c.itemScan(14) + c._poisonResistance._temporary +
|
||||
c._energyResistance._permanent + c.itemScan(15) + c._energyResistance._temporary +
|
||||
c._magicResistance._permanent + c.itemScan(16) + c._magicResistance._temporary;
|
||||
const char **_tmpConditions = c._sex == FEMALE ? (const char **)Res.CONDITION_NAMES_F : (const char **)Res.CONDITION_NAMES_M;
|
||||
|
||||
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,
|
||||
getDaysPlurals(foodVal),
|
||||
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], _tmpConditions[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]));
|
||||
}
|
||||
}
|
||||
|
||||
const char *CharacterInfo::getBornForm(const Character &c) {
|
||||
if (Common::RU_RUS == g_vm->getLanguage()) {
|
||||
switch (c._sex) {
|
||||
case MALE:
|
||||
return Res.BORN[0];
|
||||
case FEMALE:
|
||||
return Res.BORN[1];
|
||||
case YES_PLEASE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Res.BORN[0];
|
||||
}
|
||||
|
||||
const char *CharacterInfo::getFoodOnHandPlurals(int food) {
|
||||
if (Common::RU_RUS == g_vm->getLanguage()) {
|
||||
int i = food % 100;
|
||||
if (i < 5 || i > 20)
|
||||
switch (food % 10) {
|
||||
case 1:
|
||||
return Res.FOOD_ON_HAND[0];
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return Res.FOOD_ON_HAND[1];
|
||||
}
|
||||
return Res.FOOD_ON_HAND[2];
|
||||
}
|
||||
return Res.FOOD_ON_HAND[0];
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void CharacterInfo::speakText(const Common::String &text) {
|
||||
uint index = 0;
|
||||
uint statNameIndex = 0;
|
||||
|
||||
// Get the header for each piece of information
|
||||
Common::String informationHeaders[kCharacterInfoInformationCount];
|
||||
for (uint i = 0; i < kCharacterInfoInformationCount; ++i) {
|
||||
if (i != kCharacterInfoPartyGoldIndex) {
|
||||
// Items in the rightmost column already have their full names, not abbreviations
|
||||
if ((i + 1) % kCharacterInfoColumnCount != 0) {
|
||||
// Replace abbreviations with their full versions
|
||||
informationHeaders[i] = Res.STAT_NAMES[statNameIndex];
|
||||
getNextTextSection(text, index);
|
||||
} else {
|
||||
informationHeaders[i] = getNextTextSection(text, index);
|
||||
}
|
||||
}
|
||||
|
||||
// The text is displayed in order from left to right, while the stat names in the STAT_NAMES array are ordered
|
||||
// from top to bottom. Therefore, we need to set the stat name index to correspond to the STAT_NAMES array
|
||||
statNameIndex += kCharacterInfoRowCount;
|
||||
if (statNameIndex >= kCharacterInfoInformationCount) {
|
||||
statNameIndex -= kCharacterInfoInformationCount - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the text for the side buttons
|
||||
Common::String sideButtonsText = addNextTextToButtons(text, index, kCharacterInfoSideButtonCount);
|
||||
|
||||
// Party gold label (but not the value) sorts out of order and not with the rest of the information,
|
||||
// so we need to move it to its correct place
|
||||
informationHeaders[kCharacterInfoPartyGoldIndex] = getNextTextSection(text, index);
|
||||
|
||||
// Character name
|
||||
_vm->sayText(getNextTextSection(text, index), Common::TextToSpeechManager::INTERRUPT);
|
||||
|
||||
// Each attribute
|
||||
for (uint i = 0; i < kCharacterInfoInformationCount; ++i) {
|
||||
Common::String buttonText = informationHeaders[i] + ": " + getNextTextSection(text, index);
|
||||
_vm->sayText(buttonText);
|
||||
_buttonTexts.push_back(buttonText);
|
||||
}
|
||||
|
||||
_vm->sayText(sideButtonsText);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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);
|
||||
for (idx = 0; idx < ARRAYSIZE(Res.STAT_VALUES) - 1; ++idx)
|
||||
if (Res.STAT_VALUES[idx] > (int)stat1)
|
||||
break;
|
||||
|
||||
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, getBornForm(c), 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
|
||||
Common::String fmt(Res.CURRENT_MAXIMUM_TEXT);
|
||||
const char *p;
|
||||
while ((p = strstr(fmt.c_str(), "%u")) != nullptr)
|
||||
fmt.setChar('d', p - fmt.c_str() + 1);
|
||||
|
||||
msg = Common::String::format(fmt.c_str(), Res.STAT_NAMES[attrib],
|
||||
c._currentHp, c.getMaxHP());
|
||||
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:
|
||||
// Resistances
|
||||
msg = Common::String::format(Res.RESISTANCES_TEXT, Res.STAT_NAMES[attrib],
|
||||
c._fireResistance._permanent + c.itemScan(11) + c._fireResistance._temporary,
|
||||
c._coldResistance._permanent + c.itemScan(13) + c._coldResistance._temporary,
|
||||
c._electricityResistance._permanent + c.itemScan(12) + c._electricityResistance._temporary,
|
||||
c._poisonResistance._permanent + c.itemScan(14) + c._poisonResistance._temporary,
|
||||
c._energyResistance._permanent + c.itemScan(15) + c._energyResistance._temporary,
|
||||
c._magicResistance._permanent + c.itemScan(16) + c._magicResistance._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, getFoodOnHandPlurals(food), food, getDaysPlurals(food));
|
||||
break;
|
||||
}
|
||||
|
||||
case 19: {
|
||||
// Conditions
|
||||
Common::String lines[20];
|
||||
const char **_tmpConditions = c._sex == FEMALE ? (const char **)Res.CONDITION_NAMES_F : (const char **)Res.CONDITION_NAMES_M;
|
||||
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",
|
||||
_tmpConditions[condition]);
|
||||
} else {
|
||||
lines[condition] = Common::String::format("\n\t020%s\t095-%d",
|
||||
_tmpConditions[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);
|
||||
++total;
|
||||
}
|
||||
if (party._powerShield) {
|
||||
lines[17] = Common::String::format(Res.POWER_SHIELD, party._powerShield);
|
||||
++total;
|
||||
}
|
||||
if (party._holyBonus) {
|
||||
lines[18] = Common::String::format(Res.HOLY_BONUS, party._holyBonus);
|
||||
++total;
|
||||
}
|
||||
if (party._heroism) {
|
||||
lines[19] = Common::String::format(Res.HEROISM, party._heroism);
|
||||
++total;
|
||||
}
|
||||
|
||||
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();
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
|
||||
w.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
89
engines/mm/xeen/dialogs/dialogs_char_info.h
Normal file
89
engines/mm/xeen/dialogs/dialogs_char_info.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_CHAR_INFO_H
|
||||
#define XEEN_DIALOGS_CHAR_INFO_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/window.h"
|
||||
|
||||
namespace MM {
|
||||
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();
|
||||
|
||||
/**
|
||||
* Get plural day/days form
|
||||
*/
|
||||
const char *getDaysPlurals(int val);
|
||||
|
||||
/**
|
||||
* Return a string containing the details of the character
|
||||
*/
|
||||
Common::String loadCharacterDetails(const Character &c);
|
||||
|
||||
/**
|
||||
* Cursor display handling
|
||||
*/
|
||||
void showCursor(bool flag);
|
||||
|
||||
/**
|
||||
* Get gender form 'born'
|
||||
*/
|
||||
const char *getBornForm(const Character &c);
|
||||
|
||||
/**
|
||||
* Get plural form 'on hand' for food
|
||||
*/
|
||||
const char *getFoodOnHandPlurals(int food);
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text);
|
||||
#endif
|
||||
|
||||
bool expandStat(int attrib, const Character &c);
|
||||
public:
|
||||
static void show(XeenEngine *vm, int charIndex);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
265
engines/mm/xeen/dialogs/dialogs_control_panel.cpp
Normal file
265
engines/mm/xeen/dialogs/dialogs_control_panel.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_control_panel.h"
|
||||
#include "mm/xeen/dialogs/dialogs_query.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kControlPanelTextCount = 7;
|
||||
static const uint8 kControlPanelEfxIndex = 1;
|
||||
static const uint8 kControlPanelMusicIndex = 3;
|
||||
|
||||
#endif
|
||||
|
||||
enum ControlPanelButtonTTSTextIndex {
|
||||
kControlPanelLoad = 0,
|
||||
kControlPanelEfx = 1,
|
||||
kControlPanelSave = 2,
|
||||
kControlPanelMusic = 3,
|
||||
kControlPanelQuit = 4,
|
||||
kControlPanelWizard = 5
|
||||
};
|
||||
|
||||
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();
|
||||
#ifdef USE_TTS
|
||||
bool voiceText = true;
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
|
||||
do {
|
||||
Common::String btnText = getButtonText();
|
||||
Common::String text = Common::String::format(Res.CONTROL_PANEL_TEXT, btnText.c_str());
|
||||
|
||||
drawButtons(&w);
|
||||
|
||||
Common::String ttsMessage;
|
||||
w.writeString(text, false, &ttsMessage);
|
||||
w.writeString("\xB""000\t000\x1");
|
||||
w.update();
|
||||
|
||||
#ifdef USE_TTS
|
||||
if (voiceText) {
|
||||
speakText(ttsMessage);
|
||||
voiceText = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
events.updateGameCounter();
|
||||
intf.draw3d(false, false);
|
||||
|
||||
do {
|
||||
w.writeString("\r", false);
|
||||
drawButtons(&w);
|
||||
w.writeString(text, false);
|
||||
w.writeString("\v000\t000", false);
|
||||
w.frame();
|
||||
|
||||
if (_debugFlag)
|
||||
w.writeString(getTimeText());
|
||||
|
||||
w3.update();
|
||||
w.update();
|
||||
|
||||
events.pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
if (_vm->shouldExit())
|
||||
return 0;
|
||||
} while (!_buttonValue && events.timeElapsed() < 2);
|
||||
|
||||
if (Res.KeyConstants.DialogsControlPanel.KEY_QUIT == _buttonValue) {
|
||||
if (Confirm::show(g_vm, Res.CONFIRM_QUIT)) {
|
||||
g_vm->_gameMode = GMODE_QUIT;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsControlPanel.KEY_MRWIZARD == _buttonValue) {
|
||||
if (Confirm::show(g_vm, Res.MR_WIZARD)) {
|
||||
w.close();
|
||||
if (!windows[2]._enabled) {
|
||||
sound.playFX(51);
|
||||
|
||||
if (g_vm->getGameID() == GType_WorldOfXeen) {
|
||||
map._loadCcNum = 0;
|
||||
map.load(28);
|
||||
party._mazeDirection = DIR_EAST;
|
||||
} else {
|
||||
map._loadCcNum = 1;
|
||||
map.load(29);
|
||||
party._mazeDirection = DIR_SOUTH;
|
||||
}
|
||||
party.moveToRunLocation();
|
||||
}
|
||||
|
||||
party._gems = 0;
|
||||
result = 2;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsControlPanel.KEY_LOAD == _buttonValue) {
|
||||
if (_vm->_mode == MODE_COMBAT) {
|
||||
ErrorScroll::show(_vm, Res.NO_LOADING_IN_COMBAT);
|
||||
} else {
|
||||
// Close dialog and show loading dialog
|
||||
result = 3;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsControlPanel.KEY_SAVE == _buttonValue) {
|
||||
if (_vm->_mode == MODE_COMBAT) {
|
||||
ErrorScroll::show(_vm, Res.NO_SAVING_IN_COMBAT);
|
||||
} else {
|
||||
// Close dialog and show saving dialog
|
||||
result = 4;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsControlPanel.KEY_FXON == _buttonValue) {
|
||||
sound.setFxOn(!sound._fxOn);
|
||||
if (sound._fxOn)
|
||||
sound.playFX(20);
|
||||
#ifdef USE_TTS
|
||||
voiceOnOffText(sound._fxOn, kControlPanelEfxIndex);
|
||||
#endif
|
||||
} else if (Res.KeyConstants.DialogsControlPanel.KEY_MUSICON == _buttonValue) {
|
||||
sound.setMusicOn(!sound._musicOn);
|
||||
#ifdef USE_TTS
|
||||
voiceOnOffText(sound._musicOn, kControlPanelMusicIndex);
|
||||
#endif
|
||||
} else if (Common::KEYCODE_ESCAPE == _buttonValue) {
|
||||
result = 1;
|
||||
|
||||
} else if (Common::KEYCODE_g == _buttonValue) { // Goober cheat sequence
|
||||
debugCtr = 1;
|
||||
} else if (Common::KEYCODE_o == _buttonValue) {
|
||||
debugCtr = (debugCtr == 1 || debugCtr == 2) ? 2 : 0;
|
||||
} else if (Common::KEYCODE_b == _buttonValue) {
|
||||
debugCtr = (debugCtr == 2) ? 3 : 0;
|
||||
} else if (Common::KEYCODE_r == _buttonValue) {
|
||||
if (debugCtr == 3)
|
||||
_debugFlag = true;
|
||||
else
|
||||
debugCtr = 0;
|
||||
}
|
||||
|
||||
} while (!result);
|
||||
|
||||
w.close();
|
||||
intf.drawParty(true);
|
||||
|
||||
if (result == 3) {
|
||||
if (g_vm->canLoadGameStateCurrently())
|
||||
saves.loadGame();
|
||||
} else if (result == 4) {
|
||||
saves.saveGame();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ControlPanel::loadButtons() {
|
||||
_iconSprites.load("cpanel.icn");
|
||||
addButton(Common::Rect(214, 56, 244, 69), Res.KeyConstants.DialogsControlPanel.KEY_FXON, 0, &_iconSprites, kControlPanelEfx);
|
||||
addButton(Common::Rect(214, 75, 244, 88), Res.KeyConstants.DialogsControlPanel.KEY_MUSICON, 0, &_iconSprites, kControlPanelMusic);
|
||||
addButton(Common::Rect(135, 56, 165, 69), Res.KeyConstants.DialogsControlPanel.KEY_LOAD, 0, &_iconSprites, kControlPanelLoad);
|
||||
addButton(Common::Rect(135, 75, 165, 88), Res.KeyConstants.DialogsControlPanel.KEY_SAVE, 0, &_iconSprites, kControlPanelSave);
|
||||
|
||||
// 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), Res.KeyConstants.DialogsControlPanel.KEY_QUIT, 0, &_iconSprites, kControlPanelQuit);
|
||||
addButton(Common::Rect(175, 113, 205, 126), Res.KeyConstants.DialogsControlPanel.KEY_MRWIZARD, 0, &_iconSprites, kControlPanelWizard);
|
||||
}
|
||||
|
||||
Common::String ControlPanel::getButtonText() {
|
||||
Sound &sound = *g_vm->_sound;
|
||||
_btnSoundText = sound._fxOn ? 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());
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void ControlPanel::speakText(const Common::String &text) {
|
||||
uint index = 0;
|
||||
_vm->sayText(getNextTextSection(text, index, kControlPanelTextCount));
|
||||
addNextTextToButtons(text, index, kControlPanelTextCount - 1);
|
||||
}
|
||||
|
||||
void ControlPanel::voiceOnOffText(bool on, uint buttonTextIndex) {
|
||||
const char *baseMessage = on ? Res.ON : Res.OFF;
|
||||
Common::String cleanedMessage;
|
||||
for (uint i = 0; i < strlen(baseMessage); ++i) {
|
||||
if (Common::isAlpha(baseMessage[i])) {
|
||||
cleanedMessage += baseMessage[i];
|
||||
}
|
||||
}
|
||||
_vm->sayText(cleanedMessage, Common::TextToSpeechManager::INTERRUPT);
|
||||
_buttonTexts[buttonTextIndex] = cleanedMessage;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
82
engines/mm/xeen/dialogs/dialogs_control_panel.h
Normal file
82
engines/mm/xeen/dialogs/dialogs_control_panel.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_CONTROL_PANEL_H
|
||||
#define XEEN_DIALOGS_CONTROL_PANEL_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
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;
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Voices text as text-to-speech and sets the buttons
|
||||
* @param text Text of the control panel, each piece separated by a newline
|
||||
*/
|
||||
void speakText(const Common::String &text);
|
||||
|
||||
/**
|
||||
* Voices "On" or "Off" text and changes the TTS text of an on/off button to this text
|
||||
* @param on Whether to voice "on" or "off"
|
||||
* @param buttonTextIndex The index of the button text to change
|
||||
*/
|
||||
void voiceOnOffText(bool on, uint buttonTextIndex);
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Show the control panel
|
||||
*/
|
||||
static int show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
124
engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
Normal file
124
engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_copy_protection.h"
|
||||
#include "mm/xeen/dialogs/dialogs_input.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kCopyProtectionDirectionCount = 2;
|
||||
|
||||
#endif
|
||||
|
||||
bool CopyProtection::show(XeenEngine *vm) {
|
||||
CopyProtection *dlg = new CopyProtection(vm);
|
||||
int result = dlg->execute();
|
||||
delete dlg;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CopyProtection::CopyProtection(XeenEngine *vm) : Input(vm, &(*vm->_windows)[11]) {
|
||||
loadEntries();
|
||||
}
|
||||
|
||||
bool CopyProtection::execute() {
|
||||
EventsManager &events = *_vm->_events;
|
||||
Sound &sound = *_vm->_sound;
|
||||
Window &w = *_window;
|
||||
bool result = false;
|
||||
Common::String line;
|
||||
|
||||
// Choose a random entry
|
||||
ProtectionEntry &protEntry = _entries[_vm->getRandomNumber(_entries.size() - 1)];
|
||||
Common::String msg = Common::String::format(Res.WHATS_THE_PASSWORD,
|
||||
protEntry._pageNum, protEntry._lineNum, protEntry._wordNum);
|
||||
|
||||
w.open();
|
||||
Common::String ttsMessage;
|
||||
w.writeString(msg, false, &ttsMessage);
|
||||
w.update();
|
||||
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage);
|
||||
#endif
|
||||
|
||||
for (int tryNum = 0; tryNum < 3 && !_vm->shouldExit(); ++tryNum) {
|
||||
line.clear();
|
||||
if (getString(line, 20, 200, false) && !line.compareToIgnoreCase(protEntry._text)) {
|
||||
sound.playFX(20);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
sound.playFX(21);
|
||||
w.writeString("\x3l\v040\n\x4""200");
|
||||
w.writeString(Res.PASSWORD_INCORRECT);
|
||||
w.update();
|
||||
|
||||
events.updateGameCounter();
|
||||
events.wait(50, false);
|
||||
}
|
||||
|
||||
w.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
void CopyProtection::loadEntries() {
|
||||
FileManager &files = *g_vm->_files;
|
||||
File f(files._ccNum ? "timer.drv" : "cpstruct");
|
||||
ProtectionEntry pe;
|
||||
byte seed = 0;
|
||||
char text[13];
|
||||
|
||||
while (f.pos() < f.size()) {
|
||||
pe._pageNum = f.readByte() ^ seed++;
|
||||
pe._lineNum = f.readByte() ^ seed++;
|
||||
pe._wordNum = f.readByte() ^ seed++;
|
||||
|
||||
for (int idx = 0; idx < 13; ++idx)
|
||||
text[idx] = f.readByte() ^ seed++;
|
||||
text[12] = '\0';
|
||||
pe._text = Common::String(text);
|
||||
|
||||
_entries.push_back(pe);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void CopyProtection::speakText(const Common::String &text) const {
|
||||
uint index = 0;
|
||||
_vm->sayText(getNextTextSection(text, index), Common::TextToSpeechManager::INTERRUPT);
|
||||
// Combine the directions so they're spoken cleanly as one sentence
|
||||
_vm->sayText(getNextTextSection(text, index, kCopyProtectionDirectionCount, " "));
|
||||
_vm->sayText(text.substr(index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
73
engines/mm/xeen/dialogs/dialogs_copy_protection.h
Normal file
73
engines/mm/xeen/dialogs/dialogs_copy_protection.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_COPY_PROTECTION_H
|
||||
#define XEEN_DIALOGS_COPY_PROTECTION_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_input.h"
|
||||
#include "common/array.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class CopyProtection : public Input {
|
||||
struct ProtectionEntry {
|
||||
uint8 _pageNum;
|
||||
uint8 _lineNum;
|
||||
uint8 _wordNum;
|
||||
Common::String _text;
|
||||
};
|
||||
private:
|
||||
Common::Array<ProtectionEntry> _entries;
|
||||
private:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
CopyProtection(XeenEngine *vm);
|
||||
|
||||
/**
|
||||
* Execute the dialog
|
||||
*/
|
||||
bool execute();
|
||||
|
||||
/**
|
||||
* Load the copy protection entries
|
||||
*/
|
||||
void loadEntries();
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Voices text with TTS
|
||||
* @param text Text to voice
|
||||
*/
|
||||
void speakText(const Common::String &text) const;
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Show the dialog
|
||||
*/
|
||||
static bool show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
791
engines/mm/xeen/dialogs/dialogs_create_char.cpp
Normal file
791
engines/mm/xeen/dialogs/dialogs_create_char.cpp
Normal file
@@ -0,0 +1,791 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_create_char.h"
|
||||
#include "mm/xeen/dialogs/dialogs_input.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kCreateCharacterBasicInfoCount = 6;
|
||||
static const uint8 kCreateCharacterSideButtonCount = 3;
|
||||
|
||||
#endif
|
||||
|
||||
enum CreateCharacterButtonTTSTextIndex {
|
||||
kCreateCharacterRoll = 0,
|
||||
kCreateCharacterCreate = 1,
|
||||
kCreateCharacterExit = 2,
|
||||
kCreateCharacterMight = 3,
|
||||
kCreateCharacterIntellect = 4,
|
||||
kCreateCharacterPersonality = 5,
|
||||
kCreateCharacterEndurance = 6,
|
||||
kCreateCharacterSpeed = 7,
|
||||
kCreateCharacterAccuracy = 8,
|
||||
kCreateCharacterLuck = 9,
|
||||
kCreateCharacterKnight = 10,
|
||||
kCreateCharacterPaladin = 11,
|
||||
kCreateCharacterArcher = 12,
|
||||
kCreateCharacterCleric = 13,
|
||||
kCreateCharacterSorcerer = 14,
|
||||
kCreateCharacterRobber = 15,
|
||||
kCreateCharacterNinja = 16,
|
||||
kCreateCharacterBarbarian = 17,
|
||||
kCreateCharacterDruid = 18,
|
||||
kCreateCharacterRanger = 19,
|
||||
kCreateCharacterSwapMight = 20,
|
||||
kCreateCharacterSwapIntellect = 21,
|
||||
kCreateCharacterSwapPersonality = 22,
|
||||
kCreateCharacterSwapEndurance = 23,
|
||||
kCreateCharacterSwapSpeed = 24,
|
||||
kCreateCharacterSwapAccuracy = 25,
|
||||
kCreateCharacterSwapLuck = 26
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
do {
|
||||
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() == 0)
|
||||
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));
|
||||
|
||||
Common::String ttsMessage;
|
||||
// Render all on-screen text
|
||||
w.writeString(msg, false, &ttsMessage);
|
||||
w.update();
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, false, classId != -1, selectedClass);
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
if (Common::KEYCODE_UP == _buttonValue) {
|
||||
if (charIndex == 0)
|
||||
continue;
|
||||
|
||||
--charIndex;
|
||||
race = (Race)((freeCharList[charIndex] / 4) % 5);
|
||||
sex = (Sex)(freeCharList[charIndex] & 1);
|
||||
|
||||
} else if (Common::KEYCODE_DOWN == _buttonValue) {
|
||||
if (++charIndex == (int)freeCharList.size()) {
|
||||
--charIndex;
|
||||
continue;
|
||||
} else {
|
||||
race = (Race)((freeCharList[charIndex] / 4) % 5);
|
||||
sex = (Sex)(freeCharList[charIndex] & 1);
|
||||
}
|
||||
|
||||
} else if (Common::KEYCODE_PAGEUP == _buttonValue) {
|
||||
for (int tempClass = selectedClass - 1; tempClass >= 0; --tempClass) {
|
||||
if (_allowedClasses[tempClass]) {
|
||||
selectedClass = tempClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printSelectionArrow(selectedClass);
|
||||
continue;
|
||||
|
||||
} else if (Common::KEYCODE_PAGEDOWN == _buttonValue) {
|
||||
|
||||
} else if (Res.KeyConstants.DialogsCreateChar.KEY_MGT == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_INT == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_PER == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_END == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_SPD == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_ACY == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_LCK == _buttonValue) {
|
||||
if (swapAttributes(_buttonValue)) {
|
||||
checkClass();
|
||||
classId = -1;
|
||||
selectedClass = newCharDetails(race, sex, classId, selectedClass, msg);
|
||||
}
|
||||
|
||||
} else if (1000 == _buttonValue ||
|
||||
1001 == _buttonValue ||
|
||||
1002 == _buttonValue ||
|
||||
1003 == _buttonValue ||
|
||||
1004 == _buttonValue ||
|
||||
1005 == _buttonValue ||
|
||||
1006 == _buttonValue ||
|
||||
1007 == _buttonValue ||
|
||||
1008 == _buttonValue ||
|
||||
1009 == _buttonValue) {
|
||||
if (_allowedClasses[_buttonValue - 1000]) {
|
||||
selectedClass = classId = _buttonValue - 1000;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsCreateChar.KEY_CREATE == _buttonValue) {
|
||||
_vm->_mode = MODE_FF;
|
||||
bool result = saveCharacter(party._roster[freeCharList[charIndex]],
|
||||
classId, race, sex);
|
||||
_vm->_mode = MODE_4;
|
||||
|
||||
if (result)
|
||||
restartFlag = true;
|
||||
continue;
|
||||
|
||||
} else if (Common::KEYCODE_RETURN == _buttonValue) {
|
||||
classId = selectedClass;
|
||||
|
||||
} else if (Common::KEYCODE_SPACE == _buttonValue ||
|
||||
Res.KeyConstants.DialogsCreateChar.KEY_ROLL == _buttonValue) {
|
||||
// Re-roll the attributes
|
||||
rollAttributes();
|
||||
classId = -1;
|
||||
|
||||
} else {
|
||||
// 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));
|
||||
|
||||
Common::String ttsMessage;
|
||||
w.writeString(msg, false, &ttsMessage);
|
||||
w.update();
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, true, classId != -1, selectedClass);
|
||||
#endif
|
||||
|
||||
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), Res.KeyConstants.DialogsCreateChar.KEY_ROLL, &_icons, kCreateCharacterRoll);
|
||||
addButton(Common::Rect(132, 128, 156, 148), Res.KeyConstants.DialogsCreateChar.KEY_CREATE, &_icons, kCreateCharacterCreate);
|
||||
|
||||
addButton(Common::Rect(132, 158, 156, 178), Common::KEYCODE_ESCAPE, &_icons, kCreateCharacterExit);
|
||||
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), Res.KeyConstants.DialogsCreateChar.KEY_MGT, nullptr, kCreateCharacterMight);
|
||||
addButton(Common::Rect(168, 43, 192, 63), Res.KeyConstants.DialogsCreateChar.KEY_INT, nullptr, kCreateCharacterIntellect);
|
||||
addButton(Common::Rect(168, 67, 192, 87), Res.KeyConstants.DialogsCreateChar.KEY_PER, nullptr, kCreateCharacterPersonality);
|
||||
addButton(Common::Rect(168, 91, 192, 111), Res.KeyConstants.DialogsCreateChar.KEY_END, nullptr, kCreateCharacterEndurance);
|
||||
addButton(Common::Rect(168, 115, 192, 135), Res.KeyConstants.DialogsCreateChar.KEY_SPD, nullptr, kCreateCharacterSpeed);
|
||||
addButton(Common::Rect(168, 139, 192, 159), Res.KeyConstants.DialogsCreateChar.KEY_ACY, nullptr, kCreateCharacterAccuracy);
|
||||
addButton(Common::Rect(168, 163, 192, 183), Res.KeyConstants.DialogsCreateChar.KEY_LCK, nullptr, kCreateCharacterLuck);
|
||||
|
||||
addButton(Common::Rect(227, 19, 239, 29), 1000, nullptr, kCreateCharacterKnight);
|
||||
addButton(Common::Rect(227, 30, 239, 40), 1001, nullptr, kCreateCharacterPaladin);
|
||||
addButton(Common::Rect(227, 41, 239, 51), 1002, nullptr, kCreateCharacterArcher);
|
||||
addButton(Common::Rect(227, 52, 239, 62), 1003, nullptr, kCreateCharacterCleric);
|
||||
addButton(Common::Rect(227, 63, 239, 73), 1004, nullptr, kCreateCharacterSorcerer);
|
||||
addButton(Common::Rect(227, 74, 239, 84), 1005, nullptr, kCreateCharacterRobber);
|
||||
addButton(Common::Rect(227, 85, 239, 95), 1006, nullptr, kCreateCharacterNinja);
|
||||
addButton(Common::Rect(227, 96, 239, 106), 1007, nullptr, kCreateCharacterBarbarian);
|
||||
addButton(Common::Rect(227, 107, 239, 117), 1008, nullptr, kCreateCharacterDruid);
|
||||
addButton(Common::Rect(227, 118, 239, 128), 1009, nullptr, kCreateCharacterRanger);
|
||||
}
|
||||
|
||||
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) {
|
||||
const char *skillP = Res.SKILL_NAMES[Res.NEW_CHAR_RACE_SKILLS[race]];
|
||||
raceSkillStr = Common::String(skillP + Res.NEW_CHAR_SKILLS_OFFSET[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 {
|
||||
if (Res.KeyConstants.DialogsCreateChar.KEY_MGT == keycode)
|
||||
return MIGHT;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_INT == keycode)
|
||||
return INTELLECT;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_PER == keycode)
|
||||
return PERSONALITY;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_END == keycode)
|
||||
return ENDURANCE;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_SPD == keycode)
|
||||
return SPEED;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_ACY == keycode)
|
||||
return ACCURACY;
|
||||
else if (Res.KeyConstants.DialogsCreateChar.KEY_LCK == keycode)
|
||||
return LUCK;
|
||||
else
|
||||
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), Res.KeyConstants.DialogsCreateChar.KEY_MGT, nullptr, kCreateCharacterSwapMight);
|
||||
addButton(Common::Rect(168, 43, 192, 63), Res.KeyConstants.DialogsCreateChar.KEY_INT, nullptr, kCreateCharacterSwapIntellect);
|
||||
addButton(Common::Rect(168, 67, 192, 87), Res.KeyConstants.DialogsCreateChar.KEY_PER, nullptr, kCreateCharacterSwapPersonality);
|
||||
addButton(Common::Rect(168, 91, 192, 111), Res.KeyConstants.DialogsCreateChar.KEY_END, nullptr, kCreateCharacterSwapEndurance);
|
||||
addButton(Common::Rect(168, 115, 192, 135), Res.KeyConstants.DialogsCreateChar.KEY_SPD, nullptr, kCreateCharacterSwapSpeed);
|
||||
addButton(Common::Rect(168, 139, 192, 159), Res.KeyConstants.DialogsCreateChar.KEY_ACY, nullptr, kCreateCharacterSwapAccuracy);
|
||||
addButton(Common::Rect(168, 163, 192, 183), Res.KeyConstants.DialogsCreateChar.KEY_LCK, nullptr, kCreateCharacterSwapLuck);
|
||||
|
||||
#ifdef USE_TTS
|
||||
for (uint i = 0; i < TOTAL_ATTRIBUTES; ++i) {
|
||||
_buttonTexts.push_back(Res.STAT_NAMES[i]);
|
||||
}
|
||||
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
|
||||
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();
|
||||
#ifdef USE_TTS
|
||||
for (uint i = 0; i < TOTAL_ATTRIBUTES; ++i) {
|
||||
_buttonTexts.pop_back();
|
||||
}
|
||||
#endif
|
||||
_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;
|
||||
int ccNum = _vm->_files->_ccNum;
|
||||
|
||||
// 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;
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(name, Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
// Save new character details
|
||||
c.clear();
|
||||
c._name = name;
|
||||
c._savedMazeId = party._priorMazeId;
|
||||
c._xeenSide = map._loadCcNum;
|
||||
c._sex = sex;
|
||||
c._race = race;
|
||||
c._class = (CharacterClass)classId;
|
||||
c._level._permanent = ccNum ? 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._magicResistance._permanent = Res.RACE_MAGIC_RESISTANCES[race];
|
||||
c._fireResistance._permanent = Res.RACE_FIRE_RESISTANCES[race];
|
||||
c._electricityResistance._permanent = Res.RACE_ELECTRIC_RESISTANCES[race];
|
||||
c._coldResistance._permanent = Res.RACE_COLD_RESISTANCES[race];
|
||||
c._energyResistance._permanent = Res.RACE_ENERGY_RESISTANCES[race];
|
||||
c._poisonResistance._permanent = Res.RACE_POISON_RESISTANCES[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;
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void CreateCharacterDialog::speakText(const Common::String &text, bool hasAttributeLabels, bool classSelected, int selectedClass) {
|
||||
_vm->stopTextToSpeech();
|
||||
uint index = 0;
|
||||
bool addNewButtons = _buttonTexts.empty();
|
||||
|
||||
Common::String buttonTexts;
|
||||
if (!hasAttributeLabels) {
|
||||
// Roll/create/ESC buttons
|
||||
if (addNewButtons) {
|
||||
buttonTexts = addNextTextToButtons(text, index, kCreateCharacterSideButtonCount);
|
||||
} else {
|
||||
buttonTexts = getNextTextSection(text, index, kCreateCharacterSideButtonCount);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < TOTAL_ATTRIBUTES; ++i) {
|
||||
getNextTextSection(text, index);
|
||||
}
|
||||
}
|
||||
|
||||
// Race/sex/class info
|
||||
_vm->sayText(getNextTextSection(text, index, kCreateCharacterBasicInfoCount));
|
||||
|
||||
uint classIndex = 0;
|
||||
|
||||
// The selected class is at the very end of the string, but it should be voiced with the rest of the race/sex/class
|
||||
// info, so find it here early and voice it
|
||||
if (classSelected) {
|
||||
uint endClassIndex = text.findLastNotOf('\n');
|
||||
|
||||
if (endClassIndex != Common::String::npos) {
|
||||
for (uint i = endClassIndex; i >= index; --i) {
|
||||
if (text[i] == '\n') {
|
||||
classIndex = i;
|
||||
_vm->sayText(text.substr(classIndex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAttributeLabels) {
|
||||
_vm->sayText(buttonTexts);
|
||||
}
|
||||
|
||||
// Get attribute values
|
||||
for (uint i = 0; i < TOTAL_ATTRIBUTES; ++i) {
|
||||
Common::String attribute = Common::String(Res.STAT_NAMES[i]) + ": " + getNextTextSection(text, index);
|
||||
|
||||
if (addNewButtons) {
|
||||
_buttonTexts.push_back(attribute);
|
||||
} else {
|
||||
_buttonTexts[i + kCreateCharacterSideButtonCount] = attribute;
|
||||
}
|
||||
|
||||
_vm->sayText(attribute);
|
||||
}
|
||||
|
||||
// Classes
|
||||
for (int i = 0; i < TOTAL_CLASSES; ++i) {
|
||||
Common::String buttonText;
|
||||
if (_allowedClasses[i]) {
|
||||
buttonText = getNextTextSection(text, index);
|
||||
} else {
|
||||
buttonText = "";
|
||||
getNextTextSection(text, index);
|
||||
}
|
||||
|
||||
if (addNewButtons) {
|
||||
_buttonTexts.push_back(buttonText);
|
||||
} else {
|
||||
_buttonTexts[i + TOTAL_CLASSES] = buttonText;
|
||||
}
|
||||
|
||||
if (i == selectedClass) {
|
||||
_vm->sayText(buttonText);
|
||||
}
|
||||
}
|
||||
|
||||
// Skills
|
||||
_vm->sayText(text.substr(index, classIndex - index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
136
engines/mm/xeen/dialogs/dialogs_create_char.h
Normal file
136
engines/mm/xeen/dialogs/dialogs_create_char.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_CREATE_CHAR_H
|
||||
#define XEEN_DIALOGS_CREATE_CHAR_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/character.h"
|
||||
|
||||
namespace MM {
|
||||
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();
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Voices text with TTS and sets up buttons
|
||||
* @param text Text for voicing and buttons. Each section should be separated by a newline
|
||||
* @param hasAttributeLabels Whether this text has attribute labels in it
|
||||
* @param classSelected Whether a class is selected
|
||||
* @param selectedClass Class selected by the player
|
||||
*/
|
||||
void speakText(const Common::String &text, bool hasAttributeLabels, bool classSelected, int selectedClass);
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Shows the Create Character dialog
|
||||
*/
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
101
engines/mm/xeen/dialogs/dialogs_difficulty.cpp
Normal file
101
engines/mm/xeen/dialogs/dialogs_difficulty.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_difficulty.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const char *difficultyButtonsText[] = {
|
||||
"Adventurer\nWarrior", // English
|
||||
"Abenteurer\nK\204mpfer", // German
|
||||
"Aventurier\nGuerrier", // French
|
||||
"Aventurero\nGuerrero", // Spanish
|
||||
"\x80\xa2\xa0\xad\xe2\xee\xe0\xa8\xe1\n\x82\xae\xa8\xad", // Russian (Авантюрис, Воин)
|
||||
"\xab\x5f\xc0\x49\xbc\xd2\xa6\xa1\n\xbe\xd4\xa4\x68\xbc\xd2\xa6\xa1" // Chinese (冒險模式, 戰士模式)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
enum DifficultyButtonTTSTextIndex {
|
||||
kDifficultyAdventurer = 0,
|
||||
kDifficultyWarrior = 1
|
||||
};
|
||||
|
||||
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();
|
||||
#ifdef USE_TTS
|
||||
setButtonTexts(difficultyButtonsText[_vm->_ttsLanguage]);
|
||||
#endif
|
||||
}
|
||||
|
||||
int DifficultyDialog::execute() {
|
||||
EventsManager &events = *_vm->_events;
|
||||
Windows &windows = *_vm->_windows;
|
||||
|
||||
Window &w = windows[6];
|
||||
w.open();
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
w.writeString(Res.DIFFICULTY_TEXT);
|
||||
drawButtons(&w);
|
||||
|
||||
int result = -1;
|
||||
while (!_vm->shouldExit()) {
|
||||
events.pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
|
||||
if (Res.KeyConstants.DialogsDifficulty.KEY_ADVENTURER == _buttonValue)
|
||||
result = ADVENTURER;
|
||||
else if (Res.KeyConstants.DialogsDifficulty.KEY_WARRIOR == _buttonValue)
|
||||
result = WARRIOR;
|
||||
else if (Common::KEYCODE_ESCAPE != _buttonValue)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
w.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
void DifficultyDialog::loadButtons() {
|
||||
_sprites.load("choice.icn");
|
||||
|
||||
addButton(Common::Rect(68, 167, 158, 187), Res.KeyConstants.DialogsDifficulty.KEY_ADVENTURER, &_sprites, kDifficultyAdventurer);
|
||||
addButton(Common::Rect(166, 167, 256, 187), Res.KeyConstants.DialogsDifficulty.KEY_WARRIOR, &_sprites, kDifficultyWarrior);
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
61
engines/mm/xeen/dialogs/dialogs_difficulty.h
Normal file
61
engines/mm/xeen/dialogs/dialogs_difficulty.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_DIFFICULTY_H
|
||||
#define XEEN_DIALOGS_DIFFICULTY_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
104
engines/mm/xeen/dialogs/dialogs_dismiss.cpp
Normal file
104
engines/mm/xeen/dialogs/dialogs_dismiss.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_dismiss.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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();
|
||||
|
||||
bool ttsVoiceText = true;
|
||||
bool breakFlag = false;
|
||||
while (!_vm->shouldExit() && !breakFlag) {
|
||||
do {
|
||||
events.updateGameCounter();
|
||||
intf.draw3d(false, false);
|
||||
|
||||
w.frame();
|
||||
w.fill();
|
||||
w.writeString(Res.DISMISS_WHOM, ttsVoiceText);
|
||||
_iconSprites.draw(w, 0, Common::Point(225, 120));
|
||||
w.update();
|
||||
ttsVoiceText = false;
|
||||
|
||||
do {
|
||||
events.pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
} while (!_vm->shouldExit() && !_buttonValue && events.timeElapsed() < 2);
|
||||
} 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 if (party._activeParty[_buttonValue]._weapons.hasElderWeapon()) {
|
||||
w.close();
|
||||
ErrorScroll::show(_vm, Res.DELETE_CHAR_WITH_ELDER_WEAPON, 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;
|
||||
}
|
||||
}
|
||||
|
||||
w.close();
|
||||
intf.drawParty(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
|
||||
} // End of namespace MM
|
||||
47
engines/mm/xeen/dialogs/dialogs_dismiss.h
Normal file
47
engines/mm/xeen/dialogs/dialogs_dismiss.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_DISMISS_H
|
||||
#define XEEN_DIALOGS_DISMISS_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
81
engines/mm/xeen/dialogs/dialogs_exchange.cpp
Normal file
81
engines/mm/xeen/dialogs/dialogs_exchange.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_exchange.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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() && _buttonValue != charIndex) {
|
||||
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
|
||||
} // End of namespace MM
|
||||
47
engines/mm/xeen/dialogs/dialogs_exchange.h
Normal file
47
engines/mm/xeen/dialogs/dialogs_exchange.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_EXCHANGE_H
|
||||
#define XEEN_DIALOGS_EXCHANGE_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
169
engines/mm/xeen/dialogs/dialogs_info.cpp
Normal file
169
engines/mm/xeen/dialogs/dialogs_info.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_info.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kInfoTimeCount = 3;
|
||||
|
||||
#endif
|
||||
|
||||
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();
|
||||
Common::String ttsMessage;
|
||||
w.writeString(details, false, &ttsMessage);
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
speakText(ttsMessage);
|
||||
#endif
|
||||
|
||||
do {
|
||||
events.updateGameCounter();
|
||||
intf.draw3d(false, false);
|
||||
w.frame();
|
||||
w.writeString(details, false);
|
||||
w.update();
|
||||
|
||||
events.wait(1);
|
||||
} while (!_vm->shouldExit() && !events.isKeyMousePressed());
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
|
||||
events.clearEvents();
|
||||
w.close();
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void InfoDialog::speakText(const Common::String &text) const {
|
||||
uint index = 0;
|
||||
|
||||
_vm->sayText(getNextTextSection(text, index, kInfoTimeCount));
|
||||
|
||||
Common::String timeInfo[kInfoTimeCount];
|
||||
// Time, day, and year headers
|
||||
for (uint i = 0; i < kInfoTimeCount; ++i) {
|
||||
timeInfo[i] = getNextTextSection(text, index);
|
||||
}
|
||||
|
||||
// Time, day, and year numbers
|
||||
for (uint i = 0; i < kInfoTimeCount; ++i) {
|
||||
_vm->sayText(timeInfo[i] + ": " + getNextTextSection(text, index));
|
||||
}
|
||||
|
||||
// Any remaining lines
|
||||
_vm->sayText(text.substr(index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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._fireResistance) {
|
||||
_lines.push_back(Common::String::format(Res.FIRE_RESISTANCE_TEXT,
|
||||
_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._fireResistance));
|
||||
}
|
||||
|
||||
if (party._electricityResistance) {
|
||||
_lines.push_back(Common::String::format(Res.ELECRICITY_RESISTANCE_TEXT,
|
||||
_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._electricityResistance));
|
||||
}
|
||||
|
||||
if (party._coldResistance) {
|
||||
_lines.push_back(Common::String::format(Res.COLD_RESISTANCE_TEXT,
|
||||
_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._coldResistance));
|
||||
}
|
||||
|
||||
if (party._poisonResistance) {
|
||||
_lines.push_back(Common::String::format(Res.POISON_RESISTANCE_TEXT,
|
||||
_lines.size() == 0 ? 10 : 1, AA_L024, AA_R124, party._poisonResistance));
|
||||
}
|
||||
|
||||
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
|
||||
} // End of namespace MM
|
||||
51
engines/mm/xeen/dialogs/dialogs_info.h
Normal file
51
engines/mm/xeen/dialogs/dialogs_info.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_INFO_H
|
||||
#define XEEN_DIALOGS_INFO_H
|
||||
|
||||
#include "common/str-array.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class InfoDialog : public ButtonContainer {
|
||||
private:
|
||||
Common::StringArray _lines;
|
||||
|
||||
InfoDialog(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
void execute();
|
||||
|
||||
void protectionText();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text) const;
|
||||
#endif
|
||||
public:
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
409
engines/mm/xeen/dialogs/dialogs_input.cpp
Normal file
409
engines/mm/xeen/dialogs/dialogs_input.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_input.h"
|
||||
#include "mm/xeen/scripts.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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::nonEnToLower(uint16 ascii) {
|
||||
if (Common::RU_RUS == g_vm->getLanguage()) {
|
||||
switch (ascii) {
|
||||
case Common::KEYCODE_f: return 0xA0; // А
|
||||
case Common::KEYCODE_COMMA: return 0xA1; // Б
|
||||
case Common::KEYCODE_d: return 0xA2; // В
|
||||
case Common::KEYCODE_u: return 0xA3; // Г
|
||||
case Common::KEYCODE_l: return 0xA4; // Д
|
||||
case Common::KEYCODE_t: return 0xA5; // Е
|
||||
case Common::KEYCODE_BACKQUOTE: return 0xF1; // Ё
|
||||
case Common::KEYCODE_SEMICOLON: return 0xA6; // Ж
|
||||
case Common::KEYCODE_p: return 0xA7; // З
|
||||
case Common::KEYCODE_b: return 0xA8; // И
|
||||
case Common::KEYCODE_q: return 0xA9; // Й
|
||||
case Common::KEYCODE_r: return 0xAA; // К
|
||||
case Common::KEYCODE_k: return 0xAB; // Л
|
||||
case Common::KEYCODE_v: return 0xAC; // М
|
||||
case Common::KEYCODE_y: return 0xAD; // Н
|
||||
case Common::KEYCODE_j: return 0xAE; // О
|
||||
case Common::KEYCODE_g: return 0xAF; // П
|
||||
case Common::KEYCODE_h: return 0xE0; // Р
|
||||
case Common::KEYCODE_c: return 0xE1; // С
|
||||
case Common::KEYCODE_n: return 0xE2; // Т
|
||||
case Common::KEYCODE_e: return 0xE3; // У
|
||||
case Common::KEYCODE_a: return 0xE4; // Ф
|
||||
case Common::KEYCODE_LEFTBRACKET: return 0xE5; // Х
|
||||
case Common::KEYCODE_w: return 0xE6; // Ц
|
||||
case Common::KEYCODE_x: return 0xE7; // Ч
|
||||
case Common::KEYCODE_i: return 0xE8; // Ш
|
||||
case Common::KEYCODE_o: return 0xE9; // Щ
|
||||
case Common::KEYCODE_RIGHTBRACKET: return 0xEA; // Ъ
|
||||
case Common::KEYCODE_s: return 0xEB; // Ы
|
||||
case Common::KEYCODE_m: return 0xEC; // Ь
|
||||
case Common::KEYCODE_QUOTE: return 0xED; // Э
|
||||
case Common::KEYCODE_PERIOD: return 0xEE; // Ю
|
||||
case Common::KEYCODE_z: return 0xEF; // Я
|
||||
default:
|
||||
return tolower(ascii);
|
||||
}
|
||||
}
|
||||
return ascii;
|
||||
}
|
||||
|
||||
int Input::getString(Common::String &line, uint maxLen, int maxWidth, bool isNumeric) {
|
||||
bool nonEnCharset = false;
|
||||
|
||||
_vm->_noDirectionSense = true;
|
||||
Common::String msg = Common::String::format("\x3""l\t000\x4%03d\x3""c", maxWidth);
|
||||
_window->writeString(msg, false);
|
||||
_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))) {
|
||||
if (!nonEnCharset) {
|
||||
if (!isNumeric && Common::isAlpha(keyState.ascii)) {
|
||||
// The original game doesn't care about Shift or Caps Locks. The
|
||||
// capitalization is done for the user automatically at the beginning of
|
||||
// words.
|
||||
if (line.empty() || line.hasSuffix(" ")) {
|
||||
line += toupper(keyState.ascii);
|
||||
} else {
|
||||
line += tolower(keyState.ascii);
|
||||
}
|
||||
} else {
|
||||
line += keyState.ascii;
|
||||
}
|
||||
} else {
|
||||
if (!isNumeric) {
|
||||
line += nonEnToLower(keyState.ascii);
|
||||
} else {
|
||||
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;
|
||||
} else if (Common::RU_RUS == g_vm->getLanguage()) {
|
||||
if (Common::KEYCODE_F11 == keyCode) {
|
||||
nonEnCharset = true;
|
||||
} else if (Common::KEYCODE_F12 == keyCode) {
|
||||
nonEnCharset = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
msg = Common::String::format("\x3""l\t000\x4%03d\x3""c%s", maxWidth, line.c_str());
|
||||
_window->writeString(msg, false);
|
||||
_window->update();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(line, Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
_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_INTERACTIVE7;
|
||||
|
||||
PendingEvent pe;
|
||||
while (!_vm->shouldExit()) {
|
||||
events.updateGameCounter();
|
||||
|
||||
if (flag)
|
||||
intf.draw3d(false);
|
||||
_window->writeString(msg, false);
|
||||
animateCursor();
|
||||
_window->update();
|
||||
|
||||
if (flag)
|
||||
windows[3].update();
|
||||
|
||||
events.wait(1);
|
||||
if (events.getEvent(pe) && pe.isKeyboard())
|
||||
break;
|
||||
}
|
||||
|
||||
_window->writeString("", false);
|
||||
_window->update();
|
||||
|
||||
intf._tillMove = oldTillMove;
|
||||
intf._upDoorText = oldUpDoorText;
|
||||
|
||||
return pe._keyState;
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
// WORKAROUND: Fix for incorrect answer for one of the Vowelless Knight riddles
|
||||
line.toLowercase();
|
||||
if (line == "iieeeoeeeouie")
|
||||
line = "iieeeoeeaouie";
|
||||
Common::String scriptsMsg = scripts._message;
|
||||
scriptsMsg.toLowercase();
|
||||
if (scriptsMsg == "iieeeoeeeouie")
|
||||
scriptsMsg = "iieeeoeeaouie";
|
||||
|
||||
if (line == scriptsMsg) {
|
||||
result = true;
|
||||
} else if (!line.compareToIgnoreCase(expected)) {
|
||||
result = (opcode == 55) ? -1 : 1;
|
||||
}
|
||||
} else {
|
||||
// Load in the mirror list
|
||||
MirrorEntry me;
|
||||
scripts._mirror.clear();
|
||||
|
||||
File f(Common::Path(Common::String::format("%smirr.txt", files._ccNum ? "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::Path(Common::String::format("%smirr.ext", files._ccNum ? "dark" : "xeen")))) {
|
||||
while (me.synchronize(f2))
|
||||
scripts._mirror.push_back(me);
|
||||
f2.close();
|
||||
}
|
||||
|
||||
if (Common::RU_RUS == g_vm->getLanguage() && GType_Clouds == g_vm->getGameID()) {
|
||||
for (uint idx = 0; idx < 59; ++idx) {
|
||||
if (!line.compareToIgnoreCase(Res.CLOUDS_MIRROR_LOCATIONS[idx])) {
|
||||
result = idx + 1;
|
||||
sound.playFX(_vm->_files->_ccNum ? 35 : 61);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
|
||||
if (!line.compareToIgnoreCase(scripts._mirror[idx]._name)) {
|
||||
result = idx + 1;
|
||||
sound.playFX(_vm->_files->_ccNum ? 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, uint numOptions) {
|
||||
assert(numOptions <= 9);
|
||||
Choose123 *dlg = new Choose123(vm);
|
||||
int result = dlg->execute(numOptions);
|
||||
delete dlg;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int Choose123::execute(uint numOptions) {
|
||||
EventsManager &events = *_vm->_events;
|
||||
Interface &intf = *_vm->_interface;
|
||||
LocationManager &loc = *_vm->_locations;
|
||||
Windows &windows = *_vm->_windows;
|
||||
Resources &res = *_vm->_resources;
|
||||
|
||||
Mode oldMode = _vm->_mode;
|
||||
_vm->_mode = MODE_DIALOG_123;
|
||||
|
||||
loadButtons(numOptions);
|
||||
res._globalSprites.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);
|
||||
checkEvents(_vm);
|
||||
|
||||
if (_vm->shouldExit())
|
||||
return 0;
|
||||
} while (!_buttonValue);
|
||||
|
||||
if (_buttonValue == Common::KEYCODE_ESCAPE) {
|
||||
result = 0;
|
||||
} else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue < (Common::KEYCODE_1 + (int)numOptions)) {
|
||||
_buttonValue -= Common::KEYCODE_0;
|
||||
result = (_buttonValue == (int)numOptions) ? 0 : _buttonValue;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_mode = oldMode;
|
||||
intf.mainIconsPrint();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Choose123::loadButtons(uint numOptions) {
|
||||
assert(numOptions > 0 && numOptions <= 9);
|
||||
_iconSprites.load("choose.icn");
|
||||
const int XPOS[3] = { 235, 260, 286 };
|
||||
const int YPOS[3] = { 75, 96, 117 };
|
||||
|
||||
for (uint idx = 0; idx < numOptions; ++idx) {
|
||||
Common::Rect r(24, 20);
|
||||
r.moveTo(XPOS[idx % 3], YPOS[idx / 3]);
|
||||
addButton(r, Common::KEYCODE_1 + idx, &_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
|
||||
} // End of namespace MM
|
||||
109
engines/mm/xeen/dialogs/dialogs_input.h
Normal file
109
engines/mm/xeen/dialogs/dialogs_input.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_STRING_INPUT_H
|
||||
#define XEEN_DIALOGS_STRING_INPUT_H
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/screen.h"
|
||||
|
||||
namespace MM {
|
||||
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;
|
||||
|
||||
int nonEnToUpper(uint16 ascii);
|
||||
int nonEnToLower(uint16 ascii);
|
||||
|
||||
/**
|
||||
* 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(uint numOptions);
|
||||
|
||||
void loadButtons(uint numOptions);
|
||||
public:
|
||||
static int show(XeenEngine *vm, uint 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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
1200
engines/mm/xeen/dialogs/dialogs_items.cpp
Normal file
1200
engines/mm/xeen/dialogs/dialogs_items.cpp
Normal file
File diff suppressed because it is too large
Load Diff
123
engines/mm/xeen/dialogs/dialogs_items.h
Normal file
123
engines/mm/xeen/dialogs/dialogs_items.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_ITEMS_H
|
||||
#define XEEN_DIALOGS_ITEMS_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/window.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
enum ItemsMode {
|
||||
ITEMMODE_CHAR_INFO = 0, ITEMMODE_BUY = 1, ITEMMODE_SELL = 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,
|
||||
ITEMMODE_INVALID = -1
|
||||
};
|
||||
|
||||
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, ItemCategory category);
|
||||
|
||||
/**
|
||||
* Sets the equipment icon to use for each item for display
|
||||
*/
|
||||
void setEquipmentIcons();
|
||||
|
||||
/**
|
||||
* Calculate the cost of an item, or charges renaming for Misc items as appropriate
|
||||
*/
|
||||
int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel,
|
||||
ItemCategory category);
|
||||
|
||||
/**
|
||||
* Get plural gold form
|
||||
*/
|
||||
const char *getGoldPlurals(int val);
|
||||
|
||||
int doItemOptions(Character &c, int actionIndex, int itemIndex,
|
||||
ItemCategory category, ItemsMode mode);
|
||||
|
||||
void itemToGold(Character &c, int itemIndex, ItemCategory category, ItemsMode mode);
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text, uint8 headerCount, uint8 lineCount);
|
||||
#endif
|
||||
public:
|
||||
static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
|
||||
};
|
||||
|
||||
class ItemSelectionDialog : public ButtonContainer {
|
||||
private:
|
||||
SpriteResource _icons;
|
||||
int _actionIndex;
|
||||
InventoryItems &_items;
|
||||
|
||||
ItemSelectionDialog(XeenEngine *vm, int actionIndex, InventoryItems &items, const Common::StringArray &ttsItemButtonTexts) : ButtonContainer(vm),
|
||||
_actionIndex(actionIndex), _items(items) {
|
||||
loadButtons();
|
||||
#ifdef USE_TTS
|
||||
_buttonTexts = ttsItemButtonTexts;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dialog
|
||||
* @returns Selected item index
|
||||
*/
|
||||
int execute();
|
||||
|
||||
/**
|
||||
* Loads buttons
|
||||
*/
|
||||
void loadButtons();
|
||||
public:
|
||||
/**
|
||||
* Shows the dialog
|
||||
* @param actionIndex Current action type
|
||||
* @param items Currently active items category
|
||||
* @param ttsItemButtonTexts Text for each item button
|
||||
* @returns Selected item index
|
||||
*/
|
||||
static int show(int actionIndex, InventoryItems &items, const Common::StringArray &ttsItemButtonTexts);
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
471
engines/mm/xeen/dialogs/dialogs_map.cpp
Normal file
471
engines/mm/xeen/dialogs/dialogs_map.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_map.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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;
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
bool ttsVoiceText = 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]), ttsVoiceText);
|
||||
ttsVoiceText = false;
|
||||
windows[5].update();
|
||||
windows[3].update();
|
||||
|
||||
events.ipause5(2);
|
||||
drawFlag = false;
|
||||
} while (!_vm->shouldExit() && !events.isKeyMousePressed());
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
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
|
||||
} // End of namespace MM
|
||||
63
engines/mm/xeen/dialogs/dialogs_map.h
Normal file
63
engines/mm/xeen/dialogs/dialogs_map.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_MAP_H
|
||||
#define XEEN_DIALOGS_MAP_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
136
engines/mm/xeen/dialogs/dialogs_message.cpp
Normal file
136
engines/mm/xeen/dialogs/dialogs_message.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mm/xeen/dialogs/dialogs_message.h"
|
||||
#include "mm/xeen/events.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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];
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
w.open();
|
||||
w.writeString(msg);
|
||||
w.update();
|
||||
|
||||
switch (waitType) {
|
||||
case WT_FREEZE_WAIT:
|
||||
while (!_vm->shouldExit() && !events.isKeyMousePressed())
|
||||
events.pollEventsAndWait();
|
||||
|
||||
events.clearEvents();
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case WT_ANIMATED_WAIT:
|
||||
if (g_vm->_locations->isActive() && (windows[11]._enabled || _vm->_mode == MODE_INTERACTIVE7)) {
|
||||
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);
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
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();
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
_vm->_mode = oldMode;
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
62
engines/mm/xeen/dialogs/dialogs_message.h
Normal file
62
engines/mm/xeen/dialogs/dialogs_message.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_dialogs_message_H
|
||||
#define XEEN_dialogs_message_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/character.h"
|
||||
|
||||
namespace MM {
|
||||
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) { setWaitBounds(); }
|
||||
|
||||
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) { setWaitBounds(); }
|
||||
|
||||
void execute(int spellId, int componentNum);
|
||||
public:
|
||||
static void show(XeenEngine *vm, int spellId, int componentNum);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
531
engines/mm/xeen/dialogs/dialogs_party.cpp
Normal file
531
engines/mm/xeen/dialogs/dialogs_party.cpp
Normal file
@@ -0,0 +1,531 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_char_info.h"
|
||||
#include "mm/xeen/dialogs/dialogs_create_char.h"
|
||||
#include "mm/xeen/dialogs/dialogs_party.h"
|
||||
#include "mm/xeen/dialogs/dialogs_input.h"
|
||||
#include "mm/xeen/dialogs/dialogs_query.h"
|
||||
#include "mm/xeen/character.h"
|
||||
#include "mm/xeen/events.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kPartyDialogFaceCount = 4;
|
||||
static const uint8 kPartyDialogButtonCount = 6;
|
||||
static const uint8 kPartyDialogInfoPerFaceCount = 4;
|
||||
|
||||
#endif
|
||||
|
||||
enum PartyDialogButtonTTSTextIndex {
|
||||
kPartyDialogUp = 0,
|
||||
kPartyDialogDown = 1,
|
||||
kPartyDialogDelete = 2,
|
||||
kPartyDialogRemove = 3,
|
||||
kPartyDialogCreate = 4,
|
||||
kPartyDialogExit = 5,
|
||||
kPartyDialogFace1 = 6,
|
||||
kPartyDialogFace2 = 7,
|
||||
kPartyDialogFace3 = 8,
|
||||
kPartyDialogFace4 = 9
|
||||
};
|
||||
|
||||
PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(vm),
|
||||
PartyDrawer(vm), _vm(vm) {
|
||||
#ifdef USE_TTS
|
||||
_faceCount = 0;
|
||||
#endif
|
||||
initDrawStructs();
|
||||
}
|
||||
|
||||
void PartyDialog::show(XeenEngine *vm) {
|
||||
PartyDialog *dlg = new PartyDialog(vm);
|
||||
dlg->execute();
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void PartyDialog::execute() {
|
||||
EventsManager &events = *_vm->_events;
|
||||
FileManager &files = *_vm->_files;
|
||||
Interface &intf = *_vm->_interface;
|
||||
Party &party = *_vm->_party;
|
||||
Screen &screen = *_vm->_screen;
|
||||
Sound &sound = *_vm->_sound;
|
||||
Windows &windows = *_vm->_windows;
|
||||
bool modeFlag = false;
|
||||
int startingChar = 0;
|
||||
|
||||
sound.playSong(files._ccNum ? "newbrigh.m" : "inn.m");
|
||||
loadButtons();
|
||||
setupBackground();
|
||||
|
||||
Common::String ttsMessage;
|
||||
#ifdef USE_TTS
|
||||
bool returnFromCreate = false;
|
||||
#endif
|
||||
|
||||
while (!_vm->shouldExit()) {
|
||||
_vm->_mode = MODE_INTERACTIVE;
|
||||
|
||||
// Build up a list of available characters in the Roster that are on the
|
||||
// same side of Xeen as the player is currently on
|
||||
loadCharacters();
|
||||
|
||||
Window &w = windows[11];
|
||||
w.open();
|
||||
setupFaces(startingChar, false);
|
||||
w.writeString(Common::String::format(Res.PARTY_DIALOG_TEXT, _partyDetails.c_str()), false, &ttsMessage);
|
||||
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, returnFromCreate);
|
||||
returnFromCreate = false;
|
||||
#endif
|
||||
|
||||
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);
|
||||
if (Common::KEYCODE_F1 == _buttonValue ||
|
||||
Common::KEYCODE_F2 == _buttonValue ||
|
||||
Common::KEYCODE_F3 == _buttonValue ||
|
||||
Common::KEYCODE_F4 == _buttonValue ||
|
||||
Common::KEYCODE_F5 == _buttonValue ||
|
||||
Common::KEYCODE_F6 == _buttonValue) {
|
||||
// Show character info
|
||||
_buttonValue -= Common::KEYCODE_F1;
|
||||
if (_buttonValue < (int)party._activeParty.size())
|
||||
CharacterInfo::show(_vm, _buttonValue);
|
||||
} else if (Common::KEYCODE_1 == _buttonValue ||
|
||||
Common::KEYCODE_2 == _buttonValue ||
|
||||
Common::KEYCODE_3 == _buttonValue ||
|
||||
Common::KEYCODE_4 == _buttonValue) {
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (Common::KEYCODE_UP == _buttonValue ||
|
||||
Common::KEYCODE_KP8 == _buttonValue) {
|
||||
// Up arrow
|
||||
if (startingChar > 0) {
|
||||
startingChar -= 4;
|
||||
startingCharChanged(startingChar);
|
||||
}
|
||||
|
||||
} else if (Common::KEYCODE_DOWN == _buttonValue ||
|
||||
Common::KEYCODE_KP2 == _buttonValue) {
|
||||
// Down arrow
|
||||
if (startingChar < ((int)_charList.size() - 4)) {
|
||||
startingChar += 4;
|
||||
startingCharChanged(startingChar);
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsParty.KEY_EXIT == _buttonValue ||
|
||||
Common::KEYCODE_ESCAPE == _buttonValue ||
|
||||
Common::KEYCODE_SPACE == _buttonValue) {
|
||||
if (party._activeParty.size() == 0) {
|
||||
ErrorScroll::show(_vm, Res.NO_ONE_TO_ADVENTURE_WITH);
|
||||
} else {
|
||||
if (_vm->_mode != MODE_STARTUP) {
|
||||
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;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsParty.KEY_CREATE == _buttonValue) {
|
||||
// Create
|
||||
if (_charList.size() == XEEN_TOTAL_CHARACTERS) {
|
||||
ErrorScroll::show(_vm, Res.YOUR_ROSTER_IS_FULL);
|
||||
} else {
|
||||
// Save Background
|
||||
Graphics::ManagedSurface savedBg;
|
||||
savedBg.copyFrom(screen);
|
||||
|
||||
screen.fadeOut();
|
||||
w.close();
|
||||
|
||||
// Show the create character dialog
|
||||
CreateCharacterDialog::show(_vm);
|
||||
|
||||
party.copyPartyToRoster();
|
||||
//_vm->_saves->writeCharFile();
|
||||
|
||||
// Restore Background
|
||||
screen.fadeOut();
|
||||
screen.blitFrom(savedBg);
|
||||
windows[0].update();
|
||||
#ifdef USE_TTS
|
||||
returnFromCreate = true;
|
||||
#endif
|
||||
|
||||
modeFlag = true;
|
||||
breakFlag = true;
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsParty.KEY_DELETE == _buttonValue) {
|
||||
// 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();
|
||||
|
||||
loadCharacters();
|
||||
startingChar = 0;
|
||||
startingCharChanged(startingChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (Res.KeyConstants.DialogsParty.KEY_REMOVE == _buttonValue) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PartyDialog::loadCharacters() {
|
||||
Map &map = *_vm->_map;
|
||||
Party &party = *_vm->_party;
|
||||
|
||||
_charList.clear();
|
||||
for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
|
||||
Character &player = party._roster[i];
|
||||
if (player._name.empty() || player._xeenSide != map._loadCcNum)
|
||||
continue;
|
||||
|
||||
_charList.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void PartyDialog::loadButtons() {
|
||||
_uiSprites.load("inn.icn");
|
||||
addButton(Common::Rect(16, 100, 40, 120), Common::KEYCODE_UP, &_uiSprites, kPartyDialogUp);
|
||||
addButton(Common::Rect(52, 100, 76, 120), Common::KEYCODE_DOWN, &_uiSprites, kPartyDialogDown);
|
||||
|
||||
addButton(Common::Rect(87, 100, 111, 120), Res.KeyConstants.DialogsParty.KEY_DELETE, &_uiSprites, kPartyDialogDelete);
|
||||
addButton(Common::Rect(122, 100, 146, 120), Res.KeyConstants.DialogsParty.KEY_REMOVE, &_uiSprites, kPartyDialogRemove);
|
||||
addButton(Common::Rect(157, 100, 181, 120), Res.KeyConstants.DialogsParty.KEY_CREATE, &_uiSprites, kPartyDialogCreate);
|
||||
addButton(Common::Rect(192, 100, 216, 120), Res.KeyConstants.DialogsParty.KEY_EXIT, &_uiSprites, kPartyDialogExit);
|
||||
|
||||
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, nullptr, kPartyDialogFace1);
|
||||
addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, nullptr, kPartyDialogFace2);
|
||||
addButton(Common::Rect(59, 59, 91, 91), Common::KEYCODE_3, nullptr, kPartyDialogFace3);
|
||||
addButton(Common::Rect(117, 59, 151, 91), Common::KEYCODE_4, nullptr, kPartyDialogFace4);
|
||||
|
||||
#ifdef USE_TTS
|
||||
_faceCount = 0;
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_faceCount++;
|
||||
#endif
|
||||
|
||||
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);
|
||||
Common::String ttsMessage;
|
||||
w.writeString(Common::String::format(Res.PARTY_DIALOG_TEXT, _partyDetails.c_str()), false, &ttsMessage);
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, false);
|
||||
#endif
|
||||
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, nullptr, kPartyDialogFace1);
|
||||
addButton(Common::Rect(117, 16, 149, 48), Common::KEYCODE_2, nullptr, kPartyDialogFace2);
|
||||
addButton(Common::Rect(16, 59, 48, 91), Common::KEYCODE_3, nullptr, kPartyDialogFace3);
|
||||
addButton(Common::Rect(117, 59, 149, 91), Common::KEYCODE_4, nullptr, kPartyDialogFace4);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void PartyDialog::speakText(const Common::String &text, bool isCharacterCreation) {
|
||||
uint index = 0;
|
||||
|
||||
// After returning from the character creation screen, the text is duplicated, with the first iteration being
|
||||
// outdated
|
||||
if (isCharacterCreation) {
|
||||
for (uint i = 0; i < _faceCount; ++i) {
|
||||
getNextTextSection(text, index, kPartyDialogInfoPerFaceCount);
|
||||
}
|
||||
|
||||
getNextTextSection(text, index, kPartyDialogButtonCount);
|
||||
}
|
||||
|
||||
_buttonTexts.clear();
|
||||
|
||||
Common::String faceTexts[kPartyDialogFaceCount];
|
||||
for (uint8 i = 0; i < _faceCount; ++i) {
|
||||
faceTexts[i] = getNextTextSection(text, index, kPartyDialogInfoPerFaceCount);
|
||||
_vm->sayText(faceTexts[i]);
|
||||
}
|
||||
|
||||
Common::String buttonTexts = addNextTextToButtons(text, index, kPartyDialogButtonCount);
|
||||
_vm->sayText(buttonTexts);
|
||||
|
||||
// Since the number of faces can vary, sort them after the bottom buttons
|
||||
for (uint8 i = 0; i < _faceCount; ++i) {
|
||||
_buttonTexts.push_back(faceTexts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
100
engines/mm/xeen/dialogs/dialogs_party.h
Normal file
100
engines/mm/xeen/dialogs/dialogs_party.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_PARTY_H
|
||||
#define XEEN_DIALOGS_PARTY_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/interface.h"
|
||||
#include "mm/xeen/screen.h"
|
||||
#include "mm/xeen/sprites.h"
|
||||
|
||||
namespace MM {
|
||||
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;
|
||||
#ifdef USE_TTS
|
||||
uint8 _faceCount;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
PartyDialog(XeenEngine *vm);
|
||||
|
||||
/**
|
||||
* Executes the dialog
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Loads the list of character
|
||||
*/
|
||||
void loadCharacters();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text, bool isCharacterCreation);
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Show the Party dialog
|
||||
*/
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
172
engines/mm/xeen/dialogs/dialogs_query.cpp
Normal file
172
engines/mm/xeen/dialogs/dialogs_query.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_query.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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, 132), Common::KEYCODE_y, &confirmSprites);
|
||||
addButton(Common::Rect(185, 112, 209, 132), 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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
w.writeString(msg);
|
||||
w.update();
|
||||
|
||||
events.clearEvents();
|
||||
bool result = false;
|
||||
|
||||
while (!_vm->shouldExit()) {
|
||||
_buttonValue = 0;
|
||||
while (!_vm->shouldExit() && !_buttonValue) {
|
||||
events.pollEvents();
|
||||
checkEvents(_vm);
|
||||
}
|
||||
|
||||
if ((mode & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE
|
||||
|| _buttonValue == Common::KEYCODE_n)
|
||||
break;
|
||||
|
||||
if (_buttonValue == Common::KEYCODE_y) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
events.clearEvents();
|
||||
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;
|
||||
LocationManager &loc = *_vm->_locations;
|
||||
SpriteResource confirmSprites;
|
||||
bool result = false;
|
||||
|
||||
Mode oldMode = _vm->_mode;
|
||||
_vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
|
||||
events.clearEvents();
|
||||
setWaitBounds();
|
||||
|
||||
if (!type) {
|
||||
Map &map = *_vm->_map;
|
||||
Party &party = *_vm->_party;
|
||||
Resources &res = *_vm->_resources;
|
||||
Windows &windows = *_vm->_windows;
|
||||
|
||||
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
|
||||
} // End of namespace MM
|
||||
51
engines/mm/xeen/dialogs/dialogs_query.h
Normal file
51
engines/mm/xeen/dialogs/dialogs_query.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_QUERY_H
|
||||
#define XEEN_DIALOGS_QUERY_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
308
engines/mm/xeen/dialogs/dialogs_quests.cpp
Normal file
308
engines/mm/xeen/dialogs/dialogs_quests.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mm/xeen/dialogs/dialogs_quests.h"
|
||||
#include "mm/xeen/events.h"
|
||||
#include "mm/xeen/party.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
enum QuestButtonTTSTextIndex {
|
||||
kQuestItems = 0,
|
||||
kQuestCurrentQuests = 1,
|
||||
kQuestAutoNotes = 2,
|
||||
kQuestUp = 3,
|
||||
kQuestDown = 4,
|
||||
kQuestExit = 5
|
||||
};
|
||||
|
||||
#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;
|
||||
const char **questItemNames = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES;
|
||||
int itemsCount = (g_vm->getGameID() == GType_Swords) ? TOTAL_QUEST_ITEMS_SWORDS : TOTAL_QUEST_ITEMS;
|
||||
const char *title1 = (g_vm->getGameID() == GType_Swords) ? Res.SWORDS_OF_XEEN_LINE : Res.CLOUDS_OF_XEEN_LINE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Common::String ttsButtons;
|
||||
windows[29].writeString(Res.QUESTS_DIALOG_TEXT, false, &ttsButtons);
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
setButtonTexts(ttsButtons);
|
||||
#endif
|
||||
drawButtons(&windows[0]);
|
||||
Common::String ttsMessage;
|
||||
|
||||
while (!_vm->shouldExit()) {
|
||||
Common::String lines[MAX_DIALOG_LINES];
|
||||
|
||||
switch (mode) {
|
||||
case QUEST_ITEMS:
|
||||
for (int idx = 0; idx < itemsCount; ++idx)
|
||||
lines[idx] = "\b \b*";
|
||||
|
||||
count = 0;
|
||||
headerShown = false;
|
||||
for (int idx = 0; idx < itemsCount; ++idx) {
|
||||
if (party._questItems[idx]) {
|
||||
if (!count ) {
|
||||
if (_vm->getGameID() == GType_Swords)
|
||||
lines[count++] = Res.SWORDS_OF_XEEN_LINE;
|
||||
else if (idx < 35)
|
||||
lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
|
||||
} else if (_vm->getGameID() != GType_Swords && idx >= 35 && !headerShown) {
|
||||
lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
|
||||
headerShown = true;
|
||||
}
|
||||
|
||||
bool multiFlag = false;
|
||||
if (_vm->getGameID() == GType_Swords) {
|
||||
multiFlag = (idx == 20) || (idx == 27) || (idx == 41);
|
||||
} else {
|
||||
switch (idx) {
|
||||
case 17:
|
||||
case 26:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
multiFlag = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (multiFlag) {
|
||||
lines[count++] = Common::String::format("%d %s%c",
|
||||
party._questItems[idx], questItemNames[idx],
|
||||
party._questItems[idx] == 1 ? ' ' : 's');
|
||||
} else {
|
||||
lines[count++] = questItemNames[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ttsMessage.clear();
|
||||
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()
|
||||
), false, &ttsMessage);
|
||||
ttsMessage.replace('*', ' ');
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(ttsMessage);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case CURRENT_QUESTS:
|
||||
for (int idx = 0; idx < itemsCount; ++idx)
|
||||
lines[idx] = "";
|
||||
|
||||
count = 0;
|
||||
headerShown = false;
|
||||
for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) {
|
||||
if (party._questFlags[idx + 1]) {
|
||||
if (!count && !headerShown && (_vm->getGameID() == GType_Swords || idx < 29)) {
|
||||
lines[count++] = title1;
|
||||
}
|
||||
if (_vm->getGameID() != GType_Swords && 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;
|
||||
|
||||
ttsMessage.clear();
|
||||
windows[30].writeString(Common::String::format(Res.CURRENT_QUESTS_DATA,
|
||||
lines[topRow].c_str(), lines[topRow + 1].c_str(), lines[topRow + 2].c_str()), false, &ttsMessage);
|
||||
ttsMessage.replace('*', ' ');
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(ttsMessage);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AUTO_NOTES: {
|
||||
int max, offset;
|
||||
switch (_vm->getGameID()) {
|
||||
case GType_Swords:
|
||||
max = 49;
|
||||
offset = 51;
|
||||
break;
|
||||
case GType_Clouds:
|
||||
max = MAX_DIALOG_LINES;
|
||||
offset = 31;
|
||||
break;
|
||||
default:
|
||||
max = MAX_DIALOG_LINES;
|
||||
offset = 56;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < max; ++idx)
|
||||
lines[idx] = "";
|
||||
|
||||
count = 0;
|
||||
headerShown = false;
|
||||
for (int idx = 0; idx < max; ++idx) {
|
||||
if (party._worldFlags[idx + (_vm->getGameID() != GType_Swords ? 1 : 0)]) {
|
||||
if (!count && !headerShown && (_vm->getGameID() == GType_Swords || idx < 72)) {
|
||||
lines[count++] = title1;
|
||||
}
|
||||
if (idx >= 72 && !headerShown) {
|
||||
lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
|
||||
headerShown = true;
|
||||
}
|
||||
|
||||
lines[count++] = _questNotes[idx + offset];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
windows[30].writeString("\v000\t000");
|
||||
windows[24].update();
|
||||
#ifdef USE_TTS
|
||||
g_vm->sayText(ttsButtons);
|
||||
#endif
|
||||
|
||||
// Key handling
|
||||
_buttonValue = 0;
|
||||
while (!_vm->shouldExit() && !_buttonValue) {
|
||||
events.pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
}
|
||||
|
||||
if (_buttonValue == Common::KEYCODE_ESCAPE)
|
||||
break;
|
||||
|
||||
if (Res.KeyConstants.DialogsQuests.KEY_AUTO_NOTES == _buttonValue) {
|
||||
mode = AUTO_NOTES;
|
||||
topRow = 0;
|
||||
} else if (Res.KeyConstants.DialogsQuests.KEY_QUEST_ITEMS == _buttonValue) {
|
||||
mode = QUEST_ITEMS;
|
||||
topRow = 0;
|
||||
} else if (Res.KeyConstants.DialogsQuests.KEY_CURRENT_QUESTS == _buttonValue) {
|
||||
mode = CURRENT_QUESTS;
|
||||
topRow = 0;
|
||||
} else if (Common::KEYCODE_HOME == _buttonValue) {
|
||||
topRow = 0;
|
||||
} else if (Common::KEYCODE_END == _buttonValue) {
|
||||
topRow = MAX(count - 1, 0);
|
||||
} else if (Common::KEYCODE_PAGEUP == _buttonValue) {
|
||||
topRow = MAX(topRow - 3, 0);
|
||||
} else if (Common::KEYCODE_PAGEDOWN == _buttonValue) {
|
||||
topRow = CLIP(topRow + 3, 0, MAX(count - 1, 0));
|
||||
} else if (Common::KEYCODE_UP == _buttonValue ||
|
||||
Common::KEYCODE_KP8 == _buttonValue ||
|
||||
Common::KEYCODE_u == _buttonValue) {
|
||||
topRow = MAX(topRow - 1, 0);
|
||||
} else if (Common::KEYCODE_DOWN == _buttonValue ||
|
||||
Common::KEYCODE_KP2 == _buttonValue ||
|
||||
Common::KEYCODE_d == _buttonValue) {
|
||||
topRow = CLIP(topRow + 1, 0, MAX(count - 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
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), Res.KeyConstants.DialogsQuests.KEY_QUEST_ITEMS, &_iconSprites, kQuestItems);
|
||||
addButton(Common::Rect(80, 109, 104, 129), Res.KeyConstants.DialogsQuests.KEY_CURRENT_QUESTS, &_iconSprites, kQuestCurrentQuests);
|
||||
addButton(Common::Rect(148, 109, 172, 129), Res.KeyConstants.DialogsQuests.KEY_AUTO_NOTES, &_iconSprites, kQuestAutoNotes);
|
||||
|
||||
addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_UP, &_iconSprites, kQuestUp);
|
||||
addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_DOWN, &_iconSprites, kQuestDown);
|
||||
addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites, kQuestExit);
|
||||
}
|
||||
|
||||
void Quests::loadQuestNotes() {
|
||||
File f("qnotes.bin", 1);
|
||||
while (f.pos() < f.size())
|
||||
_questNotes.push_back(f.readString());
|
||||
f.close();
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
50
engines/mm/xeen/dialogs/dialogs_quests.h
Normal file
50
engines/mm/xeen/dialogs/dialogs_quests.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_QUESTS_H
|
||||
#define XEEN_DIALOGS_QUESTS_H
|
||||
|
||||
#include "common/str-array.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
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
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
138
engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
Normal file
138
engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_quick_fight.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kQuickFightInfoCount = 4;
|
||||
static const uint8 kQuickFightButtonCount = 2;
|
||||
|
||||
#endif
|
||||
|
||||
enum QuickFightButtonTTSTextIndex {
|
||||
kQuickFightNext = 0,
|
||||
kQuickFightExit = 1
|
||||
};
|
||||
|
||||
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();
|
||||
bool ttsVoiceText = true;
|
||||
|
||||
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]);
|
||||
Common::String ttsMessage;
|
||||
w.writeString(msg, ttsVoiceText, &ttsMessage);
|
||||
drawButtons(&w);
|
||||
|
||||
#ifdef USE_TTS
|
||||
if (ttsVoiceText) {
|
||||
setUpButtons(ttsMessage);
|
||||
ttsVoiceText = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wait for selection
|
||||
_buttonValue = 0;
|
||||
events.updateGameCounter();
|
||||
do {
|
||||
intf.draw3d(false, false);
|
||||
|
||||
events.pollEventsAndWait();
|
||||
checkEvents(_vm);
|
||||
if (_vm->shouldExit())
|
||||
return;
|
||||
} while (!_buttonValue && !events.timeElapsed());
|
||||
|
||||
if (Common::KEYCODE_F1 == _buttonValue ||
|
||||
Common::KEYCODE_F2 == _buttonValue ||
|
||||
Common::KEYCODE_F3 == _buttonValue ||
|
||||
Common::KEYCODE_F4 == _buttonValue ||
|
||||
Common::KEYCODE_F5 == _buttonValue ||
|
||||
Common::KEYCODE_F6 == _buttonValue) {
|
||||
int charIdx = _buttonValue - Common::KEYCODE_F1;
|
||||
if (charIdx < (int)combat._combatParty.size()) {
|
||||
// Highlight new character
|
||||
_currentChar = &party._activeParty[charIdx];
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_currentChar->_name + ": " + Res.QUICK_FIGHT_OPTIONS[_currentChar->_quickOption], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
intf.highlightChar(charIdx);
|
||||
}
|
||||
} else if (Common::KEYCODE_n == _buttonValue ||
|
||||
Res.KeyConstants.DialogsQuickFight.KEY_NEXT == _buttonValue) {
|
||||
_currentChar->_quickOption = (QuickAction)(((int)_currentChar->_quickOption + 1) % 4);
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(Res.QUICK_FIGHT_OPTIONS[_currentChar->_quickOption], Common::TextToSpeechManager::INTERRUPT);
|
||||
#endif
|
||||
}
|
||||
} 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, kQuickFightExit);
|
||||
|
||||
addButton(Common::Rect(242, 108, 266, 128), Res.KeyConstants.DialogsQuickFight.KEY_NEXT, &_icons, kQuickFightNext);
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void QuickFight::setUpButtons(const Common::String &text) {
|
||||
if (_buttonTexts.empty()) {
|
||||
uint index = 0;
|
||||
getNextTextSection(text, index, kQuickFightInfoCount);
|
||||
addNextTextToButtons(text, index, kQuickFightButtonCount);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
69
engines/mm/xeen/dialogs/dialogs_quick_fight.h
Normal file
69
engines/mm/xeen/dialogs/dialogs_quick_fight.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_QUICK_FIGHT_H
|
||||
#define XEEN_DIALOGS_QUICK_FIGHT_H
|
||||
|
||||
#include "mm/xeen/character.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/sprites.h"
|
||||
|
||||
namespace MM {
|
||||
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();
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Sets up button texts
|
||||
* @param text Text for buttons, with each button text separated by newlines
|
||||
*/
|
||||
void setUpButtons(const Common::String &text);
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Show the dialog
|
||||
*/
|
||||
static void show(XeenEngine *vm, Character *currentChar);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
165
engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
Normal file
165
engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "mm/xeen/dialogs/dialogs_quick_ref.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
static const uint8 kQuickRefUpperHeaderCount = 8;
|
||||
static const uint8 kQuickRefLowerHeaderCount = 3;
|
||||
|
||||
#endif
|
||||
|
||||
void QuickReferenceDialog::show(XeenEngine *vm) {
|
||||
QuickReferenceDialog *dlg = new QuickReferenceDialog(vm);
|
||||
dlg->execute();
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
const char *QuickReferenceDialog::getDaysPlurals(int val) {
|
||||
if (Common::RU_RUS == Common::parseLanguage(ConfMan.get("language"))) {
|
||||
int i = val % 100;
|
||||
if (i < 5 || i > 20)
|
||||
switch (val % 10) {
|
||||
case 1:
|
||||
return Res.DAYS[0];
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return Res.DAYS[1];
|
||||
}
|
||||
return Res.DAYS[2];
|
||||
} else {
|
||||
return Res.DAYS[val == 1 ? 0 : 1];
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uint partySize = combat._globalCombat == 2 ? combat._combatParty.size() : party._activeParty.size();
|
||||
for (uint idx = 0; idx < partySize; ++idx) {
|
||||
Character &c = combat._globalCombat == 2 ? *combat._combatParty[idx] :
|
||||
party._activeParty[idx];
|
||||
const char **tmpConditions = c._sex == FEMALE ? (const char **)Res.CONDITION_NAMES_F : (const char **)Res.CONDITION_NAMES_M;
|
||||
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],
|
||||
tmpConditions[condition][0], tmpConditions[condition][1],
|
||||
tmpConditions[condition][2], tmpConditions[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, getDaysPlurals(food)
|
||||
);
|
||||
|
||||
Window &w = windows[24];
|
||||
bool windowOpen = w._enabled;
|
||||
if (!windowOpen)
|
||||
w.open();
|
||||
|
||||
Common::String ttsMessage;
|
||||
|
||||
// Turn off reduced font mode and then print everything
|
||||
w.writeString("\1");
|
||||
w.writeString(msg, false, &ttsMessage);
|
||||
w.update();
|
||||
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage, partySize);
|
||||
#endif
|
||||
|
||||
// Wait for a key/mouse press
|
||||
events.clearEvents();
|
||||
while (!_vm->shouldExit() && !events.isKeyMousePressed())
|
||||
events.pollEventsAndWait();
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
events.clearEvents();
|
||||
|
||||
if (!windowOpen)
|
||||
w.close();
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void QuickReferenceDialog::speakText(const Common::String &text, uint partySize) const {
|
||||
uint index = 0;
|
||||
|
||||
// "Quick reference chart"
|
||||
_vm->sayText(getNextTextSection(text, index), Common::TextToSpeechManager::INTERRUPT);
|
||||
|
||||
// Split the header descriptors ("Name", "Cond", etc.) into an array
|
||||
// If we voice everything as originally ordered, the context isn't clear (i.e. "Name, Class, Level, ..."
|
||||
// will be voiced as one piece, which may make it difficult to match each field with the corresponding info of
|
||||
// each party member)
|
||||
Common::String headers[kQuickRefUpperHeaderCount];
|
||||
for (uint8 i = 0; i < kQuickRefUpperHeaderCount; ++i) {
|
||||
headers[i] = getNextTextSection(text, index);
|
||||
}
|
||||
|
||||
// Voice each party member's description
|
||||
for (uint i = 0; i < partySize; ++i) {
|
||||
for (uint8 j = 0; j < kQuickRefUpperHeaderCount; ++j) {
|
||||
_vm->sayText(headers[j] + ": " + getNextTextSection(text, index));
|
||||
}
|
||||
}
|
||||
|
||||
// Split the gold/gems/food descriptors into an array
|
||||
for (uint8 i = 0; i < kQuickRefLowerHeaderCount; ++i) {
|
||||
headers[i] = getNextTextSection(text, index);
|
||||
}
|
||||
|
||||
// Voice the gold/gems/food amounts
|
||||
for (uint8 i = 0; i < kQuickRefLowerHeaderCount; ++i) {
|
||||
_vm->sayText(headers[i] + ": " + getNextTextSection(text, index));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
51
engines/mm/xeen/dialogs/dialogs_quick_ref.h
Normal file
51
engines/mm/xeen/dialogs/dialogs_quick_ref.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_QUICK_REF_H
|
||||
#define XEEN_DIALOGS_QUICK_REF_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class QuickReferenceDialog : public ButtonContainer {
|
||||
private:
|
||||
QuickReferenceDialog(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
/**
|
||||
* Get plural day/days form
|
||||
*/
|
||||
const char *getDaysPlurals(int val);
|
||||
|
||||
void execute();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text, uint partySize) const;
|
||||
#endif
|
||||
public:
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
1305
engines/mm/xeen/dialogs/dialogs_spells.cpp
Normal file
1305
engines/mm/xeen/dialogs/dialogs_spells.cpp
Normal file
File diff suppressed because it is too large
Load Diff
216
engines/mm/xeen/dialogs/dialogs_spells.h
Normal file
216
engines/mm/xeen/dialogs/dialogs_spells.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_SPELLS_H
|
||||
#define XEEN_DIALOGS_SPELLS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
#include "mm/xeen/party.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
enum SpellDialogMode {
|
||||
SPELLS_DIALOG_BUY = 0, SPELLS_DIALOG_SELECT = 1, SPELLS_DIALOG_INFO = 0x80
|
||||
};
|
||||
|
||||
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) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Spells list dialog. Used for both selecting spells to cast, as well as the
|
||||
* spells listing when visiting Guild locations
|
||||
*/
|
||||
class SpellsDialog : public ButtonContainer {
|
||||
private:
|
||||
SpriteResource _iconSprites;
|
||||
SpriteResource _scrollSprites;
|
||||
Common::Array<SpellEntry> _spells;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
SpellsDialog(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
/**
|
||||
* Executes the dialog
|
||||
*/
|
||||
Character *execute(ButtonContainer *priorDialog, Character *c, int mode);
|
||||
|
||||
/**
|
||||
* Loads buttons for the dialog
|
||||
*/
|
||||
void loadButtons();
|
||||
|
||||
/**
|
||||
* Sets the spell text
|
||||
*/
|
||||
const char *setSpellText(Character *c, int isCasting);
|
||||
|
||||
#ifdef USE_TTS
|
||||
/**
|
||||
* Voices text with TTS and sets up buttons
|
||||
* @param text Text for voicing and buttons. Each section should be separated by a newline
|
||||
* @param mode Mode of the spells menu
|
||||
*/
|
||||
void speakText(const Common::String &text, int mode);
|
||||
|
||||
/**
|
||||
* Resets all button texts to what's currently on screen
|
||||
* @param text Text, both for buttons and for voicing. Each section should be separated by a newline
|
||||
* @param mode Mode of the spells menu
|
||||
* @returns All text combined
|
||||
*/
|
||||
Common::String resetButtonTexts(const Common::String &text, int mode);
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Show the spells list dialog
|
||||
*/
|
||||
static Character *show(XeenEngine *vm, ButtonContainer *priorDialog,
|
||||
Character *c, SpellDialogMode mode);
|
||||
};
|
||||
|
||||
class CastSpell : public ButtonContainer {
|
||||
private:
|
||||
SpriteResource _iconSprites;
|
||||
int _oldMode;
|
||||
private:
|
||||
CastSpell(XeenEngine *vm);
|
||||
~CastSpell() override;
|
||||
|
||||
int execute(Character *&c);
|
||||
|
||||
void loadButtons();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text);
|
||||
#endif
|
||||
public:
|
||||
static int show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text);
|
||||
#endif
|
||||
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();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text);
|
||||
#endif
|
||||
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();
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text) const;
|
||||
#endif
|
||||
public:
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
class DetectMonsters : public ButtonContainer {
|
||||
private:
|
||||
DetectMonsters(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
void execute();
|
||||
public:
|
||||
static void show(XeenEngine *vm);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
130
engines/mm/xeen/dialogs/dialogs_whowill.cpp
Normal file
130
engines/mm/xeen/dialogs/dialogs_whowill.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs_whowill.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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();
|
||||
Common::String ttsMessage;
|
||||
windows[36].writeString(msg, false, &ttsMessage);
|
||||
windows[36].update();
|
||||
|
||||
#ifdef USE_TTS
|
||||
speakText(ttsMessage);
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
intf._face1State = intf._face2State = 2;
|
||||
windows[36].close();
|
||||
return _buttonValue;
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
|
||||
void WhoWill::speakText(const Common::String &text) const {
|
||||
uint index = 0;
|
||||
// Title
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
|
||||
// "Who will" and the action verb (i.e. try)
|
||||
_vm->sayText(getNextTextSection(text, index, 2, " "));
|
||||
|
||||
// F1 - F6
|
||||
_vm->sayText(getNextTextSection(text, index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
46
engines/mm/xeen/dialogs/dialogs_whowill.h
Normal file
46
engines/mm/xeen/dialogs/dialogs_whowill.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_WHOWHILL_H
|
||||
#define XEEN_DIALOGS_WHOWHILL_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class WhoWill : public ButtonContainer {
|
||||
private:
|
||||
WhoWill(XeenEngine *vm) : ButtonContainer(vm) {}
|
||||
|
||||
int execute(int message, int action, bool type);
|
||||
|
||||
#ifdef USE_TTS
|
||||
void speakText(const Common::String &text) const;
|
||||
#endif
|
||||
public:
|
||||
static int show(XeenEngine *vm, int message, int action, bool type);
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
52
engines/mm/xeen/dialogs/please_wait.cpp
Normal file
52
engines/mm/xeen/dialogs/please_wait.cpp
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/xeen/dialogs/please_wait.h"
|
||||
#include "mm/xeen/resources.h"
|
||||
#include "mm/xeen/window.h"
|
||||
#include "mm/xeen/xeen.h"
|
||||
|
||||
namespace MM {
|
||||
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() {
|
||||
if (g_vm->_mode == MODE_STARTUP) {
|
||||
return;
|
||||
}
|
||||
|
||||
Windows &windows = *g_vm->_windows;
|
||||
Window &w = windows[9];
|
||||
w.open();
|
||||
w.writeString(_msg);
|
||||
w.update();
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
46
engines/mm/xeen/dialogs/please_wait.h
Normal file
46
engines/mm/xeen/dialogs/please_wait.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_DIALOGS_PLEASE_WAIT_H
|
||||
#define XEEN_DIALOGS_PLEASE_WAIT_H
|
||||
|
||||
#include "mm/xeen/dialogs/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace Xeen {
|
||||
|
||||
class PleaseWait {
|
||||
private:
|
||||
Common::String _msg;
|
||||
public:
|
||||
PleaseWait(bool isOops = false);
|
||||
~PleaseWait();
|
||||
|
||||
/**
|
||||
* Show the dialog
|
||||
*/
|
||||
void show();
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user