aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/ui
diff options
context:
space:
mode:
authorPeter Kohaut2018-01-28 20:59:12 +0100
committerPeter Kohaut2018-01-29 18:32:09 +0100
commit0c930b06ed7030686c7774f18126b3d37a678d60 (patch)
tree04322a848f17c3d8fc4ced7e89e6ce6dbf73dcb3 /engines/bladerunner/ui
parentfa28602abffd47988dd7d797e4c48d9e3faf47ae (diff)
downloadscummvm-rg350-0c930b06ed7030686c7774f18126b3d37a678d60.tar.gz
scummvm-rg350-0c930b06ed7030686c7774f18126b3d37a678d60.tar.bz2
scummvm-rg350-0c930b06ed7030686c7774f18126b3d37a678d60.zip
BLADERUNNER: Added KIA interfaces
Crimes interface done Suspects interface done Added some game constants Fixed font rendering for other languages Fixed anoying clang warning
Diffstat (limited to 'engines/bladerunner/ui')
-rw-r--r--engines/bladerunner/ui/kia.cpp14
-rw-r--r--engines/bladerunner/ui/kia_section_base.cpp2
-rw-r--r--engines/bladerunner/ui/kia_section_base.h2
-rw-r--r--engines/bladerunner/ui/kia_section_clues.cpp24
-rw-r--r--engines/bladerunner/ui/kia_section_clues.h3
-rw-r--r--engines/bladerunner/ui/kia_section_crimes.cpp449
-rw-r--r--engines/bladerunner/ui/kia_section_crimes.h88
-rw-r--r--engines/bladerunner/ui/kia_section_suspects.cpp555
-rw-r--r--engines/bladerunner/ui/kia_section_suspects.h93
-rw-r--r--engines/bladerunner/ui/spinner.cpp85
-rw-r--r--engines/bladerunner/ui/spinner.h8
11 files changed, 1225 insertions, 98 deletions
diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp
index 09c5918872..7e08a148fb 100644
--- a/engines/bladerunner/ui/kia.cpp
+++ b/engines/bladerunner/ui/kia.cpp
@@ -107,8 +107,8 @@ KIA::KIA(BladeRunnerEngine *vm) {
_buttons = new UIImagePicker(_vm, 22);
- _crimesSection = new KIASectionCrimes(_vm); // PlayerActor->_clues
- _suspectsSection = new KIASectionSuspects(_vm); // PlayerActor->_clues
+ _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);
@@ -318,15 +318,15 @@ void KIA::handleMouseUp(int mouseX, int mouseY, bool mainButton) {
if (_currentSection) {
_currentSection->handleMouseUp(mainButton);
}
- if (_currentSection && _currentSection->_field0) {
+ if (_currentSection && _currentSection->_scheduledSwitch) {
if (_currentSectionId == kKIASectionCrimes) {
open(kKIASectionSuspects);
- // kiaSuspects::sub_45290C(_suspectsMenu, _crimesMenu->selectedSuspectId);
+ _suspectsSection->selectSuspect(_crimesSection->_suspectSelected);
_log->next();
_log->clearFuture();
} else if (_currentSectionId == kKIASectionSuspects) {
open(kKIASectionCrimes);
- // kiaCrimes::updateCrime(_crimesMenu, *&_suspectsMenu->data[8052]);
+ _crimesSection->selectCrime(_suspectsSection->_crimeSelected);
_log->next();
_log->clearFuture();
} else {
@@ -361,7 +361,7 @@ void KIA::handleKeyUp(const Common::KeyState &kbd) {
_currentSection->handleKeyUp(kbd);
}
}
- if (_currentSection && _currentSection->_field0) {
+ if (_currentSection && _currentSection->_scheduledSwitch) {
open(kKIASectionNone);
}
}
@@ -418,7 +418,7 @@ void KIA::handleKeyDown(const Common::KeyState &kbd) {
}
break;
}
- if (_currentSection && _currentSection->_field0) {
+ if (_currentSection && _currentSection->_scheduledSwitch) {
open(kKIASectionNone);
}
}
diff --git a/engines/bladerunner/ui/kia_section_base.cpp b/engines/bladerunner/ui/kia_section_base.cpp
index 96571e5a48..95f025e336 100644
--- a/engines/bladerunner/ui/kia_section_base.cpp
+++ b/engines/bladerunner/ui/kia_section_base.cpp
@@ -26,7 +26,7 @@ namespace BladeRunner {
KIASectionBase::KIASectionBase(BladeRunnerEngine *vm) {
_vm = vm;
- _field0 = false;
+ _scheduledSwitch = false;
}
KIASectionBase::~KIASectionBase() {
diff --git a/engines/bladerunner/ui/kia_section_base.h b/engines/bladerunner/ui/kia_section_base.h
index 176e30d4b7..ea69d89768 100644
--- a/engines/bladerunner/ui/kia_section_base.h
+++ b/engines/bladerunner/ui/kia_section_base.h
@@ -41,7 +41,7 @@ protected:
BladeRunnerEngine *_vm;
public:
- bool _field0;
+ bool _scheduledSwitch;
KIASectionBase(BladeRunnerEngine *vm);
virtual ~KIASectionBase();
diff --git a/engines/bladerunner/ui/kia_section_clues.cpp b/engines/bladerunner/ui/kia_section_clues.cpp
index 9c8da60ff9..25ff27ba8d 100644
--- a/engines/bladerunner/ui/kia_section_clues.cpp
+++ b/engines/bladerunner/ui/kia_section_clues.cpp
@@ -46,7 +46,7 @@ namespace BladeRunner {
KIASectionClues::KIASectionClues(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) {
_uiContainer = new UIContainer(_vm);
- _isVisible = false;
+ _isOpen = false;
_debugIntangible = false;
_debugNop = 0;
@@ -81,13 +81,13 @@ KIASectionClues::~KIASectionClues() {
}
void KIASectionClues::open() {
- _isVisible = true;
+ _isOpen = true;
_buttons->resetImages();
_buttons->defineImage(0, Common::Rect(142, 380, 191, 395), _vm->_kia->_shapes->get(79), _vm->_kia->_shapes->get(80), _vm->_kia->_shapes->get(81), _vm->_textKIA->getText(30));
_buttons->defineImage(1, Common::Rect(193, 380, 242, 395), _vm->_kia->_shapes->get(76), _vm->_kia->_shapes->get(77), _vm->_kia->_shapes->get(78), _vm->_textKIA->getText(31));
-
_buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this);
+
_cluesScrollBox->show();
_filterScrollBox->show();
@@ -96,8 +96,8 @@ void KIASectionClues::open() {
}
void KIASectionClues::close() {
- if (_isVisible) {
- _isVisible = false;
+ if (_isOpen) {
+ _isOpen = false;
_buttons->deactivate();
_cluesScrollBox->hide();
@@ -385,22 +385,22 @@ void KIASectionClues::populateClues() {
_cluesScrollBox->sortLines();
}
-int KIASectionClues::getClueFilterTypeTextId(int i) {
- if (i) {
- return i - 1;
+int KIASectionClues::getClueFilterTypeTextId(int filterId) {
+ if (filterId) {
+ return filterId - 1;
}
return -1;
}
int KIASectionClues::getClueFilterCrimeId(int filterId) {
- if (filterId == _assetTypeFilterCount) {
- return -1;
+ if (filterId != _assetTypeFilterCount) {
+ return filterId - (_assetTypeFilterCount + 1);
}
- return filterId - (_assetTypeFilterCount + 1);
+ return -1;
}
int KIASectionClues::getLineIdForAssetType(int assetType) {
- if (assetType == -1) {
+ if (assetType == kClueTypeIntangible) {
return 0;
}
return assetType + 1;
diff --git a/engines/bladerunner/ui/kia_section_clues.h b/engines/bladerunner/ui/kia_section_clues.h
index 74f7b55f65..3f6a13d135 100644
--- a/engines/bladerunner/ui/kia_section_clues.h
+++ b/engines/bladerunner/ui/kia_section_clues.h
@@ -36,6 +36,7 @@ class UIImagePicker;
class UIScrollBox;
class KIASectionClues : public KIASectionBase {
+ //TODO: use gameInfo->getClueCount(), not in original game
static const int kClueCount = 288;
struct Line {
@@ -49,7 +50,7 @@ class KIASectionClues : public KIASectionBase {
UIScrollBox *_cluesScrollBox;
UIScrollBox *_filterScrollBox;
- bool _isVisible;
+ bool _isOpen;
bool _debugIntangible;
int _debugNop;
ActorClues *_clues;
diff --git a/engines/bladerunner/ui/kia_section_crimes.cpp b/engines/bladerunner/ui/kia_section_crimes.cpp
index 4cfaaedbad..b0b3d7c234 100644
--- a/engines/bladerunner/ui/kia_section_crimes.cpp
+++ b/engines/bladerunner/ui/kia_section_crimes.cpp
@@ -22,16 +22,459 @@
#include "bladerunner/ui/kia_section_crimes.h"
+#include "bladerunner/actor_clues.h"
+#include "bladerunner/audio_player.h"
#include "bladerunner/bladerunner.h"
+#include "bladerunner/crimes_database.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/script/kia.h"
+#include "bladerunner/suspects_database.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_log.h"
+#include "bladerunner/ui/kia_section_suspects.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/ui/ui_scroll_box.h"
+
+
+#include "graphics/surface.h"
namespace BladeRunner {
-KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm)
- : KIASectionBase(vm)
- , _shape(vm) {
+KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) {
+ _uiContainer = new UIContainer(_vm);
+ _isOpen = false;
+ _clues = clues;
+
+ _mouseX = 0;
+ _mouseY = 0;
+
+ _buttons = new UIImagePicker(_vm, 5);
+
+ _cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 50, 1, false, Common::Rect(312, 172, 500, 376), Common::Rect(506, 160, 506, 394));
+ _uiContainer->add(_cluesScrollBox);
+
+ _acquiredClueCount = 0;
+
+ _crimeSelected = -1;
+ _crimesFoundCount = 0;
+ _crimesFound.resize(_vm->_gameInfo->getCrimeCount());
+
+ _suspectSelected = -1;
+ _suspectPhotoShapeId = -1;
+ _suspectPhotoShape = nullptr;
+ _suspectsFoundCount = 0;
+ _suspectsFound.resize(_vm->_gameInfo->getSuspectCount());
+ _suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount());
}
KIASectionCrimes::~KIASectionCrimes() {
+ delete _suspectPhotoShape;
+
+ _uiContainer->clear();
+
+ delete _cluesScrollBox;
+ delete _buttons;
+ delete _uiContainer;
+}
+
+void KIASectionCrimes::open() {
+ _scheduledSwitch = false;
+
+ _buttons->resetImages();
+ _buttons->defineImage(0, Common::Rect(136, 326, 185, 342), nullptr, _vm->_kia->_shapes->get(32), _vm->_kia->_shapes->get(36), _vm->_textKIA->getText(32));
+ _buttons->defineImage(1, Common::Rect(218, 326, 269, 342), nullptr, _vm->_kia->_shapes->get(33), _vm->_kia->_shapes->get(37), _vm->_textKIA->getText(33));
+ _buttons->defineImage(2, Common::Rect(354, 128, 404, 144), nullptr, _vm->_kia->_shapes->get(30), _vm->_kia->_shapes->get(34), _vm->_textKIA->getText(34));
+ _buttons->defineImage(3, Common::Rect(425, 128, 474, 144), nullptr, _vm->_kia->_shapes->get(31), _vm->_kia->_shapes->get(35), _vm->_textKIA->getText(35));
+ _buttons->defineImage(4, Common::Rect(142, 150, 260, 297), nullptr, nullptr, nullptr, _vm->_textKIA->getText(36));
+ _buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this);
+
+ _cluesScrollBox->show();
+
+ populateAcquiredClues();
+ populateCrimes();
+ populateSuspects();
+ populateVisibleClues();
+ updateSuspectPhoto();
+
+ _isOpen = true;
+}
+
+void KIASectionCrimes::close() {
+ if (!_isOpen) {
+ return;
+ }
+ _isOpen = false;
+ _buttons->deactivate();
+ _cluesScrollBox->hide();
+ if (_suspectPhotoShapeId != -1) {
+ delete _suspectPhotoShape;
+ _suspectPhotoShape = nullptr;
+ _suspectPhotoShapeId = -1;
+ }
+}
+
+void KIASectionCrimes::draw(Graphics::Surface &surface) {
+ const char *text = nullptr;
+ if (_suspectPhotoShapeId != -1) {
+ _suspectPhotoShape->draw(surface, 201 - _suspectPhotoShape->getWidth() / 2, 223 - _suspectPhotoShape->getHeight() / 2);
+ }
+ if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) {
+ text = _vm->_textKIA->getText(49);
+ _vm->_mainFont->drawColor(text, surface, 201 - _vm->_mainFont->getTextWidth(text) / 2, 218, 0x7FFF);
+ }
+
+ surface.fillRect(Common::Rect(120, 134, 250, 145), 0);
+ surface.hLine(120, 133, 250, 0x18A5);
+ surface.hLine(120, 146, 250, 0x2D4C);
+ surface.vLine(119, 134, 145, 0x18A5);
+ surface.vLine(251, 134, 145, 0x2D4C);
+ surface.hLine(251, 146, 251, 0x2509);
+
+ if (_crimeSelected == -1) {
+ text = _vm->_textKIA->getText(49);
+ } else {
+ text = _vm->_textCrimes->getText(_crimeSelected);
+ }
+
+ _vm->_mainFont->drawColor(text, surface, 185 - _vm->_mainFont->getTextWidth(text) / 2, 136, 0x46BF);
+
+ surface.fillRect(Common::Rect(136, 304, 266, 315), 0);
+ surface.hLine(136, 303, 266, 0x18A5);
+ surface.hLine(136, 316, 266, 0x2D4C);
+ surface.vLine(135, 304, 315, 0x18A5);
+ surface.vLine(267, 304, 315, 0x2D4C);
+ surface.hLine(267, 316, 267, 0x2509);
+
+ char generatedText[64];
+ if (_suspectSelected == -1) {
+ text = _vm->_textKIA->getText(22);
+ } else {
+ const char *suspectName = _vm->_suspectsDatabase->get(_suspectSelected)->getName();
+ if (_suspectsWithIdentity[_suspectSelected]) {
+ text = suspectName;
+ } else if (_vm->_suspectsDatabase->get(_suspectSelected)->getSex()) {
+ sprintf(generatedText, "%s %s", _vm->_textKIA->getText(20), KIASectionSuspects::scrambleSuspectsName(suspectName));
+ text = generatedText;
+ } else {
+ sprintf(generatedText, "%s %s", _vm->_textKIA->getText(21), KIASectionSuspects::scrambleSuspectsName(suspectName));
+ text = generatedText;
+ }
+ }
+ _vm->_mainFont->drawColor(text, surface, 201 - _vm->_mainFont->getTextWidth(text) / 2, 306, 0x46BF);
+
+ _uiContainer->draw(surface);
+ _buttons->draw(surface);
+ _buttons->drawTooltip(surface, _mouseX, _mouseY);
+}
+
+void KIASectionCrimes::handleMouseMove(int mouseX, int mouseY) {
+ _mouseX = mouseX;
+ _mouseY = mouseY;
+ _buttons->handleMouseAction(mouseX, mouseY, false, false, false);
+ _uiContainer->handleMouseMove(mouseX, mouseY);
+}
+
+void KIASectionCrimes::handleMouseDown(bool mainButton) {
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false);
+ }
+ _uiContainer->handleMouseDown(!mainButton);
+}
+
+void KIASectionCrimes::handleMouseUp(bool mainButton) {
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false);
+ }
+ _uiContainer->handleMouseUp(!mainButton);
+}
+
+void KIASectionCrimes::saveToLog() {
+ int data[] = { _crimeSelected, _suspectSelected };
+ _vm->_kia->_log->add(2, sizeof(data), &data);
+}
+
+void KIASectionCrimes::loadFromLog() {
+ const int *data = (const int*)_vm->_kia->_log->getCurrentData();
+ _crimeSelected = data[0];
+ _suspectSelected = data[1];
+ populateSuspects();
+ populateVisibleClues();
+}
+
+void KIASectionCrimes::selectCrime(int crimeId) {
+ _crimeSelected = crimeId;
+ populateSuspects();
+ populateVisibleClues();
+ updateSuspectPhoto();
+}
+
+void KIASectionCrimes::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
+ KIASectionCrimes *self = (KIASectionCrimes *)callbackData;
+
+ if (source == self->_cluesScrollBox && lineData >= 0) {
+ if (mouseButton) {
+ if (self->_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(511), 70, 0, 0, 50, 0);
+
+ if (self->_clues->isPrivate(lineData)) {
+ self->_clues->setPrivate(lineData, false);
+ self->_cluesScrollBox->resetFlags(lineData, 0x08);
+ } else {
+ self->_clues->setPrivate(lineData, true);
+ self->_cluesScrollBox->setFlags(lineData, 0x08);
+ }
+ }
+ } else {
+ self->_clues->setViewed(lineData, true);
+ self->_cluesScrollBox->resetHighlight(lineData);
+ self->_vm->_kia->_script->playClueAssetScript(0, lineData);
+ }
+ }
+}
+
+void KIASectionCrimes::mouseUpCallback(int buttonId, void *callbackData) {
+ ((KIASectionCrimes *)callbackData)->onButtonPressed(buttonId);
+}
+
+void KIASectionCrimes::onButtonPressed(int buttonId) {
+ switch (buttonId) {
+ case 0:
+ prevSuspect();
+ break;
+ case 1:
+ nextSuspect();
+ break;
+ case 2:
+ prevCrime();
+ break;
+ case 3:
+ nextCrime();
+ break;
+ case 4:
+ if (_suspectSelected != -1) {
+ _scheduledSwitch = true;
+ }
+ break;
+ }
+}
+
+void KIASectionCrimes::populateAcquiredClues() {
+ _acquiredClueCount = 0;
+ for (int i = 0; i < kClueCount; ++i) {
+ if (_clues->isAcquired(i)) {
+ _acquiredClues[_acquiredClueCount].clueId = i;
+ _acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(i);
+ ++_acquiredClueCount;
+ }
+ }
+ // sort clues by name, is it necessary
+}
+
+void KIASectionCrimes::populateCrimes() {
+ int firstCrime = -1;
+ int crimeCount = _vm->_gameInfo->getCrimeCount();
+ for (int i = 0; i < crimeCount; ++i) {
+ _crimesFound[i] = false;
+ }
+
+ _crimesFoundCount = 0;
+
+ if (!_acquiredClueCount) {
+ return;
+ }
+
+ for (int i = 0; i < crimeCount; ++i) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == i) {
+ if (firstCrime == -1) {
+ firstCrime = i;
+ }
+ _crimesFound[i] = true;
+ ++_crimesFoundCount;
+ }
+ }
+ }
+
+ if (_crimesFoundCount > 0 && _crimeSelected == -1) {
+ _crimeSelected = firstCrime;
+ }
+}
+
+void KIASectionCrimes::populateSuspects() {
+ int firstSuspect = -1;
+ int suspectCount = _vm->_gameInfo->getSuspectCount();
+
+ for (int i = 0; i < suspectCount; ++i) {
+ _suspectsFound[i] = false;
+ _suspectsWithIdentity[i] = false;
+ }
+
+ _suspectsFoundCount = 0;
+
+ if (!_acquiredClueCount || _crimeSelected == -1) {
+ return;
+ }
+
+ for (int i = 0; i < suspectCount; ++i) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == _crimeSelected
+ && _vm->_suspectsDatabase->get(i)->hasClue(_acquiredClues[j].clueId)
+ ) {
+ if (firstSuspect == -1) {
+ firstSuspect = i;
+ }
+ _suspectsFound[i] = true;
+ ++_suspectsFoundCount;
+ }
+ }
+
+ if (_suspectsFound[i]) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_suspectsDatabase->get(i)->hasIdentityClue(_acquiredClues[j].clueId)) {
+ _suspectsWithIdentity[i] = true;
+ }
+ }
+ }
+ }
+
+ if (_suspectsFoundCount) {
+ if (_suspectSelected == -1 || !_suspectsFound[_suspectSelected]) {
+ _suspectSelected = firstSuspect;
+ }
+ } else {
+ _suspectSelected = -1;
+ }
+}
+
+void KIASectionCrimes::populateVisibleClues() {
+ _cluesScrollBox->clearLines();
+ if (_crimeSelected != -1) {
+ for (uint i = 0; i < _vm->_gameInfo->getClueCount(); ++i) {
+ if (_vm->_crimesDatabase->getAssetType(i) != -1
+ && _vm->_crimesDatabase->getCrime(i) == _crimeSelected
+ && _clues->isAcquired(i)
+ ) {
+ int flags = 0x30;
+ if (_clues->isPrivate(i)) {
+ flags = 0x08;
+ } else if (_clues->isViewed(i)) {
+ flags = 0x10;
+ }
+ _cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(i), i, flags);
+ }
+ }
+ _cluesScrollBox->sortLines();
+ }
+}
+
+void KIASectionCrimes::updateSuspectPhoto() {
+ if (_suspectPhotoShapeId != -1) {
+ delete _suspectPhotoShape;
+ _suspectPhotoShape = nullptr;
+ }
+
+ if (_suspectSelected == -1) {
+ _suspectPhotoShapeId = -1;
+ return;
+ }
+
+ SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected);
+
+ _suspectPhotoShapeId = -1;
+ int photoCluesCount = suspect->getPhotoCount();
+ if (photoCluesCount > 0) {
+ for (int i = 0 ; i < photoCluesCount; i++) {
+ //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1
+ if (_clues->isAcquired(suspect->getPhotoClueId(i))) {
+ _suspectPhotoShapeId = suspect->getPhotoShapeId(i);
+ break;
+ }
+ }
+ }
+
+ if (_suspectPhotoShapeId == -1) {
+ if (suspect->getSex()) {
+ _suspectPhotoShapeId = 14;
+ } else {
+ _suspectPhotoShapeId = 13;
+ }
+ }
+
+ if (_suspectPhotoShapeId != -1) {
+ _suspectPhotoShape = new Shape(_vm);
+ _suspectPhotoShape->readFromContainer("photos.shp", _suspectPhotoShapeId);
+ }
+}
+
+void KIASectionCrimes::nextCrime() {
+ if (_crimesFoundCount >= 2) {
+ while (true) {
+ ++_crimeSelected;
+ if (_crimeSelected >= (int)_vm->_gameInfo->getCrimeCount()){
+ _crimeSelected = 0;
+ }
+
+ if (_crimesFound[_crimeSelected]) {
+ selectCrime(_crimeSelected);
+ break;
+ }
+ }
+ }
+}
+
+void KIASectionCrimes::prevCrime() {
+ if (_crimesFoundCount >= 2) {
+ while (true) {
+ --_crimeSelected;
+ if (_crimeSelected < 0) {
+ _crimeSelected = _vm->_gameInfo->getCrimeCount() - 1;
+ }
+
+ if (_crimesFound[_crimeSelected]) {
+ selectCrime(_crimeSelected);
+ break;
+ }
+ }
+ }
+}
+
+void KIASectionCrimes::nextSuspect() {
+ if (_suspectsFoundCount >= 2) {
+ while (true) {
+ ++_suspectSelected;
+ if (_suspectSelected >= (int)_vm->_gameInfo->getSuspectCount()){
+ _suspectSelected = 0;
+ }
+
+ if (_suspectsFound[_suspectSelected]) {
+ updateSuspectPhoto();
+ break;
+ }
+ }
+ }
+}
+
+void KIASectionCrimes::prevSuspect() {
+ if (_suspectsFoundCount >= 2) {
+ while (true) {
+ --_suspectSelected;
+ if (_suspectSelected < 0){
+ _suspectSelected = _vm->_gameInfo->getSuspectCount() - 1;
+ }
+
+ if (_suspectsFound[_suspectSelected]) {
+ updateSuspectPhoto();
+ break;
+ }
+ }
+ }
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_crimes.h b/engines/bladerunner/ui/kia_section_crimes.h
index befe5e528c..1ca60eb02b 100644
--- a/engines/bladerunner/ui/kia_section_crimes.h
+++ b/engines/bladerunner/ui/kia_section_crimes.h
@@ -26,6 +26,8 @@
#include "bladerunner/shape.h"
#include "bladerunner/ui/kia_section_base.h"
+#include "common/array.h"
+
namespace BladeRunner {
class ActorClues;
@@ -35,46 +37,78 @@ class UIImagePicker;
class UIScrollBox;
class KIASectionCrimes : public KIASectionBase {
- struct Clue
- {
+ // _vm->_gameInfo->getClueCount()
+ static const int kClueCount = 288;
+
+ struct AcquiredClue {
int clueId;
int actorId;
};
-protected:
+ bool _isOpen;
- UIContainer *_uiContainer;
- // void (__cdecl **scrollboxCallback)(int, UIScrollBoxStruc *, int, int);
- int _isOpen;
- int *_list;
- UIImagePicker *_uiImagePicker;
+ UIContainer *_uiContainer;
+ UIImagePicker *_buttons;
+ UIScrollBox *_cluesScrollBox;
- UIScrollBox *_cluesScrollbox;
ActorClues *_clues;
- int _clueInfoCount;
- Clue _clueInfo[1000];
- int _selectedCrimeId;
- int _crimesFoundCount;
- int *_crimeIsKnown;
- int _selectedSuspectId;
- int _suspectsFoundCount;
- int *_suspectIsKnown;
- int *_suspectHasIdentity;
- int _mouseX;
- int _mouseY;
- int _suspectPhotoShapeId;
- int _field_15;
- Shape _shape;
+
+ int _acquiredClueCount;
+ AcquiredClue _acquiredClues[kClueCount];
+
+ int _crimeSelected;
+
+ int _crimesFoundCount;
+ Common::Array<bool> _crimesFound;
+
+ int _suspectsFoundCount;
+ Common::Array<bool> _suspectsFound;
+ Common::Array<bool> _suspectsWithIdentity;
+
+ int _mouseX;
+ int _mouseY;
+
+ int _suspectPhotoShapeId;
+ Shape *_suspectPhotoShape;
public:
- KIASectionCrimes(BladeRunnerEngine *vm);
+ int _suspectSelected;
+
+public:
+ KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues);
~KIASectionCrimes();
- void saveToLog() {}
- void loadFromLog() {}
+ void open();
+ void close();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool mainButton);
+ void handleMouseUp(bool mainButton);
+
+ void saveToLog();
+ void loadFromLog();
+
+ void selectCrime(int crimeId);
+
+private:
+ static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
+ static void mouseUpCallback(int buttonId, void *callbackData);
+
+ void onButtonPressed(int buttonId);
+
+ void populateAcquiredClues();
+ void populateCrimes();
+ void populateSuspects();
+ void populateVisibleClues();
+ void updateSuspectPhoto();
-protected:
+ void nextCrime();
+ void prevCrime();
+ void nextSuspect();
+ void prevSuspect();
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_suspects.cpp b/engines/bladerunner/ui/kia_section_suspects.cpp
new file mode 100644
index 0000000000..ce13243f76
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_suspects.cpp
@@ -0,0 +1,555 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/ui/kia_section_suspects.h"
+
+#include "bladerunner/actor_clues.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/crimes_database.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/script/kia.h"
+#include "bladerunner/suspects_database.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_log.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_check_box.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/ui/ui_scroll_box.h"
+
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+KIASectionSuspects::KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) {
+ _uiContainer = new UIContainer(_vm);
+ _isOpen = false;
+ _clues = clues;
+
+ _mouseX = 0;
+ _mouseY = 0;
+
+ _whereaboutsFilter = true;
+ _MOFilter = true;
+ _replicantFilter = true;
+ _nonReplicantFilter = true;
+ _othersFilter = true;
+
+ _buttons = new UIImagePicker(_vm, 4);
+
+ _whereaboutsCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 318, 275, 328), 1, _whereaboutsFilter);
+ _MOCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 328, 275, 338), 1, _MOFilter);
+ _replicantCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 338, 275, 348), 1, _replicantFilter);
+ _nonReplicantCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 348, 275, 358), 1, _nonReplicantFilter);
+ _othersCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 358, 275, 368), 1, _othersFilter);
+ _cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this,_vm->_gameInfo->getClueCount(), 1, false, Common::Rect(312, 172, 500, 376), Common::Rect(506, 160, 506, 394));
+ _crimesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 50, 1, false, Common::Rect(154, 258, 291, 298), Common::Rect(120, 249, 120, 297));
+ _uiContainer->add(_whereaboutsCheckBox);
+ _uiContainer->add(_MOCheckBox);
+ _uiContainer->add(_replicantCheckBox);
+ _uiContainer->add(_nonReplicantCheckBox);
+ _uiContainer->add(_othersCheckBox);
+ _uiContainer->add(_cluesScrollBox);
+ _uiContainer->add(_crimesScrollBox);
+
+ _acquiredClueCount = 0;
+
+ _suspectSelected = -1;
+ _suspectPhotoShapeId = -1;
+ _suspectPhotoShape = nullptr;
+ _suspectsFoundCount = 0;
+ _suspectsFound.resize(_vm->_gameInfo->getSuspectCount());
+ _suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount());
+
+ _crimeSelected = -1;
+}
+
+KIASectionSuspects::~KIASectionSuspects() {
+ delete _suspectPhotoShape;
+
+ _uiContainer->clear();
+
+ delete _crimesScrollBox;
+ delete _cluesScrollBox;
+ delete _othersCheckBox;
+ delete _nonReplicantCheckBox;
+ delete _replicantCheckBox;
+ delete _MOCheckBox;
+ delete _whereaboutsCheckBox;
+ delete _buttons;
+ delete _uiContainer;
+}
+
+void KIASectionSuspects::open() {
+ _scheduledSwitch = false;
+
+ _buttons->resetImages();
+ _buttons->defineImage(0, Common::Rect(142, 380, 191, 395), _vm->_kia->_shapes->get(79), _vm->_kia->_shapes->get(80), _vm->_kia->_shapes->get(81), _vm->_textKIA->getText(30));
+ _buttons->defineImage(1, Common::Rect(193, 380, 242, 395), _vm->_kia->_shapes->get(76), _vm->_kia->_shapes->get(77), _vm->_kia->_shapes->get(77), _vm->_textKIA->getText(31));
+ _buttons->defineImage(2, Common::Rect(354, 128, 404, 144), nullptr, _vm->_kia->_shapes->get(30), _vm->_kia->_shapes->get(34), _vm->_textKIA->getText(32));
+ _buttons->defineImage(3, Common::Rect(424, 128, 474, 144), nullptr, _vm->_kia->_shapes->get(31), _vm->_kia->_shapes->get(35), _vm->_textKIA->getText(33));
+ _buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this);
+
+ _cluesScrollBox->show();
+ _crimesScrollBox->show();
+ _whereaboutsCheckBox->enable();
+ _MOCheckBox->enable();
+ _replicantCheckBox->enable();
+ _nonReplicantCheckBox->enable();
+ _othersCheckBox->enable();
+ _cluesScrollBox->show();
+ _crimesScrollBox->show();
+
+ populateAcquiredClues();
+ populateSuspects();
+ populateCrimes();
+ populateVisibleClues();
+ updateSuspectPhoto();
+
+ _isOpen = true;
+}
+
+void KIASectionSuspects::close() {
+ if (!_isOpen) {
+ return;
+ }
+ _isOpen = false;
+ _buttons->deactivate();
+ _cluesScrollBox->hide();
+ if (_suspectPhotoShapeId != -1) {
+ delete _suspectPhotoShape;
+ _suspectPhotoShape = nullptr;
+ _suspectPhotoShapeId = -1;
+ }
+}
+
+void KIASectionSuspects::draw(Graphics::Surface &surface) {
+ const char *text = nullptr;
+ if (_suspectPhotoShapeId != -1) {
+ _suspectPhotoShape->draw(surface, 142, 150);
+ }
+ if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) {
+ text = _vm->_textKIA->getText(49);
+ _vm->_mainFont->drawColor(text, surface, 190 - _vm->_mainFont->getTextWidth(text) / 2, 201, 0x7FFF);
+ }
+
+ _whereaboutsCheckBox->setChecked(_whereaboutsFilter);
+ _MOCheckBox->setChecked(_MOFilter);
+ _replicantCheckBox->setChecked(_replicantFilter);
+ _nonReplicantCheckBox->setChecked(_nonReplicantFilter);
+ _othersCheckBox->setChecked(_othersFilter);
+
+ _uiContainer->draw(surface);
+
+
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(0), surface, 300, 162, 0x77DF);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(46), surface, 142, 248, 0x77DF);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(47), surface, 142, 308, 0x77DF);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(14), surface, 154, 319, 0x25B3);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(15), surface, 154, 329, 0x31F7);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(16), surface, 154, 339, 0x3A5B);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(17), surface, 154, 349, 0x31F7);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(48), surface, 154, 359, 0x25B3);
+
+
+ surface.fillRect(Common::Rect(120, 134, 250, 145), 0);
+ surface.hLine(120, 133, 250, 0x18A5);
+ surface.hLine(120, 146, 250, 0x2D4C);
+ surface.vLine(119, 134, 145, 0x18A5);
+ surface.vLine(251, 134, 145, 0x2D4C);
+ surface.hLine(251, 146, 251, 0x2509);
+
+ char generatedText[64];
+ if (_suspectSelected == -1) {
+ text = _vm->_textKIA->getText(22);
+ } else {
+ const char *suspectName = _vm->_suspectsDatabase->get(_suspectSelected)->getName();
+ if (_suspectsWithIdentity[_suspectSelected]) {
+ text = suspectName;
+ } else if (_vm->_suspectsDatabase->get(_suspectSelected)->getSex()) {
+ sprintf(generatedText, "%s %s", _vm->_textKIA->getText(20), scrambleSuspectsName(suspectName));
+ text = generatedText;
+ } else {
+ sprintf(generatedText, "%s %s", _vm->_textKIA->getText(21), scrambleSuspectsName(suspectName));
+ text = generatedText;
+ }
+ }
+
+ _vm->_mainFont->drawColor(text, surface, 185 - _vm->_mainFont->getTextWidth(text) / 2, 136, 0x46BF);
+
+ _buttons->draw(surface);
+ _buttons->drawTooltip(surface, _mouseX, _mouseY);
+}
+
+void KIASectionSuspects::handleMouseMove(int mouseX, int mouseY) {
+ _mouseX = mouseX;
+ _mouseY = mouseY;
+ _buttons->handleMouseAction(mouseX, mouseY, false, false, false);
+ _uiContainer->handleMouseMove(mouseX, mouseY);
+}
+
+void KIASectionSuspects::handleMouseDown(bool mainButton) {
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false);
+ }
+ _uiContainer->handleMouseDown(!mainButton);
+}
+
+void KIASectionSuspects::handleMouseUp(bool mainButton) {
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false);
+ }
+ _uiContainer->handleMouseUp(!mainButton);
+}
+
+void KIASectionSuspects::saveToLog() {
+ int data[] = {
+ _crimeSelected,
+ _suspectSelected,
+ _whereaboutsFilter,
+ _MOFilter,
+ _replicantFilter,
+ _nonReplicantFilter,
+ _othersFilter
+ };
+ _vm->_kia->_log->add(1, sizeof(data), &data);
+}
+
+void KIASectionSuspects::loadFromLog() {
+ const int *data = (const int*)_vm->_kia->_log->getCurrentData();
+ _crimeSelected = data[0];
+ _suspectSelected = data[1];
+ _whereaboutsFilter = data[2];
+ _MOFilter = data[3];
+ _replicantFilter = data[4];
+ _nonReplicantFilter = data[5];
+ _othersFilter = data[6];
+ populateCrimes();
+ populateVisibleClues();
+}
+
+void KIASectionSuspects::selectSuspect(int suspectId) {
+ _suspectSelected = suspectId;
+ populateCrimes();
+ populateVisibleClues();
+ updateSuspectPhoto();
+}
+
+const char *KIASectionSuspects::scrambleSuspectsName(const char *name) {
+ static char buffer[32];
+
+ char *bufferPtr = buffer;
+ const char *namePtr = name;
+
+ for (int i = 0 ; i < 6; ++i) {
+ if (Common::isAlpha(*namePtr)) {
+ char upper = toupper(*namePtr);
+ if ( upper < 'J' ){
+ *bufferPtr++ = upper - 16;
+ } else {
+ *bufferPtr++ = upper - 9;
+ }
+ } else {
+ *bufferPtr++ = '0';
+ }
+ if (*namePtr) {
+ ++namePtr;
+ }
+ if (i == 1) {
+ *bufferPtr++ = '-';
+ }
+ }
+ *bufferPtr = 0;
+ return buffer;
+}
+
+void KIASectionSuspects::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
+ KIASectionSuspects *self = (KIASectionSuspects *)callbackData;
+
+ if (source == self->_cluesScrollBox && lineData >= 0) {
+ if (mouseButton) {
+ if (self->_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(511), 70, 0, 0, 50, 0);
+
+ if (self->_clues->isPrivate(lineData)) {
+ self->_clues->setPrivate(lineData, false);
+ self->_cluesScrollBox->resetFlags(lineData, 0x08);
+ } else {
+ self->_clues->setPrivate(lineData, true);
+ self->_cluesScrollBox->setFlags(lineData, 0x08);
+ }
+ }
+ } else {
+ self->_clues->setViewed(lineData, true);
+ self->_cluesScrollBox->resetHighlight(lineData);
+ self->_vm->_kia->_script->playClueAssetScript(0, lineData);
+ }
+ } else if (source == self->_crimesScrollBox && lineData >= 0 && !mouseButton) {
+ self->_crimeSelected = lineData - 5;
+ self->_scheduledSwitch = true;
+ }
+}
+
+void KIASectionSuspects::checkBoxCallback(void *callbackData, void *source) {
+ KIASectionSuspects *self = (KIASectionSuspects *)callbackData;
+ UICheckBox *checkBox = (UICheckBox *)source;
+
+ if (checkBox == self->_whereaboutsCheckBox) {
+ self->_whereaboutsFilter = checkBox->_isChecked;
+ } else if (checkBox == self->_MOCheckBox) {
+ self->_MOFilter = checkBox->_isChecked;
+ } else if (checkBox == self->_replicantCheckBox) {
+ self->_replicantFilter = checkBox->_isChecked;
+ } else if (checkBox == self->_nonReplicantCheckBox) {
+ self->_nonReplicantFilter = checkBox->_isChecked;
+ } else if (checkBox == self->_othersCheckBox) {
+ self->_othersFilter = checkBox->_isChecked;
+ }
+ self->populateVisibleClues();
+}
+
+void KIASectionSuspects::mouseUpCallback(int buttonId, void *callbackData) {
+ ((KIASectionSuspects *)callbackData)->onButtonPressed(buttonId);
+}
+
+void KIASectionSuspects::onButtonPressed(int buttonId) {
+ switch (buttonId) {
+ case 0:
+ enableAllFilters();
+ break;
+ case 1:
+ disableAllFilters();
+ break;
+ case 2:
+ prevSuspect();
+ break;
+ case 3:
+ nextSuspect();
+ break;
+ }
+}
+
+void KIASectionSuspects::populateAcquiredClues() {
+ _acquiredClueCount = 0;
+ for (int i = 0; i < kClueCount; ++i) {
+ if (_clues->isAcquired(i)) {
+ _acquiredClues[_acquiredClueCount].clueId = i;
+ _acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(i);
+ ++_acquiredClueCount;
+ }
+ }
+ // sort clues by name, is it necessary
+}
+
+void KIASectionSuspects::populateSuspects() {
+ int firstSuspect = -1;
+ int suspectCount = _vm->_gameInfo->getSuspectCount();
+
+ for (int i = 0; i < suspectCount; ++i) {
+ _suspectsFound[i] = false;
+ _suspectsWithIdentity[i] = false;
+ }
+
+ _suspectsFoundCount = 0;
+
+ if (!_acquiredClueCount) {
+ return;
+ }
+
+ for (int i = 0; i < suspectCount; ++i) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) != -1
+ && _vm->_suspectsDatabase->get(i)->hasClue(_acquiredClues[j].clueId)
+ ) {
+ if (firstSuspect == -1) {
+ firstSuspect = i;
+ }
+ _suspectsFound[i] = true;
+ ++_suspectsFoundCount;
+ }
+ }
+
+ if (_suspectsFound[i]) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_suspectsDatabase->get(i)->hasIdentityClue(_acquiredClues[j].clueId)) {
+ _suspectsWithIdentity[i] = true;
+ }
+ }
+ }
+ }
+
+ if (_suspectsFoundCount && _suspectSelected == -1) {
+ _suspectSelected = firstSuspect;
+ }
+}
+
+void KIASectionSuspects::populateCrimes() {
+ _crimesScrollBox->clearLines();
+ if (_suspectsFoundCount > 0 && _suspectSelected != -1) {
+ for (int i = 0; i < (int)_vm->_gameInfo->getCrimeCount(); ++i) {
+ for (int j = 0; j < _acquiredClueCount; ++j) {
+ if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == i
+ && _vm->_suspectsDatabase->get(_suspectSelected)->hasClue(_acquiredClues[j].clueId)) {
+ _crimesScrollBox->addLine(_vm->_textCrimes->getText(i), i + 5, 0);
+ break;
+ }
+ }
+ }
+ _crimesScrollBox->sortLines();
+ }
+}
+
+void KIASectionSuspects::populateVisibleClues() {
+ _cluesScrollBox->clearLines();
+ if (_suspectsFoundCount > 0 && _suspectSelected != -1) {
+ for (int i = 0; i < _acquiredClueCount; ++i) {
+ int clueId = _acquiredClues[i].clueId;
+
+ if (_vm->_crimesDatabase->getAssetType(i) != -1) {
+ SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected);
+
+ bool showClue = false;
+
+ if (_whereaboutsFilter && suspect->hasWhereaboutsClue(clueId)) {
+ showClue = true;
+ } else if (_MOFilter && suspect->hasMOClue(clueId)) {
+ showClue = true;
+ } else if (_replicantFilter && suspect->hasReplicantClue(clueId)) {
+ showClue = true;
+ } else if (_nonReplicantFilter && suspect->hasNonReplicantClue(clueId)) {
+ showClue = true;
+ } else if (_othersFilter && suspect->hasOtherClue(clueId)) {
+ showClue = true;
+ }
+
+ if (showClue) {
+ int flags = 0x30;
+ if (_clues->isPrivate(clueId)) {
+ flags = 0x08;
+ } else if (_clues->isViewed(clueId)) {
+ flags = 0x10;
+ }
+ _cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(clueId), clueId, flags);
+ }
+ }
+ }
+ _cluesScrollBox->sortLines();
+ }
+}
+
+void KIASectionSuspects::updateSuspectPhoto() {
+ if (_suspectPhotoShapeId != -1) {
+ delete _suspectPhotoShape;
+ _suspectPhotoShape = nullptr;
+ }
+
+ if (_suspectSelected == -1) {
+ _suspectPhotoShapeId = -1;
+ return;
+ }
+
+ SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected);
+
+ _suspectPhotoShapeId = -1;
+ int photoCluesCount = suspect->getPhotoCount();
+ if (photoCluesCount > 0) {
+ for (int i = 0 ; i < photoCluesCount; i++) {
+ //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1
+ if (_clues->isAcquired(suspect->getPhotoClueId(i))) {
+ _suspectPhotoShapeId = suspect->getPhotoShapeId(i);
+ break;
+ }
+ }
+ }
+
+ if (_suspectPhotoShapeId == -1) {
+ if (suspect->getSex()) {
+ _suspectPhotoShapeId = 14;
+ } else {
+ _suspectPhotoShapeId = 13;
+ }
+ }
+
+ if (_suspectPhotoShapeId != -1) {
+ _suspectPhotoShape = new Shape(_vm);
+ _suspectPhotoShape->readFromContainer("photos.shp", _suspectPhotoShapeId);
+ }
+}
+
+void KIASectionSuspects::nextSuspect() {
+ if (_suspectsFoundCount >= 2) {
+ while (true) {
+ ++_suspectSelected;
+ if (_suspectSelected >= (int)_vm->_gameInfo->getSuspectCount()){
+ _suspectSelected = 0;
+ }
+
+ if (_suspectsFound[_suspectSelected]) {
+ selectSuspect(_suspectSelected);
+ break;
+ }
+ }
+ }
+}
+
+void KIASectionSuspects::prevSuspect() {
+ if (_suspectsFoundCount >= 2) {
+ while (true) {
+ --_suspectSelected;
+ if (_suspectSelected < 0){
+ _suspectSelected = _vm->_gameInfo->getSuspectCount() - 1;
+ }
+
+ if (_suspectsFound[_suspectSelected]) {
+ selectSuspect(_suspectSelected);
+ break;
+ }
+ }
+ }
+}
+
+void KIASectionSuspects::enableAllFilters() {
+ _whereaboutsFilter = true;
+ _MOFilter = true;
+ _replicantFilter = true;
+ _nonReplicantFilter = true;
+ _othersFilter = true;
+ populateVisibleClues();
+}
+
+void KIASectionSuspects::disableAllFilters() {
+ _whereaboutsFilter = false;
+ _MOFilter = false;
+ _replicantFilter = false;
+ _nonReplicantFilter = false;
+ _othersFilter = false;
+ populateVisibleClues();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_suspects.h b/engines/bladerunner/ui/kia_section_suspects.h
index 94cf1bfc06..0cc957f609 100644
--- a/engines/bladerunner/ui/kia_section_suspects.h
+++ b/engines/bladerunner/ui/kia_section_suspects.h
@@ -25,15 +25,102 @@
#include "bladerunner/ui/kia_section_base.h"
+#include "common/array.h"
+
namespace BladeRunner {
+class ActorClues;
+class BladeRunnerEngine;
+class Shape;
+class UICheckBox;
+class UIContainer;
+class UIImagePicker;
+class UIScrollBox;
+
class KIASectionSuspects : public KIASectionBase {
+ // _vm->_gameInfo->getClueCount()
+ static const int kClueCount = 288;
+
+ struct AcquiredClue {
+ int clueId;
+ int actorId;
+ };
+
+ bool _isOpen;
+
+ UIContainer *_uiContainer;
+ UIImagePicker *_buttons;
+ UIScrollBox *_cluesScrollBox;
+ UIScrollBox *_crimesScrollBox;
+ UICheckBox *_whereaboutsCheckBox;
+ UICheckBox *_MOCheckBox;
+ UICheckBox *_replicantCheckBox;
+ UICheckBox *_nonReplicantCheckBox;
+ UICheckBox *_othersCheckBox;
+
+ bool _whereaboutsFilter;
+ bool _MOFilter;
+ bool _replicantFilter;
+ bool _nonReplicantFilter;
+ bool _othersFilter;
+
+ ActorClues *_clues;
+
+ int _acquiredClueCount;
+ AcquiredClue _acquiredClues[kClueCount];
+
+ int _suspectSelected;
+ int _suspectsFoundCount;
+ Common::Array<bool> _suspectsFound;
+ Common::Array<bool> _suspectsWithIdentity;
+
+ int _mouseX;
+ int _mouseY;
+
+ int _suspectPhotoShapeId;
+ Shape *_suspectPhotoShape;
public:
- KIASectionSuspects(BladeRunnerEngine *vm): KIASectionBase(vm) {}
+ int _crimeSelected;
+
+public:
+ KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues);
+ ~KIASectionSuspects();
+
+ void open();
+ void close();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool mainButton);
+ void handleMouseUp(bool mainButton);
+
+ void saveToLog();
+ void loadFromLog();
+
+ void selectSuspect(int suspectId);
+
+ static const char *scrambleSuspectsName(const char *name);
+
+private:
+ static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
+ static void checkBoxCallback(void *callbackData, void *source);
+ static void mouseUpCallback(int buttonId, void *callbackData);
+
+ void onButtonPressed(int buttonId);
+
+ void populateAcquiredClues();
+ void populateSuspects();
+ void populateCrimes();
+ void populateVisibleClues();
+ void updateSuspectPhoto();
+
+ void nextSuspect();
+ void prevSuspect();
- void saveToLog() {}
- void loadFromLog() {}
+ void enableAllFilters();
+ void disableAllFilters();
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp
index 9018de15e6..cc913e3a9c 100644
--- a/engines/bladerunner/ui/spinner.cpp
+++ b/engines/bladerunner/ui/spinner.cpp
@@ -61,41 +61,6 @@ bool Spinner::querySelectableDestinationFlag(int destination) const {
return _isDestinationSelectable[destination];
}
-const Spinner::Destination Spinner::kSpinnerDestinationsNear[] = {
- { 0, Common::Rect(210, 263, 263, 332) },
- { 1, Common::Rect(307, 330, 361, 381) },
- { 2, Common::Rect(338, 137, 362, 169) },
- { 3, Common::Rect(248, 135, 289, 168) },
- { 4, Common::Rect(352, 222, 379, 238) },
- { -1, Common::Rect(-1,-1,-1,-1) }
-};
-
-const Spinner::Destination Spinner::kSpinnerDestinationsMedium[] = {
- { 0, Common::Rect(252, 242, 279, 283) },
- { 1, Common::Rect(301, 273, 328, 304) },
- { 2, Common::Rect(319, 182, 336, 200) },
- { 3, Common::Rect(269, 181, 293, 200) },
- { 4, Common::Rect(325, 227, 345, 240) },
- { 5, Common::Rect(259, 74, 380, 119) },
- { 6, Common::Rect(203, 124, 224, 136) },
- { 7, Common::Rect(200, 147, 222, 170) },
- { -1, Common::Rect(-1,-1,-1,-1) }
-};
-
-const Spinner::Destination Spinner::kSpinnerDestinationsFar[] = {
- { 0, Common::Rect(220, 227, 246, 262) },
- { 1, Common::Rect(260, 252, 286, 279) },
- { 2, Common::Rect(286, 178, 302, 196) },
- { 3, Common::Rect(244, 178, 263, 195) },
- { 4, Common::Rect(288, 216, 306, 228) },
- { 5, Common::Rect(249, 77, 353, 124) },
- { 6, Common::Rect(190, 127, 208, 138) },
- { 7, Common::Rect(185, 149, 206, 170) },
- { 8, Common::Rect(398, 249, 419, 268) },
- { 9, Common::Rect(390, 218, 419, 236) },
- { -1, Common::Rect(-1, -1, -1, -1) }
-};
-
int Spinner::chooseDestination(int loopId, bool immediately) {
_selectedDestination = 0;
if (!_vm->openArchive("MODE.MIX")) {
@@ -137,17 +102,17 @@ int Spinner::chooseDestination(int loopId, bool immediately) {
mapmask = 1;
if (mapmask & 4) {
- _destinations = kSpinnerDestinationsFar;
+ _destinations = getDestinationsFar();
firstShapeId = 26;
shapeCount = 20;
spinnerLoopId = 4;
} else if (mapmask & 2) {
- _destinations = kSpinnerDestinationsMedium;
+ _destinations = getDestinationsMedium();
firstShapeId = 10;
shapeCount = 16;
spinnerLoopId = 2;
} else if (mapmask & 1) {
- _destinations = kSpinnerDestinationsNear;
+ _destinations = getDestinationsNear();
firstShapeId = 0;
shapeCount = 10;
spinnerLoopId = 0;
@@ -300,4 +265,48 @@ void Spinner::resume() {
_vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr);
}
+const Spinner::Destination *Spinner::getDestinationsFar() {
+ static const Destination destinations[] = {
+ { 0, Common::Rect(220, 227, 246, 262) },
+ { 1, Common::Rect(260, 252, 286, 279) },
+ { 2, Common::Rect(286, 178, 302, 196) },
+ { 3, Common::Rect(244, 178, 263, 195) },
+ { 4, Common::Rect(288, 216, 306, 228) },
+ { 5, Common::Rect(249, 77, 353, 124) },
+ { 6, Common::Rect(190, 127, 208, 138) },
+ { 7, Common::Rect(185, 149, 206, 170) },
+ { 8, Common::Rect(398, 249, 419, 268) },
+ { 9, Common::Rect(390, 218, 419, 236) },
+ { -1, Common::Rect(-1, -1, -1, -1) }
+ };
+ return destinations;
+}
+
+const Spinner::Destination *Spinner::getDestinationsMedium() {
+ static const Destination destinations[] = {
+ { 0, Common::Rect(252, 242, 279, 283) },
+ { 1, Common::Rect(301, 273, 328, 304) },
+ { 2, Common::Rect(319, 182, 336, 200) },
+ { 3, Common::Rect(269, 181, 293, 200) },
+ { 4, Common::Rect(325, 227, 345, 240) },
+ { 5, Common::Rect(259, 74, 380, 119) },
+ { 6, Common::Rect(203, 124, 224, 136) },
+ { 7, Common::Rect(200, 147, 222, 170) },
+ { -1, Common::Rect(-1,-1,-1,-1) }
+ };
+ return destinations;
+}
+
+const Spinner::Destination *Spinner::getDestinationsNear() {
+ static const Destination destinations[] = {
+ { 0, Common::Rect(210, 263, 263, 332) },
+ { 1, Common::Rect(307, 330, 361, 381) },
+ { 2, Common::Rect(338, 137, 362, 169) },
+ { 3, Common::Rect(248, 135, 289, 168) },
+ { 4, Common::Rect(352, 222, 379, 238) },
+ { -1, Common::Rect(-1,-1,-1,-1) }
+ };
+ return destinations;
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h
index ec0f8dbe33..b1785a57eb 100644
--- a/engines/bladerunner/ui/spinner.h
+++ b/engines/bladerunner/ui/spinner.h
@@ -33,7 +33,6 @@ class Shape;
class VQAPlayer;
class UIImagePicker;
-
class Spinner {
static const int kSpinnerDestinations = 10;
@@ -42,10 +41,6 @@ class Spinner {
Common::Rect rect;
};
- static const Destination kSpinnerDestinationsNear[];
- static const Destination kSpinnerDestinationsMedium[];
- static const Destination kSpinnerDestinationsFar[];
-
BladeRunnerEngine *_vm;
bool _isDestinationSelectable[kSpinnerDestinations];
bool _isOpen;
@@ -77,6 +72,9 @@ public:
private:
static void mouseUpCallback(int, void *);
+ static const Destination *getDestinationsFar();
+ static const Destination *getDestinationsMedium();
+ static const Destination *getDestinationsNear();
};
} // End of namespace BladeRunner