mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
1556 lines
43 KiB
C++
1556 lines
43 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 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
*/
|
||
|
||
#include "bladerunner/ui/kia.h"
|
||
|
||
#include "bladerunner/actor.h"
|
||
#include "bladerunner/audio_player.h"
|
||
#include "bladerunner/bladerunner.h"
|
||
#include "bladerunner/combat.h"
|
||
#include "bladerunner/font.h"
|
||
#include "bladerunner/game_constants.h"
|
||
#include "bladerunner/game_flags.h"
|
||
#include "bladerunner/game_info.h"
|
||
#include "bladerunner/mouse.h"
|
||
#include "bladerunner/savefile.h"
|
||
#include "bladerunner/scene.h"
|
||
#include "bladerunner/shape.h"
|
||
#include "bladerunner/script/kia_script.h"
|
||
#include "bladerunner/settings.h"
|
||
#include "bladerunner/slice_renderer.h"
|
||
#include "bladerunner/text_resource.h"
|
||
#include "bladerunner/time.h"
|
||
#include "bladerunner/ui/kia_log.h"
|
||
#include "bladerunner/ui/kia_section_base.h"
|
||
#include "bladerunner/ui/kia_section_clues.h"
|
||
#include "bladerunner/ui/kia_section_crimes.h"
|
||
#include "bladerunner/ui/kia_section_diagnostic.h"
|
||
#include "bladerunner/ui/kia_section_help.h"
|
||
#include "bladerunner/ui/kia_section_load.h"
|
||
#include "bladerunner/ui/kia_section_settings.h"
|
||
#include "bladerunner/ui/kia_section_pogo.h"
|
||
#include "bladerunner/ui/kia_section_save.h"
|
||
#include "bladerunner/ui/kia_section_suspects.h"
|
||
#include "bladerunner/ui/ui_image_picker.h"
|
||
#include "bladerunner/vqa_player.h"
|
||
#include "bladerunner/subtitles.h"
|
||
|
||
#include "common/str.h"
|
||
#include "common/keyboard.h"
|
||
#include "common/debug.h"
|
||
#include "backends/keymapper/keymap.h"
|
||
#include "backends/keymapper/keymapper.h"
|
||
|
||
#include "graphics/scaler.h"
|
||
|
||
namespace BladeRunner {
|
||
|
||
const char *KIA::kPogo = "POGO";
|
||
|
||
KIA::KIA(BladeRunnerEngine *vm) {
|
||
_vm = vm;
|
||
|
||
_script = new KIAScript(_vm);
|
||
_log = new KIALog(_vm);
|
||
_shapes = new Shapes(_vm);
|
||
_playerPhotographs = new Shapes(_vm);
|
||
|
||
_forceOpen = false;
|
||
_currentSectionId = kKIASectionNone;
|
||
_lastSectionIdKIA = kKIASectionCrimes;
|
||
_lastSectionIdOptions = kKIASectionSettings;
|
||
_playerVqaTimeLast = _vm->_time->currentSystem();
|
||
_playerVqaFrame = 0;
|
||
_playerVisualizerState = 0;
|
||
_playerPhotographId = -1;
|
||
_playerSliceModelId = -1;
|
||
_playerSliceModelAngle = 0.0f;
|
||
_timeLast = _vm->_time->currentSystem();
|
||
_playerActorDialogueQueuePosition = 0;
|
||
_playerActorDialogueQueueSize = 0;
|
||
_playerActorDialogueState = 0;
|
||
_currentSection = nullptr;
|
||
_mainVqaPlayer = nullptr;
|
||
_playerVqaPlayer = nullptr;
|
||
_transitionId = 0;
|
||
|
||
_pogoPos = 0;
|
||
|
||
// original imageCount was 22. We add +1 to have a description box for objects in cut content
|
||
// We don't have separated cases here, for _vm->_cutContent since that causes assertion fault if
|
||
// loading a "restored content" save game in a "original game" version
|
||
_buttons = new UIImagePicker(_vm, 23);
|
||
|
||
_crimesSection = new KIASectionCrimes(_vm, _vm->_playerActor->_clues);
|
||
_suspectsSection = new KIASectionSuspects(_vm, _vm->_playerActor->_clues);
|
||
_cluesSection = new KIASectionClues(_vm, _vm->_playerActor->_clues);
|
||
_settingsSection = new KIASectionSettings(_vm);
|
||
_helpSection = new KIASectionHelp(_vm);
|
||
_saveSection = new KIASectionSave(_vm);
|
||
_loadSection = new KIASectionLoad(_vm);
|
||
_diagnosticSection = new KIASectionDiagnostic(_vm);
|
||
_pogoSection = new KIASectionPogo(_vm);
|
||
|
||
for (int i = 0; i < kPlayerActorDialogueQueueCapacity; ++i) {
|
||
_playerActorDialogueQueue[i].actorId = -1;
|
||
_playerActorDialogueQueue[i].sentenceId = -1;
|
||
}
|
||
}
|
||
|
||
KIA::~KIA() {
|
||
if (isOpen()) {
|
||
unload();
|
||
}
|
||
|
||
_thumbnail.free();
|
||
delete _crimesSection;
|
||
delete _suspectsSection;
|
||
delete _cluesSection;
|
||
delete _settingsSection;
|
||
delete _helpSection;
|
||
delete _saveSection;
|
||
delete _loadSection;
|
||
delete _diagnosticSection;
|
||
delete _pogoSection;
|
||
_playerImage.free();
|
||
delete _buttons;
|
||
delete _shapes;
|
||
delete _playerPhotographs;
|
||
delete _log;
|
||
delete _script;
|
||
}
|
||
|
||
void KIA::reset() {
|
||
_lastSectionIdKIA = kKIASectionCrimes;
|
||
_lastSectionIdOptions = kKIASectionSettings;
|
||
_playerImage.free();
|
||
_playerVqaFrame = 0;
|
||
_playerVisualizerState = 0;
|
||
_playerSliceModelAngle = 0.0f;
|
||
|
||
_crimesSection->reset();
|
||
_suspectsSection->reset();
|
||
_cluesSection->reset();
|
||
}
|
||
|
||
void KIA::openLastOpened() {
|
||
open(_lastSectionIdKIA);
|
||
}
|
||
|
||
void KIA::open(KIASections sectionId) {
|
||
if (_vm->getEventManager()->getKeymapper() != nullptr) {
|
||
if ( _vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kGameplayKeymapId) != nullptr) {
|
||
// When disabling a keymap, make sure all their active events in the _activeCustomEvents array
|
||
// are cleared, because as they won't get an explicit "EVENT_CUSTOM_ENGINE_ACTION_END" event.
|
||
_vm->cleanupPendingRepeatingEvents(BladeRunnerEngine::kGameplayKeymapId);
|
||
_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kGameplayKeymapId)->setEnabled(false);
|
||
}
|
||
|
||
if (_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kKiaKeymapId) != nullptr)
|
||
_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kKiaKeymapId)->setEnabled(true);
|
||
}
|
||
|
||
if (_currentSectionId == sectionId) {
|
||
return;
|
||
}
|
||
|
||
if (sectionId == kKIASectionNone) {
|
||
unload();
|
||
return;
|
||
}
|
||
|
||
if (!isOpen()) {
|
||
init();
|
||
}
|
||
|
||
switch (_currentSectionId) {
|
||
case kKIASectionCrimes:
|
||
_crimesSection->saveToLog();
|
||
break;
|
||
case kKIASectionSuspects:
|
||
_suspectsSection->saveToLog();
|
||
break;
|
||
case kKIASectionClues:
|
||
_cluesSection->saveToLog();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (sectionId != kKIASectionCrimes && sectionId != kKIASectionSuspects && sectionId != kKIASectionClues) {
|
||
playerReset();
|
||
}
|
||
|
||
_transitionId = getTransitionId(_currentSectionId, sectionId);
|
||
const char *name = getSectionVqaName(sectionId);
|
||
if (getSectionVqaName(_currentSectionId) != name) {
|
||
if (_mainVqaPlayer) {
|
||
_mainVqaPlayer->close();
|
||
delete _mainVqaPlayer;
|
||
_mainVqaPlayer = nullptr;
|
||
}
|
||
|
||
_mainVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, name);
|
||
_mainVqaPlayer->open();
|
||
}
|
||
|
||
if (_transitionId) {
|
||
playTransitionSound(_transitionId);
|
||
_mainVqaPlayer->setLoop(getVqaLoopTransition(_transitionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||
_mainVqaPlayer->setLoop(getVqaLoopMain(sectionId), -1, kLoopSetModeEnqueue, loopEnded, this);
|
||
} else {
|
||
int loopId = getVqaLoopMain(sectionId);
|
||
_mainVqaPlayer->setLoop(loopId, -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||
_mainVqaPlayer->setLoop(loopId + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||
}
|
||
|
||
_buttons->resetImages();
|
||
createButtons(sectionId);
|
||
switchSection(sectionId);
|
||
_currentSectionId = sectionId;
|
||
|
||
if (sectionId == kKIASectionCrimes || sectionId == kKIASectionSuspects || sectionId == kKIASectionClues) {
|
||
_lastSectionIdKIA = _currentSectionId;
|
||
}
|
||
|
||
if (sectionId == kKIASectionSettings || sectionId == kKIASectionHelp || sectionId == kKIASectionSave || sectionId == kKIASectionLoad) {
|
||
_lastSectionIdOptions = _currentSectionId;
|
||
}
|
||
}
|
||
|
||
bool KIA::isOpen() const {
|
||
return _currentSectionId != kKIASectionNone;
|
||
}
|
||
|
||
void KIA::tick() {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
uint32 timeNow = _vm->_time->currentSystem();
|
||
// unsigned difference is intentional
|
||
uint32 timeDiff = timeNow - _timeLast;
|
||
|
||
if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition) {
|
||
_playerActorDialogueState = 0;
|
||
} else if (_playerActorDialogueState == 0) {
|
||
if (_playerSliceModelId == -1 && _playerPhotographId == -1 && _playerImage.getPixels() == nullptr) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP16), 70, 0, 0, 50, 0);
|
||
}
|
||
_playerActorDialogueState = 1;
|
||
} else if (_playerActorDialogueState == 200) {
|
||
if (!_vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->isSpeeching()) {
|
||
if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
|
||
_playerActorDialogueQueuePosition = (_playerActorDialogueQueuePosition + 1) % kPlayerActorDialogueQueueCapacity;
|
||
}
|
||
if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
|
||
_vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
|
||
}
|
||
}
|
||
} else {
|
||
_playerActorDialogueState += timeDiff;
|
||
|
||
if (_playerActorDialogueState >= 200) {
|
||
_playerActorDialogueState = 200;
|
||
_vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
|
||
}
|
||
}
|
||
|
||
uint32 timeDiffDiv48 = (timeNow < _playerVqaTimeLast) ? 0u : (timeNow - _playerVqaTimeLast) / 48;
|
||
if (timeDiffDiv48 > 0u) {
|
||
_playerVqaTimeLast = timeNow;
|
||
if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition || _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) {
|
||
if (_playerVisualizerState > 0) {
|
||
_playerVisualizerState = (_playerVisualizerState < timeDiffDiv48) ? 0u : MAX<uint32>(_playerVisualizerState - timeDiffDiv48, 0u);
|
||
}
|
||
} else {
|
||
if (_playerVisualizerState < 2) {
|
||
_playerVisualizerState = MIN<uint32>(_playerVisualizerState + timeDiffDiv48, 2u);
|
||
}
|
||
}
|
||
|
||
if ( _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) {
|
||
if (_playerVqaFrame < 8) {
|
||
int newVqaFrame = MIN<uint32>(timeDiffDiv48 + _playerVqaFrame, 8u);
|
||
if (_playerVqaFrame <= 0 && newVqaFrame > 0) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxMECHAN1), 100, 70, 70, 50, 0);
|
||
}
|
||
_playerVqaFrame = newVqaFrame;
|
||
}
|
||
} else {
|
||
if (_playerVqaFrame > 0) {
|
||
int newVqaFrame = (_playerVqaFrame < timeDiffDiv48) ? 0 : MAX<uint32>(_playerVqaFrame - timeDiffDiv48, 0u);
|
||
if (_playerVqaFrame >= 8 && newVqaFrame < 8) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxMECHAN1C), 100, 70, 70, 50, 0);
|
||
}
|
||
_playerVqaFrame = newVqaFrame;
|
||
}
|
||
}
|
||
}
|
||
|
||
_mainVqaPlayer->update(false);
|
||
blit(_vm->_surfaceBack, _vm->_surfaceFront);
|
||
|
||
Common::Point mouse = _vm->getMousePos();
|
||
|
||
if (!_transitionId) {
|
||
_buttons->handleMouseAction(mouse.x, mouse.y, false, false, false);
|
||
if (_buttons->hasHoveredImage()) {
|
||
_vm->_mouse->setCursor(1);
|
||
} else {
|
||
_vm->_mouse->setCursor(0);
|
||
}
|
||
if (_currentSection) {
|
||
_currentSection->handleMouseMove(mouse.x, mouse.y);
|
||
}
|
||
}
|
||
|
||
if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
|
||
_shapes->get(40)->draw(_vm->_surfaceFront, 0, 0);
|
||
_shapes->get(41)->draw(_vm->_surfaceFront, 211, 447);
|
||
}
|
||
if (_currentSectionId != kKIASectionQuit && _transitionId != 14) {
|
||
if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
|
||
_vm->_mainFont->drawString(&_vm->_surfaceFront, Common::String::format("%04d", _vm->_gameVars[kVariableChinyen]), 580, 341, _vm->_surfaceFront.w, _vm->_surfaceFront.format.RGBToColor(80, 96, 136));
|
||
} else {
|
||
_shapes->get(39)->draw(_vm->_surfaceFront, 583, 342);
|
||
}
|
||
}
|
||
|
||
_playerVqaPlayer->seekToFrame(_playerVqaFrame);
|
||
_playerVqaPlayer->update(true, true);
|
||
|
||
_playerSliceModelAngle += (float)(timeDiff) * 1.0f/400.0f;
|
||
while (_playerSliceModelAngle >= 2 * M_PI) {
|
||
_playerSliceModelAngle -= (float)(2 * M_PI);
|
||
}
|
||
|
||
if (_playerVqaFrame == 8) {
|
||
if (_playerSliceModelId != -1) {
|
||
_vm->_sliceRenderer->drawOnScreen(_playerSliceModelId, 0, 585, 80, _playerSliceModelAngle, 100.0, _vm->_surfaceFront);
|
||
} else if (_playerPhotographId != -1) {
|
||
const Shape *playerPhotograph = _playerPhotographs->get(_playerPhotographId);
|
||
int width = playerPhotograph->getWidth();
|
||
int height = playerPhotograph->getHeight();
|
||
playerPhotograph->draw(_vm->_surfaceFront, 590 - width / 2, 80 - height / 2);
|
||
} else if (_playerImage.getPixels() != nullptr) {
|
||
_vm->_surfaceFront.fillRect(Common::Rect(549, 49, 631, 111), _vm->_surfaceFront.format.RGBToColor(255, 255, 255));
|
||
_vm->_surfaceFront.copyRectToSurface(_playerImage.getPixels(), _playerImage.pitch, 550, 50, _playerImage.w, _playerImage.h);
|
||
}
|
||
}
|
||
|
||
if (_playerVisualizerState == 1) {
|
||
_shapes->get(51)->draw(_vm->_surfaceFront, 576, 174);
|
||
} else if (_playerVisualizerState == 2) {
|
||
_shapes->get(50)->draw(_vm->_surfaceFront, 576, 174);
|
||
_shapes->get(_vm->_rnd.getRandomNumberRng(90, 105))->draw(_vm->_surfaceFront, 576, 174);
|
||
}
|
||
if (!_transitionId) {
|
||
_buttons->draw(_vm->_surfaceFront);
|
||
if (_currentSection) {
|
||
_currentSection->draw(_vm->_surfaceFront);
|
||
}
|
||
}
|
||
if (_vm->_settings->getAmmo(0) > 0) {
|
||
if (_vm->_settings->getAmmoType() == 0) {
|
||
_shapes->get(42)->draw(_vm->_surfaceFront, 147, 405);
|
||
} else {
|
||
_shapes->get(45)->draw(_vm->_surfaceFront, 140, 446);
|
||
}
|
||
}
|
||
if (_vm->_settings->getAmmo(1) > 0) {
|
||
if (_vm->_settings->getAmmoType() == 1) {
|
||
_shapes->get(43)->draw(_vm->_surfaceFront, 167, 394);
|
||
} else {
|
||
_shapes->get(46)->draw(_vm->_surfaceFront, 160, 446);
|
||
}
|
||
}
|
||
if (_vm->_settings->getAmmo(2) > 0) {
|
||
if (_vm->_settings->getAmmoType() == 2) {
|
||
_shapes->get(44)->draw(_vm->_surfaceFront, 189, 385);
|
||
} else {
|
||
_shapes->get(47)->draw(_vm->_surfaceFront, 182, 446);
|
||
}
|
||
}
|
||
_vm->_mainFont->drawString(&_vm->_surfaceFront, "1.00", 438, 471, _vm->_surfaceFront.w, _vm->_surfaceFront.format.RGBToColor(56, 56, 56)); // 1.01 is DVD version, but only cd handling routines were changed, no game logic
|
||
if (!_transitionId) {
|
||
_buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y);
|
||
}
|
||
_vm->_mouse->draw(_vm->_surfaceFront, mouse.x, mouse.y);
|
||
|
||
_vm->_subtitles->tick(_vm->_surfaceFront);
|
||
|
||
_vm->blitToScreen(_vm->_surfaceFront);
|
||
|
||
_timeLast = timeNow;
|
||
}
|
||
|
||
void KIA::resume() {
|
||
// vqaPlayer::clear(this->_vqaPlayerMain);
|
||
if (_transitionId) {
|
||
_mainVqaPlayer->setLoop(getVqaLoopTransition(_transitionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||
_mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId), -1, kLoopSetModeEnqueue, loopEnded, this);
|
||
} else {
|
||
_mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||
_mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId) + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||
}
|
||
}
|
||
|
||
void KIA::handleMouseDown(int mouseX, int mouseY, bool mainButton) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
if (mainButton) {
|
||
_buttons->handleMouseAction(mouseX, mouseY, true, false, false);
|
||
}
|
||
if (_currentSection) {
|
||
_currentSection->handleMouseDown(mainButton);
|
||
}
|
||
}
|
||
|
||
void KIA::handleMouseUp(int mouseX, int mouseY, bool mainButton) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
if (mainButton) {
|
||
_buttons->handleMouseAction(mouseX, mouseY, false, true, false);
|
||
}
|
||
if (_currentSection) {
|
||
_currentSection->handleMouseUp(mainButton);
|
||
}
|
||
if (_currentSection && _currentSection->_scheduledSwitch) {
|
||
if (_currentSectionId == kKIASectionCrimes) {
|
||
open(kKIASectionSuspects);
|
||
_suspectsSection->selectSuspect(_crimesSection->_suspectSelected);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
} else if (_currentSectionId == kKIASectionSuspects) {
|
||
open(kKIASectionCrimes);
|
||
_crimesSection->selectCrime(_suspectsSection->_crimeSelected);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
} else {
|
||
open(kKIASectionNone);
|
||
}
|
||
}
|
||
}
|
||
|
||
void KIA::handleMouseScroll(int mouseX, int mouseY, int direction) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
if (_currentSection) {
|
||
_currentSection->handleMouseScroll(direction);
|
||
}
|
||
}
|
||
|
||
void KIA::handleKeyUp(const Common::KeyState &kbd) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
if (_currentSection) {
|
||
_currentSection->handleKeyUp(kbd);
|
||
}
|
||
}
|
||
|
||
void KIA::handleKeyDown(const Common::KeyState &kbd) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
if (toupper(kbd.ascii) != kPogo[_pogoPos]) {
|
||
_pogoPos = 0;
|
||
}
|
||
if (_currentSectionId != kKIASectionSave) {
|
||
if (toupper(kbd.ascii) == kPogo[_pogoPos]) {
|
||
++_pogoPos;
|
||
if (!kPogo[_pogoPos]) {
|
||
open(kKIASectionPogo);
|
||
_pogoPos = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (_currentSection) {
|
||
_currentSection->handleKeyDown(kbd);
|
||
}
|
||
|
||
if (_currentSection && _currentSection->_scheduledSwitch) {
|
||
open(kKIASectionNone);
|
||
}
|
||
}
|
||
|
||
void KIA::handleCustomEventStop(const Common::Event &evt) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
if (_currentSection) {
|
||
_currentSection->handleCustomEventStop(evt);
|
||
}
|
||
}
|
||
|
||
void KIA::handleCustomEventStart(const Common::Event &evt) {
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
switch ((BladeRunnerEngine::BladeRunnerEngineMappableAction)evt.customType) {
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionToggleKiaOptions:
|
||
if (!_forceOpen) {
|
||
open(kKIASectionNone);
|
||
}
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabHelp:
|
||
open(kKIASectionHelp);
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabSaveGame:
|
||
if (!_forceOpen) {
|
||
open(kKIASectionSave);
|
||
}
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabLoadGame:
|
||
open(kKIASectionLoad);
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabQuitGame:
|
||
open(kKIASectionQuit);
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabCrimeSceneDatabase:
|
||
if (_currentSectionId != kKIASectionCrimes) {
|
||
if (!_forceOpen) {
|
||
open(kKIASectionCrimes);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
}
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabSuspectDatabase:
|
||
if (_currentSectionId != kKIASectionSuspects) {
|
||
if (!_forceOpen) {
|
||
open(kKIASectionSuspects);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
}
|
||
break;
|
||
|
||
case BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpActionOpenKIATabClueDatabase:
|
||
if (_currentSectionId != kKIASectionClues) {
|
||
if (!_forceOpen) {
|
||
open(kKIASectionClues);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
if (_currentSection) {
|
||
_currentSection->handleCustomEventStart(evt);
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (_currentSection && _currentSection->_scheduledSwitch) {
|
||
open(kKIASectionNone);
|
||
}
|
||
}
|
||
|
||
void KIA::playerReset() {
|
||
if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
|
||
int actorId = _playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId;
|
||
if (_vm->_actors[actorId]->isSpeeching()) {
|
||
_vm->_actors[actorId]->speechStop();
|
||
}
|
||
}
|
||
|
||
_playerActorDialogueQueueSize = _playerActorDialogueQueuePosition;
|
||
_playerSliceModelId = -1;
|
||
_playerPhotographId = -1;
|
||
_playerImage.free();
|
||
_playerActorDialogueState = 0;
|
||
if (_vm->_cutContent) {
|
||
_buttons->resetImage(22);
|
||
}
|
||
}
|
||
|
||
void KIA::playActorDialogue(int actorId, int sentenceId) {
|
||
int newQueueSize = (_playerActorDialogueQueueSize + 1) % kPlayerActorDialogueQueueCapacity;
|
||
if (newQueueSize != _playerActorDialogueQueuePosition) {
|
||
_playerActorDialogueQueue[_playerActorDialogueQueueSize].actorId = actorId;
|
||
_playerActorDialogueQueue[_playerActorDialogueQueueSize].sentenceId = sentenceId;
|
||
_playerActorDialogueQueueSize = newQueueSize;
|
||
}
|
||
}
|
||
|
||
void KIA::playSliceModel(int sliceModelId) {
|
||
if (_playerVqaFrame == 8) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP1), 70, 0, 0, 50, 0);
|
||
}
|
||
_playerSliceModelId = sliceModelId;
|
||
if (_vm->_cutContent) {
|
||
_buttons->defineImage(22, Common::Rect(530, 32, 635, 126), nullptr, nullptr, nullptr, _vm->_textClueTypes->getText(3)); // "OBJECT"
|
||
}
|
||
}
|
||
|
||
void KIA::playPhotograph(int photographId) {
|
||
if (_playerVqaFrame == 8) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP1), 70, 0, 0, 50, 0);
|
||
}
|
||
_playerPhotographId = photographId;
|
||
}
|
||
|
||
void KIA::playImage(const Graphics::Surface &image) {
|
||
if (image.w != 80) {
|
||
Graphics::Surface *tmp = image.scale(80, 60);
|
||
_playerImage.copyFrom(*tmp);
|
||
tmp->free();
|
||
delete tmp;
|
||
} else {
|
||
_playerImage.copyFrom(image);
|
||
}
|
||
_playerImage.convertToInPlace(screenPixelFormat());
|
||
}
|
||
|
||
const char *KIA::scrambleSuspectsName(const char *name) {
|
||
static char buffer[32];
|
||
|
||
unsigned char *bufferPtr = (unsigned char *)buffer;
|
||
const unsigned char *namePtr = (const unsigned char *)name;
|
||
|
||
for (int i = 0 ; i < 6; ++i) {
|
||
if (_vm->_language == Common::RU_RUS && _vm->_russianCP1251) {
|
||
// Algorithm added by Siberian Studio in R4 patch
|
||
if (*namePtr >= 0xC0) {
|
||
unsigned char upper = *namePtr & 0xDF;
|
||
if (upper < 201) {
|
||
*bufferPtr++ = upper - 143; /* Map А-И to 1-9 */
|
||
} else {
|
||
*bufferPtr++ = upper - 136; /* Map Й-Я to A-W */
|
||
}
|
||
} else {
|
||
*bufferPtr++ = '0';
|
||
}
|
||
} else {
|
||
if (Common::isAlpha(*namePtr)) {
|
||
char upper = toupper(*namePtr);
|
||
if ( upper < 'J' ) {
|
||
*bufferPtr++ = upper - 16; /* Map A-I to 1-9 */
|
||
} else {
|
||
*bufferPtr++ = upper - 9; /* Map J-Z to A-Q */
|
||
}
|
||
} else {
|
||
*bufferPtr++ = '0';
|
||
}
|
||
}
|
||
if (*namePtr) {
|
||
++namePtr;
|
||
}
|
||
if (i == 1) {
|
||
*bufferPtr++ = '-';
|
||
}
|
||
}
|
||
*bufferPtr = 0;
|
||
return buffer;
|
||
}
|
||
|
||
void KIA::mouseDownCallback(int buttonId, void *callbackData) {
|
||
KIA *self = (KIA *)callbackData;
|
||
switch (buttonId) {
|
||
case 0:
|
||
case 6:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4P), 100, -65, -65, 50, 0);
|
||
break;
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
case 5:
|
||
case 7:
|
||
case 8:
|
||
case 9:
|
||
case 10:
|
||
case 11:
|
||
case 12:
|
||
case 13:
|
||
case 14:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN5P), 70, 0, 0, 50, 0);
|
||
if (buttonId == 12) {
|
||
int endTrackId = self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxSHUTDOWN), 70, 0, 0, 50, 0);
|
||
|
||
self->_vm->_surfaceFront.fillRect(Common::Rect(0, 0, BladeRunnerEngine::kOriginalGameWidth, BladeRunnerEngine::kOriginalGameHeight), 0);
|
||
self->_vm->blitToScreen(self->_vm->_surfaceFront);
|
||
|
||
if (endTrackId != -1) {
|
||
// wait until the full clip has played (similar to the original)
|
||
uint32 timeNow = self->_vm->_time->currentSystem();
|
||
uint32 waittime = 16;
|
||
while (self->_vm->_audioPlayer->isActive(endTrackId)) {
|
||
if (self->_vm->_noDelayMillisFramelimiter) {
|
||
while (self->_vm->_time->currentSystem() - timeNow < waittime) { }
|
||
} else {
|
||
self->_vm->_system->delayMillis(waittime);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case 15:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4P), 70, 0, 0, 50, 0);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void KIA::mouseUpCallback(int buttonId, void *callbackData) {
|
||
KIA *self = (KIA *)callbackData;
|
||
switch (buttonId) {
|
||
case 0:
|
||
case 6:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4R), 100, -65, -65, 50, 0);
|
||
break;
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
case 5:
|
||
case 7:
|
||
case 8:
|
||
case 9:
|
||
case 10:
|
||
case 11:
|
||
case 12:
|
||
case 13:
|
||
case 14:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN5R), 70, 0, 0, 50, 0);
|
||
break;
|
||
case 15:
|
||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4R), 100, 0, 0, 50, 0);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
self->buttonClicked(buttonId);
|
||
}
|
||
|
||
void KIA::loopEnded(void *callbackData, int frame, int loopId) {
|
||
KIA *self = (KIA *)callbackData;
|
||
self->_mainVqaPlayer->setLoop(self->getVqaLoopMain(self->_currentSectionId) + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||
self->_transitionId = 0;
|
||
}
|
||
|
||
void KIA::init() {
|
||
createThumbnailFromScreen(&_thumbnail);
|
||
|
||
if (!_vm->openArchive("MODE.MIX")) {
|
||
return;
|
||
}
|
||
|
||
playerReset();
|
||
_playerVqaFrame = 0;
|
||
_playerVqaTimeLast = _vm->_time->currentSystem();
|
||
_timeLast = _vm->_time->currentSystem();
|
||
|
||
if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon) && !_vm->_gameFlags->query(kFlagKIAPrivacyAddonIntro)) {
|
||
_vm->_gameFlags->set(kFlagKIAPrivacyAddonIntro);
|
||
playPrivateAddon();
|
||
}
|
||
|
||
_shapes->load("kiaopt.shp");
|
||
_playerPhotographs->load("photos.shp");
|
||
|
||
_buttons->activate(nullptr, nullptr, mouseDownCallback, mouseUpCallback, this);
|
||
_vm->_mouse->setCursor(0);
|
||
if (_playerVqaPlayer == nullptr) {
|
||
_playerVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, "kiaover.vqa");
|
||
_playerVqaPlayer->open();
|
||
_playerVqaPlayer->setLoop(0, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||
}
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECTRO1), 70, 0, 0, 50, 0);
|
||
|
||
_vm->_time->pause();
|
||
}
|
||
|
||
void KIA::unload() {
|
||
if (_vm->getEventManager()->getKeymapper() != nullptr) {
|
||
if ( _vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kGameplayKeymapId) != nullptr)
|
||
_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kGameplayKeymapId)->setEnabled(true);
|
||
|
||
if (_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kKiaKeymapId) != nullptr) {
|
||
// When disabling a keymap, make sure all their active events in the _activeCustomEvents array
|
||
// are cleared, because as they won't get an explicit "EVENT_CUSTOM_ENGINE_ACTION_END" event.
|
||
_vm->cleanupPendingRepeatingEvents(BladeRunnerEngine::kKiaKeymapId);
|
||
_vm->getEventManager()->getKeymapper()->getKeymap(BladeRunnerEngine::kKiaKeymapId)->setEnabled(false);
|
||
}
|
||
}
|
||
|
||
_thumbnail.free();
|
||
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
|
||
_forceOpen = false;
|
||
|
||
if (_currentSection) {
|
||
_currentSection->close();
|
||
_currentSection = nullptr;
|
||
}
|
||
|
||
_buttons->resetImages();
|
||
_buttons->deactivate();
|
||
|
||
_shapes->unload();
|
||
_playerPhotographs->unload();
|
||
|
||
delete _mainVqaPlayer;
|
||
_mainVqaPlayer = nullptr;
|
||
|
||
delete _playerVqaPlayer;
|
||
_playerVqaPlayer = nullptr;
|
||
|
||
_vm->closeArchive("MODE.MIX");
|
||
|
||
_currentSectionId = kKIASectionNone;
|
||
|
||
_vm->_time->resume();
|
||
|
||
if (!_vm->_settings->isLoadingGame() && _vm->_gameIsRunning) {
|
||
_vm->_scene->resume();
|
||
}
|
||
}
|
||
|
||
void KIA::createButtons(int sectionId) {
|
||
Common::Rect kiaButton6( 66, 00, 122, 44);
|
||
Common::Rect kiaButton7( 191, 29, 233, 70);
|
||
Common::Rect kiaButton8( 234, 29, 278, 70);
|
||
Common::Rect kiaButton9( 278, 29, 321, 70);
|
||
Common::Rect kiaButton10(322, 29, 365, 70);
|
||
Common::Rect kiaButton11(366, 29, 410, 70);
|
||
Common::Rect kiaButton12(420, 286, 472, 328);
|
||
Common::Rect kiaButton13(334, 286, 386, 328);
|
||
Common::Rect kiaButton14(411, 29, 453, 70);
|
||
Common::Rect kiaButton15(264, 9, 304, 26);
|
||
Common::Rect kiaButton16(140, 406, 160, 479);
|
||
Common::Rect kiaButton17(161, 406, 180, 479);
|
||
Common::Rect kiaButton18(181, 406, 202, 479);
|
||
Common::Rect kiaButton19(575, 307, 606, 350);
|
||
Common::Rect kiaButton21(211, 443, 291, 479);
|
||
|
||
const Shape *shapeUp = nullptr;
|
||
const Shape *shapeHovered = nullptr;
|
||
const Shape *shapeDown = nullptr;
|
||
|
||
switch (sectionId) {
|
||
case kKIASectionCrimes:
|
||
case kKIASectionSuspects:
|
||
case kKIASectionClues:
|
||
_buttons->defineImage(0, kiaButton6, nullptr, nullptr, _shapes->get(1), _vm->_textKIA->getText(23));
|
||
|
||
if (_vm->_cutContent && _playerSliceModelId != -1) {
|
||
_buttons->defineImage(22, Common::Rect(530, 32, 635, 126), nullptr, nullptr, nullptr, _vm->_textClueTypes->getText(3)); // "OBJECT"
|
||
}
|
||
|
||
if (sectionId == kKIASectionCrimes) {
|
||
shapeUp = _shapes->get(2);
|
||
shapeHovered = _shapes->get(2);
|
||
shapeDown = _shapes->get(10);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(18);
|
||
}
|
||
_buttons->defineImage(1, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(24));
|
||
|
||
if (sectionId == kKIASectionSuspects) {
|
||
shapeUp = _shapes->get(3);
|
||
shapeHovered = _shapes->get(3);
|
||
shapeDown = _shapes->get(11);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(19);
|
||
}
|
||
_buttons->defineImage(2, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(25));
|
||
|
||
if (sectionId == kKIASectionClues) {
|
||
shapeUp = _shapes->get(4);
|
||
shapeHovered = _shapes->get(4);
|
||
shapeDown = _shapes->get(12);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(20);
|
||
}
|
||
_buttons->defineImage(3, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(26));
|
||
|
||
_buttons->defineImage(4, kiaButton10, nullptr, nullptr, _shapes->get(21), _vm->_textKIA->getText(27));
|
||
|
||
_buttons->defineImage(5, kiaButton11, nullptr, nullptr, _shapes->get(22), _vm->_textKIA->getText(28));
|
||
|
||
_buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(23), _vm->_textKIA->getText(29));
|
||
|
||
break;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
_buttons->defineImage(6, kiaButton6, nullptr, nullptr, _shapes->get(0), _vm->_textKIA->getText(37));
|
||
|
||
if (sectionId == kKIASectionSettings) {
|
||
shapeUp = _shapes->get(5);
|
||
shapeHovered = _shapes->get(5);
|
||
shapeDown = _shapes->get(13);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(24);
|
||
}
|
||
_buttons->defineImage(7, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(38));
|
||
|
||
if (sectionId == kKIASectionHelp) {
|
||
shapeUp = _shapes->get(6);
|
||
shapeHovered = _shapes->get(6);
|
||
shapeDown = _shapes->get(14);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(25);
|
||
}
|
||
_buttons->defineImage(8, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(41));
|
||
|
||
if (sectionId == kKIASectionSave) {
|
||
shapeUp = _shapes->get(7);
|
||
shapeHovered = _shapes->get(7);
|
||
shapeDown = _shapes->get(15);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(26);
|
||
}
|
||
_buttons->defineImage(9, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(39));
|
||
|
||
if (sectionId == kKIASectionLoad) {
|
||
shapeUp = _shapes->get(8);
|
||
shapeHovered = _shapes->get(8);
|
||
shapeDown = _shapes->get(16);
|
||
} else {
|
||
shapeUp = nullptr;
|
||
shapeHovered = nullptr;
|
||
shapeDown = _shapes->get(27);
|
||
}
|
||
_buttons->defineImage(10, kiaButton10, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(40));
|
||
|
||
_buttons->defineImage(11, kiaButton11, nullptr, nullptr, _shapes->get(28), _vm->_textKIA->getText(42));
|
||
|
||
_buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(29), _vm->_textKIA->getText(29));
|
||
|
||
break;
|
||
case kKIASectionQuit:
|
||
_buttons->defineImage(12, kiaButton12, _shapes->get(124), _shapes->get(124), _shapes->get(48), _vm->_textKIA->getText(42));
|
||
|
||
_buttons->defineImage(13, kiaButton13, _shapes->get(125), _shapes->get(125), _shapes->get(49), _vm->_textKIA->getText(29));
|
||
break;
|
||
}
|
||
|
||
if (sectionId != kKIASectionQuit) {
|
||
_buttons->defineImage(15, kiaButton15, nullptr, nullptr, _shapes->get(38), _vm->_textKIA->getText(43));
|
||
|
||
_buttons->defineImage(19, kiaButton19, nullptr, nullptr, nullptr, _vm->_textKIA->getText(44));
|
||
|
||
if (_vm->_settings->getAmmo(0) > 0) {
|
||
_buttons->defineImage(16, kiaButton16, nullptr, nullptr, nullptr, _vm->_textKIA->getText(50));
|
||
}
|
||
Common::String tooltip;
|
||
if (_vm->_settings->getAmmo(1) > 0) {
|
||
if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
|
||
tooltip = Common::String::format("%d", _vm->_settings->getAmmo(1));
|
||
} else {
|
||
tooltip = _vm->_textKIA->getText(50);
|
||
}
|
||
_buttons->defineImage(17, kiaButton17, nullptr, nullptr, nullptr, tooltip.c_str());
|
||
}
|
||
if (_vm->_settings->getAmmo(2) > 0) {
|
||
if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
|
||
tooltip = Common::String::format("%d", _vm->_settings->getAmmo(2));
|
||
} else {
|
||
tooltip = _vm->_textKIA->getText(50);
|
||
}
|
||
_buttons->defineImage(18, kiaButton18, nullptr, nullptr, nullptr, tooltip.c_str());
|
||
}
|
||
if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
|
||
_buttons->defineImage(21, kiaButton21, nullptr, nullptr, nullptr, nullptr);
|
||
}
|
||
}
|
||
}
|
||
|
||
void KIA::buttonClicked(int buttonId) {
|
||
int soundId = 0;
|
||
|
||
if (!isOpen()) {
|
||
return;
|
||
}
|
||
switch (buttonId) {
|
||
case 0:
|
||
open(kKIASectionSettings);
|
||
break;
|
||
case 1:
|
||
if (_currentSectionId != kKIASectionCrimes) {
|
||
open(kKIASectionCrimes);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
break;
|
||
case 2:
|
||
if (_currentSectionId != kKIASectionSuspects) {
|
||
open(kKIASectionSuspects);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
break;
|
||
case 3:
|
||
if (_currentSectionId != kKIASectionClues) {
|
||
open(kKIASectionClues);
|
||
_log->next();
|
||
_log->clearFuture();
|
||
}
|
||
break;
|
||
case 4:
|
||
if (_log->hasPrev()) {
|
||
int kiaLogPrevType = _log->getPrevType();
|
||
switch (kiaLogPrevType) {
|
||
case 2:
|
||
open(kKIASectionCrimes);
|
||
_log->prev();
|
||
_crimesSection->loadFromLog();
|
||
break;
|
||
case 1:
|
||
open(kKIASectionSuspects);
|
||
_log->prev();
|
||
_suspectsSection->loadFromLog();
|
||
break;
|
||
case 0:
|
||
open(kKIASectionClues);
|
||
_log->prev();
|
||
_cluesSection->loadFromLog();
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case 5:
|
||
if (_log->hasNext()) {
|
||
int kiaLogNextType = _log->getNextType();
|
||
switch (kiaLogNextType) {
|
||
case 2:
|
||
open(kKIASectionCrimes);
|
||
_log->next();
|
||
_crimesSection->loadFromLog();
|
||
break;
|
||
case 1:
|
||
open(kKIASectionSuspects);
|
||
_log->next();
|
||
_suspectsSection->loadFromLog();
|
||
break;
|
||
case 0:
|
||
open(kKIASectionClues);
|
||
_log->next();
|
||
_cluesSection->loadFromLog();
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case 6:
|
||
if (!_forceOpen) {
|
||
open(_lastSectionIdKIA);
|
||
}
|
||
break;
|
||
case 7:
|
||
open(kKIASectionSettings);
|
||
break;
|
||
case 8:
|
||
open(kKIASectionHelp);
|
||
break;
|
||
case 9:
|
||
if (!_forceOpen) {
|
||
open(kKIASectionSave);
|
||
}
|
||
break;
|
||
case 10:
|
||
open(kKIASectionLoad);
|
||
break;
|
||
case 11:
|
||
open(kKIASectionQuit);
|
||
break;
|
||
case 12:
|
||
_vm->_gameIsRunning = false;
|
||
open(kKIASectionNone);
|
||
break;
|
||
case 13:
|
||
open(_lastSectionIdOptions);
|
||
break;
|
||
case 14:
|
||
if (!_forceOpen) {
|
||
open(kKIASectionNone);
|
||
}
|
||
break;
|
||
case 15:
|
||
open(kKIASectionDiagnostic);
|
||
break;
|
||
case 16:
|
||
_vm->_settings->setAmmoType(0);
|
||
if (_vm->_rnd.getRandomNumber(1)) {
|
||
soundId = _vm->_combat->getHitSound();
|
||
} else {
|
||
soundId = _vm->_combat->getMissSound();
|
||
}
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
|
||
break;
|
||
case 17:
|
||
_vm->_settings->setAmmoType(1);
|
||
if (_vm->_rnd.getRandomNumber(1)) {
|
||
soundId = _vm->_combat->getHitSound();
|
||
} else {
|
||
soundId = _vm->_combat->getMissSound();
|
||
}
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
|
||
break;
|
||
case 18:
|
||
_vm->_settings->setAmmoType(2);
|
||
if (_vm->_rnd.getRandomNumber(1)) {
|
||
soundId = _vm->_combat->getHitSound();
|
||
} else {
|
||
soundId = _vm->_combat->getMissSound();
|
||
}
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
|
||
break;
|
||
case 19:
|
||
return;
|
||
case 20:
|
||
playerReset();
|
||
break;
|
||
case 21:
|
||
playPrivateAddon();
|
||
break;
|
||
case 22:
|
||
if (_vm->_cutContent) {
|
||
// play audio description
|
||
playObjectDescription();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
void KIA::switchSection(int sectionId) {
|
||
if (_currentSection) {
|
||
_currentSection->close();
|
||
}
|
||
switch (sectionId) {
|
||
case kKIASectionCrimes:
|
||
_currentSection = _crimesSection;
|
||
break;
|
||
case kKIASectionSuspects:
|
||
_currentSection = _suspectsSection;
|
||
break;
|
||
case kKIASectionClues:
|
||
_currentSection = _cluesSection;
|
||
break;
|
||
case kKIASectionSettings:
|
||
_currentSection = _settingsSection;
|
||
break;
|
||
case kKIASectionHelp:
|
||
_currentSection = _helpSection;
|
||
break;
|
||
case kKIASectionSave:
|
||
_currentSection = _saveSection;
|
||
break;
|
||
case kKIASectionLoad:
|
||
_currentSection = _loadSection;
|
||
break;
|
||
case kKIASectionQuit:
|
||
_currentSection = nullptr;
|
||
break;
|
||
case kKIASectionDiagnostic:
|
||
_currentSection = _diagnosticSection;
|
||
break;
|
||
case kKIASectionPogo:
|
||
_currentSection = _pogoSection;
|
||
break;
|
||
default:
|
||
_currentSection = nullptr;
|
||
break;
|
||
}
|
||
if (_currentSection) {
|
||
_currentSection->open();
|
||
}
|
||
}
|
||
|
||
const char *KIA::getSectionVqaName(int sectionId) {
|
||
switch (sectionId) {
|
||
case kKIASectionCrimes:
|
||
return "kia_crim.vqa";
|
||
case kKIASectionSuspects:
|
||
return "kia_susp.vqa";
|
||
case kKIASectionClues:
|
||
return "kia_clue.vqa";
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionQuit:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return "kia_ingm.vqa";
|
||
default:
|
||
return nullptr;
|
||
}
|
||
}
|
||
|
||
int KIA::getVqaLoopMain(int sectionId) {
|
||
switch (sectionId) {
|
||
case kKIASectionCrimes:
|
||
case kKIASectionSuspects:
|
||
case kKIASectionClues:
|
||
return 3;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return 4;
|
||
case kKIASectionQuit:
|
||
return 7;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
int KIA::getVqaLoopTransition(int transitionId) {
|
||
switch (transitionId) {
|
||
case 0:
|
||
case 2:
|
||
case 7:
|
||
case 8:
|
||
return 0;
|
||
case 1:
|
||
case 4:
|
||
case 5:
|
||
case 9:
|
||
return 1;
|
||
case 3:
|
||
case 10:
|
||
case 11:
|
||
case 12:
|
||
return 2;
|
||
case 6:
|
||
return 3;
|
||
case 13:
|
||
return 6;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
int KIA::getTransitionId(int oldSectionId, int newSectionId) {
|
||
switch (oldSectionId) {
|
||
case kKIASectionNone:
|
||
return 0;
|
||
case kKIASectionCrimes:
|
||
switch (newSectionId) {
|
||
case kKIASectionCrimes:
|
||
return 0;
|
||
case kKIASectionSuspects:
|
||
return 1;
|
||
case kKIASectionClues:
|
||
return 2;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return 3;
|
||
case kKIASectionQuit:
|
||
return 13;
|
||
}
|
||
return 0;
|
||
case kKIASectionSuspects:
|
||
switch (newSectionId) {
|
||
case kKIASectionCrimes:
|
||
return 4;
|
||
case kKIASectionSuspects:
|
||
return 0;
|
||
case kKIASectionClues:
|
||
return 5;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return 6;
|
||
case kKIASectionQuit:
|
||
return 13;
|
||
}
|
||
return 0;
|
||
case kKIASectionClues:
|
||
switch (newSectionId) {
|
||
case kKIASectionCrimes:
|
||
return 7;
|
||
case kKIASectionSuspects:
|
||
return 8;
|
||
case kKIASectionClues:
|
||
return 0;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return 9;
|
||
case kKIASectionQuit:
|
||
return 13;
|
||
}
|
||
return 0;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
switch (newSectionId) {
|
||
case kKIASectionCrimes:
|
||
return 10;
|
||
case kKIASectionSuspects:
|
||
return 11;
|
||
case kKIASectionClues:
|
||
return 12;
|
||
case kKIASectionSettings:
|
||
case kKIASectionHelp:
|
||
case kKIASectionSave:
|
||
case kKIASectionLoad:
|
||
case kKIASectionDiagnostic:
|
||
case kKIASectionPogo:
|
||
return 0;
|
||
case kKIASectionQuit:
|
||
return 13;
|
||
}
|
||
return 0;
|
||
case kKIASectionQuit:
|
||
if (newSectionId != kKIASectionQuit) {
|
||
return 14;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void KIA::playTransitionSound(int transitionId) {
|
||
switch (transitionId) {
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
case 5:
|
||
case 6:
|
||
case 7:
|
||
case 8:
|
||
case 9:
|
||
case 10:
|
||
case 11:
|
||
case 12:
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANEL1), 100, 0, 0, 50, 0);
|
||
break;
|
||
case 13:
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANEL2), 100, 0, 0, 50, 0);
|
||
break;
|
||
case 14:
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANOPEN), 100, 0, 0, 50, 0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
void KIA::playPrivateAddon() {
|
||
playerReset();
|
||
playSliceModel(524);
|
||
playActorDialogue(kActorBulletBob, 2060);
|
||
playActorDialogue(kActorBulletBob, 2070);
|
||
}
|
||
|
||
void KIA::playObjectDescription() {
|
||
if (_playerSliceModelId == -1) {
|
||
return;
|
||
}
|
||
switch (_playerSliceModelId) {
|
||
case kModelAnimationShellCasings:
|
||
playActorDialogue(kActorMcCoy, 8730);
|
||
break;
|
||
case kModelAnimationCandy:
|
||
playActorDialogue(kActorMcCoy, 8735);
|
||
break;
|
||
case kModelAnimationToyDog:
|
||
playActorDialogue(kActorMcCoy, 8740);
|
||
break;
|
||
case kModelAnimationChopstickWrapper:
|
||
playActorDialogue(kActorMcCoy, 8745);
|
||
break;
|
||
case kModelAnimationReferenceLetter:
|
||
playActorDialogue(kActorMcCoy, 8750);
|
||
break;
|
||
case kModelAnimationChromeDebris:
|
||
playActorDialogue(kActorMcCoy, 8755);
|
||
break;
|
||
case kModelAnimationLicensePlate:
|
||
playActorDialogue(kActorMcCoy, 8760);
|
||
break;
|
||
case kModelAnimationDragonflyEarring:
|
||
playActorDialogue(kActorMcCoy, 8765);
|
||
break;
|
||
case kModelAnimationDetonatorWire:
|
||
playActorDialogue(kActorMcCoy, 8770);
|
||
break;
|
||
case kModelAnimationKingstonKitchenBox:
|
||
playActorDialogue(kActorMcCoy, 8775);
|
||
break;
|
||
case kModelAnimationTyrellSalesPamphletKIA:
|
||
playActorDialogue(kActorMcCoy, 8780);
|
||
break;
|
||
case kModelAnimationRadiationGoggles:
|
||
playActorDialogue(kActorMcCoy, 8785);
|
||
break;
|
||
case kModelAnimationDogCollar:
|
||
playActorDialogue(kActorMcCoy, 8790);
|
||
break;
|
||
case kModelAnimationMaggieBracelet:
|
||
playActorDialogue(kActorMcCoy, 8795);
|
||
break;
|
||
case kModelAnimationEnvelope:
|
||
playActorDialogue(kActorMcCoy, 8800);
|
||
break;
|
||
case kModelAnimationWeaponsOrderForm:
|
||
// fall through
|
||
case kModelAnimationRequisitionForm:
|
||
// fall through
|
||
case kModelAnimationOriginalShippingForm:
|
||
// fall through
|
||
case kModelAnimationOriginalRequisitionForm:
|
||
playActorDialogue(kActorMcCoy, 8805); // A requisition form
|
||
break;
|
||
case kModelAnimationHysteriaToken:
|
||
playActorDialogue(kActorMcCoy, 8810);
|
||
break;
|
||
case kModelAnimationRagDoll:
|
||
playActorDialogue(kActorMcCoy, 8815);
|
||
break;
|
||
case kModelAnimationCheese:
|
||
playActorDialogue(kActorMcCoy, 8820);
|
||
break;
|
||
case kModelAnimationDragonflyBelt:
|
||
playActorDialogue(kActorMcCoy, 8825);
|
||
break;
|
||
case kModelAnimationStrangeScale:
|
||
playActorDialogue(kActorMcCoy, 8830);
|
||
break;
|
||
case kModelAnimationDektorasCard:
|
||
playActorDialogue(kActorMcCoy, 8835);
|
||
break;
|
||
case kModelAnimationLetter:
|
||
// fall through
|
||
case kModelAnimationGrigoriansNote:
|
||
playActorDialogue(kActorMcCoy, 8840);
|
||
break;
|
||
case kModelAnimationCollectionReceipt:
|
||
playActorDialogue(kActorMcCoy, 8845);
|
||
break;
|
||
case kModelAnimationGordosLighterReplicant:
|
||
// fall through
|
||
case kModelAnimationGordosLighterHuman:
|
||
playActorDialogue(kActorMcCoy, 8850);
|
||
break;
|
||
// case kModelAnimationBadge: // This is never discovered in-game, and uses same model as Holden's badge
|
||
// playActorDialogue(kActorMcCoy, 8855); // Baker's Badge
|
||
// break;
|
||
case kModelAnimationBadge:
|
||
playActorDialogue(kActorMcCoy, 8860);
|
||
break;
|
||
case kModelAnimationLichenDogWrapper:
|
||
playActorDialogue(kActorMcCoy, 8865);
|
||
break;
|
||
case kModelAnimationFolder:
|
||
playActorDialogue(kActorMcCoy, 8870);
|
||
break;
|
||
case kModelAnimationCandyWrapper:
|
||
playActorDialogue(kActorMcCoy, 8875);
|
||
break;
|
||
case kModelAnimationFlaskOfAbsinthe:
|
||
playActorDialogue(kActorMcCoy, 8880);
|
||
break;
|
||
case kModelAnimationPowerSource:
|
||
playActorDialogue(kActorMcCoy, 8885);
|
||
break;
|
||
case kModelAnimationBomb: // TODO - does this ever appear in KIA?
|
||
playActorDialogue(kActorMcCoy, 8890);
|
||
break;
|
||
case kModelAnimationGarterSnake:
|
||
playActorDialogue(kActorMcCoy, 8895);
|
||
break;
|
||
case kModelAnimationSlug:
|
||
playActorDialogue(kActorMcCoy, 8900);
|
||
break;
|
||
case kModelAnimationGoldfish:
|
||
playActorDialogue(kActorMcCoy, 8905);
|
||
break;
|
||
case kModelAnimationDNAEvidence01OutOf6:
|
||
// fall through
|
||
// case kModelAnimationDNAEvidence02OutOf6:
|
||
// fall through
|
||
case kModelAnimationDNAEvidence03OutOf6:
|
||
// fall through
|
||
case kModelAnimationDNAEvidence04OutOf6:
|
||
// fall through
|
||
// case kModelAnimationDNAEvidence05OutOf6:
|
||
// fall through
|
||
case kModelAnimationDNAEvidenceComplete:
|
||
// fall through
|
||
case kModelAnimationSpinnerKeys:
|
||
// fall through
|
||
case kModelAnimationBriefcase:
|
||
// fall through
|
||
case kModelAnimationCrystalsCigarette:
|
||
// fall through
|
||
case kModelAnimationVideoDisc:
|
||
// fall through
|
||
default:
|
||
playActorDialogue(kActorMcCoy, 8525);
|
||
break;
|
||
}
|
||
}
|
||
|
||
} // End of namespace BladeRunner
|