mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
The font style is diiferent for various strings (e.g. verbs are drawn outlined instead of shaded, converse line are drawn normally instead of shaded). Also implement sjis version of "bullet" for the converse strings.
2914 lines
80 KiB
C++
2914 lines
80 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
// Game interface module
|
|
#include "saga/saga.h"
|
|
|
|
#include "saga/gfx.h"
|
|
#include "saga/actor.h"
|
|
#include "saga/console.h"
|
|
#include "saga/displayinfo.h"
|
|
#include "saga/events.h"
|
|
#include "saga/font.h"
|
|
#include "saga/objectmap.h"
|
|
#include "saga/isomap.h"
|
|
#include "saga/itedata.h"
|
|
#include "saga/music.h"
|
|
#include "saga/puzzle.h"
|
|
#include "saga/render.h"
|
|
#include "saga/scene.h"
|
|
#include "saga/script.h"
|
|
#include "saga/sound.h"
|
|
#include "saga/sprite.h"
|
|
#include "saga/resource.h"
|
|
|
|
#include "saga/interface.h"
|
|
|
|
#include "common/config-manager.h"
|
|
#include "common/system.h"
|
|
#include "common/timer.h"
|
|
|
|
namespace Saga {
|
|
|
|
static const int verbToTextIdITE[] = {
|
|
kTextWalkTo, kTextLookAt, kTextPickUp, kTextTalkTo,
|
|
kTextOpen, kTextClose, kTextUse, kTextGive
|
|
};
|
|
|
|
// This maps the internally used string ITE IDs to the LUT strings loaded in IHNM
|
|
// i.e. id 12 (quit game button) maps to string 14 (Quit game)
|
|
// The comments are what the actual IHNM string is
|
|
// For the text string IDs, refer to saga.h, enum TextStringIds
|
|
static const int IHNMTextStringIdsLUT[56] = {
|
|
-1, // (Empty)
|
|
-1, // (Empty)
|
|
4, // Take
|
|
6, // Talk to
|
|
-1,
|
|
-1,
|
|
5, // Use
|
|
8, // Give
|
|
10, // Options
|
|
11, // Test
|
|
12, // Demo
|
|
13, // Help
|
|
14, // Quit Game
|
|
16, // Fast
|
|
18, // Slow
|
|
20, // On
|
|
21, // Off
|
|
15, // Continue Playing
|
|
22, // Load
|
|
23, // Save
|
|
24, // Game Options
|
|
25, // Reading Speed
|
|
26, // Music
|
|
27, // Sound
|
|
32, // Cancel
|
|
33, // Quit
|
|
34, // OK
|
|
17, // Mid
|
|
19, // Click
|
|
36, // 10%
|
|
37, // 20%
|
|
38, // 30%
|
|
39, // 40%
|
|
40, // 50%
|
|
41, // 60%
|
|
42, // 70%
|
|
43, // 80%
|
|
44, // 90%
|
|
45, // Max
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
28, // Voices
|
|
29, // Text
|
|
30, // Audio
|
|
31 // Both
|
|
};
|
|
|
|
#define buttonRes0 0x42544E00
|
|
#define buttonRes1 0x42544E01
|
|
|
|
Interface::Interface(SagaEngine *vm) : _vm(vm) {
|
|
ByteArray resourceData;
|
|
int i;
|
|
|
|
#if 0
|
|
// FTA2 related test code
|
|
|
|
// TODO: this will probably have to be moved to a new class
|
|
// It's left here for now till the code differences are figured out
|
|
if (_vm->getGameId() == GID_FTA2) {
|
|
_interfaceContext = _vm->_resource->getContext(GAME_IMAGEFILE);
|
|
_vm->_resource->loadResource(_interfaceContext, 22, resource, resourceLength); // Julian's portrait
|
|
|
|
_vm->decodeBGImage(resource, resourceLength, &_mainPanel.image,
|
|
&_mainPanel.imageLength, &_mainPanel.imageWidth, &_mainPanel.imageHeight);
|
|
|
|
free(resource);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// Load interface module resource file context
|
|
_interfaceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
|
if (_interfaceContext == NULL) {
|
|
error("Interface::Interface() resource context not found");
|
|
}
|
|
|
|
// Do nothing for SAGA2 games for now
|
|
if (_vm->isSaga2()) {
|
|
return;
|
|
}
|
|
|
|
// Main panel
|
|
_mainPanel.buttons = _vm->getDisplayInfo().mainPanelButtons;
|
|
_mainPanel.buttonsCount = _vm->getDisplayInfo().mainPanelButtonsCount;
|
|
|
|
for (i = 0; i < kVerbTypeIdsMax; i++) {
|
|
_verbTypeToPanelButton[i] = NULL;
|
|
}
|
|
|
|
for (i = 0; i < _mainPanel.buttonsCount; i++) {
|
|
if (_mainPanel.buttons[i].type == kPanelButtonVerb) {
|
|
_verbTypeToPanelButton[_mainPanel.buttons[i].id] = &_mainPanel.buttons[i];
|
|
}
|
|
}
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _mainPanel.image, &_mainPanel.imageWidth, &_mainPanel.imageHeight);
|
|
|
|
// Converse panel
|
|
_conversePanel.buttons = _vm->getDisplayInfo().conversePanelButtons;
|
|
_conversePanel.buttonsCount = _vm->getDisplayInfo().conversePanelButtonsCount;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _conversePanel.image, &_conversePanel.imageWidth, &_conversePanel.imageHeight);
|
|
|
|
// Option panel
|
|
if (!_vm->_script->isNonInteractiveDemo()) {
|
|
_optionPanel.buttons = _vm->getDisplayInfo().optionPanelButtons;
|
|
_optionPanel.buttonsCount = _vm->getDisplayInfo().optionPanelButtonsCount;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _optionPanel.image, &_optionPanel.imageWidth, &_optionPanel.imageHeight);
|
|
} else {
|
|
_optionPanel.buttons = NULL;
|
|
_optionPanel.buttonsCount = 0;
|
|
_optionPanel.sprites.clear();
|
|
}
|
|
|
|
#ifdef ENABLE_IHNM
|
|
// Quit panel
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
_quitPanel.buttons = _vm->getDisplayInfo().quitPanelButtons;
|
|
_quitPanel.buttonsCount = _vm->getDisplayInfo().quitPanelButtonsCount;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _quitPanel.image, &_quitPanel.imageWidth, &_quitPanel.imageHeight);
|
|
}
|
|
|
|
// Save panel
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
_savePanel.buttons = _vm->getDisplayInfo().savePanelButtons;
|
|
_savePanel.buttonsCount = _vm->getDisplayInfo().savePanelButtonsCount;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _savePanel.image, &_savePanel.imageWidth, &_savePanel.imageHeight);
|
|
}
|
|
|
|
// Load panel
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
_loadPanel.buttons = _vm->getDisplayInfo().loadPanelButtons;
|
|
_loadPanel.buttonsCount = _vm->getDisplayInfo().loadPanelButtonsCount;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData);
|
|
_vm->decodeBGImage(resourceData, _loadPanel.image, &_loadPanel.imageWidth, &_loadPanel.imageHeight);
|
|
}
|
|
#endif
|
|
|
|
// Main panel sprites
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites);
|
|
if (!_vm->_script->isNonInteractiveDemo()) {
|
|
// Option panel sprites
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->optionPanelSpritesResourceId, _optionPanel.sprites);
|
|
// Save panel sprites
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _savePanel.sprites);
|
|
// Load panel sprites
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _loadPanel.sprites);
|
|
// Quit panel sprites
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _quitPanel.sprites);
|
|
}
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
_vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits);
|
|
}
|
|
|
|
setPortraitBgColor(0, 0, 0);
|
|
|
|
_mainPanel.x = _vm->getDisplayInfo().mainPanelXOffset;
|
|
_mainPanel.y = _vm->getDisplayInfo().mainPanelYOffset;
|
|
_mainPanel.currentButton = NULL;
|
|
_inventoryUpButton = _mainPanel.getButton(_vm->getDisplayInfo().inventoryUpButtonIndex);
|
|
_inventoryDownButton = _mainPanel.getButton(_vm->getDisplayInfo().inventoryDownButtonIndex);
|
|
|
|
_conversePanel.x = _vm->getDisplayInfo().conversePanelXOffset;
|
|
_conversePanel.y = _vm->getDisplayInfo().conversePanelYOffset;
|
|
_conversePanel.currentButton = NULL;
|
|
_converseUpButton = _conversePanel.getButton(_vm->getDisplayInfo().converseUpButtonIndex);
|
|
_converseDownButton = _conversePanel.getButton(_vm->getDisplayInfo().converseDownButtonIndex);
|
|
|
|
_leftPortrait = 0;
|
|
_rightPortrait = 0;
|
|
|
|
_optionPanel.x = _vm->getDisplayInfo().optionPanelXOffset;
|
|
_optionPanel.y = _vm->getDisplayInfo().optionPanelYOffset;
|
|
_optionPanel.currentButton = NULL;
|
|
_optionSaveFileSlider = _optionPanel.getButton(_vm->getDisplayInfo().optionSaveFileSliderIndex);
|
|
_optionSaveFilePanel = _optionPanel.getButton(_vm->getDisplayInfo().optionSaveFilePanelIndex);
|
|
|
|
_quitPanel.x = _vm->getDisplayInfo().quitPanelXOffset;
|
|
_quitPanel.y = _vm->getDisplayInfo().quitPanelYOffset;
|
|
_quitPanel.imageWidth = _vm->getDisplayInfo().quitPanelWidth;
|
|
_quitPanel.imageHeight = _vm->getDisplayInfo().quitPanelHeight;
|
|
_quitPanel.buttons = _vm->getDisplayInfo().quitPanelButtons;
|
|
_quitPanel.buttonsCount = _vm->getDisplayInfo().quitPanelButtonsCount;
|
|
_quitPanel.currentButton = NULL;
|
|
|
|
_loadPanel.x = _vm->getDisplayInfo().loadPanelXOffset;
|
|
_loadPanel.y = _vm->getDisplayInfo().loadPanelYOffset;
|
|
_loadPanel.imageWidth = _vm->getDisplayInfo().loadPanelWidth;
|
|
_loadPanel.imageHeight = _vm->getDisplayInfo().loadPanelHeight;
|
|
_loadPanel.buttons = _vm->getDisplayInfo().loadPanelButtons;
|
|
_loadPanel.buttonsCount = _vm->getDisplayInfo().loadPanelButtonsCount;
|
|
_loadPanel.currentButton = NULL;
|
|
|
|
_savePanel.x = _vm->getDisplayInfo().savePanelXOffset;
|
|
_savePanel.y = _vm->getDisplayInfo().savePanelYOffset;
|
|
_savePanel.imageWidth = _vm->getDisplayInfo().savePanelWidth;
|
|
_savePanel.imageHeight = _vm->getDisplayInfo().savePanelHeight;
|
|
_savePanel.buttons = _vm->getDisplayInfo().savePanelButtons;
|
|
_savePanel.buttonsCount = _vm->getDisplayInfo().savePanelButtonsCount;
|
|
_saveEdit = _savePanel.getButton(_vm->getDisplayInfo().saveEditIndex);
|
|
_savePanel.currentButton = NULL;
|
|
|
|
_protectPanel.x = _vm->getDisplayInfo().protectPanelXOffset;
|
|
_protectPanel.y = _vm->getDisplayInfo().protectPanelYOffset;
|
|
_protectPanel.imageWidth = _vm->getDisplayInfo().protectPanelWidth;
|
|
_protectPanel.imageHeight = _vm->getDisplayInfo().protectPanelHeight;
|
|
_protectPanel.buttons = _vm->getDisplayInfo().protectPanelButtons;
|
|
_protectPanel.buttonsCount = _vm->getDisplayInfo().protectPanelButtonsCount;
|
|
_protectEdit = _protectPanel.getButton(_vm->getDisplayInfo().protectEditIndex);
|
|
_protectPanel.currentButton = NULL;
|
|
|
|
_active = true;
|
|
_panelMode = _lockedMode = kPanelNull;
|
|
_savedMode = -1;
|
|
_bossMode = -1;
|
|
_fadeMode = kNoFade;
|
|
_inMainMode = false;
|
|
*_statusText = 0;
|
|
_statusOnceColor = -1;
|
|
|
|
_inventoryCount = 0;
|
|
_inventoryPos = 0;
|
|
_inventoryStart = 0;
|
|
_inventoryEnd = 0;
|
|
_inventoryBox = 0;
|
|
_saveReminderState = 0;
|
|
|
|
_optionSaveFileTop = 0;
|
|
_optionSaveFileTitleNumber = 0;
|
|
|
|
_inventory.resize(ITE_INVENTORY_SIZE);
|
|
|
|
_textInput = false;
|
|
_statusTextInput = false;
|
|
_statusTextInputState = kStatusTextInputFirstRun;
|
|
|
|
_disableAbortSpeeches = false;
|
|
|
|
// set save game reminder alarm
|
|
_vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this, "sagaSaveReminder");
|
|
}
|
|
|
|
Interface::~Interface() {
|
|
_vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
|
|
}
|
|
|
|
void Interface::saveReminderCallback(void *refCon) {
|
|
((Interface *)refCon)->updateSaveReminder();
|
|
}
|
|
|
|
void Interface::updateSaveReminder() {
|
|
// CHECKME: This is potentially called from a different thread because it is
|
|
// called from a timer callback. However, it does not seem to take any
|
|
// precautions to avoid race conditions.
|
|
if (_active && _panelMode == kPanelMain) {
|
|
_saveReminderState = _saveReminderState % _vm->getDisplayInfo().saveReminderNumSprites + 1;
|
|
drawStatusBar();
|
|
_vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
|
|
_vm->getTimerManager()->installTimerProc(&saveReminderCallback, ((_vm->getGameId() == GID_ITE) ? TIMETOBLINK_ITE : TIMETOBLINK_IHNM), this, "sagaSaveReminder");
|
|
}
|
|
}
|
|
|
|
int Interface::activate() {
|
|
if (!_active) {
|
|
_active = true;
|
|
_vm->_script->_skipSpeeches = false;
|
|
_vm->_actor->_protagonist->_targetObject = ID_NOTHING;
|
|
unlockMode();
|
|
if (_panelMode == kPanelMain || _panelMode == kPanelChapterSelection) {
|
|
_saveReminderState = 1;
|
|
} else if (_panelMode == kPanelNull && _vm->isIHNMDemo()) {
|
|
_saveReminderState = 1;
|
|
}
|
|
_vm->_gfx->showCursor(true);
|
|
draw();
|
|
_vm->_render->setFullRefresh(true);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
int Interface::deactivate() {
|
|
if (_active) {
|
|
_active = false;
|
|
lockMode();
|
|
setMode(kPanelNull);
|
|
}
|
|
_vm->_gfx->showCursor(false);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
void Interface::rememberMode() {
|
|
debug(1, "rememberMode(%d)", _panelMode);
|
|
|
|
_savedMode = _panelMode;
|
|
}
|
|
|
|
void Interface::restoreMode(bool draw_) {
|
|
debug(1, "restoreMode(%d)", _savedMode);
|
|
|
|
// If _savedMode is -1 by a race condition, set it to kPanelMain
|
|
if (_savedMode == -1)
|
|
_savedMode = kPanelMain;
|
|
|
|
_panelMode = _savedMode;
|
|
_savedMode = -1;
|
|
|
|
if (draw_)
|
|
draw();
|
|
}
|
|
|
|
void Interface::setMode(int mode) {
|
|
debug(1, "Interface::setMode %i", mode);
|
|
|
|
if (mode == kPanelMain) {
|
|
_inMainMode = true;
|
|
_saveReminderState = 1;
|
|
} else if (mode == kPanelChapterSelection) {
|
|
_saveReminderState = 1;
|
|
} else if (mode == kPanelNull) {
|
|
if (_vm->isIHNMDemo()) {
|
|
_inMainMode = true;
|
|
_saveReminderState = 1;
|
|
}
|
|
} else if (mode == kPanelOption) {
|
|
// Show the cursor if it's hidden
|
|
_vm->_gfx->showCursor(true);
|
|
} else {
|
|
if (mode == kPanelConverse) {
|
|
_inMainMode = false;
|
|
}
|
|
|
|
_saveReminderState = 0;
|
|
}
|
|
|
|
_panelMode = mode;
|
|
|
|
switch (_panelMode) {
|
|
case kPanelMain:
|
|
// FIXME: Implement IHNM differences from ExecuteInventoryPanel for IHNM (though I believe they're already
|
|
// implemented)
|
|
|
|
_mainPanel.currentButton = NULL;
|
|
break;
|
|
case kPanelConverse:
|
|
_conversePanel.currentButton = NULL;
|
|
converseDisplayText();
|
|
break;
|
|
case kPanelOption:
|
|
_optionPanel.currentButton = NULL;
|
|
_vm->fillSaveList();
|
|
calcOptionSaveSlider();
|
|
if (_optionSaveFileTitleNumber >= _vm->getDisplayInfo().optionSaveFileVisible) {
|
|
_optionSaveFileTitleNumber = _vm->getDisplayInfo().optionSaveFileVisible - 1;
|
|
}
|
|
break;
|
|
case kPanelLoad:
|
|
_loadPanel.currentButton = NULL;
|
|
break;
|
|
case kPanelQuit:
|
|
_quitPanel.currentButton = NULL;
|
|
break;
|
|
case kPanelSave:
|
|
_savePanel.currentButton = NULL;
|
|
_textInputMaxWidth = _saveEdit->width - 10;
|
|
_textInput = true;
|
|
_textInputStringLength = strlen(_textInputString);
|
|
_textInputPos = _textInputStringLength + 1;
|
|
break;
|
|
case kPanelMap:
|
|
mapPanelShow();
|
|
break;
|
|
case kPanelSceneSubstitute:
|
|
_vm->_render->setFlag(RF_DEMO_SUBST);
|
|
_vm->_gfx->getCurrentPal(_mapSavedPal);
|
|
break;
|
|
case kPanelChapterSelection:
|
|
break;
|
|
case kPanelBoss:
|
|
_vm->_render->setFlag(RF_DEMO_SUBST);
|
|
break;
|
|
case kPanelProtect:
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
// This is used as the copy protection panel in ITE
|
|
_protectPanel.currentButton = NULL;
|
|
_textInputMaxWidth = _protectEdit->width - 10;
|
|
_textInput = true;
|
|
_textInputString[0] = 0;
|
|
_textInputStringLength = 0;
|
|
_textInputPos = _textInputStringLength + 1;
|
|
} else {
|
|
// In the IHNM demo, this panel mode is set by the scripts
|
|
// to flip through the pages of the help system
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
draw();
|
|
_vm->_render->setFullRefresh(true);
|
|
}
|
|
|
|
bool Interface::processAscii(Common::KeyState keystate) {
|
|
// TODO: Checking for Esc and Enter below is a bit hackish, and
|
|
// probably only works with the English version. Maybe we should
|
|
// add a flag to the button so it can indicate if it's the default
|
|
// or cancel button?
|
|
uint16 ascii = keystate.ascii;
|
|
int i;
|
|
PanelButton *panelButton;
|
|
if (_statusTextInput) {
|
|
processStatusTextInput(keystate);
|
|
return true;
|
|
}
|
|
|
|
switch (_panelMode) {
|
|
case kPanelNull:
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
|
|
if (_vm->_scene->isInIntro()) {
|
|
_vm->_scene->skipScene();
|
|
} else {
|
|
if (!_disableAbortSpeeches)
|
|
_vm->_actor->abortAllSpeeches();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
|
|
_vm->_scene->showIHNMDemoSpecialScreen();
|
|
#endif
|
|
break;
|
|
case kPanelCutaway:
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
|
|
if (!_disableAbortSpeeches)
|
|
_vm->_actor->abortAllSpeeches();
|
|
_vm->_scene->cutawaySkip();
|
|
return true;
|
|
}
|
|
|
|
#ifdef ENABLE_INHM
|
|
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
|
|
_vm->_scene->showIHNMDemoSpecialScreen();
|
|
#endif
|
|
break;
|
|
case kPanelVideo:
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
|
|
if (_vm->_scene->isInIntro()) {
|
|
_vm->_scene->skipScene();
|
|
} else {
|
|
if (!_disableAbortSpeeches)
|
|
_vm->_actor->abortAllSpeeches();
|
|
}
|
|
_vm->_scene->cutawaySkip();
|
|
return true;
|
|
}
|
|
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
|
|
_vm->_scene->showIHNMDemoSpecialScreen();
|
|
#endif
|
|
break;
|
|
case kPanelOption:
|
|
// TODO: check input dialog keys
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE || keystate.keycode == Common::KEYCODE_RETURN) { // Esc or Enter
|
|
ascii = 'c'; //continue
|
|
}
|
|
|
|
for (i = 0; i < _optionPanel.buttonsCount; i++) {
|
|
panelButton = &_optionPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonOption) {
|
|
if (panelButton->ascii == ascii) {
|
|
setOption(panelButton);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kPanelSave:
|
|
if (_textInput && processTextInput(keystate)) {
|
|
return true;
|
|
}
|
|
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
|
|
ascii = 'c'; // cancel
|
|
} else if (keystate.keycode == Common::KEYCODE_RETURN) { // Enter
|
|
ascii = 's'; // save
|
|
}
|
|
|
|
for (i = 0; i < _savePanel.buttonsCount; i++) {
|
|
panelButton = &_savePanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonSave) {
|
|
if (panelButton->ascii == ascii) {
|
|
setSave(panelButton);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kPanelQuit:
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE) {
|
|
ascii = 'c'; // cancel
|
|
} else if (keystate.keycode == Common::KEYCODE_RETURN) { // Enter
|
|
ascii = 'q'; // quit
|
|
}
|
|
|
|
for (i = 0; i < _quitPanel.buttonsCount; i++) {
|
|
panelButton = &_quitPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonQuit) {
|
|
if (panelButton->ascii == ascii) {
|
|
setQuit(panelButton);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kPanelLoad:
|
|
for (i = 0; i < _loadPanel.buttonsCount; i++) {
|
|
panelButton = &_loadPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonLoad) {
|
|
if (panelButton->ascii == ascii) {
|
|
setLoad(panelButton);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kPanelMain:
|
|
for (i = 0; i < _mainPanel.buttonsCount; i++) {
|
|
panelButton = &_mainPanel.buttons[i];
|
|
if (panelButton->ascii == ascii) {
|
|
if (panelButton->type == kPanelButtonVerb) {
|
|
_vm->_script->setVerb(panelButton->id);
|
|
}
|
|
if (panelButton->type == kPanelButtonArrow) {
|
|
inventoryChangePos(panelButton->id);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
if (keystate.keycode == Common::KEYCODE_o && keystate.hasFlags(Common::KBD_CTRL)) { // ctrl-o
|
|
if (_saveReminderState > 0) {
|
|
setMode(kPanelOption);
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case kPanelConverse:
|
|
switch (ascii) {
|
|
case 'x':
|
|
setMode(kPanelMain);
|
|
if (_vm->_scene->isITEPuzzleScene())
|
|
_vm->_puzzle->exitPuzzle();
|
|
break;
|
|
|
|
case 'u':
|
|
converseChangePos(-1);
|
|
break;
|
|
|
|
case 'd':
|
|
converseChangePos(1);
|
|
break;
|
|
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
converseSetPos(ascii);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case kPanelMap:
|
|
mapPanelClean();
|
|
break;
|
|
case kPanelSceneSubstitute:
|
|
if (keystate.keycode == Common::KEYCODE_RETURN) {
|
|
_vm->_render->clearFlag(RF_DEMO_SUBST);
|
|
_vm->_gfx->setPalette(_mapSavedPal);
|
|
setMode(kPanelMain);
|
|
_vm->_script->setNoPendingVerb();
|
|
} else if (ascii == 'q' || ascii == 'Q') {
|
|
_vm->quitGame();
|
|
}
|
|
break;
|
|
case kPanelBoss:
|
|
_vm->_render->clearFlag(RF_DEMO_SUBST);
|
|
keyBossExit();
|
|
break;
|
|
case kPanelProtect:
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
if (_textInput && processTextInput(keystate)) {
|
|
return true;
|
|
}
|
|
|
|
if (keystate.keycode == Common::KEYCODE_ESCAPE || keystate.keycode == Common::KEYCODE_RETURN) {
|
|
_vm->_script->wakeUpThreads(kWaitTypeRequest);
|
|
_vm->_interface->setMode(kPanelMain);
|
|
|
|
_protectHash = 0;
|
|
|
|
for (char *p = _textInputString; *p; p++)
|
|
_protectHash = (_protectHash << 1) + toupper(*p);
|
|
}
|
|
} else {
|
|
// In the IHNM demo, this panel mode is set by the scripts
|
|
// to flip through the pages of the help system
|
|
}
|
|
break;
|
|
case kPanelPlacard:
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
// Any keypress here returns the user back to the game
|
|
if (!_vm->isIHNMDemo()) {
|
|
_vm->_scene->clearPsychicProfile();
|
|
} else {
|
|
setMode(kPanelConverse);
|
|
_vm->_scene->_textList.clear();
|
|
_vm->_script->wakeUpThreads(kWaitTypeDelay);
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Interface::setStatusText(const char *text, int statusColor) {
|
|
if (_vm->getGameId() == GID_FTA2 || _vm->getGameId() == GID_DINO) {
|
|
warning("setStatusText not implemented for SAGA2");
|
|
return;
|
|
}
|
|
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
// Don't show the status text for the IHNM chapter selection screens (chapter 8), or
|
|
// scene 0 (IHNM demo introduction)
|
|
if (_vm->_scene->currentChapterNumber() == 8 || _vm->_scene->currentSceneNumber() == 0)
|
|
return;
|
|
}
|
|
|
|
assert(text != NULL);
|
|
assert(strlen(text) < STATUS_TEXT_LEN);
|
|
|
|
if (_vm->_render->getFlags() & RF_MAP || _vm->_interface->getMode() == kPanelPlacard)
|
|
return;
|
|
|
|
Common::strlcpy(_statusText, text, STATUS_TEXT_LEN);
|
|
_statusOnceColor = statusColor;
|
|
drawStatusBar();
|
|
}
|
|
|
|
void Interface::loadScenePortraits(int resourceId) {
|
|
_scenePortraits.clear();
|
|
|
|
_vm->_sprite->loadList(resourceId, _scenePortraits);
|
|
}
|
|
|
|
void Interface::drawVerbPanel(PanelButton* panelButton) {
|
|
PanelButton * rightButtonVerbPanelButton;
|
|
PanelButton * currentVerbPanelButton;
|
|
KnownColor textColor;
|
|
int spriteNumber;
|
|
Point point;
|
|
|
|
rightButtonVerbPanelButton = getPanelButtonByVerbType(_vm->_script->getRightButtonVerb());
|
|
currentVerbPanelButton = getPanelButtonByVerbType(_vm->_script->getCurrentVerb());
|
|
|
|
if (panelButton->state) {
|
|
textColor = kKnownColorVerbTextActive;
|
|
} else if (panelButton == rightButtonVerbPanelButton) {
|
|
textColor = kKnownColorVerbTextActive;
|
|
} else {
|
|
textColor = kKnownColorVerbText;
|
|
}
|
|
|
|
if (panelButton == currentVerbPanelButton) {
|
|
spriteNumber = panelButton->downSpriteNumber;
|
|
} else {
|
|
spriteNumber = panelButton->upSpriteNumber;
|
|
}
|
|
point.x = _mainPanel.x + panelButton->xOffset;
|
|
point.y = _mainPanel.y + panelButton->yOffset;
|
|
|
|
_vm->_sprite->draw(_mainPanel.sprites, spriteNumber, point, 256);
|
|
|
|
drawVerbPanelText(panelButton, textColor, kKnownColorVerbTextShadow);
|
|
}
|
|
|
|
void Interface::draw() {
|
|
Point leftPortraitPoint;
|
|
Point rightPortraitPoint;
|
|
Rect rect;
|
|
|
|
if (_vm->_scene->isInIntro() || _fadeMode == kFadeOut)
|
|
return;
|
|
|
|
drawStatusBar();
|
|
|
|
if (_panelMode == kPanelMain || _panelMode == kPanelMap ||
|
|
(_panelMode == kPanelNull && _vm->isIHNMDemo())) {
|
|
_mainPanel.getRect(rect);
|
|
_vm->_gfx->drawRegion(rect, _mainPanel.image.getBuffer());
|
|
|
|
for (int i = 0; i < kVerbTypeIdsMax; i++) {
|
|
if (_verbTypeToPanelButton[i] != NULL) {
|
|
drawVerbPanel(_verbTypeToPanelButton[i]);
|
|
}
|
|
}
|
|
} else if (_panelMode == kPanelConverse) {
|
|
_conversePanel.getRect(rect);
|
|
_vm->_gfx->drawRegion(rect, _conversePanel.image.getBuffer());
|
|
converseDisplayTextLines();
|
|
}
|
|
|
|
if (_panelMode == kPanelMain || _panelMode == kPanelConverse ||
|
|
_lockedMode == kPanelMain || _lockedMode == kPanelConverse ||
|
|
(_panelMode == kPanelNull && _vm->isIHNMDemo())) {
|
|
leftPortraitPoint.x = _mainPanel.x + _vm->getDisplayInfo().leftPortraitXOffset;
|
|
leftPortraitPoint.y = _mainPanel.y + _vm->getDisplayInfo().leftPortraitYOffset;
|
|
_vm->_sprite->draw(_defPortraits, _leftPortrait, leftPortraitPoint, 256);
|
|
}
|
|
|
|
if (!_inMainMode && _vm->getDisplayInfo().rightPortraitXOffset >= 0) { //FIXME: should we change !_inMainMode to _panelMode == kPanelConverse ?
|
|
rightPortraitPoint.x = _mainPanel.x + _vm->getDisplayInfo().rightPortraitXOffset;
|
|
rightPortraitPoint.y = _mainPanel.y + _vm->getDisplayInfo().rightPortraitYOffset;
|
|
|
|
// This looks like hack - particularly since it's only done for
|
|
// the right-side portrait - and perhaps it is! But as far as I
|
|
// can tell this is what the original engine does. And it keeps
|
|
// ITE from crashing when entering the Elk King's court.
|
|
|
|
if (_rightPortrait >= (int)_scenePortraits.size())
|
|
_rightPortrait = 0;
|
|
|
|
_vm->_sprite->draw(_scenePortraits, _rightPortrait, rightPortraitPoint, 256);
|
|
}
|
|
|
|
drawInventory();
|
|
}
|
|
|
|
void Interface::calcOptionSaveSlider() {
|
|
int totalFiles = _vm->getSaveFilesCount();
|
|
int visibleFiles = _vm->getDisplayInfo().optionSaveFileVisible;
|
|
int height = _optionSaveFileSlider->height;
|
|
int sliderHeight = 13; // IHNM's save file list slider has a fixed height
|
|
int pos;
|
|
|
|
if (totalFiles < visibleFiles) {
|
|
totalFiles = visibleFiles;
|
|
}
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
// ITE's save file list slider has a dynamically computed height, depending on
|
|
// the number of save games
|
|
sliderHeight = visibleFiles * height / totalFiles;
|
|
}
|
|
|
|
if (sliderHeight < 7) {
|
|
sliderHeight = 7;
|
|
}
|
|
|
|
if (totalFiles - visibleFiles <= 0) {
|
|
pos = 0;
|
|
} else {
|
|
pos = _optionSaveFileTop * (height - sliderHeight) / (totalFiles - visibleFiles);
|
|
}
|
|
_optionPanel.calcPanelButtonRect(_optionSaveFileSlider, _optionSaveRectTop);
|
|
_optionSaveRectBottom = _optionSaveRectSlider = _optionSaveRectTop;
|
|
|
|
_optionSaveRectTop.bottom = _optionSaveRectTop.top + pos;
|
|
_optionSaveRectTop.top++;
|
|
_optionSaveRectTop.right--;
|
|
|
|
_optionSaveRectSlider.top = _optionSaveRectTop.bottom;
|
|
_optionSaveRectSlider.bottom = _optionSaveRectSlider.top + sliderHeight;
|
|
|
|
_optionSaveRectBottom.top = _optionSaveRectSlider.bottom;
|
|
_optionSaveRectBottom.right--;
|
|
}
|
|
|
|
void Interface::drawPanelText(InterfacePanel *panel, PanelButton *panelButton) {
|
|
const char *text;
|
|
int textWidth, textHeight;
|
|
Rect rect;
|
|
Point textPoint;
|
|
KnownColor textShadowKnownColor = kKnownColorVerbTextShadow;
|
|
KnownFont textFont = kKnownFontMedium;
|
|
|
|
// Button differs for CD version
|
|
if (panelButton->id == kTextReadingSpeed && _vm->getGameId() == GID_ITE && !(_vm->getFeatures() & GF_ITE_FLOPPY))
|
|
return;
|
|
if (panelButton->id == kTextShowDialog && _vm->getFeatures() & GF_ITE_FLOPPY)
|
|
return;
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
text = _vm->getTextString(panelButton->id);
|
|
textFont = kKnownFontMedium;
|
|
textShadowKnownColor = kKnownColorVerbTextShadow;
|
|
} else {
|
|
if ((panelButton->id < 39 || panelButton->id > 50) && panelButton->id != kTextLoadSavedGame) {
|
|
// Read non-hardcoded strings from the LUT string table, loaded from the game
|
|
// data files
|
|
text = _vm->_script->_mainStrings.getString(IHNMTextStringIdsLUT[panelButton->id]);
|
|
} else if (panelButton->id == kTextLoadSavedGame) {
|
|
// a bit of a kludge, but it will do
|
|
text = _vm->getTextString(52);
|
|
} else {
|
|
// Hardcoded strings in IHNM are read from the ITE hardcoded strings
|
|
text = _vm->getTextString(panelButton->id);
|
|
}
|
|
textFont = kKnownFontVerb;
|
|
textShadowKnownColor = kKnownColorTransparent;
|
|
}
|
|
|
|
panel->calcPanelButtonRect(panelButton, rect);
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
textWidth = _vm->_font->getStringWidth(kKnownFontMedium, text, 0, kFontNormal);
|
|
textHeight = _vm->_font->getHeight(kKnownFontMedium);
|
|
} else {
|
|
textWidth = _vm->_font->getStringWidth(kKnownFontVerb, text, 0, kFontNormal);
|
|
textHeight = _vm->_font->getHeight(kKnownFontVerb);
|
|
}
|
|
if (panelButton->xOffset < 0) {
|
|
// Special case: Centered to dialog. This is used for things like the
|
|
// title of a dialog.
|
|
rect.left += 2 + (panel->imageWidth - 1 - textWidth) / 2;
|
|
} else {
|
|
// The standard case is used for the things that look a bit like buttons
|
|
// but are not clickable, e.g. texts like "Music", "Sound", etc.
|
|
if (_vm->getGameId() == GID_ITE && _vm->getPlatform() != Common::kPlatformPC98) {
|
|
rect.left = rect.right - textWidth - 3;
|
|
} else {
|
|
rect.left = (rect.right + rect.left - textWidth) / 2;
|
|
if (_vm->getGameId() == GID_ITE)
|
|
rect.left += 4;
|
|
}
|
|
rect.top = (rect.top + rect.bottom - textHeight) / 2;
|
|
}
|
|
|
|
textPoint.x = rect.left;
|
|
textPoint.y = rect.top + (_vm->getPlatform() == Common::kPlatformPC98 ? 0 : 1);
|
|
|
|
_vm->_font->textDraw(textFont, text, textPoint,
|
|
_vm->KnownColor2ColorId(kKnownColorVerbText), _vm->KnownColor2ColorId(textShadowKnownColor), _vm->getPlatform() == Common::kPlatformPC98 ? kFontOutline : kFontShadow);
|
|
}
|
|
|
|
void Interface::drawOption() {
|
|
const char *text;
|
|
int fontHeight;
|
|
uint idx;
|
|
int fgColor;
|
|
int bgColor;
|
|
Rect rect;
|
|
Rect rect2;
|
|
PanelButton *panelButton;
|
|
Point textPoint;
|
|
Point sliderPoint;
|
|
int spritenum = 0;
|
|
|
|
_optionPanel.getRect(rect);
|
|
_vm->_gfx->drawRegion(rect, _optionPanel.image.getBuffer());
|
|
|
|
for (int i = 0; i < _optionPanel.buttonsCount; i++) {
|
|
panelButton = &_optionPanel.buttons[i];
|
|
|
|
if (panelButton->type == kPanelButtonOption) {
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
drawPanelButtonText(&_optionPanel, panelButton);
|
|
} else {
|
|
drawPanelButtonText(&_optionPanel, panelButton, spritenum);
|
|
spritenum += 2; // 2 sprites per button (lit and unlit)
|
|
}
|
|
}
|
|
if (panelButton->type == kPanelButtonOptionText) {
|
|
drawPanelText(&_optionPanel, panelButton);
|
|
}
|
|
}
|
|
|
|
if (_optionSaveRectTop.height() > 0) {
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_gfx->drawRect(_optionSaveRectTop, kITEColorDarkGrey);
|
|
}
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
drawButtonBox(_optionSaveRectSlider, kSlider, _optionSaveFileSlider->state > 0);
|
|
} else {
|
|
panelButton = &_optionPanel.buttons[0];
|
|
sliderPoint.x = _optionPanel.x + panelButton->xOffset;
|
|
sliderPoint.y = _optionSaveRectSlider.top;
|
|
_vm->_sprite->draw(_optionPanel.sprites, 0 + _optionSaveFileSlider->state, sliderPoint, 256);
|
|
|
|
}
|
|
|
|
if (_optionSaveRectBottom.height() > 0) {
|
|
_vm->_gfx->drawRect(_optionSaveRectBottom, kITEColorDarkGrey);
|
|
}
|
|
|
|
_optionPanel.calcPanelButtonRect(_optionSaveFilePanel, rect);
|
|
rect.top++;
|
|
rect2 = rect;
|
|
fontHeight = _vm->_font->getHeight(kKnownFontSmall);
|
|
for (uint j = 0; j < _vm->getDisplayInfo().optionSaveFileVisible; j++) {
|
|
if (_vm->getGameId() == GID_ITE)
|
|
bgColor = kITEColorDarkGrey0C;
|
|
else
|
|
bgColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
fgColor = kITEColorBrightWhite;
|
|
|
|
idx = j + _optionSaveFileTop;
|
|
if (idx == _optionSaveFileTitleNumber) {
|
|
SWAP(bgColor, fgColor);
|
|
}
|
|
if (idx < _vm->getSaveFilesCount()) {
|
|
rect2.top = rect.top + j * (fontHeight + 1);
|
|
rect2.bottom = rect2.top + fontHeight;
|
|
_vm->_gfx->fillRect(rect2, bgColor);
|
|
text = _vm->getSaveFile(idx)->name;
|
|
textPoint.x = rect.left + 1;
|
|
textPoint.y = rect2.top;
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_font->textDraw(kKnownFontSmall, text, textPoint, fgColor, 0, kFontNormal);
|
|
else
|
|
_vm->_font->textDraw(kKnownFontVerb, text, textPoint, fgColor, 0, kFontNormal);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void Interface::drawQuit() {
|
|
Rect rect;
|
|
int i;
|
|
PanelButton *panelButton;
|
|
|
|
_quitPanel.getRect(rect);
|
|
if (_vm->getGameId() == GID_ITE)
|
|
drawButtonBox(rect, kButton, false);
|
|
else
|
|
_vm->_gfx->drawRegion(rect, _quitPanel.image.getBuffer());
|
|
|
|
for (i = 0; i < _quitPanel.buttonsCount; i++) {
|
|
panelButton = &_quitPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonQuit) {
|
|
drawPanelButtonText(&_quitPanel, panelButton);
|
|
}
|
|
if (panelButton->type == kPanelButtonQuitText) {
|
|
drawPanelText(&_quitPanel, panelButton);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::handleQuitUpdate(const Point& mousePoint) {
|
|
bool releasedButton;
|
|
|
|
_quitPanel.currentButton = quitHitTest(mousePoint);
|
|
releasedButton = (_quitPanel.currentButton != NULL) && (_quitPanel.currentButton->state > 0) && (!_vm->mouseButtonPressed());
|
|
|
|
if (!_vm->mouseButtonPressed()) {
|
|
_quitPanel.zeroAllButtonState();
|
|
}
|
|
|
|
if (releasedButton) {
|
|
setQuit(_quitPanel.currentButton);
|
|
}
|
|
}
|
|
|
|
void Interface::handleQuitClick(const Point& mousePoint) {
|
|
_quitPanel.currentButton = quitHitTest(mousePoint);
|
|
|
|
_quitPanel.zeroAllButtonState();
|
|
|
|
if (_quitPanel.currentButton == NULL) {
|
|
return;
|
|
}
|
|
|
|
_quitPanel.currentButton->state = 1;
|
|
}
|
|
|
|
void Interface::setQuit(PanelButton *panelButton) {
|
|
_quitPanel.currentButton = NULL;
|
|
switch (panelButton->id) {
|
|
case kTextCancel:
|
|
setMode(kPanelOption);
|
|
break;
|
|
case kTextQuit:
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->isIHNMDemo())
|
|
_vm->_scene->creditsScene(); // display sales info for IHNM demo
|
|
else
|
|
#endif
|
|
_vm->quitGame();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Interface::drawLoad() {
|
|
Rect rect;
|
|
int i;
|
|
PanelButton *panelButton;
|
|
|
|
_loadPanel.getRect(rect);
|
|
if (_vm->getGameId() == GID_ITE)
|
|
drawButtonBox(rect, kButton, false);
|
|
else
|
|
_vm->_gfx->drawRegion(rect, _loadPanel.image.getBuffer());
|
|
|
|
for (i = 0; i < _loadPanel.buttonsCount; i++) {
|
|
panelButton = &_loadPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonLoad) {
|
|
drawPanelButtonText(&_loadPanel, panelButton);
|
|
}
|
|
if (panelButton->type == kPanelButtonLoadText) {
|
|
drawPanelText(&_loadPanel, panelButton);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::handleLoadUpdate(const Point& mousePoint) {
|
|
bool releasedButton;
|
|
|
|
_loadPanel.currentButton = loadHitTest(mousePoint);
|
|
releasedButton = (_loadPanel.currentButton != NULL) && (_loadPanel.currentButton->state > 0) && (!_vm->mouseButtonPressed());
|
|
|
|
if (!_vm->mouseButtonPressed()) {
|
|
_loadPanel.zeroAllButtonState();
|
|
}
|
|
|
|
if (releasedButton) {
|
|
setLoad(_loadPanel.currentButton);
|
|
}
|
|
}
|
|
|
|
void Interface::handleLoadClick(const Point& mousePoint) {
|
|
_loadPanel.currentButton = loadHitTest(mousePoint);
|
|
|
|
_loadPanel.zeroAllButtonState();
|
|
|
|
if (_loadPanel.currentButton == NULL) {
|
|
return;
|
|
}
|
|
|
|
_loadPanel.currentButton->state = 1;
|
|
}
|
|
|
|
void Interface::setLoad(PanelButton *panelButton) {
|
|
_loadPanel.currentButton = NULL;
|
|
switch (panelButton->id) {
|
|
case kTextOK:
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
setMode(kPanelMain);
|
|
} else {
|
|
if (_vm->getSaveFilesCount() > 0) {
|
|
if (_vm->isSaveListFull() || (_optionSaveFileTitleNumber > 0)) {
|
|
debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
|
|
setMode(kPanelMain);
|
|
_vm->load(_vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber));
|
|
_vm->syncSoundSettings();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kTextCancel:
|
|
// IHNM only
|
|
setMode(kPanelOption);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Interface::processStatusTextInput(Common::KeyState keystate) {
|
|
|
|
switch (keystate.keycode) {
|
|
case Common::KEYCODE_ESCAPE:
|
|
_statusTextInputState = kStatusTextInputAborted;
|
|
_statusTextInput = false;
|
|
_vm->_script->wakeUpThreads(kWaitTypeStatusTextInput);
|
|
break;
|
|
case Common::KEYCODE_RETURN:
|
|
_statusTextInputState = kStatusTextInputEntered;
|
|
_statusTextInput = false;
|
|
_vm->_script->wakeUpThreads(kWaitTypeStatusTextInput);
|
|
break;
|
|
case Common::KEYCODE_BACKSPACE:
|
|
if (_statusTextInputPos == 0) {
|
|
break;
|
|
}
|
|
_statusTextInputPos--;
|
|
_statusTextInputString[_statusTextInputPos] = 0;
|
|
break;
|
|
default:
|
|
if (_statusTextInputPos >= STATUS_TEXT_INPUT_MAX - 1) { // -1 because of the null termination
|
|
break;
|
|
}
|
|
if (Common::isAlnum(keystate.ascii) || (keystate.ascii == ' ')) {
|
|
_statusTextInputString[_statusTextInputPos++] = keystate.ascii;
|
|
_statusTextInputString[_statusTextInputPos] = 0;
|
|
}
|
|
}
|
|
setStatusText(_statusTextInputString);
|
|
}
|
|
|
|
bool Interface::processTextInput(Common::KeyState keystate) {
|
|
char ch[2];
|
|
char tempString[SAVE_TITLE_SIZE];
|
|
uint tempWidth;
|
|
memset(tempString, 0, SAVE_TITLE_SIZE);
|
|
ch[1] = 0;
|
|
// IHNM has a smaller save title size than ITE. We only limit the save title size during text input
|
|
// in IHNM, to preserve backwards compatibility with older save games
|
|
uint save_title_size = _vm->getGameId() == GID_ITE ? SAVE_TITLE_SIZE : IHNM_SAVE_TITLE_SIZE;
|
|
|
|
switch (keystate.keycode) {
|
|
case Common::KEYCODE_RETURN:
|
|
return false;
|
|
case Common::KEYCODE_ESCAPE:
|
|
_textInput = false;
|
|
break;
|
|
case Common::KEYCODE_BACKSPACE:
|
|
if (_textInputPos <= 1) {
|
|
break;
|
|
}
|
|
_textInputPos--;
|
|
// fall through
|
|
case Common::KEYCODE_DELETE:
|
|
if (_textInputPos <= _textInputStringLength) {
|
|
if (_textInputPos != 1) {
|
|
strncpy(tempString, _textInputString, _textInputPos - 1);
|
|
}
|
|
if (_textInputPos != _textInputStringLength) {
|
|
strncat(tempString, &_textInputString[_textInputPos], _textInputStringLength - _textInputPos);
|
|
}
|
|
strcpy(_textInputString, tempString);
|
|
_textInputStringLength = strlen(_textInputString);
|
|
}
|
|
break;
|
|
case Common::KEYCODE_LEFT:
|
|
if (_textInputPos > 1) {
|
|
_textInputPos--;
|
|
}
|
|
break;
|
|
case Common::KEYCODE_RIGHT:
|
|
if (_textInputPos <= _textInputStringLength) {
|
|
_textInputPos++;
|
|
}
|
|
break;
|
|
case Common::KEYCODE_HOME:
|
|
_textInputPos = 1;
|
|
break;
|
|
case Common::KEYCODE_END:
|
|
_textInputPos = _textInputStringLength + 1;
|
|
break;
|
|
default:
|
|
if (((keystate.ascii <= 255) && (Common::isAlnum(keystate.ascii))) || (keystate.ascii == ' ') ||
|
|
(keystate.ascii == '-') || (keystate.ascii == '_')) {
|
|
if (_textInputStringLength < save_title_size - 1) {
|
|
ch[0] = keystate.ascii;
|
|
tempWidth = _vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal);
|
|
tempWidth += _vm->_font->getStringWidth(kKnownFontSmall, _textInputString, 0, kFontNormal);
|
|
if (tempWidth > _textInputMaxWidth) {
|
|
break;
|
|
}
|
|
if (_textInputPos != 1) {
|
|
strncpy(tempString, _textInputString, _textInputPos - 1);
|
|
strcat(tempString, ch);
|
|
}
|
|
if ((_textInputStringLength == 0) || (_textInputPos == 1)) {
|
|
strcpy(tempString, ch);
|
|
}
|
|
if ((_textInputStringLength != 0) && (_textInputPos != _textInputStringLength)) {
|
|
strncat(tempString, &_textInputString[_textInputPos - 1], _textInputStringLength - _textInputPos + 1);
|
|
}
|
|
|
|
strcpy(_textInputString, tempString);
|
|
_textInputStringLength = strlen(_textInputString);
|
|
_textInputPos++;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Interface::drawTextInput(InterfacePanel *panel, PanelButton *panelButton) {
|
|
Point textPoint;
|
|
Rect rect;
|
|
char ch[2];
|
|
int fgColor;
|
|
uint i;
|
|
|
|
ch[1] = 0;
|
|
panel->calcPanelButtonRect(panelButton, rect);
|
|
drawButtonBox(rect, kEdit, _textInput);
|
|
rect.left += 4;
|
|
rect.top += 4;
|
|
rect.setHeight(_vm->_font->getHeight(kKnownFontSmall));
|
|
|
|
i = 0;
|
|
while ((ch[0] = _textInputString[i++]) != 0) {
|
|
rect.setWidth(_vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal));
|
|
if ((i == _textInputPos) && _textInput) {
|
|
fgColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
_vm->_gfx->fillRect(rect, _vm->KnownColor2ColorId(kKnownColorWhite));
|
|
} else {
|
|
fgColor = _vm->KnownColor2ColorId(kKnownColorWhite);
|
|
}
|
|
textPoint.x = rect.left;
|
|
textPoint.y = rect.top + 1;
|
|
|
|
_vm->_font->textDraw(kKnownFontSmall, ch, textPoint, fgColor, 0, kFontNormal);
|
|
rect.left += rect.width();
|
|
}
|
|
if (_textInput && (_textInputPos >= i)) {
|
|
ch[0] = ' ';
|
|
rect.setWidth(_vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal));
|
|
_vm->_gfx->fillRect(rect, _vm->KnownColor2ColorId(kKnownColorWhite));
|
|
}
|
|
}
|
|
|
|
void Interface::drawSave() {
|
|
Rect rect;
|
|
int i;
|
|
PanelButton *panelButton;
|
|
|
|
_savePanel.getRect(rect);
|
|
if (_vm->getGameId() == GID_ITE)
|
|
drawButtonBox(rect, kButton, false);
|
|
else
|
|
_vm->_gfx->drawRegion(rect, _savePanel.image.getBuffer());
|
|
|
|
for (i = 0; i < _savePanel.buttonsCount; i++) {
|
|
panelButton = &_savePanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonSave) {
|
|
drawPanelButtonText(&_savePanel, panelButton);
|
|
}
|
|
if (panelButton->type == kPanelButtonSaveText) {
|
|
drawPanelText(&_savePanel, panelButton);
|
|
}
|
|
}
|
|
|
|
drawTextInput(&_savePanel, _saveEdit);
|
|
}
|
|
|
|
void Interface::drawProtect() {
|
|
Rect rect;
|
|
int i;
|
|
PanelButton *panelButton;
|
|
|
|
_protectPanel.getRect(rect);
|
|
drawButtonBox(rect, kButton, false);
|
|
|
|
for (i = 0; i < _protectPanel.buttonsCount; i++) {
|
|
panelButton = &_protectPanel.buttons[i];
|
|
if (panelButton->type == kPanelButtonProtectText) {
|
|
drawPanelText(&_protectPanel, panelButton);
|
|
}
|
|
}
|
|
drawTextInput(&_protectPanel, _protectEdit);
|
|
}
|
|
|
|
void Interface::handleSaveUpdate(const Point& mousePoint) {
|
|
bool releasedButton;
|
|
|
|
_savePanel.currentButton = saveHitTest(mousePoint);
|
|
|
|
validateSaveButtons();
|
|
|
|
releasedButton = (_savePanel.currentButton != NULL) &&
|
|
(_savePanel.currentButton->state > 0) && (!_vm->mouseButtonPressed());
|
|
|
|
if (!_vm->mouseButtonPressed()) {
|
|
_savePanel.zeroAllButtonState();
|
|
}
|
|
|
|
if (releasedButton) {
|
|
setSave(_savePanel.currentButton);
|
|
}
|
|
}
|
|
|
|
void Interface::handleSaveClick(const Point& mousePoint) {
|
|
_savePanel.currentButton = saveHitTest(mousePoint);
|
|
|
|
validateSaveButtons();
|
|
|
|
_savePanel.zeroAllButtonState();
|
|
|
|
if (_savePanel.currentButton == NULL) {
|
|
_textInput = false;
|
|
return;
|
|
}
|
|
|
|
_savePanel.currentButton->state = 1;
|
|
if (_savePanel.currentButton == _saveEdit) {
|
|
_textInput = true;
|
|
}
|
|
}
|
|
|
|
void Interface::setSave(PanelButton *panelButton) {
|
|
_savePanel.currentButton = NULL;
|
|
uint titleNumber;
|
|
char *fileName;
|
|
switch (panelButton->id) {
|
|
case kTextSave:
|
|
if (_textInputStringLength == 0) {
|
|
break;
|
|
}
|
|
if (!_vm->isSaveListFull() && (_optionSaveFileTitleNumber == 0)) {
|
|
if (_vm->locateSaveFile(_textInputString, titleNumber)) {
|
|
fileName = _vm->calcSaveFileName(_vm->getSaveFile(titleNumber)->slotNumber);
|
|
_vm->save(fileName, _textInputString);
|
|
_optionSaveFileTitleNumber = titleNumber;
|
|
} else {
|
|
fileName = _vm->calcSaveFileName(_vm->getNewSaveSlotNumber());
|
|
_vm->save(fileName, _textInputString);
|
|
_vm->fillSaveList();
|
|
calcOptionSaveSlider();
|
|
}
|
|
} else {
|
|
fileName = _vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
|
|
_vm->save(fileName, _textInputString);
|
|
}
|
|
resetSaveReminder();
|
|
|
|
_textInput = false;
|
|
setMode(kPanelOption);
|
|
break;
|
|
case kTextCancel:
|
|
_textInput = false;
|
|
setMode(kPanelOption);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Interface::resetSaveReminder() {
|
|
_vm->getTimerManager()->removeTimerProc(&saveReminderCallback);
|
|
_vm->getTimerManager()->installTimerProc(&saveReminderCallback, TIMETOSAVE, this, "sagaSaveReminder");
|
|
setSaveReminderState(1);
|
|
}
|
|
|
|
void Interface::handleOptionUpdate(const Point& mousePoint) {
|
|
int16 mouseY;
|
|
Rect rect;
|
|
int totalFiles = _vm->getSaveFilesCount();
|
|
int visibleFiles = _vm->getDisplayInfo().optionSaveFileVisible;
|
|
bool releasedButton;
|
|
|
|
if (_vm->mouseButtonPressed()) {
|
|
if (_optionSaveFileSlider->state > 0) {
|
|
_optionPanel.calcPanelButtonRect(_optionSaveFileSlider, rect);
|
|
|
|
mouseY = mousePoint.y - rect.top -_optionSaveFileMouseOff;
|
|
if (mouseY < 0)
|
|
mouseY = 0;
|
|
|
|
if (totalFiles - visibleFiles <= 0) {
|
|
_optionSaveFileTop = 0;
|
|
} else {
|
|
_optionSaveFileTop = mouseY * (totalFiles - visibleFiles) /
|
|
(_optionSaveFileSlider->height - _optionSaveRectSlider.height());
|
|
}
|
|
|
|
_optionSaveFileTop = CLIP<uint>(_optionSaveFileTop, 0, totalFiles - visibleFiles);
|
|
calcOptionSaveSlider();
|
|
}
|
|
}
|
|
|
|
_optionPanel.currentButton = optionHitTest(mousePoint);
|
|
|
|
validateOptionButtons();
|
|
|
|
releasedButton = (_optionPanel.currentButton != NULL) && (_optionPanel.currentButton->state > 0) && (!_vm->mouseButtonPressed());
|
|
|
|
if (!_vm->mouseButtonPressed()) {
|
|
_optionPanel.zeroAllButtonState();
|
|
}
|
|
|
|
if (releasedButton) {
|
|
setOption(_optionPanel.currentButton);
|
|
}
|
|
}
|
|
|
|
|
|
void Interface::handleOptionClick(const Point& mousePoint) {
|
|
Rect rect;
|
|
_optionPanel.currentButton = optionHitTest(mousePoint);
|
|
|
|
validateOptionButtons();
|
|
|
|
_optionPanel.zeroAllButtonState();
|
|
|
|
if (_optionPanel.currentButton == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (_optionPanel.currentButton == _optionSaveFileSlider) {
|
|
if ((_optionSaveRectTop.height() > 0) && (mousePoint.y < _optionSaveRectTop.bottom)) {
|
|
_optionSaveFileTop -= _vm->getDisplayInfo().optionSaveFileVisible;
|
|
} else {
|
|
if ((_optionSaveRectBottom.height() > 0) && (mousePoint.y >= _optionSaveRectBottom.top)) {
|
|
_optionSaveFileTop += _vm->getDisplayInfo().optionSaveFileVisible;
|
|
} else {
|
|
if (_vm->getDisplayInfo().optionSaveFileVisible < _vm->getSaveFilesCount()) {
|
|
_optionSaveFileMouseOff = mousePoint.y - _optionSaveRectSlider.top;
|
|
_optionPanel.currentButton->state = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
_optionSaveFileTop = CLIP<uint>(_optionSaveFileTop, 0, _vm->getSaveFilesCount() - _vm->getDisplayInfo().optionSaveFileVisible);
|
|
calcOptionSaveSlider();
|
|
} else {
|
|
if (_optionPanel.currentButton == _optionSaveFilePanel) {
|
|
_optionPanel.calcPanelButtonRect(_optionSaveFilePanel, rect);
|
|
_optionSaveFileTitleNumber = (mousePoint.y - rect.top) / (_vm->_font->getHeight(kKnownFontSmall) + 1);
|
|
|
|
if (_optionSaveFileTitleNumber >= _vm->getDisplayInfo().optionSaveFileVisible) {
|
|
_optionSaveFileTitleNumber = _vm->getDisplayInfo().optionSaveFileVisible - 1;
|
|
}
|
|
_optionSaveFileTitleNumber += _optionSaveFileTop;
|
|
if (_optionSaveFileTitleNumber >= _vm->getSaveFilesCount()) {
|
|
_optionSaveFileTitleNumber = _vm->getSaveFilesCount() - 1;
|
|
}
|
|
} else {
|
|
_optionPanel.currentButton->state = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::handleChapterSelectionUpdate(const Point& mousePoint) {
|
|
uint16 objectId;
|
|
int hitZoneIndex;
|
|
const HitZone * hitZone;
|
|
|
|
// FIXME: Original handled more object types here.
|
|
|
|
objectId = _vm->_actor->hitTest(mousePoint, true);
|
|
|
|
if (objectId == ID_NOTHING) {
|
|
hitZoneIndex = _vm->_scene->_objectMap->hitTest(mousePoint);
|
|
|
|
if ((hitZoneIndex != -1)) {
|
|
hitZone = _vm->_scene->_objectMap->getHitZone(hitZoneIndex);
|
|
objectId = hitZone->getHitZoneId();
|
|
}
|
|
}
|
|
|
|
if (objectId != _vm->_script->_pointerObject) {
|
|
_vm->_script->_pointerObject = objectId;
|
|
}
|
|
}
|
|
|
|
void Interface::handleChapterSelectionClick(const Point& mousePoint) {
|
|
int obj = _vm->_script->_pointerObject;
|
|
|
|
_vm->_actor->abortSpeech();
|
|
|
|
if (obj) {
|
|
int script = 0;
|
|
HitZone *hitZone;
|
|
ActorData *a;
|
|
ObjectData *o;
|
|
Event event;
|
|
|
|
switch (objectTypeId(obj)) {
|
|
case kGameObjectHitZone:
|
|
hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(obj));
|
|
|
|
if (hitZone == NULL)
|
|
return;
|
|
|
|
if (hitZone->getFlags() & kHitZoneEnabled)
|
|
script = hitZone->getScriptNumber();
|
|
break;
|
|
|
|
case kGameObjectActor:
|
|
a = _vm->_actor->getActor(obj);
|
|
script = a->_scriptEntrypointNumber;
|
|
break;
|
|
|
|
case kGameObjectObject:
|
|
o = _vm->_actor->getObj(obj);
|
|
script = o->_scriptEntrypointNumber;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (script > 0) {
|
|
event.type = kEvTOneshot;
|
|
event.code = kScriptEvent;
|
|
event.op = kEventExecNonBlocking;
|
|
event.time = 0;
|
|
event.param = _vm->_scene->getScriptModuleNumber();
|
|
event.param2 = script;
|
|
event.param3 = _vm->_script->getVerbType(kVerbUse); // Action
|
|
event.param4 = obj; // Object
|
|
event.param5 = 0; // With Object
|
|
event.param6 = obj; // Actor
|
|
_vm->_events->queue(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::setOption(PanelButton *panelButton) {
|
|
_optionPanel.currentButton = NULL;
|
|
switch (panelButton->id) {
|
|
case kTextContinuePlaying:
|
|
ConfMan.flushToDisk();
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
setMode(kPanelMain);
|
|
} else {
|
|
if (_vm->_scene->currentChapterNumber() == 8) {
|
|
setMode(kPanelChapterSelection);
|
|
} else if (_vm->_scene->isNonInteractiveIHNMDemoPart()) {
|
|
setMode(kPanelNull);
|
|
} else {
|
|
setMode(kPanelMain);
|
|
}
|
|
}
|
|
break;
|
|
case kTextQuitGame:
|
|
setMode(kPanelQuit);
|
|
break;
|
|
case kTextLoad:
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
if (_vm->getSaveFilesCount() > 0) {
|
|
if (_vm->isSaveListFull() || (_optionSaveFileTitleNumber > 0)) {
|
|
debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
|
|
setMode(kPanelMain);
|
|
_vm->load(_vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber));
|
|
_vm->syncSoundSettings();
|
|
}
|
|
}
|
|
} else {
|
|
setMode(kPanelLoad);
|
|
}
|
|
break;
|
|
case kTextSave:
|
|
// Disallow saving in the non-interactive part of the IHNM demo (original demo didn't support saving at all)
|
|
if (_vm->_scene->isNonInteractiveIHNMDemoPart())
|
|
return;
|
|
|
|
if (!_vm->isSaveListFull() && (_optionSaveFileTitleNumber == 0)) {
|
|
_textInputString[0] = 0;
|
|
} else {
|
|
strcpy(_textInputString, _vm->getSaveFile(_optionSaveFileTitleNumber)->name);
|
|
}
|
|
setMode(kPanelSave);
|
|
break;
|
|
case kTextReadingSpeed:
|
|
if (_vm->getGameId() == GID_ITE && !(_vm->getFeatures() & GF_ITE_FLOPPY)) {
|
|
_vm->_subtitlesEnabled = !_vm->_subtitlesEnabled;
|
|
ConfMan.setBool("subtitles", _vm->_subtitlesEnabled);
|
|
} else {
|
|
_vm->_readingSpeed = (_vm->_readingSpeed + 1) % 4;
|
|
_vm->setTalkspeed(_vm->_readingSpeed);
|
|
}
|
|
break;
|
|
case kTextMusic:
|
|
_vm->_musicVolume = _vm->_musicVolume + 25;
|
|
if (_vm->_musicVolume > 255) _vm->_musicVolume = 0;
|
|
_vm->_music->setVolume(_vm->_musicVolume, 1);
|
|
ConfMan.setInt("music_volume", _vm->_musicVolume);
|
|
break;
|
|
case kTextSound:
|
|
_vm->_soundVolume = _vm->_soundVolume + 25;
|
|
if (_vm->_soundVolume > 255) _vm->_soundVolume = 0;
|
|
ConfMan.setInt("sfx_volume", _vm->_soundVolume);
|
|
_vm->_sound->setVolume();
|
|
break;
|
|
case kTextVoices:
|
|
if (_vm->_voiceFilesExist) {
|
|
if (_vm->_subtitlesEnabled && _vm->_voicesEnabled) { // Both
|
|
_vm->_subtitlesEnabled = false; // Set it to "Audio"
|
|
_vm->_voicesEnabled = true; // Not necessary, just for completeness
|
|
} else if (!_vm->_subtitlesEnabled && _vm->_voicesEnabled) {
|
|
_vm->_subtitlesEnabled = true; // Set it to "Text"
|
|
_vm->_voicesEnabled = false;
|
|
} else if (_vm->_subtitlesEnabled && !_vm->_voicesEnabled) {
|
|
_vm->_subtitlesEnabled = true; // Set it to "Both"
|
|
_vm->_voicesEnabled = true;
|
|
}
|
|
} else {
|
|
_vm->_subtitlesEnabled = true; // Set it to "Text"
|
|
_vm->_voicesEnabled = false;
|
|
}
|
|
|
|
_vm->_speechVolume = _vm->_speechVolume + 25;
|
|
if (_vm->_speechVolume > 255) _vm->_speechVolume = 0;
|
|
ConfMan.setInt("speech_volume", _vm->_speechVolume);
|
|
_vm->_sound->setVolume();
|
|
|
|
ConfMan.setBool("subtitles", _vm->_subtitlesEnabled);
|
|
ConfMan.setBool("voices", _vm->_voicesEnabled);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Interface::update(const Point& mousePoint, int updateFlag) {
|
|
|
|
if (!_active && _panelMode == kPanelNull && (updateFlag & UPDATE_MOUSECLICK))
|
|
_vm->_actor->abortSpeech();
|
|
|
|
if (_vm->_scene->isInIntro() || _fadeMode == kFadeOut || !_active) {
|
|
// When opening the psychic profile, or the options screen in the non-interactive part of the IHNM demo,
|
|
// the interface is locked (_active is false)
|
|
// Don't return in those cases, so that mouse actions can be processed
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
return;
|
|
} else {
|
|
if (_panelMode == kPanelPlacard && (updateFlag & UPDATE_MOUSECLICK)) {
|
|
// the psychic profile or the special screen in IHNM demo is open, don't return
|
|
} else if (_panelMode == kPanelOption || _panelMode == kPanelQuit) {
|
|
// options/quit panel is open, set interface to active and don't return
|
|
_vm->_actor->abortSpeech(); // abort any speech being played
|
|
_active = true;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_statusTextInput) {
|
|
return;
|
|
}
|
|
|
|
switch (_panelMode) {
|
|
case kPanelMain:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
bool lastWasPlayfield = _lastMousePoint.y < _vm->_scene->getHeight();
|
|
if (mousePoint.y < _vm->_scene->getHeight()) {
|
|
if (!lastWasPlayfield) {
|
|
handleMainUpdate(mousePoint);
|
|
}
|
|
_vm->_script->whichObject(mousePoint);
|
|
} else {
|
|
if (lastWasPlayfield) {
|
|
_vm->_script->setNonPlayfieldVerb();
|
|
}
|
|
handleMainUpdate(mousePoint);
|
|
}
|
|
|
|
} else {
|
|
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
if (mousePoint.y < _vm->_scene->getHeight()) {
|
|
_vm->_script->playfieldClick(mousePoint, (updateFlag & UPDATE_LEFTBUTTONCLICK) != 0);
|
|
} else {
|
|
handleMainClick(mousePoint);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelConverse:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
handleConverseUpdate(mousePoint);
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
handleConverseClick(mousePoint);
|
|
}
|
|
if (updateFlag & UPDATE_WHEELUP) {
|
|
converseChangePos(-1);
|
|
}
|
|
if (updateFlag & UPDATE_WHEELDOWN) {
|
|
converseChangePos(1);
|
|
}
|
|
|
|
if (_vm->_scene->isITEPuzzleScene()) {
|
|
_vm->_puzzle->handleClick(mousePoint);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelOption:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
handleOptionUpdate(mousePoint);
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
handleOptionClick(mousePoint);
|
|
}
|
|
if (updateFlag & UPDATE_WHEELUP) {
|
|
if (_optionSaveFileTop)
|
|
_optionSaveFileTop--;
|
|
calcOptionSaveSlider();
|
|
}
|
|
if (updateFlag & UPDATE_WHEELDOWN) {
|
|
if (_optionSaveFileTop < _vm->getSaveFilesCount() - _vm->getDisplayInfo().optionSaveFileVisible)
|
|
_optionSaveFileTop++;
|
|
calcOptionSaveSlider();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelQuit:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
handleQuitUpdate(mousePoint);
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
handleQuitClick(mousePoint);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelLoad:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
|
|
handleLoadUpdate(mousePoint);
|
|
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
handleLoadClick(mousePoint);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelSave:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
|
|
handleSaveUpdate(mousePoint);
|
|
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
handleSaveClick(mousePoint);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelMap:
|
|
if (updateFlag & UPDATE_MOUSECLICK)
|
|
mapPanelClean();
|
|
break;
|
|
|
|
case kPanelSceneSubstitute:
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
_vm->_render->clearFlag(RF_DEMO_SUBST);
|
|
_vm->_gfx->setPalette(_mapSavedPal);
|
|
setMode(kPanelMain);
|
|
_vm->_script->setNoPendingVerb();
|
|
}
|
|
break;
|
|
|
|
case kPanelChapterSelection:
|
|
if (updateFlag & UPDATE_MOUSEMOVE) {
|
|
handleChapterSelectionUpdate(mousePoint);
|
|
} else {
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
Rect rect;
|
|
rect.left = _vm->getDisplayInfo().saveReminderXOffset;
|
|
rect.top = _vm->getDisplayInfo().saveReminderYOffset;
|
|
|
|
rect.right = rect.left + _vm->getDisplayInfo().saveReminderWidth;
|
|
rect.bottom = rect.top + _vm->getDisplayInfo().saveReminderHeight;
|
|
if (rect.contains(mousePoint))
|
|
setMode(kPanelOption);
|
|
else
|
|
handleChapterSelectionClick(mousePoint);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kPanelProtect:
|
|
// No mouse interaction
|
|
break;
|
|
|
|
case kPanelPlacard:
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->getGameId() == GID_IHNM) {
|
|
// Any mouse click here returns the user back to the game
|
|
if (updateFlag & UPDATE_MOUSECLICK) {
|
|
if (!_vm->isIHNMDemo()) {
|
|
_vm->_scene->clearPsychicProfile();
|
|
_vm->_script->wakeUpThreads(kWaitTypeDelay);
|
|
} else {
|
|
setMode(kPanelConverse);
|
|
_vm->_scene->_textList.clear();
|
|
_vm->_script->wakeUpThreads(kWaitTypeDelay);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case kPanelNull:
|
|
#ifdef ENABLE_IHNM
|
|
if (_vm->_scene->isNonInteractiveIHNMDemoPart() && (updateFlag & UPDATE_MOUSECLICK))
|
|
_vm->_scene->showIHNMDemoSpecialScreen();
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_lastMousePoint = mousePoint;
|
|
}
|
|
|
|
void Interface::drawStatusBar() {
|
|
Rect rect;
|
|
Point textPoint;
|
|
int stringWidth;
|
|
int color;
|
|
// The default colors in the Spanish version of IHNM are shifted by one
|
|
// Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)". This
|
|
// also applies to the German and French versions (bug #7064 - "IHNM:
|
|
// text mistake in german version").
|
|
int offset = (_vm->getFeatures() & GF_IHNM_COLOR_FIX) ? 1 : 0;
|
|
|
|
// Disable the status text in IHNM when the chapter is 8
|
|
if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 8)
|
|
return;
|
|
|
|
// Don't draw the status bar while fading out
|
|
if (_fadeMode == kFadeOut)
|
|
return;
|
|
|
|
// Erase background of status bar
|
|
rect.left = _vm->getDisplayInfo().statusXOffset;
|
|
rect.top = _vm->getDisplayInfo().statusYOffset;
|
|
rect.right = rect.left + _vm->getDisplayInfo().width;
|
|
rect.bottom = rect.top + _vm->getDisplayInfo().statusHeight;
|
|
|
|
_vm->_gfx->drawRect(rect, _vm->getDisplayInfo().statusBGColor - offset);
|
|
|
|
stringWidth = _vm->_font->getStringWidth(kKnownFontSmall, _statusText, 0, kFontNormal);
|
|
|
|
if (_statusOnceColor == -1)
|
|
color = _vm->getDisplayInfo().statusTextColor - offset;
|
|
else
|
|
color = _statusOnceColor;
|
|
|
|
textPoint.x = _vm->getDisplayInfo().statusXOffset + (_vm->getDisplayInfo().statusWidth - stringWidth) / 2;
|
|
textPoint.y = _vm->getDisplayInfo().statusYOffset + _vm->getDisplayInfo().statusTextY;
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_font->textDraw(kKnownFontSmall, _statusText, textPoint, color, 0, kFontNormal);
|
|
else
|
|
_vm->_font->textDraw(kKnownFontVerb, _statusText, textPoint, color, 0, kFontNormal);
|
|
|
|
if (_saveReminderState > 0) {
|
|
rect.left = _vm->getDisplayInfo().saveReminderXOffset;
|
|
rect.top = _vm->getDisplayInfo().saveReminderYOffset;
|
|
|
|
rect.right = rect.left + _vm->getDisplayInfo().saveReminderWidth;
|
|
rect.bottom = rect.top + _vm->getDisplayInfo().saveReminderHeight;
|
|
_vm->_sprite->draw(_vm->_sprite->_saveReminderSprites,
|
|
_vm->getDisplayInfo().saveReminderFirstSpriteNumber + _saveReminderState - 1,
|
|
rect, 256);
|
|
|
|
}
|
|
}
|
|
|
|
void Interface::handleMainClick(const Point& mousePoint) {
|
|
|
|
PanelButton *panelButton;
|
|
|
|
panelButton = verbHitTest(mousePoint);
|
|
if (panelButton) {
|
|
_vm->_script->setVerb(panelButton->id);
|
|
return;
|
|
}
|
|
|
|
panelButton = _mainPanel.hitTest(mousePoint, kPanelAllButtons);
|
|
|
|
if (panelButton != NULL) {
|
|
if (panelButton->type == kPanelButtonArrow) {
|
|
panelButton->state = 1;
|
|
converseChangePos(panelButton->id);
|
|
}
|
|
|
|
if (panelButton->type == kPanelButtonInventory) {
|
|
if (_vm->_script->_pointerObject != ID_NOTHING) {
|
|
_vm->_script->hitObject(_vm->leftMouseButtonPressed());
|
|
}
|
|
if (_vm->_script->_pendingVerb) {
|
|
_vm->_actor->_protagonist->_currentAction = kActionWait;
|
|
_vm->_script->doVerb();
|
|
}
|
|
}
|
|
} else {
|
|
if (_saveReminderState > 0) {
|
|
Rect rect;
|
|
rect.left = _vm->getDisplayInfo().saveReminderXOffset;
|
|
rect.top = _vm->getDisplayInfo().saveReminderYOffset;
|
|
|
|
rect.right = rect.left + _vm->getDisplayInfo().saveReminderWidth;
|
|
rect.bottom = rect.top + _vm->getDisplayInfo().saveReminderHeight;
|
|
if (rect.contains(mousePoint)) {
|
|
setMode(kPanelOption);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::handleMainUpdate(const Point& mousePoint) {
|
|
PanelButton *panelButton;
|
|
|
|
panelButton = verbHitTest(mousePoint);
|
|
if (_mainPanel.currentButton != panelButton) {
|
|
if (_mainPanel.currentButton) {
|
|
if (_mainPanel.currentButton->type == kPanelButtonVerb) {
|
|
setVerbState(_mainPanel.currentButton->id, 0);
|
|
}
|
|
}
|
|
if (panelButton) {
|
|
setVerbState(panelButton->id, 1);
|
|
}
|
|
}
|
|
|
|
if (panelButton) {
|
|
_mainPanel.currentButton = panelButton;
|
|
return;
|
|
}
|
|
|
|
|
|
if (!_vm->mouseButtonPressed()) { // remove pressed flag
|
|
if (_inventoryUpButton) {
|
|
_inventoryUpButton->state = 0;
|
|
_inventoryDownButton->state = 0;
|
|
}
|
|
}
|
|
|
|
panelButton = _mainPanel.hitTest(mousePoint, kPanelAllButtons);
|
|
|
|
bool changed = false;
|
|
|
|
if ((panelButton != NULL) && (panelButton->type == kPanelButtonArrow)) {
|
|
if (panelButton->state == 1) {
|
|
inventoryChangePos(panelButton->id);
|
|
}
|
|
changed = true;
|
|
} else {
|
|
_vm->_script->whichObject(mousePoint);
|
|
}
|
|
|
|
changed = changed || (panelButton != _mainPanel.currentButton);
|
|
_mainPanel.currentButton = panelButton;
|
|
if (changed) {
|
|
draw();
|
|
}
|
|
}
|
|
|
|
//inventory stuff
|
|
void Interface::inventoryChangePos(int chg) {
|
|
// Arrows will scroll the inventory up or down up to 4 items
|
|
for (int i = 1; i <= 4; i++) {
|
|
if ((chg < 0 && _inventoryStart + chg >= 0) ||
|
|
(chg > 0 && _inventoryStart < _inventoryEnd)) {
|
|
_inventoryStart += chg;
|
|
}
|
|
}
|
|
draw();
|
|
}
|
|
|
|
void Interface::inventorySetPos(int key) {
|
|
_inventoryBox = key - '1';
|
|
_inventoryPos = _inventoryStart + _inventoryBox;
|
|
if (_inventoryPos >= _inventoryCount)
|
|
_inventoryPos = -1;
|
|
}
|
|
|
|
void Interface::updateInventory(int pos) {
|
|
int cols = _vm->getDisplayInfo().inventoryColumns;
|
|
if (pos >= _inventoryCount) {
|
|
pos = _inventoryCount - 1;
|
|
}
|
|
if (pos < 0) {
|
|
pos = 0;
|
|
}
|
|
_inventoryStart = (pos - cols) / cols * cols;
|
|
if (_inventoryStart < 0) {
|
|
_inventoryStart = 0;
|
|
}
|
|
|
|
_inventoryEnd = (_inventoryCount - 1 - cols) / cols * cols;
|
|
if (_inventoryEnd < 0) {
|
|
_inventoryEnd = 0;
|
|
}
|
|
}
|
|
|
|
void Interface::addToInventory(int objectId) {
|
|
if (uint(_inventoryCount) >= _inventory.size()) {
|
|
return;
|
|
}
|
|
|
|
for (int i = _inventoryCount; i > 0; i--) {
|
|
_inventory[i] = _inventory[i - 1];
|
|
}
|
|
|
|
_inventory[0] = objectId;
|
|
_inventoryCount++;
|
|
|
|
_inventoryPos = 0;
|
|
updateInventory(0);
|
|
draw();
|
|
}
|
|
|
|
void Interface::removeFromInventory(int objectId) {
|
|
int j = inventoryItemPosition(objectId);
|
|
if (j == -1) {
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
|
|
for (i = j; i < _inventoryCount - 1; i++) {
|
|
_inventory[i] = _inventory[i + 1];
|
|
}
|
|
|
|
--_inventoryCount;
|
|
_inventory[_inventoryCount] = 0;
|
|
updateInventory(j);
|
|
draw();
|
|
}
|
|
|
|
void Interface::clearInventory() {
|
|
for (int i = 0; i < _inventoryCount; i++)
|
|
_inventory[i] = 0;
|
|
|
|
_inventoryCount = 0;
|
|
updateInventory(0);
|
|
}
|
|
|
|
int Interface::inventoryItemPosition(int objectId) {
|
|
for (int i = 0; i < _inventoryCount; i++)
|
|
if (_inventory[i] == objectId)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
void Interface::drawInventory() {
|
|
if (!isInMainMode())
|
|
return;
|
|
|
|
Rect rect;
|
|
int ci = _inventoryStart;
|
|
ObjectData *obj;
|
|
|
|
if (_inventoryStart != 0) {
|
|
drawPanelButtonArrow(&_mainPanel, _inventoryUpButton);
|
|
}
|
|
if (_inventoryStart != _inventoryEnd) {
|
|
drawPanelButtonArrow(&_mainPanel, _inventoryDownButton);
|
|
}
|
|
|
|
for (int i = 0; i < _mainPanel.buttonsCount; i++) {
|
|
if (_mainPanel.buttons[i].type != kPanelButtonInventory) {
|
|
continue;
|
|
}
|
|
_mainPanel.calcPanelButtonRect(&_mainPanel.buttons[i], rect);
|
|
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_gfx->drawRect(rect, kITEColorDarkGrey);
|
|
else
|
|
_vm->_gfx->drawRect(rect, _vm->KnownColor2ColorId(kKnownColorBlack));
|
|
|
|
if (ci < _inventoryCount) {
|
|
obj = _vm->_actor->getObj(_inventory[ci]);
|
|
_vm->_sprite->draw(_vm->_sprite->_inventorySprites, obj->_spriteListResourceId, rect, 256);
|
|
}
|
|
|
|
ci++;
|
|
}
|
|
}
|
|
|
|
void Interface::setVerbState(int verb, int state) {
|
|
PanelButton * panelButton = getPanelButtonByVerbType(verb);
|
|
if (panelButton == NULL) return;
|
|
if (state == 2) {
|
|
state = (_mainPanel.currentButton == panelButton) ? 1 : 0;
|
|
}
|
|
panelButton->state = state;
|
|
draw();
|
|
}
|
|
|
|
void Interface::drawButtonBox(const Rect& rect, ButtonKind kind, bool down) {
|
|
byte cornerColor;
|
|
byte frameColor;
|
|
byte fillColor;
|
|
byte solidColor;
|
|
byte odl, our, idl, iur;
|
|
|
|
switch (kind) {
|
|
case kSlider:
|
|
cornerColor = 0x8b;
|
|
frameColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
fillColor = kITEColorLightBlue96;
|
|
odl = kITEColorDarkBlue8a;
|
|
our = kITEColorLightBlue92;
|
|
idl = 0x89;
|
|
iur = 0x94;
|
|
solidColor = down ? kITEColorLightBlue94 : kITEColorLightBlue96;
|
|
break;
|
|
case kEdit:
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
cornerColor = frameColor = fillColor = kITEColorLightBlue96;
|
|
our = kITEColorDarkBlue8a;
|
|
odl = kITEColorLightBlue94;
|
|
solidColor = down ? kITEColorBlue : kITEColorDarkGrey0C;
|
|
} else {
|
|
cornerColor = frameColor = fillColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
our = odl = solidColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
}
|
|
iur = 0x97;
|
|
idl = 0x95;
|
|
break;
|
|
default:
|
|
cornerColor = 0x8b;
|
|
frameColor = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
solidColor = fillColor = kITEColorLightBlue96;
|
|
odl = kITEColorDarkBlue8a;
|
|
our = kITEColorLightBlue94;
|
|
idl = 0x97;
|
|
iur = 0x95;
|
|
if (down) {
|
|
SWAP(odl, our);
|
|
SWAP(idl, iur);
|
|
}
|
|
break;
|
|
}
|
|
|
|
int x = rect.left;
|
|
int y = rect.top;
|
|
int w = rect.width();
|
|
int h = rect.height();
|
|
int xe = rect.right - 1;
|
|
int ye = rect.bottom - 1;
|
|
|
|
_vm->_gfx->setPixelColor(x, y, cornerColor);
|
|
_vm->_gfx->setPixelColor(x, ye, cornerColor);
|
|
_vm->_gfx->setPixelColor(xe, y, cornerColor);
|
|
_vm->_gfx->setPixelColor(xe, ye, cornerColor);
|
|
_vm->_gfx->hLine(x + 1, y, x + w - 2, frameColor);
|
|
_vm->_gfx->hLine(x + 1, ye, x + w - 2, frameColor);
|
|
_vm->_gfx->vLine(x, y + 1, y + h - 2, frameColor);
|
|
_vm->_gfx->vLine(xe, y + 1, y + h - 2, frameColor);
|
|
|
|
x++;
|
|
y++;
|
|
xe--;
|
|
ye--;
|
|
w -= 2;
|
|
h -= 2;
|
|
_vm->_gfx->vLine(x, y, y + h - 1, odl);
|
|
_vm->_gfx->hLine(x, ye, x + w - 1, odl);
|
|
_vm->_gfx->vLine(xe, y, y + h - 2, our);
|
|
_vm->_gfx->hLine(x + 1, y, x + 1 + w - 2, our);
|
|
|
|
x++;
|
|
y++;
|
|
xe--;
|
|
ye--;
|
|
w -= 2;
|
|
h -= 2;
|
|
_vm->_gfx->setPixelColor(x, y, fillColor);
|
|
_vm->_gfx->setPixelColor(xe, ye, fillColor);
|
|
_vm->_gfx->vLine(x, y + 1, y + 1 + h - 2, idl);
|
|
_vm->_gfx->hLine(x + 1, ye, x + 1 + w - 2, idl);
|
|
_vm->_gfx->vLine(xe, y, y + h - 2, iur);
|
|
_vm->_gfx->hLine(x + 1, y, x + 1 + w - 2, iur);
|
|
|
|
x++; y++;
|
|
w -= 2; h -= 2;
|
|
|
|
Common::Rect fill(x, y, x + w, y + h);
|
|
_vm->_gfx->fillRect(fill, solidColor);
|
|
_vm->_render->addDirtyRect(rect);
|
|
}
|
|
|
|
static const int readingSpeeds[] = { kTextClick, kTextSlow, kTextMid, kTextFast };
|
|
|
|
void Interface::drawPanelButtonText(InterfacePanel *panel, PanelButton *panelButton, int spritenum) {
|
|
const char *text;
|
|
int textId;
|
|
int textWidth;
|
|
int textHeight;
|
|
Point point;
|
|
Point texturePoint;
|
|
KnownColor textColor;
|
|
Rect rect;
|
|
int litButton = 0;
|
|
KnownColor textShadowKnownColor = kKnownColorVerbTextShadow;
|
|
KnownFont textFont = kKnownFontMedium;
|
|
|
|
textId = panelButton->id;
|
|
switch (panelButton->id) {
|
|
case kTextReadingSpeed:
|
|
if (_vm->getGameId() == GID_ITE && !(_vm->getFeatures() & GF_ITE_FLOPPY)) {
|
|
if (_vm->_subtitlesEnabled)
|
|
textId = kTextOn;
|
|
else
|
|
textId = kTextOff;
|
|
} else {
|
|
textId = readingSpeeds[_vm->_readingSpeed];
|
|
}
|
|
break;
|
|
case kTextMusic:
|
|
if (_vm->_musicVolume) {
|
|
textId = kText10Percent + _vm->_musicVolume / 25 - 1;
|
|
if (textId > kTextMax) {
|
|
textId = kTextMax;
|
|
}
|
|
}
|
|
else
|
|
textId = kTextOff;
|
|
break;
|
|
case kTextSound:
|
|
if (_vm->_soundVolume) {
|
|
textId = kText10Percent + _vm->_soundVolume / 25 - 1;
|
|
if (textId > kTextMax) {
|
|
textId = kTextMax;
|
|
}
|
|
}
|
|
else
|
|
textId = kTextOff;
|
|
break;
|
|
case kTextVoices:
|
|
if (_vm->_subtitlesEnabled && _vm->_voicesEnabled)
|
|
textId = kTextBoth;
|
|
else if (_vm->_subtitlesEnabled && !_vm->_voicesEnabled)
|
|
textId = kTextText;
|
|
else if (!_vm->_subtitlesEnabled && _vm->_voicesEnabled)
|
|
textId = kTextAudio;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
if (textId > kTextEnterProtectAnswer)
|
|
error("This should not happen. Please report to ScummVM Team how you achieved this error.");
|
|
|
|
text = _vm->getTextString(textId);
|
|
textFont = kKnownFontMedium;
|
|
textShadowKnownColor = kKnownColorVerbTextShadow;
|
|
textWidth = _vm->_font->getStringWidth(kKnownFontMedium, text, 0, kFontNormal);
|
|
textHeight = _vm->_font->getHeight(kKnownFontMedium);
|
|
} else {
|
|
if (textId < 39 || textId > 50) {
|
|
// Read non-hardcoded strings from the LUT string table, loaded from the game
|
|
// data files
|
|
text = _vm->_script->_mainStrings.getString(IHNMTextStringIdsLUT[textId]);
|
|
} else {
|
|
// Hardcoded strings in IHNM are read from the ITE hardcoded strings
|
|
text = _vm->getTextString(textId);
|
|
}
|
|
|
|
textFont = kKnownFontVerb;
|
|
textShadowKnownColor = kKnownColorTransparent;
|
|
textWidth = _vm->_font->getStringWidth(kKnownFontVerb, text, 0, kFontNormal);
|
|
textHeight = _vm->_font->getHeight(kKnownFontVerb);
|
|
}
|
|
|
|
point.x = panel->x + panelButton->xOffset + (panelButton->width / 2) - (textWidth / 2);
|
|
point.y = panel->y + panelButton->yOffset + (panelButton->height / 2) - (textHeight / 2);
|
|
|
|
if (panelButton == panel->currentButton) {
|
|
textColor = kKnownColorVerbTextActive;
|
|
} else {
|
|
textColor = kKnownColorVerbText;
|
|
}
|
|
|
|
panel->calcPanelButtonRect(panelButton, rect);
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
drawButtonBox(rect, kButton, panelButton->state > 0);
|
|
} else {
|
|
litButton = panelButton->state > 0;
|
|
|
|
if (panel == &_optionPanel) {
|
|
texturePoint.x = _optionPanel.x + panelButton->xOffset - 1;
|
|
texturePoint.y = _optionPanel.y + panelButton->yOffset - 1;
|
|
_vm->_sprite->draw(_optionPanel.sprites, spritenum + 2 + litButton, texturePoint, 256);
|
|
} else if (panel == &_quitPanel) {
|
|
texturePoint.x = _quitPanel.x + panelButton->xOffset - 3;
|
|
texturePoint.y = _quitPanel.y + panelButton->yOffset - 3;
|
|
_vm->_sprite->draw(_quitPanel.sprites, litButton, texturePoint, 256);
|
|
} else if (panel == &_savePanel) {
|
|
texturePoint.x = _savePanel.x + panelButton->xOffset - 3;
|
|
texturePoint.y = _savePanel.y + panelButton->yOffset - 3;
|
|
_vm->_sprite->draw(_savePanel.sprites, litButton, texturePoint, 256);
|
|
// Input text box sprite
|
|
texturePoint.x = _savePanel.x + _saveEdit->xOffset - 2;
|
|
texturePoint.y = _savePanel.y + _saveEdit->yOffset - 2;
|
|
_vm->_sprite->draw(_savePanel.sprites, 2, texturePoint, 256);
|
|
} else if (panel == &_loadPanel) {
|
|
texturePoint.x = _loadPanel.x + panelButton->xOffset - 3;
|
|
texturePoint.y = _loadPanel.y + panelButton->yOffset - 3;
|
|
_vm->_sprite->draw(_loadPanel.sprites, litButton, texturePoint, 256);
|
|
} else {
|
|
// revert to default behavior
|
|
drawButtonBox(rect, kButton, panelButton->state > 0);
|
|
}
|
|
}
|
|
|
|
_vm->_font->textDraw(textFont, text, point,
|
|
_vm->KnownColor2ColorId(textColor), _vm->KnownColor2ColorId(textShadowKnownColor), _vm->getPlatform() == Common::kPlatformPC98 ? kFontOutline : kFontShadow);
|
|
}
|
|
|
|
void Interface::drawPanelButtonArrow(InterfacePanel *panel, PanelButton *panelButton) {
|
|
Point point;
|
|
int spriteNumber;
|
|
|
|
if (panel->currentButton == panelButton) {
|
|
if (panelButton->state != 0) {
|
|
spriteNumber = panelButton->downSpriteNumber;
|
|
} else {
|
|
spriteNumber = panelButton->overSpriteNumber;
|
|
}
|
|
} else {
|
|
spriteNumber = panelButton->upSpriteNumber;
|
|
}
|
|
|
|
point.x = panel->x + panelButton->xOffset;
|
|
point.y = panel->y + panelButton->yOffset;
|
|
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_sprite->draw(_vm->_sprite->_mainSprites, spriteNumber, point, 256);
|
|
else
|
|
_vm->_sprite->draw(_vm->_sprite->_arrowSprites, spriteNumber, point, 256);
|
|
}
|
|
|
|
void Interface::drawVerbPanelText(PanelButton *panelButton, KnownColor textKnownColor, KnownColor textShadowKnownColor) {
|
|
const char *text;
|
|
int textWidth;
|
|
Point point;
|
|
int textId;
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
textId = verbToTextIdITE[panelButton->id - 1];
|
|
text = _vm->getTextString(textId);
|
|
} else {
|
|
textId = panelButton->id;
|
|
text = _vm->_script->_mainStrings.getString(textId + 1);
|
|
textShadowKnownColor = kKnownColorTransparent;
|
|
}
|
|
|
|
textWidth = _vm->_font->getStringWidth(kKnownFontVerb, text, 0, kFontNormal);
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
point.x = _mainPanel.x + panelButton->xOffset + 1 + (panelButton->width - 1 - textWidth) / 2;
|
|
point.y = _mainPanel.y + panelButton->yOffset + 1;
|
|
} else {
|
|
point.x = _mainPanel.x + panelButton->xOffset + 1 + (panelButton->width - textWidth) / 2;
|
|
point.y = _mainPanel.y + panelButton->yOffset + 12;
|
|
}
|
|
|
|
_vm->_font->textDraw(kKnownFontVerb, text, point,
|
|
_vm->KnownColor2ColorId(textKnownColor), _vm->KnownColor2ColorId(textShadowKnownColor),
|
|
(textShadowKnownColor != kKnownColorTransparent) ? (_vm->getPlatform() == Common::kPlatformPC98 ? kFontOutline : kFontShadow) : kFontNormal);
|
|
}
|
|
|
|
|
|
// Converse stuff
|
|
void Interface::converseClear() {
|
|
for (int i = 0; i < CONVERSE_MAX_TEXTS; i++) {
|
|
_converseText[i].text.clear();
|
|
_converseText[i].stringNum = -1;
|
|
_converseText[i].replyId = 0;
|
|
_converseText[i].replyFlags = 0;
|
|
_converseText[i].replyBit = 0;
|
|
}
|
|
|
|
_converseTextCount = 0;
|
|
_converseStrCount = 0;
|
|
_converseStartPos = 0;
|
|
_converseEndPos = 0;
|
|
_conversePos = -1;
|
|
}
|
|
|
|
bool Interface::converseAddText(const char *text, int strId, int replyId, byte replyFlags, int replyBit) {
|
|
int count = 0; // count how many pieces of text per string
|
|
int i;
|
|
int len;
|
|
byte c;
|
|
|
|
assert(strlen(text) < CONVERSE_MAX_WORK_STRING);
|
|
|
|
Common::strlcpy(_converseWorkString, text, CONVERSE_MAX_WORK_STRING);
|
|
|
|
while (1) {
|
|
len = strlen(_converseWorkString);
|
|
|
|
for (i = len; i >= 0; i--) {
|
|
c = _converseWorkString[i];
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
if ((c == ' ' || c == '\0') && (_vm->_font->getStringWidth(kKnownFontSmall, _converseWorkString, i, kFontNormal) <= _vm->getDisplayInfo().converseMaxTextWidth))
|
|
break;
|
|
} else {
|
|
if ((c == ' ' || c == '\0') && (_vm->_font->getStringWidth(kKnownFontVerb, _converseWorkString, i, kFontNormal) <= _vm->getDisplayInfo().converseMaxTextWidth))
|
|
break;
|
|
}
|
|
}
|
|
if (i < 0) {
|
|
return true;
|
|
}
|
|
|
|
if (_converseTextCount == CONVERSE_MAX_TEXTS) {
|
|
return true;
|
|
}
|
|
|
|
_converseText[_converseTextCount].text.resize(i + 1);
|
|
strncpy(&_converseText[_converseTextCount].text.front(), _converseWorkString, i);
|
|
|
|
_converseText[_converseTextCount].strId = strId;
|
|
_converseText[_converseTextCount].text[i] = 0;
|
|
_converseText[_converseTextCount].textNum = count;
|
|
_converseText[_converseTextCount].stringNum = _converseStrCount;
|
|
_converseText[_converseTextCount].replyId = replyId;
|
|
_converseText[_converseTextCount].replyFlags = replyFlags;
|
|
_converseText[_converseTextCount].replyBit = replyBit;
|
|
|
|
_converseTextCount++;
|
|
count++;
|
|
|
|
if (len == i)
|
|
break;
|
|
|
|
strncpy(_converseWorkString, &_converseWorkString[i + 1], len - i);
|
|
}
|
|
|
|
_converseStrCount++;
|
|
|
|
return false;
|
|
}
|
|
|
|
void Interface::converseDisplayText() {
|
|
int end;
|
|
|
|
_converseStartPos = 0;
|
|
|
|
end = _converseTextCount - _vm->getDisplayInfo().converseTextLines;
|
|
|
|
if (end < 0)
|
|
end = 0;
|
|
|
|
_converseEndPos = end;
|
|
draw();
|
|
}
|
|
|
|
|
|
void Interface::converseSetTextLines(int row) {
|
|
int pos = row + _converseStartPos;
|
|
if (pos >= _converseTextCount)
|
|
pos = -1;
|
|
if (pos != _conversePos) {
|
|
_conversePos = pos;
|
|
draw();
|
|
}
|
|
}
|
|
|
|
void Interface::converseDisplayTextLines() {
|
|
int relPos;
|
|
byte foregnd;
|
|
byte backgnd;
|
|
byte bulletForegnd;
|
|
byte bulletBackgnd;
|
|
const char *str;
|
|
static const char bulletStr[3][3] = {
|
|
"\xb7", "\x81\x45", ">"
|
|
};
|
|
const char *bullet = (_vm->getGameId() == GID_ITE) ? (_vm->getPlatform() == Common::kPlatformPC98 ? bulletStr[1] : bulletStr[0]) : bulletStr[2];
|
|
|
|
assert(_conversePanel.buttonsCount >= 6);
|
|
Rect rect(8, _vm->getDisplayInfo().converseTextLines * _vm->getDisplayInfo().converseTextHeight);
|
|
rect.moveTo(_conversePanel.x + _conversePanel.buttons[0].xOffset, _conversePanel.y + _conversePanel.buttons[0].yOffset);
|
|
|
|
Point textPoint;
|
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
bulletForegnd = kITEColorGreen;
|
|
bulletBackgnd = kITEColorBlack;
|
|
} else {
|
|
bulletForegnd = _vm->KnownColor2ColorId(kKnownColorBrightWhite);
|
|
bulletBackgnd = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
}
|
|
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_gfx->drawRect(rect, kITEColorDarkGrey); // fill bullet place
|
|
else if (_vm->getGameId() == GID_IHNM)
|
|
// TODO: Add these to IHNM_DisplayInfo?
|
|
_vm->_gfx->drawRect(Common::Rect(118, 345, 603, 463), _vm->KnownColor2ColorId(kKnownColorBlack)); // fill converse rect
|
|
|
|
for (int i = 0; i < _vm->getDisplayInfo().converseTextLines; i++) {
|
|
relPos = _converseStartPos + i;
|
|
|
|
if (_converseTextCount <= relPos) {
|
|
break;
|
|
}
|
|
|
|
if (_conversePos >= 0 && _converseText[_conversePos].stringNum == _converseText[relPos].stringNum) {
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
foregnd = kITEColorBrightWhite;
|
|
backgnd = (!_vm->leftMouseButtonPressed()) ? kITEColorDarkGrey : kITEColorGrey;
|
|
} else {
|
|
foregnd = _vm->KnownColor2ColorId(kKnownColorVerbTextActive);
|
|
backgnd = _vm->KnownColor2ColorId(kKnownColorVerbTextActive);
|
|
}
|
|
} else {
|
|
if (_vm->getGameId() == GID_ITE) {
|
|
foregnd = kITEColorBlue;
|
|
backgnd = kITEColorDarkGrey;
|
|
} else {
|
|
foregnd = _vm->KnownColor2ColorId(kKnownColorBrightWhite);
|
|
backgnd = _vm->KnownColor2ColorId(kKnownColorBlack);
|
|
}
|
|
}
|
|
|
|
_conversePanel.calcPanelButtonRect(&_conversePanel.buttons[i], rect);
|
|
rect.left += 8;
|
|
_vm->_gfx->drawRect(rect, backgnd);
|
|
|
|
str = &_converseText[relPos].text.front();
|
|
|
|
if (_converseText[relPos].textNum == 0) { // first entry
|
|
textPoint.x = rect.left - 6;
|
|
textPoint.y = rect.top;
|
|
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_font->textDraw(kKnownFontSmall, bullet, textPoint, bulletForegnd, bulletBackgnd, _vm->getPlatform() == Common::kPlatformPC98 ? kFontNormal : (FontEffectFlags)(kFontShadow | kFontDontmap));
|
|
else
|
|
_vm->_font->textDraw(kKnownFontVerb, bullet, textPoint, bulletForegnd, bulletBackgnd, (FontEffectFlags)(kFontShadow | kFontDontmap));
|
|
}
|
|
textPoint.x = rect.left + 1;
|
|
textPoint.y = rect.top;
|
|
if (_vm->getGameId() == GID_ITE)
|
|
_vm->_font->textDraw(kKnownFontSmall, str, textPoint, foregnd, kITEColorBlack, _vm->getPlatform() == Common::kPlatformPC98 ? kFontNormal : kFontShadow);
|
|
else
|
|
_vm->_font->textDraw(kKnownFontVerb, str, textPoint, foregnd, _vm->KnownColor2ColorId(kKnownColorBlack), kFontShadow);
|
|
}
|
|
|
|
if (_converseStartPos != 0) {
|
|
drawPanelButtonArrow(&_conversePanel, _converseUpButton);
|
|
}
|
|
|
|
if (_converseStartPos != _converseEndPos) {
|
|
drawPanelButtonArrow(&_conversePanel, _converseDownButton);
|
|
}
|
|
}
|
|
|
|
void Interface::converseChangePos(int chg) {
|
|
// Arrows will scroll the converse panel or down up to 4 conversation options
|
|
for (int i = 1; i <= 4; i++) {
|
|
if ((chg < 0 && _converseStartPos + chg >= 0) ||
|
|
(chg > 0 && _converseStartPos < _converseEndPos)) {
|
|
_converseStartPos += chg;
|
|
}
|
|
}
|
|
draw();
|
|
}
|
|
|
|
void Interface::converseSetPos(int key) {
|
|
Converse *ct;
|
|
int selection = key - '1';
|
|
|
|
if (selection >= _converseTextCount)
|
|
return;
|
|
|
|
converseSetTextLines(selection);
|
|
|
|
ct = &_converseText[_conversePos];
|
|
|
|
_vm->_script->finishDialog(ct->strId, ct->replyId, ct->replyFlags, ct->replyBit);
|
|
|
|
if (_vm->_scene->isITEPuzzleScene())
|
|
_vm->_puzzle->handleReply(ct->replyId);
|
|
|
|
_conversePos = -1;
|
|
}
|
|
|
|
|
|
void Interface::handleConverseUpdate(const Point& mousePoint) {
|
|
bool changed;
|
|
|
|
PanelButton *last = _conversePanel.currentButton;
|
|
|
|
if (!_vm->mouseButtonPressed()) { // remove pressed flag
|
|
if (_converseUpButton) {
|
|
_converseUpButton->state = 0;
|
|
_converseDownButton->state = 0;
|
|
}
|
|
}
|
|
|
|
_conversePanel.currentButton = converseHitTest(mousePoint);
|
|
changed = last != _conversePanel.currentButton;
|
|
|
|
|
|
if (_conversePanel.currentButton == NULL) {
|
|
_conversePos = -1;
|
|
if (changed) {
|
|
draw();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (_conversePanel.currentButton->type == kPanelButtonConverseText) {
|
|
converseSetTextLines(_conversePanel.currentButton->id);
|
|
}
|
|
|
|
if (_conversePanel.currentButton->type == kPanelButtonArrow) {
|
|
if (_conversePanel.currentButton->state == 1) {
|
|
converseChangePos(_conversePanel.currentButton->id);
|
|
}
|
|
draw();
|
|
}
|
|
}
|
|
|
|
|
|
void Interface::handleConverseClick(const Point& mousePoint) {
|
|
_conversePanel.currentButton = converseHitTest(mousePoint);
|
|
|
|
if (_conversePanel.currentButton == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (_conversePanel.currentButton->type == kPanelButtonConverseText) {
|
|
converseSetPos(_conversePanel.currentButton->ascii);
|
|
}
|
|
|
|
if (_conversePanel.currentButton->type == kPanelButtonArrow) {
|
|
_conversePanel.currentButton->state = 1;
|
|
converseChangePos(_conversePanel.currentButton->id);
|
|
}
|
|
|
|
}
|
|
|
|
void Interface::saveState(Common::OutSaveFile *out) {
|
|
out->writeUint16LE(_inventoryCount);
|
|
|
|
for (int i = 0; i < _inventoryCount; i++) {
|
|
out->writeUint16LE(_inventory[i]);
|
|
}
|
|
}
|
|
|
|
void Interface::loadState(Common::InSaveFile *in) {
|
|
_inventoryCount = in->readUint16LE();
|
|
|
|
for (int i = 0; i < _inventoryCount; i++) {
|
|
_inventory[i] = in->readUint16LE();
|
|
}
|
|
|
|
updateInventory(0);
|
|
}
|
|
|
|
void Interface::mapPanelShow() {
|
|
int i;
|
|
ByteArray resourceData;
|
|
Rect rect;
|
|
ByteArray image;
|
|
int imageWidth, imageHeight;
|
|
const byte *pal;
|
|
PalEntry cPal[PAL_ENTRIES];
|
|
|
|
_vm->_gfx->showCursor(false);
|
|
|
|
rect.left = rect.top = 0;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, _vm->_resource->convertResourceId(RID_ITE_TYCHO_MAP), resourceData);
|
|
if (resourceData.empty()) {
|
|
error("Interface::mapPanelShow() unable to load Tycho map resource");
|
|
}
|
|
|
|
_vm->_gfx->getCurrentPal(_mapSavedPal);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
_vm->_gfx->palToBlack(_mapSavedPal, 0.2 * i);
|
|
_vm->_render->drawScene();
|
|
_vm->_system->delayMillis(5);
|
|
}
|
|
|
|
_vm->_render->setFlag(RF_MAP);
|
|
|
|
_vm->decodeBGImage(resourceData, image, &imageWidth, &imageHeight);
|
|
pal = _vm->getImagePal(resourceData);
|
|
|
|
for (i = 0; i < PAL_ENTRIES; i++) {
|
|
cPal[i].red = *pal++;
|
|
cPal[i].green = *pal++;
|
|
cPal[i].blue = *pal++;
|
|
}
|
|
|
|
rect.setWidth(imageWidth);
|
|
rect.setHeight(imageHeight);
|
|
|
|
_vm->_gfx->drawRegion(rect, image.getBuffer());
|
|
|
|
// Evil Evil
|
|
for (i = 0; i < 6; i++) {
|
|
_vm->_gfx->blackToPal(cPal, 0.2 * i);
|
|
_vm->_render->drawScene();
|
|
_vm->_system->delayMillis(5);
|
|
}
|
|
|
|
|
|
setSaveReminderState(false);
|
|
|
|
_mapPanelCrossHairState = true;
|
|
}
|
|
|
|
void Interface::mapPanelClean() {
|
|
PalEntry pal[PAL_ENTRIES];
|
|
int i;
|
|
|
|
_vm->_gfx->getCurrentPal(pal);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
_vm->_gfx->palToBlack(pal, 0.2 * i);
|
|
_vm->_render->drawScene();
|
|
_vm->_system->delayMillis(5);
|
|
}
|
|
|
|
_vm->_render->clearFlag(RF_MAP);
|
|
setMode(kPanelMain);
|
|
|
|
_vm->_gfx->showCursor(true);
|
|
_vm->_render->drawScene();
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
_vm->_gfx->blackToPal(_mapSavedPal, 0.2 * i);
|
|
_vm->_render->drawScene();
|
|
_vm->_system->delayMillis(5);
|
|
}
|
|
}
|
|
|
|
void Interface::mapPanelDrawCrossHair() {
|
|
_mapPanelCrossHairState = !_mapPanelCrossHairState;
|
|
|
|
Point mapPosition = _vm->_isoMap->getMapPosition();
|
|
Rect screen(_vm->getDisplayInfo().width, _vm->_scene->getHeight());
|
|
|
|
if (screen.contains(mapPosition)) {
|
|
_vm->_sprite->draw(_vm->_sprite->_mainSprites,
|
|
_mapPanelCrossHairState ? RID_ITE_SPR_CROSSHAIR : RID_ITE_SPR_CROSSHAIR + 1,
|
|
mapPosition, 256);
|
|
}
|
|
}
|
|
|
|
void Interface::keyBoss() {
|
|
if (_vm->getGameId() == GID_ITE)
|
|
return;
|
|
|
|
if (_bossMode != -1 || _fadeMode != kNoFade)
|
|
return;
|
|
|
|
_vm->_sound->pauseVoice();
|
|
_vm->_sound->pauseSound();
|
|
_vm->_music->pause();
|
|
|
|
int i;
|
|
ByteArray resourceData;
|
|
Rect rect;
|
|
ByteArray image;
|
|
int imageWidth, imageHeight;
|
|
//const byte *pal;
|
|
PalEntry cPal[PAL_ENTRIES];
|
|
|
|
_vm->_gfx->showCursor(false);
|
|
|
|
rect.left = rect.top = 0;
|
|
|
|
_vm->_resource->loadResource(_interfaceContext, RID_IHNM_BOSS_SCREEN, resourceData);
|
|
if (resourceData.empty()) {
|
|
error("Interface::bossKey() unable to load Boss image resource");
|
|
}
|
|
|
|
_bossMode = _panelMode;
|
|
setMode(kPanelBoss);
|
|
|
|
_vm->decodeBGImage(resourceData, image, &imageWidth, &imageHeight);
|
|
rect.setWidth(imageWidth);
|
|
rect.setHeight(imageHeight);
|
|
|
|
_vm->_gfx->getCurrentPal(_mapSavedPal);
|
|
//pal = _vm->getImagePal(resourceData);
|
|
|
|
cPal[0].red = 0;
|
|
cPal[0].green = 0;
|
|
cPal[0].blue = 0;
|
|
|
|
for (i = 1; i < PAL_ENTRIES; i++) {
|
|
cPal[i].red = 128;
|
|
cPal[i].green = 128;
|
|
cPal[i].blue = 128;
|
|
}
|
|
|
|
_vm->_gfx->drawRegion(rect, image.getBuffer());
|
|
|
|
_vm->_gfx->setPalette(cPal);
|
|
}
|
|
|
|
|
|
void Interface::keyBossExit() {
|
|
PalEntry pal[PAL_ENTRIES];
|
|
|
|
_vm->_sound->resumeVoice();
|
|
_vm->_sound->resumeSound();
|
|
_vm->_music->resume();
|
|
|
|
_vm->_gfx->getCurrentPal(pal);
|
|
|
|
_vm->_gfx->palToBlack(pal, 1);
|
|
setMode(_bossMode);
|
|
|
|
_vm->_render->drawScene();
|
|
|
|
_vm->_gfx->blackToPal(_mapSavedPal, 1);
|
|
|
|
_vm->_gfx->showCursor(true);
|
|
|
|
_bossMode = -1;
|
|
}
|
|
|
|
|
|
} // End of namespace Saga
|