1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 // Game interface module
27 #include "saga/saga.h"
30 #include "saga/actor.h"
31 #include "saga/console.h"
32 #include "saga/displayinfo.h"
33 #include "saga/events.h"
34 #include "saga/font.h"
35 #include "saga/objectmap.h"
36 #include "saga/isomap.h"
37 #include "saga/itedata.h"
38 #include "saga/music.h"
39 #include "saga/puzzle.h"
40 #include "saga/render.h"
41 #include "saga/scene.h"
42 #include "saga/script.h"
43 #include "saga/sound.h"
44 #include "saga/sprite.h"
45 #include "saga/resource.h"
47 #include "saga/interface.h"
49 #include "common/config-manager.h"
50 #include "common/system.h"
51 #include "common/timer.h"
55 static const int verbToTextIdITE
[] = {
56 kTextWalkTo
, kTextLookAt
, kTextPickUp
, kTextTalkTo
,
57 kTextOpen
, kTextClose
, kTextUse
, kTextGive
60 // This maps the internally used string ITE IDs to the LUT strings loaded in IHNM
61 // i.e. id 12 (quit game button) maps to string 14 (Quit game)
62 // The comments are what the actual IHNM string is
63 // For the text string IDs, refer to saga.h, enum TextStringIds
64 static const int IHNMTextStringIdsLUT
[56] = {
82 15, // Continue Playing
123 #define buttonRes0 0x42544E00
124 #define buttonRes1 0x42544E01
126 Interface::Interface(SagaEngine
*vm
) : _vm(vm
) {
128 size_t resourceLength
;
132 // FTA2 related test code
134 // TODO: this will probably have to be moved to a new class
135 // It's left here for now till the code differences are figured out
136 if (_vm
->getGameId() == GID_FTA2
) {
137 _interfaceContext
= _vm
->_resource
->getContext(GAME_IMAGEFILE
);
138 _vm
->_resource
->loadResource(_interfaceContext
, 22, resource
, resourceLength
); // Julian's portrait
140 _vm
->decodeBGImage(resource
, resourceLength
, &_mainPanel
.image
,
141 &_mainPanel
.imageLength
, &_mainPanel
.imageWidth
, &_mainPanel
.imageHeight
);
148 // Load interface module resource file context
149 _interfaceContext
= _vm
->_resource
->getContext(GAME_RESOURCEFILE
);
150 if (_interfaceContext
== NULL
) {
151 error("Interface::Interface() resource context not found");
154 // Do nothing for SAGA2 games for now
155 if (_vm
->isSaga2()) {
160 _mainPanel
.buttons
= _vm
->getDisplayInfo().mainPanelButtons
;
161 _mainPanel
.buttonsCount
= _vm
->getDisplayInfo().mainPanelButtonsCount
;
163 for (i
= 0; i
< kVerbTypeIdsMax
; i
++) {
164 _verbTypeToPanelButton
[i
] = NULL
;
167 for (i
= 0; i
< _mainPanel
.buttonsCount
; i
++) {
168 if (_mainPanel
.buttons
[i
].type
== kPanelButtonVerb
) {
169 _verbTypeToPanelButton
[_mainPanel
.buttons
[i
].id
] = &_mainPanel
.buttons
[i
];
173 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->mainPanelResourceId
, resource
, resourceLength
);
174 _vm
->decodeBGImage(resource
, resourceLength
, &_mainPanel
.image
,
175 &_mainPanel
.imageLength
, &_mainPanel
.imageWidth
, &_mainPanel
.imageHeight
);
180 _conversePanel
.buttons
= _vm
->getDisplayInfo().conversePanelButtons
;
181 _conversePanel
.buttonsCount
= _vm
->getDisplayInfo().conversePanelButtonsCount
;
183 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->conversePanelResourceId
, resource
, resourceLength
);
184 _vm
->decodeBGImage(resource
, resourceLength
, &_conversePanel
.image
,
185 &_conversePanel
.imageLength
, &_conversePanel
.imageWidth
, &_conversePanel
.imageHeight
);
189 if (!(_vm
->getFeatures() & GF_NON_INTERACTIVE
)) {
190 _optionPanel
.buttons
= _vm
->getDisplayInfo().optionPanelButtons
;
191 _optionPanel
.buttonsCount
= _vm
->getDisplayInfo().optionPanelButtonsCount
;
193 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->optionPanelResourceId
, resource
, resourceLength
);
194 _vm
->decodeBGImage(resource
, resourceLength
, &_optionPanel
.image
,
195 &_optionPanel
.imageLength
, &_optionPanel
.imageWidth
, &_optionPanel
.imageHeight
);
198 _optionPanel
.buttons
= NULL
;
199 _optionPanel
.buttonsCount
= 0;
200 _optionPanel
.sprites
.spriteCount
= 0;
205 if (_vm
->getGameId() == GID_IHNM
) {
206 _quitPanel
.buttons
= _vm
->getDisplayInfo().quitPanelButtons
;
207 _quitPanel
.buttonsCount
= _vm
->getDisplayInfo().quitPanelButtonsCount
;
209 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->warningPanelResourceId
, resource
, resourceLength
);
210 _vm
->decodeBGImage(resource
, resourceLength
, &_quitPanel
.image
,
211 &_quitPanel
.imageLength
, &_quitPanel
.imageWidth
, &_quitPanel
.imageHeight
);
216 if (_vm
->getGameId() == GID_IHNM
) {
217 _savePanel
.buttons
= _vm
->getDisplayInfo().savePanelButtons
;
218 _savePanel
.buttonsCount
= _vm
->getDisplayInfo().savePanelButtonsCount
;
220 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->warningPanelResourceId
, resource
, resourceLength
);
221 _vm
->decodeBGImage(resource
, resourceLength
, &_savePanel
.image
,
222 &_savePanel
.imageLength
, &_savePanel
.imageWidth
, &_savePanel
.imageHeight
);
227 if (_vm
->getGameId() == GID_IHNM
) {
228 _loadPanel
.buttons
= _vm
->getDisplayInfo().loadPanelButtons
;
229 _loadPanel
.buttonsCount
= _vm
->getDisplayInfo().loadPanelButtonsCount
;
231 _vm
->_resource
->loadResource(_interfaceContext
, _vm
->getResourceDescription()->warningPanelResourceId
, resource
, resourceLength
);
232 _vm
->decodeBGImage(resource
, resourceLength
, &_loadPanel
.image
,
233 &_loadPanel
.imageLength
, &_loadPanel
.imageWidth
, &_loadPanel
.imageHeight
);
238 // Main panel sprites
239 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->mainPanelSpritesResourceId
, _mainPanel
.sprites
);
240 if (!(_vm
->getFeatures() & GF_NON_INTERACTIVE
)) {
241 // Option panel sprites
242 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->optionPanelSpritesResourceId
, _optionPanel
.sprites
);
243 // Save panel sprites
244 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->warningPanelSpritesResourceId
, _savePanel
.sprites
);
245 // Load panel sprites
246 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->warningPanelSpritesResourceId
, _loadPanel
.sprites
);
247 // Quit panel sprites
248 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->warningPanelSpritesResourceId
, _quitPanel
.sprites
);
251 if (_vm
->getGameId() == GID_ITE
) {
252 _vm
->_sprite
->loadList(_vm
->getResourceDescription()->defaultPortraitsResourceId
, _defPortraits
);
255 setPortraitBgColor(0, 0, 0);
257 _mainPanel
.x
= _vm
->getDisplayInfo().mainPanelXOffset
;
258 _mainPanel
.y
= _vm
->getDisplayInfo().mainPanelYOffset
;
259 _mainPanel
.currentButton
= NULL
;
260 _inventoryUpButton
= _mainPanel
.getButton(_vm
->getDisplayInfo().inventoryUpButtonIndex
);
261 _inventoryDownButton
= _mainPanel
.getButton(_vm
->getDisplayInfo().inventoryDownButtonIndex
);
263 _conversePanel
.x
= _vm
->getDisplayInfo().conversePanelXOffset
;
264 _conversePanel
.y
= _vm
->getDisplayInfo().conversePanelYOffset
;
265 _conversePanel
.currentButton
= NULL
;
266 _converseUpButton
= _conversePanel
.getButton(_vm
->getDisplayInfo().converseUpButtonIndex
);
267 _converseDownButton
= _conversePanel
.getButton(_vm
->getDisplayInfo().converseDownButtonIndex
);
272 _optionPanel
.x
= _vm
->getDisplayInfo().optionPanelXOffset
;
273 _optionPanel
.y
= _vm
->getDisplayInfo().optionPanelYOffset
;
274 _optionPanel
.currentButton
= NULL
;
275 _optionSaveFileSlider
= _optionPanel
.getButton(_vm
->getDisplayInfo().optionSaveFileSliderIndex
);
276 _optionSaveFilePanel
= _optionPanel
.getButton(_vm
->getDisplayInfo().optionSaveFilePanelIndex
);
278 _quitPanel
.x
= _vm
->getDisplayInfo().quitPanelXOffset
;
279 _quitPanel
.y
= _vm
->getDisplayInfo().quitPanelYOffset
;
280 _quitPanel
.imageWidth
= _vm
->getDisplayInfo().quitPanelWidth
;
281 _quitPanel
.imageHeight
= _vm
->getDisplayInfo().quitPanelHeight
;
282 _quitPanel
.buttons
= _vm
->getDisplayInfo().quitPanelButtons
;
283 _quitPanel
.buttonsCount
= _vm
->getDisplayInfo().quitPanelButtonsCount
;
284 _quitPanel
.currentButton
= NULL
;
286 _loadPanel
.x
= _vm
->getDisplayInfo().loadPanelXOffset
;
287 _loadPanel
.y
= _vm
->getDisplayInfo().loadPanelYOffset
;
288 _loadPanel
.imageWidth
= _vm
->getDisplayInfo().loadPanelWidth
;
289 _loadPanel
.imageHeight
= _vm
->getDisplayInfo().loadPanelHeight
;
290 _loadPanel
.buttons
= _vm
->getDisplayInfo().loadPanelButtons
;
291 _loadPanel
.buttonsCount
= _vm
->getDisplayInfo().loadPanelButtonsCount
;
292 _loadPanel
.currentButton
= NULL
;
294 _savePanel
.x
= _vm
->getDisplayInfo().savePanelXOffset
;
295 _savePanel
.y
= _vm
->getDisplayInfo().savePanelYOffset
;
296 _savePanel
.imageWidth
= _vm
->getDisplayInfo().savePanelWidth
;
297 _savePanel
.imageHeight
= _vm
->getDisplayInfo().savePanelHeight
;
298 _savePanel
.buttons
= _vm
->getDisplayInfo().savePanelButtons
;
299 _savePanel
.buttonsCount
= _vm
->getDisplayInfo().savePanelButtonsCount
;
300 _saveEdit
= _savePanel
.getButton(_vm
->getDisplayInfo().saveEditIndex
);
301 _savePanel
.currentButton
= NULL
;
303 _protectPanel
.x
= _vm
->getDisplayInfo().protectPanelXOffset
;
304 _protectPanel
.y
= _vm
->getDisplayInfo().protectPanelYOffset
;
305 _protectPanel
.imageWidth
= _vm
->getDisplayInfo().protectPanelWidth
;
306 _protectPanel
.imageHeight
= _vm
->getDisplayInfo().protectPanelHeight
;
307 _protectPanel
.buttons
= _vm
->getDisplayInfo().protectPanelButtons
;
308 _protectPanel
.buttonsCount
= _vm
->getDisplayInfo().protectPanelButtonsCount
;
309 _protectEdit
= _protectPanel
.getButton(_vm
->getDisplayInfo().protectEditIndex
);
310 _protectPanel
.currentButton
= NULL
;
313 _panelMode
= _lockedMode
= kPanelNull
;
319 _statusOnceColor
= -1;
326 _inventorySize
= ITE_INVENTORY_SIZE
;
327 _saveReminderState
= 0;
329 _optionSaveFileTop
= 0;
330 _optionSaveFileTitleNumber
= 0;
332 _inventory
= (uint16
*)calloc(_inventorySize
, sizeof(uint16
));
333 if (_inventory
== NULL
) {
334 error("Interface::Interface(): not enough memory");
338 _statusTextInput
= false;
339 _statusTextInputState
= kStatusTextInputFirstRun
;
341 _disableAbortSpeeches
= false;
343 // set save game reminder alarm
344 _vm
->getTimerManager()->installTimerProc(&saveReminderCallback
, TIMETOSAVE
, this);
347 Interface::~Interface(void) {
350 free(_mainPanel
.image
);
351 free(_conversePanel
.image
);
352 free(_optionPanel
.image
);
353 free(_quitPanel
.image
);
354 free(_loadPanel
.image
);
355 free(_savePanel
.image
);
357 _mainPanel
.sprites
.freeMem();
358 _conversePanel
.sprites
.freeMem();
359 _optionPanel
.sprites
.freeMem();
360 _quitPanel
.sprites
.freeMem();
361 _loadPanel
.sprites
.freeMem();
362 _savePanel
.sprites
.freeMem();
363 _protectPanel
.sprites
.freeMem();
365 _defPortraits
.freeMem();
366 _scenePortraits
.freeMem();
369 void Interface::saveReminderCallback(void *refCon
) {
370 ((Interface
*)refCon
)->updateSaveReminder();
373 void Interface::updateSaveReminder() {
374 if (_active
&& _panelMode
== kPanelMain
) {
375 _saveReminderState
= _saveReminderState
% _vm
->getDisplayInfo().saveReminderNumSprites
+ 1;
377 _vm
->getTimerManager()->removeTimerProc(&saveReminderCallback
);
378 _vm
->getTimerManager()->installTimerProc(&saveReminderCallback
, ((_vm
->getGameId() == GID_ITE
) ? TIMETOBLINK_ITE
: TIMETOBLINK_IHNM
), this);
382 int Interface::activate() {
385 _vm
->_script
->_skipSpeeches
= false;
386 _vm
->_actor
->_protagonist
->_targetObject
= ID_NOTHING
;
388 if (_panelMode
== kPanelMain
|| _panelMode
== kPanelChapterSelection
) {
389 _saveReminderState
= 1;
390 } else if (_panelMode
== kPanelNull
&& _vm
->getFeatures() & GF_IHNM_DEMO
) {
391 _saveReminderState
= 1;
393 _vm
->_gfx
->showCursor(true);
395 _vm
->_render
->setFullRefresh(true);
401 int Interface::deactivate() {
407 _vm
->_gfx
->showCursor(false);
412 void Interface::rememberMode() {
413 debug(1, "rememberMode(%d)", _panelMode
);
415 _savedMode
= _panelMode
;
418 void Interface::restoreMode(bool draw_
) {
419 debug(1, "restoreMode(%d)", _savedMode
);
421 // If _savedMode is -1 by a race condition, set it to kPanelMain
422 if (_savedMode
== -1)
423 _savedMode
= kPanelMain
;
425 _panelMode
= _savedMode
;
432 void Interface::setMode(int mode
) {
433 debug(1, "Interface::setMode %i", mode
);
435 if (mode
== kPanelMain
) {
437 _saveReminderState
= 1;
438 } else if (mode
== kPanelChapterSelection
) {
439 _saveReminderState
= 1;
440 } else if (mode
== kPanelNull
) {
441 if (_vm
->getFeatures() & GF_IHNM_DEMO
) {
443 _saveReminderState
= 1;
445 } else if (mode
== kPanelOption
) {
446 // Show the cursor if it's hidden
447 _vm
->_gfx
->showCursor(true);
449 if (mode
== kPanelConverse
) {
453 _saveReminderState
= 0;
458 switch (_panelMode
) {
460 // FIXME: Implement IHNM differences from ExecuteInventoryPanel for IHNM (though I believe they're already
463 _mainPanel
.currentButton
= NULL
;
466 _conversePanel
.currentButton
= NULL
;
467 converseDisplayText();
470 _optionPanel
.currentButton
= NULL
;
472 calcOptionSaveSlider();
473 if (_optionSaveFileTitleNumber
>= _vm
->getDisplayInfo().optionSaveFileVisible
) {
474 _optionSaveFileTitleNumber
= _vm
->getDisplayInfo().optionSaveFileVisible
- 1;
478 _loadPanel
.currentButton
= NULL
;
481 _quitPanel
.currentButton
= NULL
;
484 _savePanel
.currentButton
= NULL
;
485 _textInputMaxWidth
= _saveEdit
->width
- 10;
487 _textInputStringLength
= strlen(_textInputString
);
488 _textInputPos
= _textInputStringLength
+ 1;
493 case kPanelSceneSubstitute
:
494 _vm
->_render
->setFlag(RF_DEMO_SUBST
);
495 _vm
->_gfx
->getCurrentPal(_mapSavedPal
);
497 case kPanelChapterSelection
:
500 _vm
->_render
->setFlag(RF_DEMO_SUBST
);
503 if (_vm
->getGameId() == GID_ITE
) {
504 // This is used as the copy protection panel in ITE
505 _protectPanel
.currentButton
= NULL
;
506 _textInputMaxWidth
= _protectEdit
->width
- 10;
508 _textInputString
[0] = 0;
509 _textInputStringLength
= 0;
510 _textInputPos
= _textInputStringLength
+ 1;
512 // In the IHNM demo, this panel mode is set by the scripts
513 // to flip through the pages of the help system
519 _vm
->_render
->setFullRefresh(true);
522 bool Interface::processAscii(Common::KeyState keystate
) {
523 // TODO: Checking for Esc and Enter below is a bit hackish, and
524 // probably only works with the English version. Maybe we should
525 // add a flag to the button so it can indicate if it's the default
527 uint16 ascii
= keystate
.ascii
;
529 PanelButton
*panelButton
;
530 if (_statusTextInput
) {
531 processStatusTextInput(keystate
);
535 switch (_panelMode
) {
537 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
) {
538 if (_vm
->_scene
->isInIntro()) {
539 _vm
->_scene
->skipScene();
541 if (!_disableAbortSpeeches
)
542 _vm
->_actor
->abortAllSpeeches();
547 if (_vm
->_scene
->isNonInteractiveIHNMDemoPart())
548 _vm
->_scene
->showIHNMDemoSpecialScreen();
551 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
) {
552 if (!_disableAbortSpeeches
)
553 _vm
->_actor
->abortAllSpeeches();
554 _vm
->_scene
->cutawaySkip();
558 if (_vm
->_scene
->isNonInteractiveIHNMDemoPart())
559 _vm
->_scene
->showIHNMDemoSpecialScreen();
562 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
) {
563 if (_vm
->_scene
->isInIntro()) {
564 _vm
->_scene
->skipScene();
566 if (!_disableAbortSpeeches
)
567 _vm
->_actor
->abortAllSpeeches();
569 _vm
->_scene
->cutawaySkip();
573 if (_vm
->_scene
->isNonInteractiveIHNMDemoPart())
574 _vm
->_scene
->showIHNMDemoSpecialScreen();
577 // TODO: check input dialog keys
578 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
|| keystate
.keycode
== Common::KEYCODE_RETURN
) { // Esc or Enter
579 ascii
= 'c'; //continue
582 for (i
= 0; i
< _optionPanel
.buttonsCount
; i
++) {
583 panelButton
= &_optionPanel
.buttons
[i
];
584 if (panelButton
->type
== kPanelButtonOption
) {
585 if (panelButton
->ascii
== ascii
) {
586 setOption(panelButton
);
593 if (_textInput
&& processTextInput(keystate
)) {
597 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
) {
598 ascii
= 'c'; // cancel
599 } else if (keystate
.keycode
== Common::KEYCODE_RETURN
) { // Enter
603 for (i
= 0; i
< _savePanel
.buttonsCount
; i
++) {
604 panelButton
= &_savePanel
.buttons
[i
];
605 if (panelButton
->type
== kPanelButtonSave
) {
606 if (panelButton
->ascii
== ascii
) {
607 setSave(panelButton
);
614 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
) {
615 ascii
= 'c'; // cancel
616 } else if (keystate
.keycode
== Common::KEYCODE_RETURN
) { // Enter
620 for (i
= 0; i
< _quitPanel
.buttonsCount
; i
++) {
621 panelButton
= &_quitPanel
.buttons
[i
];
622 if (panelButton
->type
== kPanelButtonQuit
) {
623 if (panelButton
->ascii
== ascii
) {
624 setQuit(panelButton
);
631 for (i
= 0; i
< _loadPanel
.buttonsCount
; i
++) {
632 panelButton
= &_loadPanel
.buttons
[i
];
633 if (panelButton
->type
== kPanelButtonLoad
) {
634 if (panelButton
->ascii
== ascii
) {
635 setLoad(panelButton
);
642 for (i
= 0; i
< _mainPanel
.buttonsCount
; i
++) {
643 panelButton
= &_mainPanel
.buttons
[i
];
644 if (panelButton
->ascii
== ascii
) {
645 if (panelButton
->type
== kPanelButtonVerb
) {
646 _vm
->_script
->setVerb(panelButton
->id
);
648 if (panelButton
->type
== kPanelButtonArrow
) {
649 inventoryChangePos(panelButton
->id
);
654 if (keystate
.keycode
== Common::KEYCODE_o
&& keystate
.flags
== Common::KBD_CTRL
) { // ctrl-o
655 if (_saveReminderState
> 0) {
656 setMode(kPanelOption
);
665 if (_vm
->_scene
->isITEPuzzleScene())
666 _vm
->_puzzle
->exitPuzzle();
670 converseChangePos(-1);
674 converseChangePos(1);
686 converseSetPos(ascii
);
693 case kPanelSceneSubstitute
:
694 if (keystate
.keycode
== Common::KEYCODE_RETURN
) {
695 _vm
->_render
->clearFlag(RF_DEMO_SUBST
);
696 _vm
->_gfx
->setPalette(_mapSavedPal
);
698 _vm
->_script
->setNoPendingVerb();
699 } else if (ascii
== 'q' || ascii
== 'Q') {
704 _vm
->_render
->clearFlag(RF_DEMO_SUBST
);
708 if (_vm
->getGameId() == GID_ITE
) {
709 if (_textInput
&& processTextInput(keystate
)) {
713 if (keystate
.keycode
== Common::KEYCODE_ESCAPE
|| keystate
.keycode
== Common::KEYCODE_RETURN
) {
714 _vm
->_script
->wakeUpThreads(kWaitTypeRequest
);
715 _vm
->_interface
->setMode(kPanelMain
);
719 for (char *p
= _textInputString
; *p
; p
++)
720 _protectHash
= (_protectHash
<< 1) + toupper(*p
);
723 // In the IHNM demo, this panel mode is set by the scripts
724 // to flip through the pages of the help system
729 if (_vm
->getGameId() == GID_IHNM
) {
730 // Any keypress here returns the user back to the game
731 if (!(_vm
->getFeatures() & GF_IHNM_DEMO
)) {
732 _vm
->_scene
->clearPsychicProfile();
734 setMode(kPanelConverse
);
735 _vm
->_scene
->_textList
.clear();
736 _vm
->_script
->wakeUpThreads(kWaitTypeDelay
);
745 void Interface::setStatusText(const char *text
, int statusColor
) {
746 if (_vm
->getGameId() == GID_IHNM
) {
747 // Don't show the status text for the IHNM chapter selection screens (chapter 8), or
748 // scene 0 (IHNM demo introduction)
749 if (_vm
->_scene
->currentChapterNumber() == 8 || _vm
->_scene
->currentSceneNumber() == 0)
753 assert(text
!= NULL
);
754 assert(strlen(text
) < STATUS_TEXT_LEN
);
756 if (_vm
->_render
->getFlags() & RF_MAP
|| _vm
->_interface
->getMode() == kPanelPlacard
)
759 strncpy(_statusText
, text
, STATUS_TEXT_LEN
);
760 _statusOnceColor
= statusColor
;
764 void Interface::loadScenePortraits(int resourceId
) {
765 _scenePortraits
.freeMem();
767 _vm
->_sprite
->loadList(resourceId
, _scenePortraits
);
770 void Interface::drawVerbPanel(PanelButton
* panelButton
) {
771 PanelButton
* rightButtonVerbPanelButton
;
772 PanelButton
* currentVerbPanelButton
;
773 KnownColor textColor
;
777 rightButtonVerbPanelButton
= getPanelButtonByVerbType(_vm
->_script
->getRightButtonVerb());
778 currentVerbPanelButton
= getPanelButtonByVerbType(_vm
->_script
->getCurrentVerb());
780 if (panelButton
->state
) {
781 textColor
= kKnownColorVerbTextActive
;
782 } else if (panelButton
== rightButtonVerbPanelButton
) {
783 textColor
= kKnownColorVerbTextActive
;
785 textColor
= kKnownColorVerbText
;
788 if (panelButton
== currentVerbPanelButton
) {
789 spriteNumber
= panelButton
->downSpriteNumber
;
791 spriteNumber
= panelButton
->upSpriteNumber
;
793 point
.x
= _mainPanel
.x
+ panelButton
->xOffset
;
794 point
.y
= _mainPanel
.y
+ panelButton
->yOffset
;
796 _vm
->_sprite
->draw(_mainPanel
.sprites
, spriteNumber
, point
, 256);
798 drawVerbPanelText(panelButton
, textColor
, kKnownColorVerbTextShadow
);
801 void Interface::draw() {
802 Point leftPortraitPoint
;
803 Point rightPortraitPoint
;
806 if (_vm
->_scene
->isInIntro() || _fadeMode
== kFadeOut
)
811 if (_panelMode
== kPanelMain
|| _panelMode
== kPanelMap
||
812 (_panelMode
== kPanelNull
&& _vm
->getFeatures() & GF_IHNM_DEMO
)) {
813 _mainPanel
.getRect(rect
);
814 _vm
->_gfx
->drawRegion(rect
, _mainPanel
.image
);
816 for (int i
= 0; i
< kVerbTypeIdsMax
; i
++) {
817 if (_verbTypeToPanelButton
[i
] != NULL
) {
818 drawVerbPanel(_verbTypeToPanelButton
[i
]);
821 } else if (_panelMode
== kPanelConverse
) {
822 _conversePanel
.getRect(rect
);
823 _vm
->_gfx
->drawRegion(rect
, _conversePanel
.image
);
824 converseDisplayTextLines();
827 if (_panelMode
== kPanelMain
|| _panelMode
== kPanelConverse
||
828 _lockedMode
== kPanelMain
|| _lockedMode
== kPanelConverse
||
829 (_panelMode
== kPanelNull
&& _vm
->getFeatures() & GF_IHNM_DEMO
)) {
830 leftPortraitPoint
.x
= _mainPanel
.x
+ _vm
->getDisplayInfo().leftPortraitXOffset
;
831 leftPortraitPoint
.y
= _mainPanel
.y
+ _vm
->getDisplayInfo().leftPortraitYOffset
;
832 _vm
->_sprite
->draw(_defPortraits
, _leftPortrait
, leftPortraitPoint
, 256);
835 if (!_inMainMode
&& _vm
->getDisplayInfo().rightPortraitXOffset
>= 0) { //FIXME: should we change !_inMainMode to _panelMode == kPanelConverse ?
836 rightPortraitPoint
.x
= _mainPanel
.x
+ _vm
->getDisplayInfo().rightPortraitXOffset
;
837 rightPortraitPoint
.y
= _mainPanel
.y
+ _vm
->getDisplayInfo().rightPortraitYOffset
;
839 // This looks like hack - particularly since it's only done for
840 // the right-side portrait - and perhaps it is! But as far as I
841 // can tell this is what the original engine does. And it keeps
842 // ITE from crashing when entering the Elk King's court.
844 if (_rightPortrait
>= _scenePortraits
.spriteCount
)
847 _vm
->_sprite
->draw(_scenePortraits
, _rightPortrait
, rightPortraitPoint
, 256);
853 void Interface::calcOptionSaveSlider() {
854 int totalFiles
= _vm
->getSaveFilesCount();
855 int visibleFiles
= _vm
->getDisplayInfo().optionSaveFileVisible
;
856 int height
= _optionSaveFileSlider
->height
;
857 int sliderHeight
= 13; // IHNM's save file list slider has a fixed height
860 if (totalFiles
< visibleFiles
) {
861 totalFiles
= visibleFiles
;
864 if (_vm
->getGameId() == GID_ITE
) {
865 // ITE's save file list slider has a dynamically computed height, depending on
866 // the number of save games
867 sliderHeight
= visibleFiles
* height
/ totalFiles
;
870 if (sliderHeight
< 7) {
874 if (totalFiles
- visibleFiles
<= 0) {
877 pos
= _optionSaveFileTop
* (height
- sliderHeight
) / (totalFiles
- visibleFiles
);
879 _optionPanel
.calcPanelButtonRect(_optionSaveFileSlider
, _optionSaveRectTop
);
880 _optionSaveRectBottom
= _optionSaveRectSlider
= _optionSaveRectTop
;
882 _optionSaveRectTop
.bottom
= _optionSaveRectTop
.top
+ pos
;
883 _optionSaveRectTop
.top
++;
884 _optionSaveRectTop
.right
--;
886 _optionSaveRectSlider
.top
= _optionSaveRectTop
.bottom
;
887 _optionSaveRectSlider
.bottom
= _optionSaveRectSlider
.top
+ sliderHeight
;
889 _optionSaveRectBottom
.top
= _optionSaveRectSlider
.bottom
;
890 _optionSaveRectBottom
.right
--;
893 void Interface::drawPanelText(InterfacePanel
*panel
, PanelButton
*panelButton
) {
898 KnownColor textShadowKnownColor
= kKnownColorVerbTextShadow
;
899 KnownFont textFont
= kKnownFontMedium
;
901 // Button differs for CD version
902 if (panelButton
->id
== kTextReadingSpeed
&& _vm
->getGameId() == GID_ITE
&& !(_vm
->getFeatures() & GF_ITE_FLOPPY
))
904 if (panelButton
->id
== kTextShowDialog
&& _vm
->getFeatures() & GF_ITE_FLOPPY
)
907 if (_vm
->getGameId() == GID_ITE
) {
908 text
= _vm
->getTextString(panelButton
->id
);
909 textFont
= kKnownFontMedium
;
910 textShadowKnownColor
= kKnownColorVerbTextShadow
;
912 if ((panelButton
->id
< 39 || panelButton
->id
> 50) && panelButton
->id
!= kTextLoadSavedGame
) {
913 // Read non-hardcoded strings from the LUT string table, loaded from the game
915 text
= _vm
->_script
->_mainStrings
.getString(IHNMTextStringIdsLUT
[panelButton
->id
]);
916 } else if (panelButton
->id
== kTextLoadSavedGame
) {
917 // a bit of a kludge, but it will do
918 text
= _vm
->getTextString(52);
920 // Hardcoded strings in IHNM are read from the ITE hardcoded strings
921 text
= _vm
->getTextString(panelButton
->id
);
923 textFont
= kKnownFontVerb
;
924 textShadowKnownColor
= kKnownColorTransparent
;
927 panel
->calcPanelButtonRect(panelButton
, rect
);
928 if (panelButton
->xOffset
< 0) {
929 if (_vm
->getGameId() == GID_ITE
)
930 textWidth
= _vm
->_font
->getStringWidth(kKnownFontMedium
, text
, 0, kFontNormal
);
932 textWidth
= _vm
->_font
->getStringWidth(kKnownFontVerb
, text
, 0, kFontNormal
);
933 rect
.left
+= 2 + (panel
->imageWidth
- 1 - textWidth
) / 2;
936 textPoint
.x
= rect
.left
;
937 textPoint
.y
= rect
.top
+ 1;
939 _vm
->_font
->textDraw(textFont
, text
, textPoint
,
940 _vm
->KnownColor2ColorId(kKnownColorVerbText
), _vm
->KnownColor2ColorId(textShadowKnownColor
), kFontShadow
);
943 void Interface::drawOption() {
951 PanelButton
*panelButton
;
957 _optionPanel
.getRect(rect
);
958 _vm
->_gfx
->drawRegion(rect
, _optionPanel
.image
);
960 for (int i
= 0; i
< _optionPanel
.buttonsCount
; i
++) {
961 panelButton
= &_optionPanel
.buttons
[i
];
963 if (panelButton
->type
== kPanelButtonOption
) {
964 if (_vm
->getGameId() == GID_ITE
) {
965 drawPanelButtonText(&_optionPanel
, panelButton
);
967 drawPanelButtonText(&_optionPanel
, panelButton
, spritenum
);
968 spritenum
+= 2; // 2 sprites per button (lit and unlit)
971 if (panelButton
->type
== kPanelButtonOptionText
) {
972 drawPanelText(&_optionPanel
, panelButton
);
976 if (_optionSaveRectTop
.height() > 0) {
977 if (_vm
->getGameId() == GID_ITE
)
978 _vm
->_gfx
->drawRect(_optionSaveRectTop
, kITEColorDarkGrey
);
981 if (_vm
->getGameId() == GID_ITE
) {
982 drawButtonBox(_optionSaveRectSlider
, kSlider
, _optionSaveFileSlider
->state
> 0);
984 panelButton
= &_optionPanel
.buttons
[0];
985 sliderPoint
.x
= _optionPanel
.x
+ panelButton
->xOffset
;
986 sliderPoint
.y
= _optionSaveRectSlider
.top
;
987 _vm
->_sprite
->draw(_optionPanel
.sprites
, 0 + _optionSaveFileSlider
->state
, sliderPoint
, 256);
991 if (_optionSaveRectBottom
.height() > 0) {
992 _vm
->_gfx
->drawRect(_optionSaveRectBottom
, kITEColorDarkGrey
);
995 _optionPanel
.calcPanelButtonRect(_optionSaveFilePanel
, rect
);
998 fontHeight
= _vm
->_font
->getHeight(kKnownFontSmall
);
999 for (uint j
= 0; j
< _vm
->getDisplayInfo().optionSaveFileVisible
; j
++) {
1000 if (_vm
->getGameId() == GID_ITE
)
1001 bgColor
= kITEColorDarkGrey0C
;
1003 bgColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
1004 fgColor
= kITEColorBrightWhite
;
1006 idx
= j
+ _optionSaveFileTop
;
1007 if (idx
== _optionSaveFileTitleNumber
) {
1008 SWAP(bgColor
, fgColor
);
1010 if (idx
< _vm
->getSaveFilesCount()) {
1011 rect2
.top
= rect
.top
+ j
* (fontHeight
+ 1);
1012 rect2
.bottom
= rect2
.top
+ fontHeight
;
1013 _vm
->_gfx
->fillRect(rect2
, bgColor
);
1014 text
= _vm
->getSaveFile(idx
)->name
;
1015 textPoint
.x
= rect
.left
+ 1;
1016 textPoint
.y
= rect2
.top
;
1017 if (_vm
->getGameId() == GID_ITE
)
1018 _vm
->_font
->textDraw(kKnownFontSmall
, text
, textPoint
, fgColor
, 0, kFontNormal
);
1020 _vm
->_font
->textDraw(kKnownFontVerb
, text
, textPoint
, fgColor
, 0, kFontNormal
);
1026 void Interface::drawQuit() {
1029 PanelButton
*panelButton
;
1031 _quitPanel
.getRect(rect
);
1032 if (_vm
->getGameId() == GID_ITE
)
1033 drawButtonBox(rect
, kButton
, false);
1035 _vm
->_gfx
->drawRegion(rect
, _quitPanel
.image
);
1037 for (i
= 0; i
< _quitPanel
.buttonsCount
; i
++) {
1038 panelButton
= &_quitPanel
.buttons
[i
];
1039 if (panelButton
->type
== kPanelButtonQuit
) {
1040 drawPanelButtonText(&_quitPanel
, panelButton
);
1042 if (panelButton
->type
== kPanelButtonQuitText
) {
1043 drawPanelText(&_quitPanel
, panelButton
);
1048 void Interface::handleQuitUpdate(const Point
& mousePoint
) {
1049 bool releasedButton
;
1051 _quitPanel
.currentButton
= quitHitTest(mousePoint
);
1052 releasedButton
= (_quitPanel
.currentButton
!= NULL
) && (_quitPanel
.currentButton
->state
> 0) && (!_vm
->mouseButtonPressed());
1054 if (!_vm
->mouseButtonPressed()) {
1055 _quitPanel
.zeroAllButtonState();
1058 if (releasedButton
) {
1059 setQuit(_quitPanel
.currentButton
);
1063 void Interface::handleQuitClick(const Point
& mousePoint
) {
1064 _quitPanel
.currentButton
= quitHitTest(mousePoint
);
1066 _quitPanel
.zeroAllButtonState();
1068 if (_quitPanel
.currentButton
== NULL
) {
1072 _quitPanel
.currentButton
->state
= 1;
1075 void Interface::setQuit(PanelButton
*panelButton
) {
1076 _quitPanel
.currentButton
= NULL
;
1077 switch (panelButton
->id
) {
1079 setMode(kPanelOption
);
1083 if (_vm
->getFeatures() & GF_IHNM_DEMO
)
1084 _vm
->_scene
->creditsScene(); // display sales info for IHNM demo
1092 void Interface::drawLoad() {
1095 PanelButton
*panelButton
;
1097 _loadPanel
.getRect(rect
);
1098 if (_vm
->getGameId() == GID_ITE
)
1099 drawButtonBox(rect
, kButton
, false);
1101 _vm
->_gfx
->drawRegion(rect
, _loadPanel
.image
);
1103 for (i
= 0; i
< _loadPanel
.buttonsCount
; i
++) {
1104 panelButton
= &_loadPanel
.buttons
[i
];
1105 if (panelButton
->type
== kPanelButtonLoad
) {
1106 drawPanelButtonText(&_loadPanel
, panelButton
);
1108 if (panelButton
->type
== kPanelButtonLoadText
) {
1109 drawPanelText(&_loadPanel
, panelButton
);
1114 void Interface::handleLoadUpdate(const Point
& mousePoint
) {
1115 bool releasedButton
;
1117 _loadPanel
.currentButton
= loadHitTest(mousePoint
);
1118 releasedButton
= (_loadPanel
.currentButton
!= NULL
) && (_loadPanel
.currentButton
->state
> 0) && (!_vm
->mouseButtonPressed());
1120 if (!_vm
->mouseButtonPressed()) {
1121 _loadPanel
.zeroAllButtonState();
1124 if (releasedButton
) {
1125 setLoad(_loadPanel
.currentButton
);
1129 void Interface::handleLoadClick(const Point
& mousePoint
) {
1130 _loadPanel
.currentButton
= loadHitTest(mousePoint
);
1132 _loadPanel
.zeroAllButtonState();
1134 if (_loadPanel
.currentButton
== NULL
) {
1138 _loadPanel
.currentButton
->state
= 1;
1141 void Interface::setLoad(PanelButton
*panelButton
) {
1142 _loadPanel
.currentButton
= NULL
;
1143 switch (panelButton
->id
) {
1145 if (_vm
->getGameId() == GID_ITE
) {
1146 setMode(kPanelMain
);
1148 if (_vm
->getSaveFilesCount() > 0) {
1149 if (_vm
->isSaveListFull() || (_optionSaveFileTitleNumber
> 0)) {
1150 debug(1, "Loading save game %d", _vm
->getSaveFile(_optionSaveFileTitleNumber
)->slotNumber
);
1151 setMode(kPanelMain
);
1152 _vm
->load(_vm
->calcSaveFileName(_vm
->getSaveFile(_optionSaveFileTitleNumber
)->slotNumber
));
1153 _vm
->syncSoundSettings();
1160 setMode(kPanelOption
);
1165 void Interface::processStatusTextInput(Common::KeyState keystate
) {
1167 switch (keystate
.keycode
) {
1168 case Common::KEYCODE_ESCAPE
:
1169 _statusTextInputState
= kStatusTextInputAborted
;
1170 _statusTextInput
= false;
1171 _vm
->_script
->wakeUpThreads(kWaitTypeStatusTextInput
);
1173 case Common::KEYCODE_RETURN
:
1174 _statusTextInputState
= kStatusTextInputEntered
;
1175 _statusTextInput
= false;
1176 _vm
->_script
->wakeUpThreads(kWaitTypeStatusTextInput
);
1178 case Common::KEYCODE_BACKSPACE
:
1179 if (_statusTextInputPos
== 0) {
1182 _statusTextInputPos
--;
1183 _statusTextInputString
[_statusTextInputPos
] = 0;
1185 if (_statusTextInputPos
>= STATUS_TEXT_INPUT_MAX
) {
1188 if (isalnum(keystate
.ascii
) || (keystate
.ascii
== ' ')) {
1189 _statusTextInputString
[_statusTextInputPos
++] = keystate
.ascii
;
1190 _statusTextInputString
[_statusTextInputPos
] = 0;
1193 setStatusText(_statusTextInputString
);
1196 bool Interface::processTextInput(Common::KeyState keystate
) {
1198 char tempString
[SAVE_TITLE_SIZE
];
1200 memset(tempString
, 0, SAVE_TITLE_SIZE
);
1202 // IHNM has a smaller save title size than ITE. We only limit the save title size during text input
1203 // in IHNM, to preserve backwards compatibility with older save games
1204 uint save_title_size
= _vm
->getGameId() == GID_ITE
? SAVE_TITLE_SIZE
: IHNM_SAVE_TITLE_SIZE
;
1206 switch (keystate
.keycode
) {
1207 case Common::KEYCODE_RETURN
:
1209 case Common::KEYCODE_ESCAPE
:
1212 case Common::KEYCODE_BACKSPACE
:
1213 if (_textInputPos
<= 1) {
1217 case Common::KEYCODE_DELETE
:
1218 if (_textInputPos
<= _textInputStringLength
) {
1219 if (_textInputPos
!= 1) {
1220 strncpy(tempString
, _textInputString
, _textInputPos
- 1);
1222 if (_textInputPos
!= _textInputStringLength
) {
1223 strncat(tempString
, &_textInputString
[_textInputPos
], _textInputStringLength
- _textInputPos
);
1225 strcpy(_textInputString
, tempString
);
1226 _textInputStringLength
= strlen(_textInputString
);
1229 case Common::KEYCODE_LEFT
:
1230 if (_textInputPos
> 1) {
1234 case Common::KEYCODE_RIGHT
:
1235 if (_textInputPos
<= _textInputStringLength
) {
1239 case Common::KEYCODE_HOME
:
1242 case Common::KEYCODE_END
:
1243 _textInputPos
= _textInputStringLength
+ 1;
1246 if (((keystate
.ascii
<= 255) && (isalnum(keystate
.ascii
))) || (keystate
.ascii
== ' ') ||
1247 (keystate
.ascii
== '-') || (keystate
.ascii
== '_')) {
1248 if (_textInputStringLength
< save_title_size
- 1) {
1249 ch
[0] = keystate
.ascii
;
1250 tempWidth
= _vm
->_font
->getStringWidth(kKnownFontSmall
, ch
, 0, kFontNormal
);
1251 tempWidth
+= _vm
->_font
->getStringWidth(kKnownFontSmall
, _textInputString
, 0, kFontNormal
);
1252 if (tempWidth
> _textInputMaxWidth
) {
1255 if (_textInputPos
!= 1) {
1256 strncpy(tempString
, _textInputString
, _textInputPos
- 1);
1257 strcat(tempString
, ch
);
1259 if ((_textInputStringLength
== 0) || (_textInputPos
== 1)) {
1260 strcpy(tempString
, ch
);
1262 if ((_textInputStringLength
!= 0) && (_textInputPos
!= _textInputStringLength
)) {
1263 strncat(tempString
, &_textInputString
[_textInputPos
- 1], _textInputStringLength
- _textInputPos
+ 1);
1266 strcpy(_textInputString
, tempString
);
1267 _textInputStringLength
= strlen(_textInputString
);
1276 void Interface::drawTextInput(InterfacePanel
*panel
, PanelButton
*panelButton
) {
1284 panel
->calcPanelButtonRect(panelButton
, rect
);
1285 drawButtonBox(rect
, kEdit
, _textInput
);
1288 rect
.setHeight(_vm
->_font
->getHeight(kKnownFontSmall
));
1291 while ((ch
[0] = _textInputString
[i
++]) != 0) {
1292 rect
.setWidth(_vm
->_font
->getStringWidth(kKnownFontSmall
, ch
, 0, kFontNormal
));
1293 if ((i
== _textInputPos
) && _textInput
) {
1294 fgColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
1295 _vm
->_gfx
->fillRect(rect
, _vm
->KnownColor2ColorId(kKnownColorWhite
));
1297 fgColor
= _vm
->KnownColor2ColorId(kKnownColorWhite
);
1299 textPoint
.x
= rect
.left
;
1300 textPoint
.y
= rect
.top
+ 1;
1302 _vm
->_font
->textDraw(kKnownFontSmall
, ch
, textPoint
, fgColor
, 0, kFontNormal
);
1303 rect
.left
+= rect
.width();
1305 if (_textInput
&& (_textInputPos
>= i
)) {
1307 rect
.setWidth(_vm
->_font
->getStringWidth(kKnownFontSmall
, ch
, 0, kFontNormal
));
1308 _vm
->_gfx
->fillRect(rect
, _vm
->KnownColor2ColorId(kKnownColorWhite
));
1312 void Interface::drawSave() {
1315 PanelButton
*panelButton
;
1317 _savePanel
.getRect(rect
);
1318 if (_vm
->getGameId() == GID_ITE
)
1319 drawButtonBox(rect
, kButton
, false);
1321 _vm
->_gfx
->drawRegion(rect
, _savePanel
.image
);
1323 for (i
= 0; i
< _savePanel
.buttonsCount
; i
++) {
1324 panelButton
= &_savePanel
.buttons
[i
];
1325 if (panelButton
->type
== kPanelButtonSave
) {
1326 drawPanelButtonText(&_savePanel
, panelButton
);
1328 if (panelButton
->type
== kPanelButtonSaveText
) {
1329 drawPanelText(&_savePanel
, panelButton
);
1333 drawTextInput(&_savePanel
, _saveEdit
);
1336 void Interface::drawProtect() {
1339 PanelButton
*panelButton
;
1341 _protectPanel
.getRect(rect
);
1342 drawButtonBox(rect
, kButton
, false);
1344 for (i
= 0; i
< _protectPanel
.buttonsCount
; i
++) {
1345 panelButton
= &_protectPanel
.buttons
[i
];
1346 if (panelButton
->type
== kPanelButtonProtectText
) {
1347 drawPanelText(&_protectPanel
, panelButton
);
1350 drawTextInput(&_protectPanel
, _protectEdit
);
1353 void Interface::handleSaveUpdate(const Point
& mousePoint
) {
1354 bool releasedButton
;
1356 _savePanel
.currentButton
= saveHitTest(mousePoint
);
1358 validateSaveButtons();
1360 releasedButton
= (_savePanel
.currentButton
!= NULL
) &&
1361 (_savePanel
.currentButton
->state
> 0) && (!_vm
->mouseButtonPressed());
1363 if (!_vm
->mouseButtonPressed()) {
1364 _savePanel
.zeroAllButtonState();
1367 if (releasedButton
) {
1368 setSave(_savePanel
.currentButton
);
1372 void Interface::handleSaveClick(const Point
& mousePoint
) {
1373 _savePanel
.currentButton
= saveHitTest(mousePoint
);
1375 validateSaveButtons();
1377 _savePanel
.zeroAllButtonState();
1379 if (_savePanel
.currentButton
== NULL
) {
1384 _savePanel
.currentButton
->state
= 1;
1385 if (_savePanel
.currentButton
== _saveEdit
) {
1390 void Interface::setSave(PanelButton
*panelButton
) {
1391 _savePanel
.currentButton
= NULL
;
1394 switch (panelButton
->id
) {
1396 if (_textInputStringLength
== 0 ) {
1399 if (!_vm
->isSaveListFull() && (_optionSaveFileTitleNumber
== 0)) {
1400 if (_vm
->locateSaveFile(_textInputString
, titleNumber
)) {
1401 fileName
= _vm
->calcSaveFileName(_vm
->getSaveFile(titleNumber
)->slotNumber
);
1402 _vm
->save(fileName
, _textInputString
);
1403 _optionSaveFileTitleNumber
= titleNumber
;
1405 fileName
= _vm
->calcSaveFileName(_vm
->getNewSaveSlotNumber());
1406 _vm
->save(fileName
, _textInputString
);
1407 _vm
->fillSaveList();
1408 calcOptionSaveSlider();
1411 fileName
= _vm
->calcSaveFileName(_vm
->getSaveFile(_optionSaveFileTitleNumber
)->slotNumber
);
1412 _vm
->save(fileName
, _textInputString
);
1414 _vm
->getTimerManager()->removeTimerProc(&saveReminderCallback
);
1415 _vm
->getTimerManager()->installTimerProc(&saveReminderCallback
, TIMETOSAVE
, this);
1416 setSaveReminderState(1);
1419 setMode(kPanelOption
);
1423 setMode(kPanelOption
);
1428 void Interface::handleOptionUpdate(const Point
& mousePoint
) {
1431 int totalFiles
= _vm
->getSaveFilesCount();
1432 int visibleFiles
= _vm
->getDisplayInfo().optionSaveFileVisible
;
1433 bool releasedButton
;
1435 if (_vm
->mouseButtonPressed()) {
1436 if (_optionSaveFileSlider
->state
> 0) {
1437 _optionPanel
.calcPanelButtonRect(_optionSaveFileSlider
, rect
);
1439 mouseY
= mousePoint
.y
- rect
.top
-_optionSaveFileMouseOff
;
1443 if (totalFiles
- visibleFiles
<= 0) {
1444 _optionSaveFileTop
= 0;
1446 _optionSaveFileTop
= mouseY
* (totalFiles
- visibleFiles
) /
1447 (_optionSaveFileSlider
->height
- _optionSaveRectSlider
.height());
1450 _optionSaveFileTop
= CLIP
<uint
>(_optionSaveFileTop
, 0, totalFiles
- visibleFiles
);
1451 calcOptionSaveSlider();
1455 _optionPanel
.currentButton
= optionHitTest(mousePoint
);
1457 validateOptionButtons();
1459 releasedButton
= (_optionPanel
.currentButton
!= NULL
) && (_optionPanel
.currentButton
->state
> 0) && (!_vm
->mouseButtonPressed());
1461 if (!_vm
->mouseButtonPressed()) {
1462 _optionPanel
.zeroAllButtonState();
1465 if (releasedButton
) {
1466 setOption(_optionPanel
.currentButton
);
1471 void Interface::handleOptionClick(const Point
& mousePoint
) {
1473 _optionPanel
.currentButton
= optionHitTest(mousePoint
);
1475 validateOptionButtons();
1477 _optionPanel
.zeroAllButtonState();
1479 if (_optionPanel
.currentButton
== NULL
) {
1483 if (_optionPanel
.currentButton
== _optionSaveFileSlider
) {
1484 if ((_optionSaveRectTop
.height() > 0) && (mousePoint
.y
< _optionSaveRectTop
.bottom
)) {
1485 _optionSaveFileTop
-= _vm
->getDisplayInfo().optionSaveFileVisible
;
1487 if ((_optionSaveRectBottom
.height() > 0) && (mousePoint
.y
>= _optionSaveRectBottom
.top
)) {
1488 _optionSaveFileTop
+= _vm
->getDisplayInfo().optionSaveFileVisible
;
1490 if (_vm
->getDisplayInfo().optionSaveFileVisible
< _vm
->getSaveFilesCount()) {
1491 _optionSaveFileMouseOff
= mousePoint
.y
- _optionSaveRectSlider
.top
;
1492 _optionPanel
.currentButton
->state
= 1;
1497 _optionSaveFileTop
= CLIP
<uint
>(_optionSaveFileTop
, 0, _vm
->getSaveFilesCount() - _vm
->getDisplayInfo().optionSaveFileVisible
);
1498 calcOptionSaveSlider();
1500 if (_optionPanel
.currentButton
== _optionSaveFilePanel
) {
1501 _optionPanel
.calcPanelButtonRect(_optionSaveFilePanel
, rect
);
1502 _optionSaveFileTitleNumber
= (mousePoint
.y
- rect
.top
) / (_vm
->_font
->getHeight(kKnownFontSmall
) + 1);
1504 if (_optionSaveFileTitleNumber
>= _vm
->getDisplayInfo().optionSaveFileVisible
) {
1505 _optionSaveFileTitleNumber
= _vm
->getDisplayInfo().optionSaveFileVisible
- 1;
1507 _optionSaveFileTitleNumber
+= _optionSaveFileTop
;
1508 if (_optionSaveFileTitleNumber
>= _vm
->getSaveFilesCount()) {
1509 _optionSaveFileTitleNumber
= _vm
->getSaveFilesCount() - 1;
1512 _optionPanel
.currentButton
->state
= 1;
1517 void Interface::handleChapterSelectionUpdate(const Point
& mousePoint
) {
1520 const HitZone
* hitZone
;
1522 // FIXME: Original handled more object types here.
1524 objectId
= _vm
->_actor
->hitTest(mousePoint
, true);
1526 if (objectId
== ID_NOTHING
) {
1527 hitZoneIndex
= _vm
->_scene
->_objectMap
->hitTest(mousePoint
);
1529 if ((hitZoneIndex
!= -1)) {
1530 hitZone
= _vm
->_scene
->_objectMap
->getHitZone(hitZoneIndex
);
1531 objectId
= hitZone
->getHitZoneId();
1535 if (objectId
!= _vm
->_script
->_pointerObject
) {
1536 _vm
->_script
->_pointerObject
= objectId
;
1540 void Interface::handleChapterSelectionClick(const Point
& mousePoint
) {
1541 int obj
= _vm
->_script
->_pointerObject
;
1543 _vm
->_actor
->abortSpeech();
1552 switch (objectTypeId(obj
)) {
1553 case kGameObjectHitZone
:
1554 hitZone
= _vm
->_scene
->_objectMap
->getHitZone(objectIdToIndex(obj
));
1556 if (hitZone
== NULL
)
1559 if (hitZone
->getFlags() & kHitZoneEnabled
)
1560 script
= hitZone
->getScriptNumber();
1563 case kGameObjectActor
:
1564 a
= _vm
->_actor
->getActor(obj
);
1565 script
= a
->_scriptEntrypointNumber
;
1568 case kGameObjectObject
:
1569 o
= _vm
->_actor
->getObj(obj
);
1570 script
= o
->_scriptEntrypointNumber
;
1575 event
.type
= kEvTOneshot
;
1576 event
.code
= kScriptEvent
;
1577 event
.op
= kEventExecNonBlocking
;
1579 event
.param
= _vm
->_scene
->getScriptModuleNumber();
1580 event
.param2
= script
;
1581 event
.param3
= _vm
->_script
->getVerbType(kVerbUse
); // Action
1582 event
.param4
= obj
; // Object
1583 event
.param5
= 0; // With Object
1584 event
.param6
= obj
; // Actor
1585 _vm
->_events
->queue(&event
);
1590 void Interface::setOption(PanelButton
*panelButton
) {
1591 _optionPanel
.currentButton
= NULL
;
1592 switch (panelButton
->id
) {
1593 case kTextContinuePlaying
:
1594 ConfMan
.flushToDisk();
1595 if (_vm
->getGameId() == GID_ITE
) {
1596 setMode(kPanelMain
);
1598 if (_vm
->_scene
->currentChapterNumber() == 8) {
1599 setMode(kPanelChapterSelection
);
1600 } else if (_vm
->_scene
->isNonInteractiveIHNMDemoPart()) {
1601 setMode(kPanelNull
);
1603 setMode(kPanelMain
);
1608 setMode(kPanelQuit
);
1611 if (_vm
->getGameId() == GID_ITE
) {
1612 if (_vm
->getSaveFilesCount() > 0) {
1613 if (_vm
->isSaveListFull() || (_optionSaveFileTitleNumber
> 0)) {
1614 debug(1, "Loading save game %d", _vm
->getSaveFile(_optionSaveFileTitleNumber
)->slotNumber
);
1615 setMode(kPanelMain
);
1616 _vm
->load(_vm
->calcSaveFileName(_vm
->getSaveFile(_optionSaveFileTitleNumber
)->slotNumber
));
1617 _vm
->syncSoundSettings();
1621 setMode(kPanelLoad
);
1625 // Disallow saving in the non-interactive part of the IHNM demo (original demo didn't support saving at all)
1626 if (_vm
->_scene
->isNonInteractiveIHNMDemoPart())
1629 if (!_vm
->isSaveListFull() && (_optionSaveFileTitleNumber
== 0)) {
1630 _textInputString
[0] = 0;
1632 strcpy(_textInputString
, _vm
->getSaveFile(_optionSaveFileTitleNumber
)->name
);
1634 setMode(kPanelSave
);
1636 case kTextReadingSpeed
:
1637 if (_vm
->getGameId() == GID_ITE
&& !(_vm
->getFeatures() & GF_ITE_FLOPPY
)) {
1638 _vm
->_subtitlesEnabled
= !_vm
->_subtitlesEnabled
;
1639 ConfMan
.setBool("subtitles", _vm
->_subtitlesEnabled
);
1641 _vm
->_readingSpeed
= (_vm
->_readingSpeed
+ 1) % 4;
1642 _vm
->setTalkspeed(_vm
->_readingSpeed
);
1646 _vm
->_musicVolume
= _vm
->_musicVolume
+ 25;
1647 if (_vm
->_musicVolume
> 255) _vm
->_musicVolume
= 0;
1648 _vm
->_music
->setVolume(_vm
->_musicVolume
, 1);
1649 ConfMan
.setInt("music_volume", _vm
->_musicVolume
);
1652 _vm
->_soundVolume
= _vm
->_soundVolume
+ 25;
1653 if (_vm
->_soundVolume
> 255) _vm
->_soundVolume
= 0;
1654 ConfMan
.setInt("sfx_volume", _vm
->_soundVolume
);
1655 _vm
->_sound
->setVolume();
1658 if (_vm
->_voiceFilesExist
) {
1659 if (_vm
->_subtitlesEnabled
&& _vm
->_voicesEnabled
) { // Both
1660 _vm
->_subtitlesEnabled
= false; // Set it to "Audio"
1661 _vm
->_voicesEnabled
= true; // Not necessary, just for completeness
1662 } else if (!_vm
->_subtitlesEnabled
&& _vm
->_voicesEnabled
) {
1663 _vm
->_subtitlesEnabled
= true; // Set it to "Text"
1664 _vm
->_voicesEnabled
= false;
1665 } else if (_vm
->_subtitlesEnabled
&& !_vm
->_voicesEnabled
) {
1666 _vm
->_subtitlesEnabled
= true; // Set it to "Both"
1667 _vm
->_voicesEnabled
= true;
1670 _vm
->_subtitlesEnabled
= true; // Set it to "Text"
1671 _vm
->_voicesEnabled
= false;
1674 _vm
->_speechVolume
= _vm
->_speechVolume
+ 25;
1675 if (_vm
->_speechVolume
> 255) _vm
->_speechVolume
= 0;
1676 ConfMan
.setInt("speech_volume", _vm
->_speechVolume
);
1677 _vm
->_sound
->setVolume();
1679 ConfMan
.setBool("subtitles", _vm
->_subtitlesEnabled
);
1680 ConfMan
.setBool("voices", _vm
->_voicesEnabled
);
1685 void Interface::update(const Point
& mousePoint
, int updateFlag
) {
1687 if (!_active
&& _panelMode
== kPanelNull
&& (updateFlag
& UPDATE_MOUSECLICK
))
1688 _vm
->_actor
->abortSpeech();
1690 if (_vm
->_scene
->isInIntro() || _fadeMode
== kFadeOut
|| !_active
) {
1691 // When opening the psychic profile, or the options screen in the non-interactive part of the IHNM demo,
1692 // the interface is locked (_active is false)
1693 // Don't return in those cases, so that mouse actions can be processed
1694 if (_vm
->getGameId() == GID_ITE
) {
1697 if (_panelMode
== kPanelPlacard
&& (updateFlag
& UPDATE_MOUSECLICK
)) {
1698 // the psychic profile or the special screen in IHNM demo is open, don't return
1699 } else if (_panelMode
== kPanelOption
|| _panelMode
== kPanelQuit
) {
1700 // options/quit panel is open, set interface to active and don't return
1701 _vm
->_actor
->abortSpeech(); // abort any speech being played
1709 if (_statusTextInput
) {
1713 switch (_panelMode
) {
1715 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1716 bool lastWasPlayfield
= _lastMousePoint
.y
< _vm
->_scene
->getHeight();
1717 if (mousePoint
.y
< _vm
->_scene
->getHeight()) {
1718 if (!lastWasPlayfield
) {
1719 handleMainUpdate(mousePoint
);
1721 _vm
->_script
->whichObject(mousePoint
);
1723 if (lastWasPlayfield
) {
1724 _vm
->_script
->setNonPlayfieldVerb();
1726 handleMainUpdate(mousePoint
);
1731 if (updateFlag
& UPDATE_MOUSECLICK
) {
1732 if (mousePoint
.y
< _vm
->_scene
->getHeight()) {
1733 _vm
->_script
->playfieldClick(mousePoint
, (updateFlag
& UPDATE_LEFTBUTTONCLICK
) != 0);
1735 handleMainClick(mousePoint
);
1741 case kPanelConverse
:
1742 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1743 handleConverseUpdate(mousePoint
);
1745 if (updateFlag
& UPDATE_MOUSECLICK
) {
1746 handleConverseClick(mousePoint
);
1748 if (updateFlag
& UPDATE_WHEELUP
) {
1749 converseChangePos(-1);
1751 if (updateFlag
& UPDATE_WHEELDOWN
) {
1752 converseChangePos(1);
1755 if (_vm
->_scene
->isITEPuzzleScene()) {
1756 _vm
->_puzzle
->handleClick(mousePoint
);
1762 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1763 handleOptionUpdate(mousePoint
);
1765 if (updateFlag
& UPDATE_MOUSECLICK
) {
1766 handleOptionClick(mousePoint
);
1768 if (updateFlag
& UPDATE_WHEELUP
) {
1769 if (_optionSaveFileTop
)
1770 _optionSaveFileTop
--;
1771 calcOptionSaveSlider();
1773 if (updateFlag
& UPDATE_WHEELDOWN
) {
1774 if (_optionSaveFileTop
< _vm
->getSaveFilesCount() - _vm
->getDisplayInfo().optionSaveFileVisible
)
1775 _optionSaveFileTop
++;
1776 calcOptionSaveSlider();
1782 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1783 handleQuitUpdate(mousePoint
);
1785 if (updateFlag
& UPDATE_MOUSECLICK
) {
1786 handleQuitClick(mousePoint
);
1792 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1794 handleLoadUpdate(mousePoint
);
1797 if (updateFlag
& UPDATE_MOUSECLICK
) {
1798 handleLoadClick(mousePoint
);
1804 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1806 handleSaveUpdate(mousePoint
);
1809 if (updateFlag
& UPDATE_MOUSECLICK
) {
1810 handleSaveClick(mousePoint
);
1816 if (updateFlag
& UPDATE_MOUSECLICK
)
1820 case kPanelSceneSubstitute
:
1821 if (updateFlag
& UPDATE_MOUSECLICK
) {
1822 _vm
->_render
->clearFlag(RF_DEMO_SUBST
);
1823 _vm
->_gfx
->setPalette(_mapSavedPal
);
1824 setMode(kPanelMain
);
1825 _vm
->_script
->setNoPendingVerb();
1829 case kPanelChapterSelection
:
1830 if (updateFlag
& UPDATE_MOUSEMOVE
) {
1831 handleChapterSelectionUpdate(mousePoint
);
1833 if (updateFlag
& UPDATE_MOUSECLICK
) {
1835 rect
.left
= _vm
->getDisplayInfo().saveReminderXOffset
;
1836 rect
.top
= _vm
->getDisplayInfo().saveReminderYOffset
;
1838 rect
.right
= rect
.left
+ _vm
->getDisplayInfo().saveReminderWidth
;
1839 rect
.bottom
= rect
.top
+ _vm
->getDisplayInfo().saveReminderHeight
;
1840 if (rect
.contains(mousePoint
))
1841 setMode(kPanelOption
);
1843 handleChapterSelectionClick(mousePoint
);
1849 // No mouse interaction
1854 if (_vm
->getGameId() == GID_IHNM
) {
1855 // Any mouse click here returns the user back to the game
1856 if (updateFlag
& UPDATE_MOUSECLICK
) {
1857 if (!(_vm
->getFeatures() & GF_IHNM_DEMO
)) {
1858 _vm
->_scene
->clearPsychicProfile();
1860 setMode(kPanelConverse
);
1861 _vm
->_scene
->_textList
.clear();
1862 _vm
->_script
->wakeUpThreads(kWaitTypeDelay
);
1870 if (_vm
->_scene
->isNonInteractiveIHNMDemoPart() && (updateFlag
& UPDATE_MOUSECLICK
))
1871 _vm
->_scene
->showIHNMDemoSpecialScreen();
1875 _lastMousePoint
= mousePoint
;
1878 void Interface::drawStatusBar() {
1883 // The default colors in the Spanish version of IHNM are shifted by one
1884 // Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)"
1885 int offset
= (_vm
->getLanguage() == Common::ES_ESP
) ? 1 : 0;
1887 // Disable the status text in IHNM when the chapter is 8
1888 if (_vm
->getGameId() == GID_IHNM
&& _vm
->_scene
->currentChapterNumber() == 8)
1891 // Don't draw the status bar while fading out
1892 if (_fadeMode
== kFadeOut
)
1895 // Erase background of status bar
1896 rect
.left
= _vm
->getDisplayInfo().statusXOffset
;
1897 rect
.top
= _vm
->getDisplayInfo().statusYOffset
;
1898 rect
.right
= rect
.left
+ _vm
->getDisplayInfo().width
;
1899 rect
.bottom
= rect
.top
+ _vm
->getDisplayInfo().statusHeight
;
1901 _vm
->_gfx
->drawRect(rect
, _vm
->getDisplayInfo().statusBGColor
- offset
);
1903 stringWidth
= _vm
->_font
->getStringWidth(kKnownFontSmall
, _statusText
, 0, kFontNormal
);
1905 if (_statusOnceColor
== -1)
1906 color
= _vm
->getDisplayInfo().statusTextColor
- offset
;
1908 color
= _statusOnceColor
;
1910 textPoint
.x
= _vm
->getDisplayInfo().statusXOffset
+ (_vm
->getDisplayInfo().statusWidth
- stringWidth
) / 2;
1911 textPoint
.y
= _vm
->getDisplayInfo().statusYOffset
+ _vm
->getDisplayInfo().statusTextY
;
1912 if (_vm
->getGameId() == GID_ITE
)
1913 _vm
->_font
->textDraw(kKnownFontSmall
, _statusText
, textPoint
, color
, 0, kFontNormal
);
1915 _vm
->_font
->textDraw(kKnownFontVerb
, _statusText
, textPoint
, color
, 0, kFontNormal
);
1917 if (_saveReminderState
> 0) {
1918 rect
.left
= _vm
->getDisplayInfo().saveReminderXOffset
;
1919 rect
.top
= _vm
->getDisplayInfo().saveReminderYOffset
;
1921 rect
.right
= rect
.left
+ _vm
->getDisplayInfo().saveReminderWidth
;
1922 rect
.bottom
= rect
.top
+ _vm
->getDisplayInfo().saveReminderHeight
;
1923 _vm
->_sprite
->draw(_vm
->_sprite
->_saveReminderSprites
,
1924 _vm
->getDisplayInfo().saveReminderFirstSpriteNumber
+ _saveReminderState
- 1,
1930 void Interface::handleMainClick(const Point
& mousePoint
) {
1932 PanelButton
*panelButton
;
1934 panelButton
= verbHitTest(mousePoint
);
1936 _vm
->_script
->setVerb(panelButton
->id
);
1940 panelButton
= _mainPanel
.hitTest(mousePoint
, kPanelAllButtons
);
1942 if (panelButton
!= NULL
) {
1943 if (panelButton
->type
== kPanelButtonArrow
) {
1944 panelButton
->state
= 1;
1945 converseChangePos(panelButton
->id
);
1948 if (panelButton
->type
== kPanelButtonInventory
) {
1949 if (_vm
->_script
->_pointerObject
!= ID_NOTHING
) {
1950 _vm
->_script
->hitObject(_vm
->leftMouseButtonPressed());
1952 if (_vm
->_script
->_pendingVerb
) {
1953 _vm
->_actor
->_protagonist
->_currentAction
= kActionWait
;
1954 _vm
->_script
->doVerb();
1958 if (_saveReminderState
> 0) {
1960 rect
.left
= _vm
->getDisplayInfo().saveReminderXOffset
;
1961 rect
.top
= _vm
->getDisplayInfo().saveReminderYOffset
;
1963 rect
.right
= rect
.left
+ _vm
->getDisplayInfo().saveReminderWidth
;
1964 rect
.bottom
= rect
.top
+ _vm
->getDisplayInfo().saveReminderHeight
;
1965 if (rect
.contains(mousePoint
)) {
1966 setMode(kPanelOption
);
1972 void Interface::handleMainUpdate(const Point
& mousePoint
) {
1973 PanelButton
*panelButton
;
1975 panelButton
= verbHitTest(mousePoint
);
1976 if (_mainPanel
.currentButton
!= panelButton
) {
1977 if (_mainPanel
.currentButton
) {
1978 if (_mainPanel
.currentButton
->type
== kPanelButtonVerb
) {
1979 setVerbState(_mainPanel
.currentButton
->id
, 0);
1983 setVerbState(panelButton
->id
, 1);
1988 _mainPanel
.currentButton
= panelButton
;
1993 if (!_vm
->mouseButtonPressed()) { // remove pressed flag
1994 if (_inventoryUpButton
) {
1995 _inventoryUpButton
->state
= 0;
1996 _inventoryDownButton
->state
= 0;
2000 panelButton
= _mainPanel
.hitTest(mousePoint
, kPanelAllButtons
);
2002 bool changed
= false;
2004 if ((panelButton
!= NULL
) && (panelButton
->type
== kPanelButtonArrow
)) {
2005 if (panelButton
->state
== 1) {
2006 inventoryChangePos(panelButton
->id
);
2010 _vm
->_script
->whichObject(mousePoint
);
2013 changed
= changed
|| (panelButton
!= _mainPanel
.currentButton
);
2014 _mainPanel
.currentButton
= panelButton
;
2021 void Interface::inventoryChangePos(int chg
) {
2022 // Arrows will scroll the inventory up or down up to 4 items
2023 for (int i
= 1; i
<= 4; i
++) {
2024 if ((chg
< 0 && _inventoryStart
+ chg
>= 0) ||
2025 (chg
> 0 && _inventoryStart
< _inventoryEnd
)) {
2026 _inventoryStart
+= chg
;
2032 void Interface::inventorySetPos(int key
) {
2033 _inventoryBox
= key
- '1';
2034 _inventoryPos
= _inventoryStart
+ _inventoryBox
;
2035 if (_inventoryPos
>= _inventoryCount
)
2039 void Interface::updateInventory(int pos
) {
2040 int cols
= _vm
->getDisplayInfo().inventoryColumns
;
2041 if (pos
>= _inventoryCount
) {
2042 pos
= _inventoryCount
- 1;
2047 _inventoryStart
= (pos
- cols
) / cols
* cols
;
2048 if (_inventoryStart
< 0) {
2049 _inventoryStart
= 0;
2052 _inventoryEnd
= (_inventoryCount
- 1 - cols
) / cols
* cols
;
2053 if (_inventoryEnd
< 0) {
2058 void Interface::addToInventory(int objectId
) {
2059 if (_inventoryCount
>= _inventorySize
) {
2063 for (int i
= _inventoryCount
; i
> 0; i
--) {
2064 _inventory
[i
] = _inventory
[i
- 1];
2067 _inventory
[0] = objectId
;
2075 void Interface::removeFromInventory(int objectId
) {
2076 int j
= inventoryItemPosition(objectId
);
2083 for (i
= j
; i
< _inventoryCount
- 1; i
++) {
2084 _inventory
[i
] = _inventory
[i
+ 1];
2088 _inventory
[_inventoryCount
] = 0;
2093 void Interface::clearInventory() {
2094 for (int i
= 0; i
< _inventoryCount
; i
++)
2097 _inventoryCount
= 0;
2101 int Interface::inventoryItemPosition(int objectId
) {
2102 for (int i
= 0; i
< _inventoryCount
; i
++)
2103 if (_inventory
[i
] == objectId
)
2109 void Interface::drawInventory() {
2110 if (!isInMainMode())
2114 int ci
= _inventoryStart
;
2117 if (_inventoryStart
!= 0) {
2118 drawPanelButtonArrow(&_mainPanel
, _inventoryUpButton
);
2120 if (_inventoryStart
!= _inventoryEnd
) {
2121 drawPanelButtonArrow(&_mainPanel
, _inventoryDownButton
);
2124 for (int i
= 0; i
< _mainPanel
.buttonsCount
; i
++) {
2125 if (_mainPanel
.buttons
[i
].type
!= kPanelButtonInventory
) {
2128 _mainPanel
.calcPanelButtonRect(&_mainPanel
.buttons
[i
], rect
);
2130 if (_vm
->getGameId() == GID_ITE
)
2131 _vm
->_gfx
->drawRect(rect
, kITEColorDarkGrey
);
2133 _vm
->_gfx
->drawRect(rect
, _vm
->KnownColor2ColorId(kKnownColorBlack
));
2135 if (ci
< _inventoryCount
) {
2136 obj
= _vm
->_actor
->getObj(_inventory
[ci
]);
2137 _vm
->_sprite
->draw(_vm
->_sprite
->_inventorySprites
, obj
->_spriteListResourceId
, rect
, 256);
2144 void Interface::setVerbState(int verb
, int state
) {
2145 PanelButton
* panelButton
= getPanelButtonByVerbType(verb
);
2146 if (panelButton
== NULL
) return;
2148 state
= (_mainPanel
.currentButton
== panelButton
) ? 1 : 0;
2150 panelButton
->state
= state
;
2154 void Interface::drawButtonBox(const Rect
& rect
, ButtonKind kind
, bool down
) {
2159 byte odl
, our
, idl
, iur
;
2164 frameColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2165 fillColor
= kITEColorLightBlue96
;
2166 odl
= kITEColorDarkBlue8a
;
2167 our
= kITEColorLightBlue92
;
2170 solidColor
= down
? kITEColorLightBlue94
: kITEColorLightBlue96
;
2173 if (_vm
->getGameId() == GID_ITE
) {
2174 cornerColor
= frameColor
= fillColor
= kITEColorLightBlue96
;
2175 our
= kITEColorDarkBlue8a
;
2176 odl
= kITEColorLightBlue94
;
2177 solidColor
= down
? kITEColorBlue
: kITEColorDarkGrey0C
;
2179 cornerColor
= frameColor
= fillColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2180 our
= odl
= solidColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2187 frameColor
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2188 solidColor
= fillColor
= kITEColorLightBlue96
;
2189 odl
= kITEColorDarkBlue8a
;
2190 our
= kITEColorLightBlue94
;
2202 int w
= rect
.width();
2203 int h
= rect
.height();
2204 int xe
= rect
.right
- 1;
2205 int ye
= rect
.bottom
- 1;
2207 _vm
->_gfx
->setPixelColor(x
, y
, cornerColor
);
2208 _vm
->_gfx
->setPixelColor(x
, ye
, cornerColor
);
2209 _vm
->_gfx
->setPixelColor(xe
, y
, cornerColor
);
2210 _vm
->_gfx
->setPixelColor(xe
, ye
, cornerColor
);
2211 _vm
->_gfx
->hLine(x
+ 1, y
, x
+ w
- 2, frameColor
);
2212 _vm
->_gfx
->hLine(x
+ 1, ye
, x
+ w
- 2, frameColor
);
2213 _vm
->_gfx
->vLine(x
, y
+ 1, y
+ h
- 2, frameColor
);
2214 _vm
->_gfx
->vLine(xe
, y
+ 1, y
+ h
- 2, frameColor
);
2222 _vm
->_gfx
->vLine(x
, y
, y
+ h
- 1, odl
);
2223 _vm
->_gfx
->hLine(x
, ye
, x
+ w
- 1, odl
);
2224 _vm
->_gfx
->vLine(xe
, y
, y
+ h
- 2, our
);
2225 _vm
->_gfx
->hLine(x
+ 1, y
, x
+ 1 + w
- 2, our
);
2233 _vm
->_gfx
->setPixelColor(x
, y
, fillColor
);
2234 _vm
->_gfx
->setPixelColor(xe
, ye
, fillColor
);
2235 _vm
->_gfx
->vLine(x
, y
+ 1, y
+ 1 + h
- 2, idl
);
2236 _vm
->_gfx
->hLine(x
+ 1, ye
, x
+ 1 + w
- 2, idl
);
2237 _vm
->_gfx
->vLine(xe
, y
, y
+ h
- 2, iur
);
2238 _vm
->_gfx
->hLine(x
+ 1, y
, x
+ 1 + w
- 2, iur
);
2243 Common::Rect
fill(x
, y
, x
+ w
, y
+ h
);
2244 _vm
->_gfx
->fillRect(fill
, solidColor
);
2245 _vm
->_render
->addDirtyRect(rect
);
2248 static const int readingSpeeds
[] = { kTextClick
, kTextSlow
, kTextMid
, kTextFast
};
2250 void Interface::drawPanelButtonText(InterfacePanel
*panel
, PanelButton
*panelButton
, int spritenum
) {
2257 KnownColor textColor
;
2260 KnownColor textShadowKnownColor
= kKnownColorVerbTextShadow
;
2261 KnownFont textFont
= kKnownFontMedium
;
2263 textId
= panelButton
->id
;
2264 switch (panelButton
->id
) {
2265 case kTextReadingSpeed
:
2266 if (_vm
->getGameId() == GID_ITE
&& !(_vm
->getFeatures() & GF_ITE_FLOPPY
)) {
2267 if (_vm
->_subtitlesEnabled
)
2272 textId
= readingSpeeds
[_vm
->_readingSpeed
];
2276 if (_vm
->_musicVolume
)
2277 textId
= kText10Percent
+ _vm
->_musicVolume
/ 25 - 1;
2282 if (_vm
->_soundVolume
)
2283 textId
= kText10Percent
+ _vm
->_soundVolume
/ 25 - 1;
2288 if (_vm
->_subtitlesEnabled
&& _vm
->_voicesEnabled
)
2290 else if (_vm
->_subtitlesEnabled
&& !_vm
->_voicesEnabled
)
2292 else if (!_vm
->_subtitlesEnabled
&& _vm
->_voicesEnabled
)
2293 textId
= kTextAudio
;
2296 if (_vm
->getGameId() == GID_ITE
) {
2297 text
= _vm
->getTextString(textId
);
2298 textFont
= kKnownFontMedium
;
2299 textShadowKnownColor
= kKnownColorVerbTextShadow
;
2300 textWidth
= _vm
->_font
->getStringWidth(kKnownFontMedium
, text
, 0, kFontNormal
);
2301 textHeight
= _vm
->_font
->getHeight(kKnownFontMedium
);
2303 if (textId
< 39 || textId
> 50) {
2304 // Read non-hardcoded strings from the LUT string table, loaded from the game
2306 text
= _vm
->_script
->_mainStrings
.getString(IHNMTextStringIdsLUT
[textId
]);
2308 // Hardcoded strings in IHNM are read from the ITE hardcoded strings
2309 text
= _vm
->getTextString(textId
);
2312 textFont
= kKnownFontVerb
;
2313 textShadowKnownColor
= kKnownColorTransparent
;
2314 textWidth
= _vm
->_font
->getStringWidth(kKnownFontVerb
, text
, 0, kFontNormal
);
2315 textHeight
= _vm
->_font
->getHeight(kKnownFontVerb
);
2318 point
.x
= panel
->x
+ panelButton
->xOffset
+ (panelButton
->width
/ 2) - (textWidth
/ 2);
2319 point
.y
= panel
->y
+ panelButton
->yOffset
+ (panelButton
->height
/ 2) - (textHeight
/ 2);
2321 if (panelButton
== panel
->currentButton
) {
2322 textColor
= kKnownColorVerbTextActive
;
2324 textColor
= kKnownColorVerbText
;
2327 panel
->calcPanelButtonRect(panelButton
, rect
);
2328 if (_vm
->getGameId() == GID_ITE
) {
2329 drawButtonBox(rect
, kButton
, panelButton
->state
> 0);
2331 litButton
= panelButton
->state
> 0;
2333 if (panel
== &_optionPanel
) {
2334 texturePoint
.x
= _optionPanel
.x
+ panelButton
->xOffset
- 1;
2335 texturePoint
.y
= _optionPanel
.y
+ panelButton
->yOffset
- 1;
2336 _vm
->_sprite
->draw(_optionPanel
.sprites
, spritenum
+ 2 + litButton
, texturePoint
, 256);
2337 } else if (panel
== &_quitPanel
) {
2338 texturePoint
.x
= _quitPanel
.x
+ panelButton
->xOffset
- 3;
2339 texturePoint
.y
= _quitPanel
.y
+ panelButton
->yOffset
- 3;
2340 _vm
->_sprite
->draw(_quitPanel
.sprites
, litButton
, texturePoint
, 256);
2341 } else if (panel
== &_savePanel
) {
2342 texturePoint
.x
= _savePanel
.x
+ panelButton
->xOffset
- 3;
2343 texturePoint
.y
= _savePanel
.y
+ panelButton
->yOffset
- 3;
2344 _vm
->_sprite
->draw(_savePanel
.sprites
, litButton
, texturePoint
, 256);
2345 // Input text box sprite
2346 texturePoint
.x
= _savePanel
.x
+ _saveEdit
->xOffset
- 2;
2347 texturePoint
.y
= _savePanel
.y
+ _saveEdit
->yOffset
- 2;
2348 _vm
->_sprite
->draw(_savePanel
.sprites
, 2, texturePoint
, 256);
2349 } else if (panel
== &_loadPanel
) {
2350 texturePoint
.x
= _loadPanel
.x
+ panelButton
->xOffset
- 3;
2351 texturePoint
.y
= _loadPanel
.y
+ panelButton
->yOffset
- 3;
2352 _vm
->_sprite
->draw(_loadPanel
.sprites
, litButton
, texturePoint
, 256);
2354 // revert to default behavior
2355 drawButtonBox(rect
, kButton
, panelButton
->state
> 0);
2359 _vm
->_font
->textDraw(textFont
, text
, point
,
2360 _vm
->KnownColor2ColorId(textColor
), _vm
->KnownColor2ColorId(textShadowKnownColor
), kFontShadow
);
2363 void Interface::drawPanelButtonArrow(InterfacePanel
*panel
, PanelButton
*panelButton
) {
2367 if (panel
->currentButton
== panelButton
) {
2368 if (panelButton
->state
!= 0) {
2369 spriteNumber
= panelButton
->downSpriteNumber
;
2371 spriteNumber
= panelButton
->overSpriteNumber
;
2374 spriteNumber
= panelButton
->upSpriteNumber
;
2377 point
.x
= panel
->x
+ panelButton
->xOffset
;
2378 point
.y
= panel
->y
+ panelButton
->yOffset
;
2380 if (_vm
->getGameId() == GID_ITE
)
2381 _vm
->_sprite
->draw(_vm
->_sprite
->_mainSprites
, spriteNumber
, point
, 256);
2383 _vm
->_sprite
->draw(_vm
->_sprite
->_arrowSprites
, spriteNumber
, point
, 256);
2386 void Interface::drawVerbPanelText(PanelButton
*panelButton
, KnownColor textKnownColor
, KnownColor textShadowKnownColor
) {
2392 if (_vm
->getGameId() == GID_ITE
) {
2393 textId
= verbToTextIdITE
[panelButton
->id
- 1];
2394 text
= _vm
->getTextString(textId
);
2396 textId
= panelButton
->id
;
2397 text
= _vm
->_script
->_mainStrings
.getString(textId
+ 1);
2398 textShadowKnownColor
= kKnownColorTransparent
;
2401 textWidth
= _vm
->_font
->getStringWidth(kKnownFontVerb
, text
, 0, kFontNormal
);
2403 if (_vm
->getGameId() == GID_ITE
) {
2404 point
.x
= _mainPanel
.x
+ panelButton
->xOffset
+ 1 + (panelButton
->width
- 1 - textWidth
) / 2;
2405 point
.y
= _mainPanel
.y
+ panelButton
->yOffset
+ 1;
2407 point
.x
= _mainPanel
.x
+ panelButton
->xOffset
+ 1 + (panelButton
->width
- textWidth
) / 2;
2408 point
.y
= _mainPanel
.y
+ panelButton
->yOffset
+ 12;
2411 _vm
->_font
->textDraw(kKnownFontVerb
, text
, point
,
2412 _vm
->KnownColor2ColorId(textKnownColor
), _vm
->KnownColor2ColorId(textShadowKnownColor
),
2413 (textShadowKnownColor
!= kKnownColorTransparent
) ? kFontShadow
: kFontNormal
);
2418 void Interface::converseInit(void) {
2419 for (int i
= 0; i
< CONVERSE_MAX_TEXTS
; i
++)
2420 _converseText
[i
].text
= NULL
;
2424 void Interface::converseClear(void) {
2425 for (int i
= 0; i
< CONVERSE_MAX_TEXTS
; i
++) {
2426 if (_converseText
[i
].text
!= NULL
) {
2427 free(_converseText
[i
].text
);
2428 _converseText
[i
].text
= NULL
;
2430 _converseText
[i
].stringNum
= -1;
2431 _converseText
[i
].replyId
= 0;
2432 _converseText
[i
].replyFlags
= 0;
2433 _converseText
[i
].replyBit
= 0;
2436 _converseTextCount
= 0;
2437 _converseStrCount
= 0;
2438 _converseStartPos
= 0;
2439 _converseEndPos
= 0;
2443 bool Interface::converseAddText(const char *text
, int strId
, int replyId
, byte replyFlags
, int replyBit
) {
2444 int count
= 0; // count how many pieces of text per string
2449 assert(strlen(text
) < CONVERSE_MAX_WORK_STRING
);
2451 strncpy(_converseWorkString
, text
, CONVERSE_MAX_WORK_STRING
);
2454 len
= strlen(_converseWorkString
);
2456 for (i
= len
; i
>= 0; i
--) {
2457 c
= _converseWorkString
[i
];
2459 if (_vm
->getGameId() == GID_ITE
) {
2460 if ((c
== ' ' || c
== '\0') && (_vm
->_font
->getStringWidth(kKnownFontSmall
, _converseWorkString
, i
, kFontNormal
) <= _vm
->getDisplayInfo().converseMaxTextWidth
))
2463 if ((c
== ' ' || c
== '\0') && (_vm
->_font
->getStringWidth(kKnownFontVerb
, _converseWorkString
, i
, kFontNormal
) <= _vm
->getDisplayInfo().converseMaxTextWidth
))
2471 if (_converseTextCount
== CONVERSE_MAX_TEXTS
) {
2475 _converseText
[_converseTextCount
].text
= (char *)malloc(i
+ 1);
2476 strncpy(_converseText
[_converseTextCount
].text
, _converseWorkString
, i
);
2478 _converseText
[_converseTextCount
].strId
= strId
;
2479 _converseText
[_converseTextCount
].text
[i
] = 0;
2480 _converseText
[_converseTextCount
].textNum
= count
;
2481 _converseText
[_converseTextCount
].stringNum
= _converseStrCount
;
2482 _converseText
[_converseTextCount
].replyId
= replyId
;
2483 _converseText
[_converseTextCount
].replyFlags
= replyFlags
;
2484 _converseText
[_converseTextCount
].replyBit
= replyBit
;
2486 _converseTextCount
++;
2492 strncpy(_converseWorkString
, &_converseWorkString
[i
+ 1], len
- i
);
2495 _converseStrCount
++;
2500 void Interface::converseDisplayText() {
2503 _converseStartPos
= 0;
2505 end
= _converseTextCount
- _vm
->getDisplayInfo().converseTextLines
;
2510 _converseEndPos
= end
;
2515 void Interface::converseSetTextLines(int row
) {
2516 int pos
= row
+ _converseStartPos
;
2517 if (pos
>= _converseTextCount
)
2519 if (pos
!= _conversePos
) {
2525 void Interface::converseDisplayTextLines() {
2535 Rect
rect(8, _vm
->getDisplayInfo().converseTextLines
* _vm
->getDisplayInfo().converseTextHeight
);
2538 assert(_conversePanel
.buttonsCount
>= 6);
2540 if (_vm
->getGameId() == GID_ITE
) {
2541 bulletForegnd
= kITEColorGreen
;
2542 bulletBackgnd
= kITEColorBlack
;
2544 bulletForegnd
= _vm
->KnownColor2ColorId(kKnownColorBrightWhite
);
2545 bulletBackgnd
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2546 bullet
[0] = '>'; // different bullet in IHNM
2549 rect
.moveTo(_conversePanel
.x
+ _conversePanel
.buttons
[0].xOffset
,
2550 _conversePanel
.y
+ _conversePanel
.buttons
[0].yOffset
);
2552 if (_vm
->getGameId() == GID_ITE
)
2553 _vm
->_gfx
->drawRect(rect
, kITEColorDarkGrey
); //fill bullet place
2555 _vm
->_gfx
->drawRect(rect
, _vm
->KnownColor2ColorId(kKnownColorBlack
)); //fill bullet place
2557 for (int i
= 0; i
< _vm
->getDisplayInfo().converseTextLines
; i
++) {
2558 relPos
= _converseStartPos
+ i
;
2560 if (_converseTextCount
<= relPos
) {
2564 if (_conversePos
>= 0 && _converseText
[_conversePos
].stringNum
== _converseText
[relPos
].stringNum
) {
2565 if (_vm
->getGameId() == GID_ITE
) {
2566 foregnd
= kITEColorBrightWhite
;
2567 backgnd
= (!_vm
->leftMouseButtonPressed()) ? kITEColorDarkGrey
: kITEColorGrey
;
2569 foregnd
= _vm
->KnownColor2ColorId(kKnownColorVerbTextActive
);
2570 backgnd
= _vm
->KnownColor2ColorId(kKnownColorVerbTextActive
);
2573 if (_vm
->getGameId() == GID_ITE
) {
2574 foregnd
= kITEColorBlue
;
2575 backgnd
= kITEColorDarkGrey
;
2577 foregnd
= _vm
->KnownColor2ColorId(kKnownColorBrightWhite
);
2578 backgnd
= _vm
->KnownColor2ColorId(kKnownColorBlack
);
2582 _conversePanel
.calcPanelButtonRect(&_conversePanel
.buttons
[i
], rect
);
2584 _vm
->_gfx
->drawRect(rect
, backgnd
);
2586 str
= _converseText
[relPos
].text
;
2588 if (_converseText
[relPos
].textNum
== 0) { // first entry
2589 textPoint
.x
= rect
.left
- 6;
2590 textPoint
.y
= rect
.top
;
2592 if (_vm
->getGameId() == GID_ITE
)
2593 _vm
->_font
->textDraw(kKnownFontSmall
, bullet
, textPoint
, bulletForegnd
, bulletBackgnd
, (FontEffectFlags
)(kFontShadow
| kFontDontmap
));
2595 _vm
->_font
->textDraw(kKnownFontVerb
, bullet
, textPoint
, bulletForegnd
, bulletBackgnd
, (FontEffectFlags
)(kFontShadow
| kFontDontmap
));
2597 textPoint
.x
= rect
.left
+ 1;
2598 textPoint
.y
= rect
.top
;
2599 if (_vm
->getGameId() == GID_ITE
)
2600 _vm
->_font
->textDraw(kKnownFontSmall
, str
, textPoint
, foregnd
, kITEColorBlack
, kFontShadow
);
2602 _vm
->_font
->textDraw(kKnownFontVerb
, str
, textPoint
, foregnd
, _vm
->KnownColor2ColorId(kKnownColorBlack
), kFontShadow
);
2605 if (_converseStartPos
!= 0) {
2606 drawPanelButtonArrow(&_conversePanel
, _converseUpButton
);
2609 if (_converseStartPos
!= _converseEndPos
) {
2610 drawPanelButtonArrow(&_conversePanel
, _converseDownButton
);
2614 void Interface::converseChangePos(int chg
) {
2615 // Arrows will scroll the converse panel or down up to 4 conversation options
2616 for (int i
= 1; i
<= 4; i
++) {
2617 if ((chg
< 0 && _converseStartPos
+ chg
>= 0) ||
2618 (chg
> 0 && _converseStartPos
< _converseEndPos
)) {
2619 _converseStartPos
+= chg
;
2625 void Interface::converseSetPos(int key
) {
2627 int selection
= key
- '1';
2629 if (selection
>= _converseTextCount
)
2632 converseSetTextLines(selection
);
2634 ct
= &_converseText
[_conversePos
];
2636 _vm
->_script
->finishDialog(ct
->strId
, ct
->replyId
, ct
->replyFlags
, ct
->replyBit
);
2638 if (_vm
->_scene
->isITEPuzzleScene())
2639 _vm
->_puzzle
->handleReply(ct
->replyId
);
2645 void Interface::handleConverseUpdate(const Point
& mousePoint
) {
2648 PanelButton
*last
= _conversePanel
.currentButton
;
2650 if (!_vm
->mouseButtonPressed()) { // remove pressed flag
2651 if (_converseUpButton
) {
2652 _converseUpButton
->state
= 0;
2653 _converseDownButton
->state
= 0;
2657 _conversePanel
.currentButton
= converseHitTest(mousePoint
);
2658 changed
= last
!= _conversePanel
.currentButton
;
2661 if (_conversePanel
.currentButton
== NULL
) {
2669 if (_conversePanel
.currentButton
->type
== kPanelButtonConverseText
) {
2670 converseSetTextLines(_conversePanel
.currentButton
->id
);
2673 if (_conversePanel
.currentButton
->type
== kPanelButtonArrow
) {
2674 if (_conversePanel
.currentButton
->state
== 1) {
2675 converseChangePos(_conversePanel
.currentButton
->id
);
2682 void Interface::handleConverseClick(const Point
& mousePoint
) {
2683 _conversePanel
.currentButton
= converseHitTest(mousePoint
);
2685 if (_conversePanel
.currentButton
== NULL
) {
2689 if (_conversePanel
.currentButton
->type
== kPanelButtonConverseText
) {
2690 converseSetPos(_conversePanel
.currentButton
->ascii
);
2693 if (_conversePanel
.currentButton
->type
== kPanelButtonArrow
) {
2694 _conversePanel
.currentButton
->state
= 1;
2695 converseChangePos(_conversePanel
.currentButton
->id
);
2700 void Interface::saveState(Common::OutSaveFile
*out
) {
2701 out
->writeUint16LE(_inventoryCount
);
2703 for (int i
= 0; i
< _inventoryCount
; i
++) {
2704 out
->writeUint16LE(_inventory
[i
]);
2708 void Interface::loadState(Common::InSaveFile
*in
) {
2709 _inventoryCount
= in
->readUint16LE();
2711 for (int i
= 0; i
< _inventoryCount
; i
++) {
2712 _inventory
[i
] = in
->readUint16LE();
2718 void Interface::mapPanelShow() {
2721 size_t resourceLength
, imageLength
;
2724 int imageWidth
, imageHeight
;
2726 PalEntry cPal
[PAL_ENTRIES
];
2728 _vm
->_gfx
->showCursor(false);
2730 rect
.left
= rect
.top
= 0;
2732 _vm
->_resource
->loadResource(_interfaceContext
,
2733 _vm
->_resource
->convertResourceId(RID_ITE_TYCHO_MAP
), resource
, resourceLength
);
2734 if (resourceLength
== 0) {
2735 error("Interface::mapPanelShow() unable to load Tycho map resource");
2738 _vm
->_gfx
->getCurrentPal(_mapSavedPal
);
2740 for (i
= 0; i
< 6 ; i
++) {
2741 _vm
->_gfx
->palToBlack(_mapSavedPal
, 0.2 * i
);
2742 _vm
->_render
->drawScene();
2743 _vm
->_system
->delayMillis(5);
2746 _vm
->_render
->setFlag(RF_MAP
);
2748 _vm
->decodeBGImage(resource
, resourceLength
, &image
, &imageLength
, &imageWidth
, &imageHeight
);
2749 pal
= _vm
->getImagePal(resource
, resourceLength
);
2751 for (i
= 0; i
< PAL_ENTRIES
; i
++) {
2752 cPal
[i
].red
= *pal
++;
2753 cPal
[i
].green
= *pal
++;
2754 cPal
[i
].blue
= *pal
++;
2757 rect
.setWidth(imageWidth
);
2758 rect
.setHeight(imageHeight
);
2760 _vm
->_gfx
->drawRegion(rect
, image
);
2763 for (i
= 0; i
< 6 ; i
++) {
2764 _vm
->_gfx
->blackToPal(cPal
, 0.2 * i
);
2765 _vm
->_render
->drawScene();
2766 _vm
->_system
->delayMillis(5);
2772 setSaveReminderState(false);
2774 _mapPanelCrossHairState
= true;
2777 void Interface::mapPanelClean() {
2778 PalEntry pal
[PAL_ENTRIES
];
2781 _vm
->_gfx
->getCurrentPal(pal
);
2783 for (i
= 0; i
< 6 ; i
++) {
2784 _vm
->_gfx
->palToBlack(pal
, 0.2 * i
);
2785 _vm
->_render
->drawScene();
2786 _vm
->_system
->delayMillis(5);
2789 _vm
->_render
->clearFlag(RF_MAP
);
2790 setMode(kPanelMain
);
2792 _vm
->_gfx
->showCursor(true);
2793 _vm
->_render
->drawScene();
2795 for (i
= 0; i
< 6 ; i
++) {
2796 _vm
->_gfx
->blackToPal(_mapSavedPal
, 0.2 * i
);
2797 _vm
->_render
->drawScene();
2798 _vm
->_system
->delayMillis(5);
2802 void Interface::mapPanelDrawCrossHair() {
2803 _mapPanelCrossHairState
= !_mapPanelCrossHairState
;
2805 Point mapPosition
= _vm
->_isoMap
->getMapPosition();
2806 Rect
screen(_vm
->getDisplayInfo().width
, _vm
->_scene
->getHeight());
2808 if (screen
.contains(mapPosition
)) {
2809 _vm
->_sprite
->draw(_vm
->_sprite
->_mainSprites
,
2810 _mapPanelCrossHairState
? RID_ITE_SPR_CROSSHAIR
: RID_ITE_SPR_CROSSHAIR
+ 1,
2815 void Interface::keyBoss() {
2816 if (_vm
->getGameId() == GID_ITE
)
2819 if (_bossMode
!= -1 || _fadeMode
!= kNoFade
)
2822 _vm
->_sound
->pauseVoice();
2823 _vm
->_sound
->pauseSound();
2824 _vm
->_music
->pause();
2828 size_t resourceLength
, imageLength
;
2831 int imageWidth
, imageHeight
;
2833 PalEntry cPal
[PAL_ENTRIES
];
2835 _vm
->_gfx
->showCursor(false);
2837 rect
.left
= rect
.top
= 0;
2839 _vm
->_resource
->loadResource(_interfaceContext
, RID_IHNM_BOSS_SCREEN
, resource
, resourceLength
);
2840 if (resourceLength
== 0) {
2841 error("Interface::bossKey() unable to load Boss image resource");
2844 _bossMode
= _panelMode
;
2845 setMode(kPanelBoss
);
2847 _vm
->decodeBGImage(resource
, resourceLength
, &image
, &imageLength
, &imageWidth
, &imageHeight
);
2848 rect
.setWidth(imageWidth
);
2849 rect
.setHeight(imageHeight
);
2851 _vm
->_gfx
->getCurrentPal(_mapSavedPal
);
2852 pal
= _vm
->getImagePal(resource
, resourceLength
);
2858 for (i
= 1; i
< PAL_ENTRIES
; i
++) {
2860 cPal
[i
].green
= 128;
2864 _vm
->_gfx
->drawRegion(rect
, image
);
2866 _vm
->_gfx
->setPalette(cPal
);
2873 void Interface::keyBossExit() {
2874 PalEntry pal
[PAL_ENTRIES
];
2876 _vm
->_sound
->resumeVoice();
2877 _vm
->_sound
->resumeSound();
2878 _vm
->_music
->resume();
2880 _vm
->_gfx
->getCurrentPal(pal
);
2882 _vm
->_gfx
->palToBlack(pal
, 1);
2885 _vm
->_render
->drawScene();
2887 _vm
->_gfx
->blackToPal(_mapSavedPal
, 1);
2889 _vm
->_gfx
->showCursor(true);
2895 } // End of namespace Saga