1 /* ScummVM - Graphic Adventure Engine
2 *
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.
6 *
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.
11 *
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.
16 *
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.
20 *
21 */
22
23 #include "bladerunner/ui/kia.h"
24
25 #include "bladerunner/actor.h"
26 #include "bladerunner/audio_player.h"
27 #include "bladerunner/bladerunner.h"
28 #include "bladerunner/combat.h"
29 #include "bladerunner/font.h"
30 #include "bladerunner/game_constants.h"
31 #include "bladerunner/game_flags.h"
32 #include "bladerunner/game_info.h"
33 #include "bladerunner/mouse.h"
34 #include "bladerunner/savefile.h"
35 #include "bladerunner/scene.h"
36 #include "bladerunner/shape.h"
37 #include "bladerunner/script/kia_script.h"
38 #include "bladerunner/settings.h"
39 #include "bladerunner/slice_renderer.h"
40 #include "bladerunner/text_resource.h"
41 #include "bladerunner/time.h"
42 #include "bladerunner/ui/kia_log.h"
43 #include "bladerunner/ui/kia_section_base.h"
44 #include "bladerunner/ui/kia_section_clues.h"
45 #include "bladerunner/ui/kia_section_crimes.h"
46 #include "bladerunner/ui/kia_section_diagnostic.h"
47 #include "bladerunner/ui/kia_section_help.h"
48 #include "bladerunner/ui/kia_section_load.h"
49 #include "bladerunner/ui/kia_section_settings.h"
50 #include "bladerunner/ui/kia_section_pogo.h"
51 #include "bladerunner/ui/kia_section_save.h"
52 #include "bladerunner/ui/kia_section_suspects.h"
53 #include "bladerunner/ui/ui_image_picker.h"
54 #include "bladerunner/vqa_player.h"
55 #include "bladerunner/subtitles.h"
56
57 #include "common/str.h"
58 #include "common/keyboard.h"
59 #include "common/debug.h"
60
61 #include "graphics/scaler.h"
62
63 namespace BladeRunner {
64
65 const char *KIA::kPogo = "POGO";
66
KIA(BladeRunnerEngine * vm)67 KIA::KIA(BladeRunnerEngine *vm) {
68 _vm = vm;
69
70 _script = new KIAScript(_vm);
71 _log = new KIALog(_vm);
72 _shapes = new Shapes(_vm);
73 _playerPhotographs = new Shapes(_vm);
74
75 _forceOpen = false;
76 _currentSectionId = kKIASectionNone;
77 _lastSectionIdKIA = kKIASectionCrimes;
78 _lastSectionIdOptions = kKIASectionSettings;
79 _playerVqaTimeLast = _vm->_time->currentSystem();
80 _playerVqaFrame = 0;
81 _playerVisualizerState = 0;
82 _playerPhotographId = -1;
83 _playerSliceModelId = -1;
84 _playerSliceModelAngle = 0.0f;
85 _timeLast = _vm->_time->currentSystem();
86 _playerActorDialogueQueuePosition = 0;
87 _playerActorDialogueQueueSize = 0;
88 _playerActorDialogueState = 0;
89 _currentSection = nullptr;
90 _mainVqaPlayer = nullptr;
91 _playerVqaPlayer = nullptr;
92 _transitionId = 0;
93
94 _pogoPos = 0;
95
96 // original imageCount was 22. We add +1 to have a description box for objects in cut content
97 // We don't have separated cases here, for _vm->_cutContent since that causes assertion fault if
98 // loading a "restored content" save game in a "original game" version
99 _buttons = new UIImagePicker(_vm, 23);
100
101 _crimesSection = new KIASectionCrimes(_vm, _vm->_playerActor->_clues);
102 _suspectsSection = new KIASectionSuspects(_vm, _vm->_playerActor->_clues);
103 _cluesSection = new KIASectionClues(_vm, _vm->_playerActor->_clues);
104 _settingsSection = new KIASectionSettings(_vm);
105 _helpSection = new KIASectionHelp(_vm);
106 _saveSection = new KIASectionSave(_vm);
107 _loadSection = new KIASectionLoad(_vm);
108 _diagnosticSection = new KIASectionDiagnostic(_vm);
109 _pogoSection = new KIASectionPogo(_vm);
110
111 for (int i = 0; i < kPlayerActorDialogueQueueCapacity; ++i) {
112 _playerActorDialogueQueue[i].actorId = -1;
113 _playerActorDialogueQueue[i].sentenceId = -1;
114 }
115 }
116
~KIA()117 KIA::~KIA() {
118 if (isOpen()) {
119 unload();
120 }
121
122 _thumbnail.free();
123 delete _crimesSection;
124 delete _suspectsSection;
125 delete _cluesSection;
126 delete _settingsSection;
127 delete _helpSection;
128 delete _saveSection;
129 delete _loadSection;
130 delete _diagnosticSection;
131 delete _pogoSection;
132 _playerImage.free();
133 delete _buttons;
134 delete _shapes;
135 delete _playerPhotographs;
136 delete _log;
137 delete _script;
138 }
139
reset()140 void KIA::reset() {
141 _lastSectionIdKIA = kKIASectionCrimes;
142 _lastSectionIdOptions = kKIASectionSettings;
143 _playerImage.free();
144 _playerVqaFrame = 0;
145 _playerVisualizerState = 0;
146 _playerSliceModelAngle = 0.0f;
147
148 _crimesSection->reset();
149 _suspectsSection->reset();
150 _cluesSection->reset();
151 }
152
openLastOpened()153 void KIA::openLastOpened() {
154 open(_lastSectionIdKIA);
155 }
156
open(KIASections sectionId)157 void KIA::open(KIASections sectionId) {
158 if (_currentSectionId == sectionId) {
159 return;
160 }
161
162 if (sectionId == kKIASectionNone) {
163 unload();
164 return;
165 }
166
167 if (!isOpen()) {
168 init();
169 }
170
171 switch (_currentSectionId) {
172 case kKIASectionCrimes:
173 _crimesSection->saveToLog();
174 break;
175 case kKIASectionSuspects:
176 _suspectsSection->saveToLog();
177 break;
178 case kKIASectionClues:
179 _cluesSection->saveToLog();
180 break;
181 default:
182 break;
183 }
184
185 if (sectionId != kKIASectionCrimes && sectionId != kKIASectionSuspects && sectionId != kKIASectionClues) {
186 playerReset();
187 }
188
189 _transitionId = getTransitionId(_currentSectionId, sectionId);
190 const char *name = getSectionVqaName(sectionId);
191 if (getSectionVqaName(_currentSectionId) != name) {
192 if (_mainVqaPlayer) {
193 _mainVqaPlayer->close();
194 delete _mainVqaPlayer;
195 _mainVqaPlayer = nullptr;
196 }
197
198 _mainVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, name);
199 _mainVqaPlayer->open();
200 }
201
202 if (_transitionId) {
203 playTransitionSound(_transitionId);
204 _mainVqaPlayer->setLoop(getVqaLoopTransition(_transitionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
205 _mainVqaPlayer->setLoop(getVqaLoopMain(sectionId), -1, kLoopSetModeEnqueue, loopEnded, this);
206 } else {
207 int loopId = getVqaLoopMain(sectionId);
208 _mainVqaPlayer->setLoop(loopId, -1, kLoopSetModeImmediate, nullptr, nullptr);
209 _mainVqaPlayer->setLoop(loopId + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
210 }
211
212 _buttons->resetImages();
213 createButtons(sectionId);
214 switchSection(sectionId);
215 _currentSectionId = sectionId;
216
217 if (sectionId == kKIASectionCrimes || sectionId == kKIASectionSuspects || sectionId == kKIASectionClues) {
218 _lastSectionIdKIA = _currentSectionId;
219 }
220
221 if (sectionId == kKIASectionSettings || sectionId == kKIASectionHelp || sectionId == kKIASectionSave || sectionId == kKIASectionLoad) {
222 _lastSectionIdOptions = _currentSectionId;
223 }
224 }
225
isOpen() const226 bool KIA::isOpen() const {
227 return _currentSectionId != kKIASectionNone;
228 }
229
tick()230 void KIA::tick() {
231 if (!isOpen()) {
232 return;
233 }
234
235 uint32 timeNow = _vm->_time->currentSystem();
236 // unsigned difference is intentional
237 uint32 timeDiff = timeNow - _timeLast;
238
239 if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition) {
240 _playerActorDialogueState = 0;
241 } else if (_playerActorDialogueState == 0) {
242 if (_playerSliceModelId == -1 && _playerPhotographId == -1 && _playerImage.getPixels() == nullptr) {
243 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP16), 70, 0, 0, 50, 0);
244 }
245 _playerActorDialogueState = 1;
246 } else if (_playerActorDialogueState == 200) {
247 if (!_vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->isSpeeching()) {
248 if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
249 _playerActorDialogueQueuePosition = (_playerActorDialogueQueuePosition + 1) % kPlayerActorDialogueQueueCapacity;
250 }
251 if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
252 _vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
253 }
254 }
255 } else {
256 _playerActorDialogueState += timeDiff;
257
258 if (_playerActorDialogueState >= 200) {
259 _playerActorDialogueState = 200;
260 _vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
261 }
262 }
263
264 uint32 timeDiffDiv48 = (timeNow < _playerVqaTimeLast) ? 0u : (timeNow - _playerVqaTimeLast) / 48;
265 if (timeDiffDiv48 > 0u) {
266 _playerVqaTimeLast = timeNow;
267 if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition || _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) {
268 if (_playerVisualizerState > 0) {
269 _playerVisualizerState = (_playerVisualizerState < timeDiffDiv48) ? 0u : MAX<uint32>(_playerVisualizerState - timeDiffDiv48, 0u);
270 }
271 } else {
272 if (_playerVisualizerState < 2) {
273 _playerVisualizerState = MIN<uint32>(_playerVisualizerState + timeDiffDiv48, 2u);
274 }
275 }
276
277 if ( _playerSliceModelId != -1 || _playerPhotographId != -1 || _playerImage.getPixels() != nullptr) {
278 if (_playerVqaFrame < 8) {
279 int newVqaFrame = MIN<uint32>(timeDiffDiv48 + _playerVqaFrame, 8u);
280 if (_playerVqaFrame <= 0 && newVqaFrame > 0) {
281 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxMECHAN1), 100, 70, 70, 50, 0);
282 }
283 _playerVqaFrame = newVqaFrame;
284 }
285 } else {
286 if (_playerVqaFrame > 0) {
287 int newVqaFrame = (_playerVqaFrame < timeDiffDiv48) ? 0 : MAX<uint32>(_playerVqaFrame - timeDiffDiv48, 0u);
288 if (_playerVqaFrame >= 8 && newVqaFrame < 8) {
289 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxMECHAN1C), 100, 70, 70, 50, 0);
290 }
291 _playerVqaFrame = newVqaFrame;
292 }
293 }
294 }
295
296 _mainVqaPlayer->update(false);
297 blit(_vm->_surfaceBack, _vm->_surfaceFront);
298
299 Common::Point mouse = _vm->getMousePos();
300
301 if (!_transitionId) {
302 _buttons->handleMouseAction(mouse.x, mouse.y, false, false, false);
303 if (_buttons->hasHoveredImage()) {
304 _vm->_mouse->setCursor(1);
305 } else {
306 _vm->_mouse->setCursor(0);
307 }
308 if (_currentSection) {
309 _currentSection->handleMouseMove(mouse.x, mouse.y);
310 }
311 }
312
313 if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
314 _shapes->get(40)->draw(_vm->_surfaceFront, 0, 0);
315 _shapes->get(41)->draw(_vm->_surfaceFront, 211, 447);
316 }
317 if (_currentSectionId != kKIASectionQuit && _transitionId != 14) {
318 if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
319 _vm->_mainFont->drawString(&_vm->_surfaceFront, Common::String::format("%04d", _vm->_gameVars[kVariableChinyen]), 580, 341, _vm->_surfaceFront.w, _vm->_surfaceFront.format.RGBToColor(80, 96, 136));
320 } else {
321 _shapes->get(39)->draw(_vm->_surfaceFront, 583, 342);
322 }
323 }
324
325 _playerVqaPlayer->seekToFrame(_playerVqaFrame);
326 _playerVqaPlayer->update(true, true);
327
328 _playerSliceModelAngle += (float)(timeDiff) * 1.0f/400.0f;
329 while (_playerSliceModelAngle >= 2 * M_PI) {
330 _playerSliceModelAngle -= (float)(2 * M_PI);
331 }
332
333 if (_playerVqaFrame == 8) {
334 if (_playerSliceModelId != -1) {
335 _vm->_sliceRenderer->drawOnScreen(_playerSliceModelId, 0, 585, 80, _playerSliceModelAngle, 100.0, _vm->_surfaceFront);
336 } else if (_playerPhotographId != -1) {
337 const Shape *playerPhotograph = _playerPhotographs->get(_playerPhotographId);
338 int width = playerPhotograph->getWidth();
339 int height = playerPhotograph->getHeight();
340 playerPhotograph->draw(_vm->_surfaceFront, 590 - width / 2, 80 - height / 2);
341 } else if (_playerImage.getPixels() != nullptr) {
342 _vm->_surfaceFront.fillRect(Common::Rect(549, 49, 631, 111), _vm->_surfaceFront.format.RGBToColor(255, 255, 255));
343 _vm->_surfaceFront.copyRectToSurface(_playerImage.getPixels(), _playerImage.pitch, 550, 50, _playerImage.w, _playerImage.h);
344 }
345 }
346
347 if (_playerVisualizerState == 1) {
348 _shapes->get(51)->draw(_vm->_surfaceFront, 576, 174);
349 } else if (_playerVisualizerState == 2) {
350 _shapes->get(50)->draw(_vm->_surfaceFront, 576, 174);
351 _shapes->get(_vm->_rnd.getRandomNumberRng(90, 105))->draw(_vm->_surfaceFront, 576, 174);
352 }
353 if (!_transitionId) {
354 _buttons->draw(_vm->_surfaceFront);
355 if (_currentSection) {
356 _currentSection->draw(_vm->_surfaceFront);
357 }
358 }
359 if (_vm->_settings->getAmmo(0) > 0) {
360 if (_vm->_settings->getAmmoType() == 0) {
361 _shapes->get(42)->draw(_vm->_surfaceFront, 147, 405);
362 } else {
363 _shapes->get(45)->draw(_vm->_surfaceFront, 140, 446);
364 }
365 }
366 if (_vm->_settings->getAmmo(1) > 0) {
367 if (_vm->_settings->getAmmoType() == 1) {
368 _shapes->get(43)->draw(_vm->_surfaceFront, 167, 394);
369 } else {
370 _shapes->get(46)->draw(_vm->_surfaceFront, 160, 446);
371 }
372 }
373 if (_vm->_settings->getAmmo(2) > 0) {
374 if (_vm->_settings->getAmmoType() == 2) {
375 _shapes->get(44)->draw(_vm->_surfaceFront, 189, 385);
376 } else {
377 _shapes->get(47)->draw(_vm->_surfaceFront, 182, 446);
378 }
379 }
380 _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
381 if (!_transitionId) {
382 _buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y);
383 }
384 _vm->_mouse->draw(_vm->_surfaceFront, mouse.x, mouse.y);
385
386 _vm->_subtitles->tick(_vm->_surfaceFront);
387
388 _vm->blitToScreen(_vm->_surfaceFront);
389
390 _timeLast = timeNow;
391 }
392
resume()393 void KIA::resume() {
394 // vqaPlayer::clear(this->_vqaPlayerMain);
395 if (_transitionId) {
396 _mainVqaPlayer->setLoop(getVqaLoopTransition(_transitionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
397 _mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId), -1, kLoopSetModeEnqueue, loopEnded, this);
398 } else {
399 _mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
400 _mainVqaPlayer->setLoop(getVqaLoopMain(_currentSectionId) + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
401 }
402 }
403
handleMouseDown(int mouseX,int mouseY,bool mainButton)404 void KIA::handleMouseDown(int mouseX, int mouseY, bool mainButton) {
405 if (!isOpen()) {
406 return;
407 }
408 if (mainButton) {
409 _buttons->handleMouseAction(mouseX, mouseY, true, false, false);
410 }
411 if (_currentSection) {
412 _currentSection->handleMouseDown(mainButton);
413 }
414 }
415
handleMouseUp(int mouseX,int mouseY,bool mainButton)416 void KIA::handleMouseUp(int mouseX, int mouseY, bool mainButton) {
417 if (!isOpen()) {
418 return;
419 }
420 if (mainButton) {
421 _buttons->handleMouseAction(mouseX, mouseY, false, true, false);
422 }
423 if (_currentSection) {
424 _currentSection->handleMouseUp(mainButton);
425 }
426 if (_currentSection && _currentSection->_scheduledSwitch) {
427 if (_currentSectionId == kKIASectionCrimes) {
428 open(kKIASectionSuspects);
429 _suspectsSection->selectSuspect(_crimesSection->_suspectSelected);
430 _log->next();
431 _log->clearFuture();
432 } else if (_currentSectionId == kKIASectionSuspects) {
433 open(kKIASectionCrimes);
434 _crimesSection->selectCrime(_suspectsSection->_crimeSelected);
435 _log->next();
436 _log->clearFuture();
437 } else {
438 open(kKIASectionNone);
439 }
440 }
441 }
442
handleMouseScroll(int mouseX,int mouseY,int direction)443 void KIA::handleMouseScroll(int mouseX, int mouseY, int direction) {
444 if (!isOpen()) {
445 return;
446 }
447 if (_currentSection) {
448 _currentSection->handleMouseScroll(direction);
449 }
450 }
451
handleKeyUp(const Common::KeyState & kbd)452 void KIA::handleKeyUp(const Common::KeyState &kbd) {
453 if (!isOpen()) {
454 return;
455 }
456
457 if (_currentSection) {
458 _currentSection->handleKeyUp(kbd);
459 }
460 }
461
handleKeyDown(const Common::KeyState & kbd)462 void KIA::handleKeyDown(const Common::KeyState &kbd) {
463 if (!isOpen()) {
464 return;
465 }
466
467 if (toupper(kbd.ascii) != kPogo[_pogoPos]) {
468 _pogoPos = 0;
469 }
470 if (_currentSectionId != kKIASectionSave) {
471 if (toupper(kbd.ascii) == kPogo[_pogoPos]) {
472 ++_pogoPos;
473 if (!kPogo[_pogoPos]) {
474 open(kKIASectionPogo);
475 _pogoPos = 0;
476 }
477 }
478 }
479
480 switch (kbd.keycode) {
481 case Common::KEYCODE_ESCAPE:
482 if (!_forceOpen) {
483 open(kKIASectionNone);
484 }
485 break;
486
487 case Common::KEYCODE_F1:
488 open(kKIASectionHelp);
489 break;
490
491 case Common::KEYCODE_F2:
492 if (!_forceOpen) {
493 open(kKIASectionSave);
494 }
495 break;
496 case Common::KEYCODE_F3:
497 open(kKIASectionLoad);
498 break;
499
500 case Common::KEYCODE_F10:
501 open(kKIASectionQuit);
502 break;
503
504 case Common::KEYCODE_F4:
505 if (_currentSectionId != kKIASectionCrimes) {
506 if (!_forceOpen) {
507 open(kKIASectionCrimes);
508 _log->next();
509 _log->clearFuture();
510 }
511 }
512 break;
513
514 case Common::KEYCODE_F5:
515 if (_currentSectionId != kKIASectionSuspects) {
516 if (!_forceOpen) {
517 open(kKIASectionSuspects);
518 _log->next();
519 _log->clearFuture();
520 }
521 }
522 break;
523
524 case Common::KEYCODE_F6:
525 if (_currentSectionId != kKIASectionClues) {
526 if (!_forceOpen) {
527 open(kKIASectionClues);
528 _log->next();
529 _log->clearFuture();
530 }
531 }
532 break;
533
534 default:
535 if (_currentSection) {
536 _currentSection->handleKeyDown(kbd);
537 }
538 break;
539 }
540
541 if (_currentSection && _currentSection->_scheduledSwitch) {
542 open(kKIASectionNone);
543 }
544 }
545
playerReset()546 void KIA::playerReset() {
547 if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
548 int actorId = _playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId;
549 if (_vm->_actors[actorId]->isSpeeching()) {
550 _vm->_actors[actorId]->speechStop();
551 }
552 }
553
554 _playerActorDialogueQueueSize = _playerActorDialogueQueuePosition;
555 _playerSliceModelId = -1;
556 _playerPhotographId = -1;
557 _playerImage.free();
558 _playerActorDialogueState = 0;
559 if (_vm->_cutContent) {
560 _buttons->resetImage(22);
561 }
562 }
563
playActorDialogue(int actorId,int sentenceId)564 void KIA::playActorDialogue(int actorId, int sentenceId) {
565 int newQueueSize = (_playerActorDialogueQueueSize + 1) % kPlayerActorDialogueQueueCapacity;
566 if (newQueueSize != _playerActorDialogueQueuePosition) {
567 _playerActorDialogueQueue[_playerActorDialogueQueueSize].actorId = actorId;
568 _playerActorDialogueQueue[_playerActorDialogueQueueSize].sentenceId = sentenceId;
569 _playerActorDialogueQueueSize = newQueueSize;
570 }
571 }
572
playSliceModel(int sliceModelId)573 void KIA::playSliceModel(int sliceModelId) {
574 if (_playerVqaFrame == 8) {
575 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP1), 70, 0, 0, 50, 0);
576 }
577 _playerSliceModelId = sliceModelId;
578 if (_vm->_cutContent) {
579 _buttons->defineImage(22, Common::Rect(530, 32, 635, 126), nullptr, nullptr, nullptr, _vm->_textClueTypes->getText(3)); // "OBJECT"
580 }
581 }
582
playPhotograph(int photographId)583 void KIA::playPhotograph(int photographId) {
584 if (_playerVqaFrame == 8) {
585 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBEEP1), 70, 0, 0, 50, 0);
586 }
587 _playerPhotographId = photographId;
588 }
589
playImage(const Graphics::Surface & image)590 void KIA::playImage(const Graphics::Surface &image) {
591 if (image.w != 80) {
592 Graphics::Surface *tmp = image.scale(80, 60);
593 _playerImage.copyFrom(*tmp);
594 tmp->free();
595 delete tmp;
596 } else {
597 _playerImage.copyFrom(image);
598 }
599 _playerImage.convertToInPlace(screenPixelFormat());
600 }
601
scrambleSuspectsName(const char * name)602 const char *KIA::scrambleSuspectsName(const char *name) {
603 static char buffer[32];
604
605 unsigned char *bufferPtr = (unsigned char *)buffer;
606 const unsigned char *namePtr = (const unsigned char *)name;
607
608 for (int i = 0 ; i < 6; ++i) {
609 if (_vm->_language == Common::RU_RUS && _vm->_russianCP1251) {
610 // Algorithm added by Siberian Studio in R4 patch
611 if (*namePtr >= 0xC0) {
612 unsigned char upper = *namePtr & 0xDF;
613 if (upper < 201) {
614 *bufferPtr++ = upper - 143; /* Map А-И to 1-9 */
615 } else {
616 *bufferPtr++ = upper - 136; /* Map Й-Я to A-W */
617 }
618 } else {
619 *bufferPtr++ = '0';
620 }
621 } else {
622 if (Common::isAlpha(*namePtr)) {
623 char upper = toupper(*namePtr);
624 if ( upper < 'J' ) {
625 *bufferPtr++ = upper - 16; /* Map A-I to 1-9 */
626 } else {
627 *bufferPtr++ = upper - 9; /* Map J-Z to A-Q */
628 }
629 } else {
630 *bufferPtr++ = '0';
631 }
632 }
633 if (*namePtr) {
634 ++namePtr;
635 }
636 if (i == 1) {
637 *bufferPtr++ = '-';
638 }
639 }
640 *bufferPtr = 0;
641 return buffer;
642 }
643
mouseDownCallback(int buttonId,void * callbackData)644 void KIA::mouseDownCallback(int buttonId, void *callbackData) {
645 KIA *self = (KIA *)callbackData;
646 switch (buttonId) {
647 case 0:
648 case 6:
649 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4P), 100, -65, -65, 50, 0);
650 break;
651 case 1:
652 case 2:
653 case 3:
654 case 4:
655 case 5:
656 case 7:
657 case 8:
658 case 9:
659 case 10:
660 case 11:
661 case 12:
662 case 13:
663 case 14:
664 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN5P), 70, 0, 0, 50, 0);
665 if (buttonId == 12) {
666 int endTrackId = self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxSHUTDOWN), 70, 0, 0, 50, 0);
667
668 self->_vm->_surfaceFront.fillRect(Common::Rect(0, 0, 640, 480), 0);
669 self->_vm->blitToScreen(self->_vm->_surfaceFront);
670
671 if (endTrackId != -1) {
672 // wait until the full clip has played (similar to the original)
673 uint32 timeNow = self->_vm->_time->currentSystem();
674 uint32 waittime = 16;
675 while (self->_vm->_audioPlayer->isActive(endTrackId)) {
676 if (self->_vm->_noDelayMillisFramelimiter) {
677 while (self->_vm->_time->currentSystem() - timeNow < waittime) { }
678 } else {
679 self->_vm->_system->delayMillis(waittime);
680 }
681 }
682 }
683 }
684 break;
685 case 15:
686 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4P), 70, 0, 0, 50, 0);
687 break;
688 default:
689 break;
690 }
691 }
692
mouseUpCallback(int buttonId,void * callbackData)693 void KIA::mouseUpCallback(int buttonId, void *callbackData) {
694 KIA *self = (KIA *)callbackData;
695 switch (buttonId) {
696 case 0:
697 case 6:
698 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4R), 100, -65, -65, 50, 0);
699 break;
700 case 1:
701 case 2:
702 case 3:
703 case 4:
704 case 5:
705 case 7:
706 case 8:
707 case 9:
708 case 10:
709 case 11:
710 case 12:
711 case 13:
712 case 14:
713 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN5R), 70, 0, 0, 50, 0);
714 break;
715 case 15:
716 self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxBUTN4R), 100, 0, 0, 50, 0);
717 break;
718 default:
719 break;
720 }
721 self->buttonClicked(buttonId);
722 }
723
loopEnded(void * callbackData,int frame,int loopId)724 void KIA::loopEnded(void *callbackData, int frame, int loopId) {
725 KIA *self = (KIA *)callbackData;
726 self->_mainVqaPlayer->setLoop(self->getVqaLoopMain(self->_currentSectionId) + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
727 self->_transitionId = 0;
728 }
729
init()730 void KIA::init() {
731 createThumbnailFromScreen(&_thumbnail);
732
733 if (!_vm->openArchive("MODE.MIX")) {
734 return;
735 }
736
737 playerReset();
738 _playerVqaFrame = 0;
739 _playerVqaTimeLast = _vm->_time->currentSystem();
740 _timeLast = _vm->_time->currentSystem();
741
742 if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon) && !_vm->_gameFlags->query(kFlagKIAPrivacyAddonIntro)) {
743 _vm->_gameFlags->set(kFlagKIAPrivacyAddonIntro);
744 playPrivateAddon();
745 }
746
747 _shapes->load("kiaopt.shp");
748 _playerPhotographs->load("photos.shp");
749
750 _buttons->activate(nullptr, nullptr, mouseDownCallback, mouseUpCallback, this);
751 _vm->_mouse->setCursor(0);
752 if (_playerVqaPlayer == nullptr) {
753 _playerVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, "kiaover.vqa");
754 _playerVqaPlayer->open();
755 _playerVqaPlayer->setLoop(0, -1, kLoopSetModeJustStart, nullptr, nullptr);
756 }
757 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECTRO1), 70, 0, 0, 50, 0);
758
759 _vm->_time->pause();
760 }
761
unload()762 void KIA::unload() {
763 _thumbnail.free();
764
765 if (!isOpen()) {
766 return;
767 }
768
769 _forceOpen = false;
770
771 if (_currentSection) {
772 _currentSection->close();
773 _currentSection = nullptr;
774 }
775
776 _buttons->resetImages();
777 _buttons->deactivate();
778
779 _shapes->unload();
780 _playerPhotographs->unload();
781
782 delete _mainVqaPlayer;
783 _mainVqaPlayer = nullptr;
784
785 delete _playerVqaPlayer;
786 _playerVqaPlayer = nullptr;
787
788 _vm->closeArchive("MODE.MIX");
789
790 _currentSectionId = kKIASectionNone;
791
792 _vm->_time->resume();
793
794 if (!_vm->_settings->isLoadingGame() && _vm->_gameIsRunning) {
795 _vm->_scene->resume();
796 }
797 }
798
createButtons(int sectionId)799 void KIA::createButtons(int sectionId) {
800 Common::Rect kiaButton6( 66, 00, 122, 44);
801 Common::Rect kiaButton7( 191, 29, 233, 70);
802 Common::Rect kiaButton8( 234, 29, 278, 70);
803 Common::Rect kiaButton9( 278, 29, 321, 70);
804 Common::Rect kiaButton10(322, 29, 365, 70);
805 Common::Rect kiaButton11(366, 29, 410, 70);
806 Common::Rect kiaButton12(420, 286, 472, 328);
807 Common::Rect kiaButton13(334, 286, 386, 328);
808 Common::Rect kiaButton14(411, 29, 453, 70);
809 Common::Rect kiaButton15(264, 9, 304, 26);
810 Common::Rect kiaButton16(140, 406, 160, 479);
811 Common::Rect kiaButton17(161, 406, 180, 479);
812 Common::Rect kiaButton18(181, 406, 202, 479);
813 Common::Rect kiaButton19(575, 307, 606, 350);
814 Common::Rect kiaButton21(211, 443, 291, 479);
815
816 const Shape *shapeUp = nullptr;
817 const Shape *shapeHovered = nullptr;
818 const Shape *shapeDown = nullptr;
819
820 switch (sectionId) {
821 case kKIASectionCrimes:
822 case kKIASectionSuspects:
823 case kKIASectionClues:
824 _buttons->defineImage(0, kiaButton6, nullptr, nullptr, _shapes->get(1), _vm->_textKIA->getText(23));
825
826 if (_vm->_cutContent && _playerSliceModelId != -1) {
827 _buttons->defineImage(22, Common::Rect(530, 32, 635, 126), nullptr, nullptr, nullptr, _vm->_textClueTypes->getText(3)); // "OBJECT"
828 }
829
830 if (sectionId == kKIASectionCrimes) {
831 shapeUp = _shapes->get(2);
832 shapeHovered = _shapes->get(2);
833 shapeDown = _shapes->get(10);
834 } else {
835 shapeUp = nullptr;
836 shapeHovered = nullptr;
837 shapeDown = _shapes->get(18);
838 }
839 _buttons->defineImage(1, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(24));
840
841 if (sectionId == kKIASectionSuspects) {
842 shapeUp = _shapes->get(3);
843 shapeHovered = _shapes->get(3);
844 shapeDown = _shapes->get(11);
845 } else {
846 shapeUp = nullptr;
847 shapeHovered = nullptr;
848 shapeDown = _shapes->get(19);
849 }
850 _buttons->defineImage(2, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(25));
851
852 if (sectionId == kKIASectionClues) {
853 shapeUp = _shapes->get(4);
854 shapeHovered = _shapes->get(4);
855 shapeDown = _shapes->get(12);
856 } else {
857 shapeUp = nullptr;
858 shapeHovered = nullptr;
859 shapeDown = _shapes->get(20);
860 }
861 _buttons->defineImage(3, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(26));
862
863 _buttons->defineImage(4, kiaButton10, nullptr, nullptr, _shapes->get(21), _vm->_textKIA->getText(27));
864
865 _buttons->defineImage(5, kiaButton11, nullptr, nullptr, _shapes->get(22), _vm->_textKIA->getText(28));
866
867 _buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(23), _vm->_textKIA->getText(29));
868
869 break;
870 case kKIASectionSettings:
871 case kKIASectionHelp:
872 case kKIASectionSave:
873 case kKIASectionLoad:
874 case kKIASectionDiagnostic:
875 case kKIASectionPogo:
876 _buttons->defineImage(6, kiaButton6, nullptr, nullptr, _shapes->get(0), _vm->_textKIA->getText(37));
877
878 if (sectionId == kKIASectionSettings) {
879 shapeUp = _shapes->get(5);
880 shapeHovered = _shapes->get(5);
881 shapeDown = _shapes->get(13);
882 } else {
883 shapeUp = nullptr;
884 shapeHovered = nullptr;
885 shapeDown = _shapes->get(24);
886 }
887 _buttons->defineImage(7, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(38));
888
889 if (sectionId == kKIASectionHelp) {
890 shapeUp = _shapes->get(6);
891 shapeHovered = _shapes->get(6);
892 shapeDown = _shapes->get(14);
893 } else {
894 shapeUp = nullptr;
895 shapeHovered = nullptr;
896 shapeDown = _shapes->get(25);
897 }
898 _buttons->defineImage(8, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(41));
899
900 if (sectionId == kKIASectionSave) {
901 shapeUp = _shapes->get(7);
902 shapeHovered = _shapes->get(7);
903 shapeDown = _shapes->get(15);
904 } else {
905 shapeUp = nullptr;
906 shapeHovered = nullptr;
907 shapeDown = _shapes->get(26);
908 }
909 _buttons->defineImage(9, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(39));
910
911 if (sectionId == kKIASectionLoad) {
912 shapeUp = _shapes->get(8);
913 shapeHovered = _shapes->get(8);
914 shapeDown = _shapes->get(16);
915 } else {
916 shapeUp = nullptr;
917 shapeHovered = nullptr;
918 shapeDown = _shapes->get(27);
919 }
920 _buttons->defineImage(10, kiaButton10, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(40));
921
922 _buttons->defineImage(11, kiaButton11, nullptr, nullptr, _shapes->get(28), _vm->_textKIA->getText(42));
923
924 _buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(29), _vm->_textKIA->getText(29));
925
926 break;
927 case kKIASectionQuit:
928 _buttons->defineImage(12, kiaButton12, _shapes->get(124), _shapes->get(124), _shapes->get(48), _vm->_textKIA->getText(42));
929
930 _buttons->defineImage(13, kiaButton13, _shapes->get(125), _shapes->get(125), _shapes->get(49), _vm->_textKIA->getText(29));
931 break;
932 }
933
934 if (sectionId != kKIASectionQuit) {
935 _buttons->defineImage(15, kiaButton15, nullptr, nullptr, _shapes->get(38), _vm->_textKIA->getText(43));
936
937 _buttons->defineImage(19, kiaButton19, nullptr, nullptr, nullptr, _vm->_textKIA->getText(44));
938
939 if (_vm->_settings->getAmmo(0) > 0) {
940 _buttons->defineImage(16, kiaButton16, nullptr, nullptr, nullptr, _vm->_textKIA->getText(50));
941 }
942 Common::String tooltip;
943 if (_vm->_settings->getAmmo(1) > 0) {
944 if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
945 tooltip = Common::String::format("%d", _vm->_settings->getAmmo(1));
946 } else {
947 tooltip = _vm->_textKIA->getText(50);
948 }
949 _buttons->defineImage(17, kiaButton17, nullptr, nullptr, nullptr, tooltip.c_str());
950 }
951 if (_vm->_settings->getAmmo(2) > 0) {
952 if (_vm->_settings->getDifficulty() > kGameDifficultyEasy) {
953 tooltip = Common::String::format("%d", _vm->_settings->getAmmo(2));
954 } else {
955 tooltip = _vm->_textKIA->getText(50);
956 }
957 _buttons->defineImage(18, kiaButton18, nullptr, nullptr, nullptr, tooltip.c_str());
958 }
959 if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
960 _buttons->defineImage(21, kiaButton21, nullptr, nullptr, nullptr, nullptr);
961 }
962 }
963 }
964
buttonClicked(int buttonId)965 void KIA::buttonClicked(int buttonId) {
966 int soundId = 0;
967
968 if (!isOpen()) {
969 return;
970 }
971 switch (buttonId) {
972 case 0:
973 open(kKIASectionSettings);
974 break;
975 case 1:
976 if (_currentSectionId != kKIASectionCrimes) {
977 open(kKIASectionCrimes);
978 _log->next();
979 _log->clearFuture();
980 }
981 break;
982 case 2:
983 if (_currentSectionId != kKIASectionSuspects) {
984 open(kKIASectionSuspects);
985 _log->next();
986 _log->clearFuture();
987 }
988 break;
989 case 3:
990 if (_currentSectionId != kKIASectionClues) {
991 open(kKIASectionClues);
992 _log->next();
993 _log->clearFuture();
994 }
995 break;
996 case 4:
997 if (_log->hasPrev()) {
998 int kiaLogPrevType = _log->getPrevType();
999 switch (kiaLogPrevType) {
1000 case 2:
1001 open(kKIASectionCrimes);
1002 _log->prev();
1003 _crimesSection->loadFromLog();
1004 break;
1005 case 1:
1006 open(kKIASectionSuspects);
1007 _log->prev();
1008 _suspectsSection->loadFromLog();
1009 break;
1010 case 0:
1011 open(kKIASectionClues);
1012 _log->prev();
1013 _cluesSection->loadFromLog();
1014 break;
1015 }
1016 }
1017 break;
1018 case 5:
1019 if (_log->hasNext()) {
1020 int kiaLogNextType = _log->getNextType();
1021 switch (kiaLogNextType) {
1022 case 2:
1023 open(kKIASectionCrimes);
1024 _log->next();
1025 _crimesSection->loadFromLog();
1026 break;
1027 case 1:
1028 open(kKIASectionSuspects);
1029 _log->next();
1030 _suspectsSection->loadFromLog();
1031 break;
1032 case 0:
1033 open(kKIASectionClues);
1034 _log->next();
1035 _cluesSection->loadFromLog();
1036 break;
1037 }
1038 }
1039 break;
1040 case 6:
1041 if (!_forceOpen) {
1042 open(_lastSectionIdKIA);
1043 }
1044 break;
1045 case 7:
1046 open(kKIASectionSettings);
1047 break;
1048 case 8:
1049 open(kKIASectionHelp);
1050 break;
1051 case 9:
1052 if (!_forceOpen) {
1053 open(kKIASectionSave);
1054 }
1055 break;
1056 case 10:
1057 open(kKIASectionLoad);
1058 break;
1059 case 11:
1060 open(kKIASectionQuit);
1061 break;
1062 case 12:
1063 _vm->_gameIsRunning = false;
1064 open(kKIASectionNone);
1065 break;
1066 case 13:
1067 open(_lastSectionIdOptions);
1068 break;
1069 case 14:
1070 if (!_forceOpen) {
1071 open(kKIASectionNone);
1072 }
1073 break;
1074 case 15:
1075 open(kKIASectionDiagnostic);
1076 break;
1077 case 16:
1078 _vm->_settings->setAmmoType(0);
1079 if (_vm->_rnd.getRandomNumber(1)) {
1080 soundId = _vm->_combat->getHitSound();
1081 } else {
1082 soundId = _vm->_combat->getMissSound();
1083 }
1084 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
1085 break;
1086 case 17:
1087 _vm->_settings->setAmmoType(1);
1088 if (_vm->_rnd.getRandomNumber(1)) {
1089 soundId = _vm->_combat->getHitSound();
1090 } else {
1091 soundId = _vm->_combat->getMissSound();
1092 }
1093 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
1094 break;
1095 case 18:
1096 _vm->_settings->setAmmoType(2);
1097 if (_vm->_rnd.getRandomNumber(1)) {
1098 soundId = _vm->_combat->getHitSound();
1099 } else {
1100 soundId = _vm->_combat->getMissSound();
1101 }
1102 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
1103 break;
1104 case 19:
1105 return;
1106 case 20:
1107 playerReset();
1108 break;
1109 case 21:
1110 playPrivateAddon();
1111 break;
1112 case 22:
1113 if (_vm->_cutContent) {
1114 // play audio description
1115 playObjectDescription();
1116 }
1117 break;
1118 }
1119 }
1120
switchSection(int sectionId)1121 void KIA::switchSection(int sectionId) {
1122 if (_currentSection) {
1123 _currentSection->close();
1124 }
1125 switch (sectionId) {
1126 case kKIASectionCrimes:
1127 _currentSection = _crimesSection;
1128 break;
1129 case kKIASectionSuspects:
1130 _currentSection = _suspectsSection;
1131 break;
1132 case kKIASectionClues:
1133 _currentSection = _cluesSection;
1134 break;
1135 case kKIASectionSettings:
1136 _currentSection = _settingsSection;
1137 break;
1138 case kKIASectionHelp:
1139 _currentSection = _helpSection;
1140 break;
1141 case kKIASectionSave:
1142 _currentSection = _saveSection;
1143 break;
1144 case kKIASectionLoad:
1145 _currentSection = _loadSection;
1146 break;
1147 case kKIASectionQuit:
1148 _currentSection = nullptr;
1149 break;
1150 case kKIASectionDiagnostic:
1151 _currentSection = _diagnosticSection;
1152 break;
1153 case kKIASectionPogo:
1154 _currentSection = _pogoSection;
1155 break;
1156 default:
1157 _currentSection = nullptr;
1158 break;
1159 }
1160 if (_currentSection) {
1161 _currentSection->open();
1162 }
1163 }
1164
getSectionVqaName(int sectionId)1165 const char *KIA::getSectionVqaName(int sectionId) {
1166 switch (sectionId) {
1167 case kKIASectionCrimes:
1168 return "kia_crim.vqa";
1169 case kKIASectionSuspects:
1170 return "kia_susp.vqa";
1171 case kKIASectionClues:
1172 return "kia_clue.vqa";
1173 case kKIASectionSettings:
1174 case kKIASectionHelp:
1175 case kKIASectionSave:
1176 case kKIASectionLoad:
1177 case kKIASectionQuit:
1178 case kKIASectionDiagnostic:
1179 case kKIASectionPogo:
1180 return "kia_ingm.vqa";
1181 default:
1182 return nullptr;
1183 }
1184 }
1185
getVqaLoopMain(int sectionId)1186 int KIA::getVqaLoopMain(int sectionId) {
1187 switch (sectionId) {
1188 case kKIASectionCrimes:
1189 case kKIASectionSuspects:
1190 case kKIASectionClues:
1191 return 3;
1192 case kKIASectionSettings:
1193 case kKIASectionHelp:
1194 case kKIASectionSave:
1195 case kKIASectionLoad:
1196 case kKIASectionDiagnostic:
1197 case kKIASectionPogo:
1198 return 4;
1199 case kKIASectionQuit:
1200 return 7;
1201 default:
1202 return 0;
1203 }
1204 }
1205
getVqaLoopTransition(int transitionId)1206 int KIA::getVqaLoopTransition(int transitionId) {
1207 switch (transitionId) {
1208 case 0:
1209 case 2:
1210 case 7:
1211 case 8:
1212 return 0;
1213 case 1:
1214 case 4:
1215 case 5:
1216 case 9:
1217 return 1;
1218 case 3:
1219 case 10:
1220 case 11:
1221 case 12:
1222 return 2;
1223 case 6:
1224 return 3;
1225 case 13:
1226 return 6;
1227 default:
1228 return 0;
1229 }
1230 }
1231
getTransitionId(int oldSectionId,int newSectionId)1232 int KIA::getTransitionId(int oldSectionId, int newSectionId) {
1233 switch (oldSectionId) {
1234 case kKIASectionNone:
1235 return 0;
1236 case kKIASectionCrimes:
1237 switch (newSectionId) {
1238 case kKIASectionCrimes:
1239 return 0;
1240 case kKIASectionSuspects:
1241 return 1;
1242 case kKIASectionClues:
1243 return 2;
1244 case kKIASectionSettings:
1245 case kKIASectionHelp:
1246 case kKIASectionSave:
1247 case kKIASectionLoad:
1248 case kKIASectionDiagnostic:
1249 case kKIASectionPogo:
1250 return 3;
1251 case kKIASectionQuit:
1252 return 13;
1253 }
1254 return 0;
1255 case kKIASectionSuspects:
1256 switch (newSectionId) {
1257 case kKIASectionCrimes:
1258 return 4;
1259 case kKIASectionSuspects:
1260 return 0;
1261 case kKIASectionClues:
1262 return 5;
1263 case kKIASectionSettings:
1264 case kKIASectionHelp:
1265 case kKIASectionSave:
1266 case kKIASectionLoad:
1267 case kKIASectionDiagnostic:
1268 case kKIASectionPogo:
1269 return 6;
1270 case kKIASectionQuit:
1271 return 13;
1272 }
1273 return 0;
1274 case kKIASectionClues:
1275 switch (newSectionId) {
1276 case kKIASectionCrimes:
1277 return 7;
1278 case kKIASectionSuspects:
1279 return 8;
1280 case kKIASectionClues:
1281 return 0;
1282 case kKIASectionSettings:
1283 case kKIASectionHelp:
1284 case kKIASectionSave:
1285 case kKIASectionLoad:
1286 case kKIASectionDiagnostic:
1287 case kKIASectionPogo:
1288 return 9;
1289 case kKIASectionQuit:
1290 return 13;
1291 }
1292 return 0;
1293 case kKIASectionSettings:
1294 case kKIASectionHelp:
1295 case kKIASectionSave:
1296 case kKIASectionLoad:
1297 case kKIASectionDiagnostic:
1298 case kKIASectionPogo:
1299 switch (newSectionId) {
1300 case kKIASectionCrimes:
1301 return 10;
1302 case kKIASectionSuspects:
1303 return 11;
1304 case kKIASectionClues:
1305 return 12;
1306 case kKIASectionSettings:
1307 case kKIASectionHelp:
1308 case kKIASectionSave:
1309 case kKIASectionLoad:
1310 case kKIASectionDiagnostic:
1311 case kKIASectionPogo:
1312 return 0;
1313 case kKIASectionQuit:
1314 return 13;
1315 }
1316 return 0;
1317 case kKIASectionQuit:
1318 if (newSectionId != kKIASectionQuit) {
1319 return 14;
1320 }
1321 }
1322 return 0;
1323 }
1324
playTransitionSound(int transitionId)1325 void KIA::playTransitionSound(int transitionId) {
1326 switch (transitionId) {
1327 case 1:
1328 case 2:
1329 case 3:
1330 case 4:
1331 case 5:
1332 case 6:
1333 case 7:
1334 case 8:
1335 case 9:
1336 case 10:
1337 case 11:
1338 case 12:
1339 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANEL1), 100, 0, 0, 50, 0);
1340 break;
1341 case 13:
1342 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANEL2), 100, 0, 0, 50, 0);
1343 break;
1344 case 14:
1345 _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxPANOPEN), 100, 0, 0, 50, 0);
1346 break;
1347 }
1348 }
1349
playPrivateAddon()1350 void KIA::playPrivateAddon() {
1351 playerReset();
1352 playSliceModel(524);
1353 playActorDialogue(kActorBulletBob, 2060);
1354 playActorDialogue(kActorBulletBob, 2070);
1355 }
1356
playObjectDescription()1357 void KIA::playObjectDescription() {
1358 if (_playerSliceModelId == -1) {
1359 return;
1360 }
1361 switch (_playerSliceModelId) {
1362 case kModelAnimationShellCasings:
1363 playActorDialogue(kActorMcCoy, 8730);
1364 break;
1365 case kModelAnimationCandy:
1366 playActorDialogue(kActorMcCoy, 8735);
1367 break;
1368 case kModelAnimationToyDog:
1369 playActorDialogue(kActorMcCoy, 8740);
1370 break;
1371 case kModelAnimationChopstickWrapper:
1372 playActorDialogue(kActorMcCoy, 8745);
1373 break;
1374 case kModelAnimationReferenceLetter:
1375 playActorDialogue(kActorMcCoy, 8750);
1376 break;
1377 case kModelAnimationChromeDebris:
1378 playActorDialogue(kActorMcCoy, 8755);
1379 break;
1380 case kModelAnimationLicensePlate:
1381 playActorDialogue(kActorMcCoy, 8760);
1382 break;
1383 case kModelAnimationDragonflyEarring:
1384 playActorDialogue(kActorMcCoy, 8765);
1385 break;
1386 case kModelAnimationDetonatorWire:
1387 playActorDialogue(kActorMcCoy, 8770);
1388 break;
1389 case kModelAnimationKingstonKitchenBox:
1390 playActorDialogue(kActorMcCoy, 8775);
1391 break;
1392 case kModelAnimationTyrellSalesPamphletKIA:
1393 playActorDialogue(kActorMcCoy, 8780);
1394 break;
1395 case kModelAnimationRadiationGoggles:
1396 playActorDialogue(kActorMcCoy, 8785);
1397 break;
1398 case kModelAnimationDogCollar:
1399 playActorDialogue(kActorMcCoy, 8790);
1400 break;
1401 case kModelAnimationMaggieBracelet:
1402 playActorDialogue(kActorMcCoy, 8795);
1403 break;
1404 case kModelAnimationEnvelope:
1405 playActorDialogue(kActorMcCoy, 8800);
1406 break;
1407 case kModelAnimationWeaponsOrderForm:
1408 // fall through
1409 case kModelAnimationRequisitionForm:
1410 // fall through
1411 case kModelAnimationOriginalShippingForm:
1412 // fall through
1413 case kModelAnimationOriginalRequisitionForm:
1414 playActorDialogue(kActorMcCoy, 8805); // A requisition form
1415 break;
1416 case kModelAnimationHysteriaToken:
1417 playActorDialogue(kActorMcCoy, 8810);
1418 break;
1419 case kModelAnimationRagDoll:
1420 playActorDialogue(kActorMcCoy, 8815);
1421 break;
1422 case kModelAnimationCheese:
1423 playActorDialogue(kActorMcCoy, 8820);
1424 break;
1425 case kModelAnimationDragonflyBelt:
1426 playActorDialogue(kActorMcCoy, 8825);
1427 break;
1428 case kModelAnimationStrangeScale:
1429 playActorDialogue(kActorMcCoy, 8830);
1430 break;
1431 case kModelAnimationDektorasCard:
1432 playActorDialogue(kActorMcCoy, 8835);
1433 break;
1434 case kModelAnimationLetter:
1435 // fall through
1436 case kModelAnimationGrigoriansNote:
1437 playActorDialogue(kActorMcCoy, 8840);
1438 break;
1439 case kModelAnimationCollectionReceipt:
1440 playActorDialogue(kActorMcCoy, 8845);
1441 break;
1442 case kModelAnimationGordosLighterReplicant:
1443 // fall through
1444 case kModelAnimationGordosLighterHuman:
1445 playActorDialogue(kActorMcCoy, 8850);
1446 break;
1447 // case kModelAnimationBadge: // This is never discovered in-game, and uses same model as Holden's badge
1448 // playActorDialogue(kActorMcCoy, 8855); // Baker's Badge
1449 // break;
1450 case kModelAnimationBadge:
1451 playActorDialogue(kActorMcCoy, 8860);
1452 break;
1453 case kModelAnimationLichenDogWrapper:
1454 playActorDialogue(kActorMcCoy, 8865);
1455 break;
1456 case kModelAnimationFolder:
1457 playActorDialogue(kActorMcCoy, 8870);
1458 break;
1459 case kModelAnimationCandyWrapper:
1460 playActorDialogue(kActorMcCoy, 8875);
1461 break;
1462 case kModelAnimationFlaskOfAbsinthe:
1463 playActorDialogue(kActorMcCoy, 8880);
1464 break;
1465 case kModelAnimationPowerSource:
1466 playActorDialogue(kActorMcCoy, 8885);
1467 break;
1468 case kModelAnimationBomb: // TODO - does this ever appear in KIA?
1469 playActorDialogue(kActorMcCoy, 8890);
1470 break;
1471 case kModelAnimationGarterSnake:
1472 playActorDialogue(kActorMcCoy, 8895);
1473 break;
1474 case kModelAnimationSlug:
1475 playActorDialogue(kActorMcCoy, 8900);
1476 break;
1477 case kModelAnimationGoldfish:
1478 playActorDialogue(kActorMcCoy, 8905);
1479 break;
1480 case kModelAnimationDNAEvidence01OutOf6:
1481 // fall through
1482 // case kModelAnimationDNAEvidence02OutOf6:
1483 // fall through
1484 case kModelAnimationDNAEvidence03OutOf6:
1485 // fall through
1486 case kModelAnimationDNAEvidence04OutOf6:
1487 // fall through
1488 // case kModelAnimationDNAEvidence05OutOf6:
1489 // fall through
1490 case kModelAnimationDNAEvidenceComplete:
1491 // fall through
1492 case kModelAnimationSpinnerKeys:
1493 // fall through
1494 case kModelAnimationBriefcase:
1495 // fall through
1496 case kModelAnimationCrystalsCigarette:
1497 // fall through
1498 case kModelAnimationVideoDisc:
1499 // fall through
1500 default:
1501 playActorDialogue(kActorMcCoy, 8525);
1502 break;
1503 }
1504 }
1505
1506 } // End of namespace BladeRunner
1507