2014-05-16 21:58:49 +02:00
|
|
|
/* 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/bladerunner.h"
|
|
|
|
|
2015-05-02 22:31:07 +02:00
|
|
|
#include "bladerunner/actor.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/actor_dialogue_queue.h"
|
2015-02-06 15:31:43 +01:00
|
|
|
#include "bladerunner/ambient_sounds.h"
|
2017-08-24 23:43:47 +02:00
|
|
|
#include "bladerunner/audio_mixer.h"
|
2015-02-06 15:31:43 +01:00
|
|
|
#include "bladerunner/audio_player.h"
|
2015-02-10 19:33:35 +01:00
|
|
|
#include "bladerunner/audio_speech.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "bladerunner/chapters.h"
|
2016-09-10 18:16:17 +02:00
|
|
|
#include "bladerunner/combat.h"
|
2016-10-06 00:59:11 +02:00
|
|
|
#include "bladerunner/crimes_database.h"
|
2018-02-25 19:31:52 +01:00
|
|
|
#include "bladerunner/debugger.h"
|
2017-08-22 18:57:50 +02:00
|
|
|
#include "bladerunner/dialogue_menu.h"
|
2016-10-06 21:23:46 +02:00
|
|
|
#include "bladerunner/font.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/game_flags.h"
|
|
|
|
#include "bladerunner/game_info.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "bladerunner/image.h"
|
2016-10-08 21:06:22 +02:00
|
|
|
#include "bladerunner/item_pickup.h"
|
2016-09-10 18:16:17 +02:00
|
|
|
#include "bladerunner/items.h"
|
|
|
|
#include "bladerunner/lights.h"
|
2015-05-01 09:43:04 +02:00
|
|
|
#include "bladerunner/mouse.h"
|
2017-09-10 20:19:02 +02:00
|
|
|
#include "bladerunner/music.h"
|
2014-05-17 17:13:49 +02:00
|
|
|
#include "bladerunner/outtake.h"
|
2016-10-04 02:21:08 +02:00
|
|
|
#include "bladerunner/obstacles.h"
|
2017-08-27 22:39:36 +02:00
|
|
|
#include "bladerunner/overlays.h"
|
2017-08-24 23:43:47 +02:00
|
|
|
#include "bladerunner/regions.h"
|
2018-03-17 16:14:48 +01:00
|
|
|
#include "bladerunner/savefile.h"
|
2014-05-25 15:01:06 +02:00
|
|
|
#include "bladerunner/scene.h"
|
2015-09-13 01:48:13 +02:00
|
|
|
#include "bladerunner/scene_objects.h"
|
2017-09-10 20:19:02 +02:00
|
|
|
#include "bladerunner/screen_effects.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/set.h"
|
2018-02-10 20:34:28 +01:00
|
|
|
#include "bladerunner/script/ai_script.h"
|
|
|
|
#include "bladerunner/script/init_script.h"
|
|
|
|
#include "bladerunner/script/kia_script.h"
|
2018-03-24 02:42:51 +01:00
|
|
|
#include "bladerunner/script/police_maze.h"
|
2018-02-10 20:34:28 +01:00
|
|
|
#include "bladerunner/script/scene_script.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "bladerunner/settings.h"
|
2015-05-01 09:43:04 +02:00
|
|
|
#include "bladerunner/shape.h"
|
2014-06-05 23:49:57 +02:00
|
|
|
#include "bladerunner/slice_animations.h"
|
|
|
|
#include "bladerunner/slice_renderer.h"
|
2018-06-18 14:10:00 +03:00
|
|
|
#include "bladerunner/subtitles.h"
|
2017-08-24 23:43:47 +02:00
|
|
|
#include "bladerunner/suspects_database.h"
|
2015-02-07 17:08:08 +01:00
|
|
|
#include "bladerunner/text_resource.h"
|
2018-03-23 23:14:34 +01:00
|
|
|
#include "bladerunner/time.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/ui/elevator.h"
|
2018-03-27 18:43:27 +02:00
|
|
|
#include "bladerunner/ui/end_credits.h"
|
2018-01-31 00:37:19 +01:00
|
|
|
#include "bladerunner/ui/esper.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/ui/kia.h"
|
2018-03-25 16:52:48 +02:00
|
|
|
#include "bladerunner/ui/scores.h"
|
2018-01-14 12:12:06 +01:00
|
|
|
#include "bladerunner/ui/spinner.h"
|
2018-02-10 20:34:28 +01:00
|
|
|
#include "bladerunner/ui/vk.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "bladerunner/vqa_decoder.h"
|
2015-09-15 20:26:46 +02:00
|
|
|
#include "bladerunner/waypoints.h"
|
2017-03-28 17:50:04 +02:00
|
|
|
#include "bladerunner/zbuffer.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2015-05-01 09:43:04 +02:00
|
|
|
#include "common/array.h"
|
2018-04-03 22:04:20 +02:00
|
|
|
#include "common/config-manager.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "common/error.h"
|
|
|
|
#include "common/events.h"
|
2018-03-17 16:14:48 +01:00
|
|
|
#include "common/savefile.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
#include "common/system.h"
|
2019-01-12 18:11:38 +01:00
|
|
|
#include "common/debug-channels.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
#include "engines/util.h"
|
2018-01-14 13:33:45 +01:00
|
|
|
#include "engines/advancedDetector.h"
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
#include "graphics/pixelformat.h"
|
2017-08-24 23:43:47 +02:00
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
namespace BladeRunner {
|
|
|
|
|
2018-01-14 13:33:45 +01:00
|
|
|
BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *desc)
|
2016-10-12 23:00:33 +02:00
|
|
|
: Engine(syst),
|
|
|
|
_rnd("bladerunner") {
|
2018-01-14 12:12:06 +01:00
|
|
|
|
2019-01-12 18:11:38 +01:00
|
|
|
DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts");
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
_windowIsActive = true;
|
2018-02-12 20:53:13 +01:00
|
|
|
_gameIsRunning = true;
|
|
|
|
|
2018-03-27 23:43:38 +02:00
|
|
|
_vqaIsPlaying = false;
|
|
|
|
_vqaStopIsRequested = false;
|
2018-07-02 10:45:17 +03:00
|
|
|
_subtitlesEnabled = false;
|
2018-03-27 23:43:38 +02:00
|
|
|
|
2015-05-01 10:13:30 +02:00
|
|
|
_playerLosesControlCounter = 0;
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2016-10-22 18:30:46 +02:00
|
|
|
_playerActorIdle = false;
|
2018-02-12 20:53:13 +01:00
|
|
|
_playerDead = false;
|
|
|
|
_speechSkipped = false;
|
|
|
|
_gameOver = false;
|
|
|
|
_gameAutoSave = 0;
|
|
|
|
_gameIsLoading = false;
|
|
|
|
_sceneIsLoading = false;
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
_runningActorId = -1;
|
2018-02-12 20:53:13 +01:00
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = false;
|
|
|
|
|
|
|
|
_walkSoundId = -1;
|
|
|
|
_walkSoundVolume = 0;
|
2016-09-29 22:30:50 +02:00
|
|
|
_walkSoundBalance = 0;
|
2018-01-14 13:33:45 +01:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_crimesDatabase = nullptr;
|
|
|
|
|
2018-01-14 13:33:45 +01:00
|
|
|
switch (desc->language) {
|
2018-02-05 18:46:09 +01:00
|
|
|
case Common::EN_ANY:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "E";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
case Common::DE_DEU:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "G";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
case Common::FR_FRA:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "F";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
case Common::IT_ITA:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "I";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
case Common::RU_RUS:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "R";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
case Common::ES_ESP:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "S";
|
2018-02-05 18:46:09 +01:00
|
|
|
break;
|
|
|
|
default:
|
2018-02-13 23:08:37 +01:00
|
|
|
_languageCode = "E";
|
2018-01-14 13:33:45 +01:00
|
|
|
}
|
2018-02-01 20:40:49 +01:00
|
|
|
|
|
|
|
_screenEffects = nullptr;
|
|
|
|
_combat = nullptr;
|
|
|
|
_actorDialogueQueue = nullptr;
|
|
|
|
_settings = nullptr;
|
|
|
|
_itemPickup = nullptr;
|
|
|
|
_lights = nullptr;
|
|
|
|
_obstacles = nullptr;
|
|
|
|
_sceneScript = nullptr;
|
2018-12-15 22:40:07 +01:00
|
|
|
_time = nullptr;
|
2018-02-01 20:40:49 +01:00
|
|
|
_gameInfo = nullptr;
|
|
|
|
_waypoints = nullptr;
|
|
|
|
_gameVars = nullptr;
|
|
|
|
_view = nullptr;
|
|
|
|
_sceneObjects = nullptr;
|
|
|
|
_gameFlags = nullptr;
|
|
|
|
_items = nullptr;
|
|
|
|
_audioMixer = nullptr;
|
|
|
|
_audioPlayer = nullptr;
|
|
|
|
_music = nullptr;
|
|
|
|
_audioSpeech = nullptr;
|
|
|
|
_ambientSounds = nullptr;
|
|
|
|
_chapters = nullptr;
|
|
|
|
_overlays = nullptr;
|
|
|
|
_zbuffer = nullptr;
|
|
|
|
_playerActor = nullptr;
|
|
|
|
_textActorNames = nullptr;
|
|
|
|
_textCrimes = nullptr;
|
|
|
|
_textClueTypes = nullptr;
|
|
|
|
_textKIA = nullptr;
|
|
|
|
_textSpinnerDestinations = nullptr;
|
|
|
|
_textVK = nullptr;
|
|
|
|
_textOptions = nullptr;
|
|
|
|
_dialogueMenu = nullptr;
|
|
|
|
_suspectsDatabase = nullptr;
|
|
|
|
_kia = nullptr;
|
2018-03-27 18:43:27 +02:00
|
|
|
_endCredits = nullptr;
|
2018-02-01 20:40:49 +01:00
|
|
|
_spinner = nullptr;
|
2018-03-27 18:47:22 +02:00
|
|
|
_scores = nullptr;
|
2018-02-01 20:40:49 +01:00
|
|
|
_elevator = nullptr;
|
|
|
|
_mainFont = nullptr;
|
2018-06-18 14:10:00 +03:00
|
|
|
_subtitles = nullptr;
|
2018-02-12 20:53:13 +01:00
|
|
|
_esper = nullptr;
|
|
|
|
_vk = nullptr;
|
2018-03-28 23:41:29 +02:00
|
|
|
_policeMaze = nullptr;
|
2018-02-01 20:40:49 +01:00
|
|
|
_mouse = nullptr;
|
|
|
|
_sliceAnimations = nullptr;
|
|
|
|
_sliceRenderer = nullptr;
|
|
|
|
_crimesDatabase = nullptr;
|
|
|
|
_scene = nullptr;
|
|
|
|
_aiScripts = nullptr;
|
|
|
|
for (int i = 0; i != kActorCount; ++i) {
|
2018-02-25 19:31:52 +01:00
|
|
|
_actors[i] = nullptr;
|
2018-02-01 20:40:49 +01:00
|
|
|
}
|
2018-02-25 19:31:52 +01:00
|
|
|
_debugger = nullptr;
|
2018-02-18 22:18:41 +01:00
|
|
|
walkingReset();
|
2018-02-25 19:31:52 +01:00
|
|
|
|
|
|
|
_actorUpdateCounter = 0;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2014-05-30 13:52:59 -07:00
|
|
|
BladeRunnerEngine::~BladeRunnerEngine() {
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
|
2018-11-21 23:16:15 +01:00
|
|
|
return
|
|
|
|
f == kSupportsRTL ||
|
|
|
|
f == kSupportsLoadingDuringRuntime ||
|
|
|
|
f == kSupportsSavingDuringRuntime;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BladeRunnerEngine::canLoadGameStateCurrently() {
|
|
|
|
return
|
|
|
|
playerHasControl() &&
|
|
|
|
!_sceneScript->isInsideScript() &&
|
|
|
|
!_aiScripts->isInsideScript() &&
|
|
|
|
!_kia->isOpen() &&
|
|
|
|
!_spinner->isOpen() &&
|
|
|
|
!_vk->isOpen() &&
|
|
|
|
!_elevator->isOpen();
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Error BladeRunnerEngine::loadGameState(int slot) {
|
2018-12-05 18:18:13 +01:00
|
|
|
Common::InSaveFile *saveFile = BladeRunner::SaveFileManager::openForLoading(_targetName, slot);
|
2018-11-21 23:16:15 +01:00
|
|
|
if (saveFile == nullptr || saveFile->err()) {
|
|
|
|
delete saveFile;
|
|
|
|
return Common::kReadingFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
BladeRunner::SaveFileHeader header;
|
2018-11-25 21:47:00 +01:00
|
|
|
if (!BladeRunner::SaveFileManager::readHeader(*saveFile, header)) {
|
2018-11-21 23:16:15 +01:00
|
|
|
error("Invalid savegame");
|
|
|
|
}
|
|
|
|
|
|
|
|
loadGame(*saveFile);
|
|
|
|
|
|
|
|
delete saveFile;
|
|
|
|
|
|
|
|
return Common::kNoError;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BladeRunnerEngine::canSaveGameStateCurrently() {
|
|
|
|
return
|
|
|
|
playerHasControl() &&
|
|
|
|
!_sceneScript->isInsideScript() &&
|
|
|
|
!_aiScripts->isInsideScript() &&
|
|
|
|
!_kia->isOpen() &&
|
|
|
|
!_spinner->isOpen() &&
|
|
|
|
!_vk->isOpen() &&
|
|
|
|
!_elevator->isOpen();
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) {
|
2018-12-05 18:18:13 +01:00
|
|
|
Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_targetName, slot);
|
2018-11-21 23:16:15 +01:00
|
|
|
if (saveFile == nullptr || saveFile->err()) {
|
|
|
|
delete saveFile;
|
|
|
|
return Common::kReadingFailed;
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
Graphics::Surface thumbnail = generateThumbnail();
|
2018-11-21 23:16:15 +01:00
|
|
|
|
|
|
|
BladeRunner::SaveFileHeader header;
|
|
|
|
header._name = desc;
|
2018-11-25 21:47:00 +01:00
|
|
|
|
|
|
|
BladeRunner::SaveFileManager::writeHeader(*saveFile, header);
|
2018-11-21 23:16:15 +01:00
|
|
|
|
|
|
|
saveGame(*saveFile, thumbnail);
|
|
|
|
|
|
|
|
saveFile->finalize();
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
thumbnail.free();
|
2018-11-21 23:16:15 +01:00
|
|
|
|
|
|
|
delete saveFile;
|
|
|
|
|
|
|
|
return Common::kNoError;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::Error BladeRunnerEngine::run() {
|
2014-05-30 12:45:01 -07:00
|
|
|
Graphics::PixelFormat format = createRGB555();
|
2017-10-01 00:56:01 -05:00
|
|
|
initGraphics(640, 480, &format);
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2015-02-06 15:31:43 +01:00
|
|
|
_system->showMouse(true);
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
bool hasSavegames = !SaveFileManager::list(_targetName).empty();
|
|
|
|
|
|
|
|
if (!startup(hasSavegames)) {
|
2015-02-10 21:09:12 +01:00
|
|
|
shutdown();
|
2014-05-30 10:24:24 -07:00
|
|
|
return Common::Error(Common::kUnknownError, "Failed to initialize resources");
|
2015-02-10 21:09:12 +01:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
|
|
|
|
|
2018-01-28 20:59:12 +01:00
|
|
|
#if BLADERUNNER_DEBUG_GAME
|
|
|
|
{
|
|
|
|
#else
|
2014-05-20 11:30:16 +02:00
|
|
|
if (warnUserAboutUnsupportedGame()) {
|
2018-01-28 20:59:12 +01:00
|
|
|
#endif
|
2018-11-25 21:47:00 +01:00
|
|
|
if (hasSavegames) {
|
|
|
|
_kia->_forceOpen = true;
|
|
|
|
_kia->open(kKIASectionLoad);
|
|
|
|
}
|
|
|
|
// TODO: why is game starting new game here when everything is done in startup?
|
|
|
|
// else {
|
|
|
|
// newGame(1);
|
|
|
|
// }
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2014-05-20 11:30:16 +02:00
|
|
|
gameLoop();
|
2018-03-27 18:43:27 +02:00
|
|
|
|
|
|
|
_mouse->disable();
|
|
|
|
|
|
|
|
if (_gameOver) {
|
|
|
|
// autoSaveGame(4, 1); // TODO
|
|
|
|
_endCredits->show();
|
|
|
|
}
|
2014-05-20 11:30:16 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
shutdown();
|
|
|
|
|
|
|
|
return Common::kNoError;
|
|
|
|
}
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
bool BladeRunnerEngine::startup(bool hasSavegames) {
|
2018-01-14 12:12:06 +01:00
|
|
|
// These are static objects in original game
|
|
|
|
|
|
|
|
_screenEffects = new ScreenEffects(this, 0x8000);
|
|
|
|
|
2018-03-27 18:43:27 +02:00
|
|
|
_endCredits = new EndCredits(this);
|
2018-01-14 12:12:06 +01:00
|
|
|
|
|
|
|
_actorDialogueQueue = new ActorDialogueQueue(this);
|
|
|
|
|
|
|
|
_settings = new Settings(this);
|
|
|
|
|
|
|
|
_itemPickup = new ItemPickup(this);
|
|
|
|
|
|
|
|
_lights = new Lights(this);
|
|
|
|
|
|
|
|
// TODO: outtake player - but this is done bit differently
|
|
|
|
|
2018-03-23 18:47:04 +01:00
|
|
|
_policeMaze = new PoliceMaze(this);
|
2018-01-14 12:12:06 +01:00
|
|
|
|
|
|
|
_obstacles = new Obstacles(this);
|
|
|
|
|
|
|
|
_sceneScript = new SceneScript(this);
|
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
_debugger = new Debugger(this);
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
// This is the original startup in the game
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
bool r;
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_surfaceFront.create(640, 480, createRGB555());
|
|
|
|
_surfaceBack.create(640, 480, createRGB555());
|
2017-07-30 22:34:21 +02:00
|
|
|
_surface4.create(640, 480, createRGB555());
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2018-12-15 22:40:07 +01:00
|
|
|
_time = new Time(this);
|
2018-03-23 23:14:34 +01:00
|
|
|
|
2018-09-02 13:44:21 +03:00
|
|
|
// Try to load the SUBTITLES.MIX first, before Startup.MIX
|
|
|
|
// allows overriding any identically named resources (such as the original font files and as a bonus also the TRE files for the UI and dialogue menu)
|
|
|
|
_subtitles = new Subtitles(this);
|
|
|
|
r = openArchive("SUBTITLES.MIX");
|
|
|
|
if (!r) {
|
|
|
|
_subtitles->setSubtitlesSystemInactive(true); // no subtitles support
|
|
|
|
}
|
|
|
|
_subtitles->init();
|
|
|
|
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
r = openArchive("STARTUP.MIX");
|
|
|
|
if (!r)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_gameInfo = new GameInfo(this);
|
|
|
|
if (!_gameInfo)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
r = _gameInfo->open("GAMEINFO.DAT");
|
2018-03-17 16:40:33 +01:00
|
|
|
if (!r) {
|
2014-05-16 21:58:49 +02:00
|
|
|
return false;
|
2018-03-17 16:40:33 +01:00
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2016-10-08 21:06:22 +02:00
|
|
|
// TODO: Create datetime - not used
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
// TODO: Create graphics surfaces 1-4
|
|
|
|
|
|
|
|
// TODO: Allocate audio cache
|
|
|
|
|
|
|
|
if (hasSavegames) {
|
|
|
|
if (!loadSplash()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-15 20:26:46 +02:00
|
|
|
_waypoints = new Waypoints(this, _gameInfo->getWaypointCount());
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
_combat = new Combat(this);
|
2015-02-06 15:31:43 +01:00
|
|
|
|
2018-03-17 16:14:48 +01:00
|
|
|
_gameVars = new int[_gameInfo->getGlobalVarCount()]();
|
2015-02-06 15:31:43 +01:00
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
// TODO: Init Actor AI Update counter
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
// Seed rand
|
|
|
|
|
|
|
|
// TODO: Sine and cosine lookup tables for intervals of 1.0, 4.0, and 12.0
|
2018-11-21 23:16:15 +01:00
|
|
|
_cosTable1024 = new Common::CosineTable(1024); // 10-bits = 1024 points for 2*PI;
|
|
|
|
_sinTable1024 = new Common::SineTable(1024);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
_view = new View();
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2015-09-13 01:48:13 +02:00
|
|
|
_sceneObjects = new SceneObjects(this, _view);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
_gameFlags = new GameFlags();
|
|
|
|
_gameFlags->setFlagCount(_gameInfo->getFlagCount());
|
2018-07-02 10:45:17 +03:00
|
|
|
|
|
|
|
// Assign default values to the ScummVM configuration manager, in case settings are missing
|
|
|
|
ConfMan.registerDefault("subtitles", "true");
|
|
|
|
// get value from the ScummVM configuration manager
|
|
|
|
_subtitlesEnabled = ConfMan.getBool("subtitles");
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2015-09-15 20:26:46 +02:00
|
|
|
_items = new Items(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-08-24 23:43:47 +02:00
|
|
|
_audioMixer = new AudioMixer(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
_audioPlayer = new AudioPlayer(this);
|
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
_music = new Music(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
_audioSpeech = new AudioSpeech(this);
|
|
|
|
|
|
|
|
_ambientSounds = new AmbientSounds(this);
|
|
|
|
|
|
|
|
// TODO: Read BLADE.INI
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
_chapters = new Chapters(this);
|
|
|
|
if (!_chapters)
|
|
|
|
return false;
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
if (!openArchive("MUSIC.MIX"))
|
2014-05-16 21:58:49 +02:00
|
|
|
return false;
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
if (!openArchive("SFX.MIX"))
|
2014-05-16 21:58:49 +02:00
|
|
|
return false;
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
if (!openArchive("SPCHSFX.TLK"))
|
|
|
|
return false;
|
|
|
|
|
2017-08-27 22:39:36 +02:00
|
|
|
_overlays = new Overlays(this);
|
|
|
|
_overlays->init();
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-03-28 17:50:04 +02:00
|
|
|
_zbuffer = new ZBuffer();
|
|
|
|
_zbuffer->init(640, 480);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2015-05-02 22:31:07 +02:00
|
|
|
int actorCount = (int)_gameInfo->getActorCount();
|
2018-01-14 12:12:06 +01:00
|
|
|
assert(actorCount < kActorCount);
|
2015-05-02 22:31:07 +02:00
|
|
|
for (int i = 0; i != actorCount; ++i) {
|
|
|
|
_actors[i] = new Actor(this, i);
|
2016-09-10 18:16:17 +02:00
|
|
|
_actors[i]->setup(i);
|
2015-05-02 22:31:07 +02:00
|
|
|
}
|
2018-01-14 12:12:06 +01:00
|
|
|
_actors[kActorVoiceOver] = new Actor(this, kActorVoiceOver);
|
2015-05-02 22:31:07 +02:00
|
|
|
_playerActor = _actors[_gameInfo->getPlayerId()];
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
_playerActor->setFPS(15);
|
2018-02-18 22:18:41 +01:00
|
|
|
_playerActor->timerStart(6, 200);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
// TODO: Set actor ids (redundant?)
|
|
|
|
|
2018-03-17 16:14:48 +01:00
|
|
|
_policeMaze = new PoliceMaze(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
_textActorNames = new TextResource(this);
|
|
|
|
if (!_textActorNames->open("ACTORS"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_textCrimes = new TextResource(this);
|
|
|
|
if (!_textCrimes->open("CRIMES"))
|
|
|
|
return false;
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_textClueTypes = new TextResource(this);
|
|
|
|
if (!_textClueTypes->open("CLUETYPE"))
|
2015-05-02 12:01:47 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
_textKIA = new TextResource(this);
|
|
|
|
if (!_textKIA->open("KIA"))
|
|
|
|
return false;
|
|
|
|
|
2017-03-29 01:50:47 +02:00
|
|
|
_textSpinnerDestinations = new TextResource(this);
|
|
|
|
if (!_textSpinnerDestinations->open("SPINDEST"))
|
2014-05-16 21:58:49 +02:00
|
|
|
return false;
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
_textVK = new TextResource(this);
|
|
|
|
if (!_textVK->open("VK"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_textOptions = new TextResource(this);
|
|
|
|
if (!_textOptions->open("OPTIONS"))
|
|
|
|
return false;
|
|
|
|
|
2017-08-22 18:57:50 +02:00
|
|
|
_dialogueMenu = new DialogueMenu(this);
|
|
|
|
if (!_dialogueMenu->loadText("DLGMENU"))
|
|
|
|
return false;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_suspectsDatabase = new SuspectsDatabase(this, _gameInfo->getSuspectCount());
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_kia = new KIA(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-07-31 00:11:00 +02:00
|
|
|
_spinner = new Spinner(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-08-24 22:34:40 +02:00
|
|
|
_elevator = new Elevator(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-03-25 16:52:48 +02:00
|
|
|
_scores = new Scores(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-06 21:23:46 +02:00
|
|
|
_mainFont = new Font(this);
|
|
|
|
_mainFont->open("KIA6PT.FON", 640, 480, -1, 0, 0x252D);
|
2016-10-12 23:00:33 +02:00
|
|
|
_mainFont->setSpacing(1, 0);
|
2018-07-02 10:45:17 +03:00
|
|
|
|
2015-05-01 09:43:04 +02:00
|
|
|
for (int i = 0; i != 43; ++i) {
|
|
|
|
Shape *shape = new Shape(this);
|
2018-01-31 00:37:19 +01:00
|
|
|
shape->open("SHAPES.SHP", i);
|
2015-05-01 09:43:04 +02:00
|
|
|
_shapes.push_back(shape);
|
|
|
|
}
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
_esper = new ESPER(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
_vk = new VK(this);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
_mouse = new Mouse(this);
|
|
|
|
// _mouse->setCursorPosition(320, 240);
|
2015-05-01 09:43:04 +02:00
|
|
|
_mouse->setCursor(0);
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
_sliceAnimations = new SliceAnimations(this);
|
2014-06-05 23:49:57 +02:00
|
|
|
r = _sliceAnimations->open("INDEX.DAT");
|
|
|
|
if (!r)
|
|
|
|
return false;
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
r = _sliceAnimations->openCoreAnim();
|
2017-08-26 21:27:54 +02:00
|
|
|
if (!r) {
|
2015-05-02 12:01:47 +02:00
|
|
|
return false;
|
2017-08-26 21:27:54 +02:00
|
|
|
}
|
2015-02-06 15:31:43 +01:00
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
_sliceRenderer = new SliceRenderer(this);
|
2017-09-10 20:19:02 +02:00
|
|
|
_sliceRenderer->setScreenEffects(_screenEffects);
|
2015-02-07 17:08:08 +01:00
|
|
|
|
2016-10-06 00:59:11 +02:00
|
|
|
_crimesDatabase = new CrimesDatabase(this, "CLUES", _gameInfo->getClueCount());
|
2015-02-07 17:08:08 +01:00
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
// TODO: Scene
|
|
|
|
_scene = new Scene(this);
|
|
|
|
|
|
|
|
// Load INIT.DLL
|
2018-02-10 20:34:28 +01:00
|
|
|
InitScript initScript(this);
|
2015-02-07 11:41:52 +01:00
|
|
|
initScript.SCRIPT_Initialize_Game();
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
// TODO: Load AI-ACT1.DLL
|
2017-03-20 22:55:31 +01:00
|
|
|
_aiScripts = new AIScripts(this, actorCount);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2014-05-25 15:01:06 +02:00
|
|
|
initChapterAndScene();
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-25 15:01:06 +02:00
|
|
|
void BladeRunnerEngine::initChapterAndScene() {
|
2014-05-16 21:58:49 +02:00
|
|
|
// TODO: Init actors...
|
2017-03-23 16:20:10 +01:00
|
|
|
for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
|
2018-02-10 20:34:28 +01:00
|
|
|
_aiScripts->initialize(i);
|
2017-03-23 16:20:10 +01:00
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2017-03-23 16:20:10 +01:00
|
|
|
for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
|
2017-03-29 01:50:47 +02:00
|
|
|
_actors[i]->changeAnimationMode(kAnimationModeIdle);
|
2017-03-23 16:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1, end = _gameInfo->getActorCount(); i != end; ++i) { // skip first actor, probably player
|
|
|
|
_actors[i]->movementTrackNext(true);
|
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2018-04-03 22:04:20 +02:00
|
|
|
if (ConfMan.hasKey("boot_param")) {
|
|
|
|
int param = ConfMan.getInt("boot_param"); // CTTTSSS
|
|
|
|
int chapter = param / 1000000;
|
|
|
|
param -= chapter * 1000000;
|
|
|
|
int set = param / 1000;
|
|
|
|
param -= set * 1000;
|
|
|
|
int scene = param;
|
|
|
|
|
|
|
|
_settings->setChapter(chapter);
|
|
|
|
_settings->setNewSetAndScene(set, scene);
|
|
|
|
} else {
|
|
|
|
_settings->setChapter(1);
|
|
|
|
_settings->setNewSetAndScene(_gameInfo->getInitialSetId(), _gameInfo->getInitialSceneId());
|
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::shutdown() {
|
2015-02-06 15:31:43 +01:00
|
|
|
_mixer->stopAll();
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
// TODO: Write BLADE.INI
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
delete _vk;
|
|
|
|
_vk = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
delete _esper;
|
|
|
|
_esper = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _mouse;
|
2016-10-02 02:47:12 +02:00
|
|
|
_mouse = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
for (uint i = 0; i != _shapes.size(); ++i) {
|
|
|
|
delete _shapes[i];
|
|
|
|
}
|
|
|
|
_shapes.clear();
|
|
|
|
|
|
|
|
// TODO: Shutdown Scene
|
|
|
|
delete _scene;
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
if (_chapters) {
|
|
|
|
if (_chapters->hasOpenResources())
|
|
|
|
_chapters->closeResources();
|
|
|
|
delete _chapters;
|
2016-10-02 02:47:12 +02:00
|
|
|
_chapters = nullptr;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2016-10-06 00:59:11 +02:00
|
|
|
delete _crimesDatabase;
|
|
|
|
_crimesDatabase = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _sliceRenderer;
|
2016-10-02 02:47:12 +02:00
|
|
|
_sliceRenderer = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _sliceAnimations;
|
2016-10-02 02:47:12 +02:00
|
|
|
_sliceAnimations = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _textActorNames;
|
2016-10-02 02:47:12 +02:00
|
|
|
_textActorNames = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _textCrimes;
|
2016-10-02 02:47:12 +02:00
|
|
|
_textCrimes = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
delete _textClueTypes;
|
|
|
|
_textClueTypes = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _textKIA;
|
2016-10-02 02:47:12 +02:00
|
|
|
_textKIA = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-03-29 01:50:47 +02:00
|
|
|
delete _textSpinnerDestinations;
|
|
|
|
_textSpinnerDestinations = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _textVK;
|
2016-10-02 02:47:12 +02:00
|
|
|
_textVK = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _textOptions;
|
2016-10-02 02:47:12 +02:00
|
|
|
_textOptions = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
delete _dialogueMenu;
|
|
|
|
_dialogueMenu = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _ambientSounds;
|
2017-09-10 20:19:02 +02:00
|
|
|
_ambientSounds = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-08-27 22:39:36 +02:00
|
|
|
delete _overlays;
|
|
|
|
_overlays = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _audioSpeech;
|
2017-09-10 20:19:02 +02:00
|
|
|
_audioSpeech = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
delete _music;
|
|
|
|
_music = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _audioPlayer;
|
2017-09-10 20:19:02 +02:00
|
|
|
_audioPlayer = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-08-24 23:43:47 +02:00
|
|
|
delete _audioMixer;
|
2017-09-10 20:19:02 +02:00
|
|
|
_audioMixer = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
if (isArchiveOpen("MUSIC.MIX")) {
|
2014-05-16 21:58:49 +02:00
|
|
|
closeArchive("MUSIC.MIX");
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
if (isArchiveOpen("SFX.MIX")) {
|
2014-05-16 21:58:49 +02:00
|
|
|
closeArchive("SFX.MIX");
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
if (isArchiveOpen("SPCHSFX.TLK")) {
|
2014-05-16 21:58:49 +02:00
|
|
|
closeArchive("SPCHSFX.TLK");
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2016-10-12 23:00:33 +02:00
|
|
|
if (_mainFont) {
|
2016-10-06 21:23:46 +02:00
|
|
|
_mainFont->close();
|
|
|
|
delete _mainFont;
|
|
|
|
_mainFont = nullptr;
|
|
|
|
}
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-08-01 18:05:28 +03:00
|
|
|
if(isArchiveOpen("SUBTITLES.MIX")) {
|
2018-08-01 20:41:36 +03:00
|
|
|
closeArchive("SUBTITLES.MIX");
|
2018-08-01 18:05:28 +03:00
|
|
|
}
|
2018-07-02 10:45:17 +03:00
|
|
|
if (_subtitles) {
|
|
|
|
delete _subtitles;
|
|
|
|
_subtitles = nullptr;
|
2018-06-18 14:10:00 +03:00
|
|
|
}
|
2018-07-02 10:45:17 +03:00
|
|
|
|
2015-09-19 01:43:38 +02:00
|
|
|
delete _items;
|
2016-10-02 02:47:12 +02:00
|
|
|
_items = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _gameFlags;
|
2016-10-02 02:47:12 +02:00
|
|
|
_gameFlags = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2015-09-13 01:48:13 +02:00
|
|
|
delete _view;
|
2016-10-02 02:47:12 +02:00
|
|
|
_view = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2015-09-13 01:48:13 +02:00
|
|
|
delete _sceneObjects;
|
2016-10-02 02:47:12 +02:00
|
|
|
_sceneObjects = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-06-23 21:34:38 -07:00
|
|
|
delete _cosTable1024;
|
|
|
|
delete _sinTable1024;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-28 22:34:04 +02:00
|
|
|
delete _aiScripts;
|
|
|
|
_aiScripts = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete[] _gameVars;
|
2016-10-02 02:47:12 +02:00
|
|
|
_gameVars = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
delete _waypoints;
|
2016-10-02 02:47:12 +02:00
|
|
|
_waypoints = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
// TODO: Delete Cover waypoints
|
|
|
|
|
|
|
|
// TODO: Delete Flee waypoints
|
|
|
|
|
2018-03-25 16:52:48 +02:00
|
|
|
delete _scores;
|
|
|
|
_scores = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-03-27 18:43:27 +02:00
|
|
|
delete _endCredits;
|
|
|
|
_endCredits = nullptr;
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
delete _elevator;
|
|
|
|
_elevator = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-08-24 23:43:47 +02:00
|
|
|
delete _spinner;
|
|
|
|
_spinner = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
delete _kia;
|
|
|
|
_kia = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-08 21:06:22 +02:00
|
|
|
delete _suspectsDatabase;
|
|
|
|
_suspectsDatabase = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-08 21:06:22 +02:00
|
|
|
// TODO: Delete datetime - not used
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-28 22:34:04 +02:00
|
|
|
int actorCount = (int)_gameInfo->getActorCount();
|
|
|
|
for (int i = 0; i != actorCount; ++i) {
|
|
|
|
delete _actors[i];
|
|
|
|
_actors[i] = nullptr;
|
|
|
|
}
|
2018-01-14 12:12:06 +01:00
|
|
|
delete _actors[kActorVoiceOver];
|
|
|
|
_actors[kActorVoiceOver] = nullptr;
|
2017-03-23 00:25:38 +01:00
|
|
|
|
2016-10-28 22:34:04 +02:00
|
|
|
_playerActor = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
delete _gameInfo;
|
2016-10-02 02:47:12 +02:00
|
|
|
_gameInfo = nullptr;
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
// TODO: Delete graphics surfaces here
|
2017-07-30 22:34:21 +02:00
|
|
|
_surface4.free();
|
2018-01-14 12:12:06 +01:00
|
|
|
_surfaceBack.free();
|
|
|
|
_surfaceFront.free();
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
if (isArchiveOpen("STARTUP.MIX")) {
|
2014-05-16 21:58:49 +02:00
|
|
|
closeArchive("STARTUP.MIX");
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2015-05-02 12:01:47 +02:00
|
|
|
|
|
|
|
// TODO: Delete MIXArchives here
|
|
|
|
|
2018-12-15 22:40:07 +01:00
|
|
|
delete _time;
|
|
|
|
_time = nullptr;
|
2018-01-14 12:12:06 +01:00
|
|
|
|
|
|
|
// These are static objects in original game
|
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
delete _debugger;
|
|
|
|
_debugger = nullptr;
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
delete _zbuffer;
|
|
|
|
_zbuffer = nullptr;
|
|
|
|
|
|
|
|
delete _itemPickup;
|
|
|
|
_itemPickup = nullptr;
|
|
|
|
|
2018-03-23 18:47:04 +01:00
|
|
|
delete _policeMaze;
|
|
|
|
_policeMaze = nullptr;
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
delete _obstacles;
|
|
|
|
_obstacles = nullptr;
|
|
|
|
|
|
|
|
delete _actorDialogueQueue;
|
|
|
|
_actorDialogueQueue = nullptr;
|
|
|
|
|
|
|
|
delete _combat;
|
|
|
|
_combat = nullptr;
|
|
|
|
|
|
|
|
delete _screenEffects;
|
|
|
|
_screenEffects = nullptr;
|
|
|
|
|
|
|
|
delete _lights;
|
|
|
|
_lights = nullptr;
|
|
|
|
|
|
|
|
delete _settings;
|
|
|
|
_settings = nullptr;
|
|
|
|
|
|
|
|
delete _sceneScript;
|
|
|
|
_sceneScript = nullptr;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2015-05-02 12:01:47 +02:00
|
|
|
bool BladeRunnerEngine::loadSplash() {
|
2014-05-16 21:58:49 +02:00
|
|
|
Image img(this);
|
2017-09-10 20:19:02 +02:00
|
|
|
if (!img.open("SPLASH.IMG")) {
|
2015-05-02 12:01:47 +02:00
|
|
|
return false;
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
img.copyToSurface(&_surfaceFront);
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
blitToScreen(_surfaceFront);
|
2015-05-02 12:01:47 +02:00
|
|
|
|
2016-10-22 18:30:46 +02:00
|
|
|
return true;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
Common::Point BladeRunnerEngine::getMousePos() const {
|
2018-01-29 21:48:48 +01:00
|
|
|
Common::Point p = _eventMan->getMousePos();
|
|
|
|
p.x = CLIP(p.x, int16(0), int16(639));
|
|
|
|
p.y = CLIP(p.y, int16(0), int16(479));
|
|
|
|
return p;
|
2017-07-31 00:11:00 +02:00
|
|
|
}
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
bool BladeRunnerEngine::isMouseButtonDown() const {
|
|
|
|
return _eventMan->getButtonState() != 0;
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
void BladeRunnerEngine::gameLoop() {
|
|
|
|
_gameIsRunning = true;
|
|
|
|
do {
|
2019-01-08 19:25:27 +01:00
|
|
|
if (_playerDead) {
|
|
|
|
playerDied();
|
|
|
|
_playerDead = false;
|
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
gameTick();
|
2016-09-10 18:16:17 +02:00
|
|
|
} while (_gameIsRunning);
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::gameTick() {
|
|
|
|
handleEvents();
|
|
|
|
|
|
|
|
if (_gameIsRunning && _windowIsActive) {
|
2018-11-25 21:47:00 +01:00
|
|
|
if (!_kia->isOpen() && !_sceneScript->isInsideScript() && !_aiScripts->isInsideScript()) {
|
2017-08-24 23:43:47 +02:00
|
|
|
_settings->openNewScene();
|
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
// TODO: Autosave
|
2017-08-24 23:43:47 +02:00
|
|
|
|
|
|
|
//probably not needed, this version of tick is just loading data from buffer
|
|
|
|
//_audioMixer->tick();
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_kia->isOpen()) {
|
2018-01-14 12:12:06 +01:00
|
|
|
_kia->tick();
|
|
|
|
return;
|
|
|
|
}
|
2017-07-31 00:11:00 +02:00
|
|
|
|
|
|
|
if (_spinner->isOpen()) {
|
|
|
|
_spinner->tick();
|
|
|
|
_ambientSounds->tick();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_esper->isOpen()) {
|
|
|
|
_esper->tick();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
if (_vk->isOpen()) {
|
|
|
|
_vk->tick();
|
|
|
|
_ambientSounds->tick();
|
|
|
|
return;
|
|
|
|
}
|
2017-08-24 22:34:40 +02:00
|
|
|
|
|
|
|
if (_elevator->isOpen()) {
|
|
|
|
_elevator->tick();
|
|
|
|
_ambientSounds->tick();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-25 16:52:48 +02:00
|
|
|
if (_scores->isOpen()) {
|
|
|
|
_scores->tick();
|
|
|
|
_ambientSounds->tick();
|
|
|
|
return;
|
|
|
|
}
|
2016-10-03 11:24:13 +02:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
_actorDialogueQueue->tick();
|
2016-09-10 18:16:17 +02:00
|
|
|
if (_scene->didPlayerWalkIn()) {
|
2018-02-10 20:34:28 +01:00
|
|
|
_sceneScript->playerWalkedIn();
|
2016-09-10 18:16:17 +02:00
|
|
|
}
|
2017-08-22 18:57:50 +02:00
|
|
|
bool inDialogueMenu = _dialogueMenu->isVisible();
|
2018-03-17 16:40:33 +01:00
|
|
|
if (!inDialogueMenu) {
|
|
|
|
for (int i = 0; i < (int)_gameInfo->getActorCount(); ++i) {
|
|
|
|
_actors[i]->tickCombat();
|
|
|
|
}
|
2017-08-22 18:57:50 +02:00
|
|
|
}
|
2017-03-28 17:50:04 +02:00
|
|
|
|
2018-03-23 18:47:04 +01:00
|
|
|
_policeMaze->tick();
|
|
|
|
|
2017-08-22 18:57:50 +02:00
|
|
|
// TODO: Gun range announcements
|
2017-03-28 17:50:04 +02:00
|
|
|
_zbuffer->clean();
|
2015-02-06 15:31:43 +01:00
|
|
|
|
|
|
|
_ambientSounds->tick();
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2014-05-25 15:01:06 +02:00
|
|
|
bool backgroundChanged = false;
|
2017-07-30 22:34:21 +02:00
|
|
|
int frame = _scene->advanceFrame();
|
2014-05-25 15:01:06 +02:00
|
|
|
if (frame >= 0) {
|
2018-02-10 20:34:28 +01:00
|
|
|
_sceneScript->sceneFrameAdvanced(frame);
|
2014-05-25 15:01:06 +02:00
|
|
|
backgroundChanged = true;
|
|
|
|
}
|
2018-01-14 12:12:06 +01:00
|
|
|
blit(_surfaceBack, _surfaceFront);
|
2017-08-27 22:39:36 +02:00
|
|
|
|
|
|
|
_overlays->tick();
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2017-08-22 18:57:50 +02:00
|
|
|
if (!inDialogueMenu) {
|
2017-03-20 22:55:31 +01:00
|
|
|
actorsUpdate();
|
2017-08-22 18:57:50 +02:00
|
|
|
}
|
2017-03-20 22:55:31 +01:00
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
if (_settings->getNewScene() == -1 || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
|
2018-02-12 20:53:13 +01:00
|
|
|
_sliceRenderer->setView(_view);
|
2014-06-05 23:49:57 +02:00
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
// Tick and draw all actors in current set
|
2017-03-20 22:55:31 +01:00
|
|
|
int setId = _scene->getSetId();
|
2016-09-10 18:16:17 +02:00
|
|
|
for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
|
2017-03-20 22:55:31 +01:00
|
|
|
if (_actors[i]->getSetId() == setId) {
|
2018-02-25 19:31:52 +01:00
|
|
|
Common::Rect screenRect;
|
|
|
|
if (_actors[i]->tick(backgroundChanged, &screenRect)) {
|
|
|
|
_zbuffer->mark(screenRect);
|
2017-03-20 22:55:31 +01:00
|
|
|
}
|
2016-09-12 00:54:40 +02:00
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
}
|
2014-06-05 23:49:57 +02:00
|
|
|
|
2016-10-02 00:20:56 +02:00
|
|
|
_items->tick();
|
2016-10-03 11:24:13 +02:00
|
|
|
|
2016-10-08 21:06:22 +02:00
|
|
|
_itemPickup->tick();
|
|
|
|
_itemPickup->draw();
|
|
|
|
|
2017-07-31 00:11:00 +02:00
|
|
|
Common::Point p = getMousePos();
|
2017-08-22 18:57:50 +02:00
|
|
|
|
|
|
|
if (_dialogueMenu->isVisible()) {
|
|
|
|
_dialogueMenu->tick(p.x, p.y);
|
2018-01-14 12:12:06 +01:00
|
|
|
_dialogueMenu->draw(_surfaceFront);
|
2017-08-22 18:57:50 +02:00
|
|
|
}
|
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
if (_debugger->_viewZBuffer) {
|
|
|
|
_surfaceFront.copyRectToSurface(_zbuffer->getData(), 1280, 0, 0, 640, 480);
|
|
|
|
}
|
2018-02-19 22:04:44 +01:00
|
|
|
|
2015-09-15 20:26:46 +02:00
|
|
|
_mouse->tick(p.x, p.y);
|
2018-01-14 12:12:06 +01:00
|
|
|
_mouse->draw(_surfaceFront, p.x, p.y);
|
2015-05-01 09:43:04 +02:00
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
// TODO: Process AUD
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2016-10-03 12:38:43 +02:00
|
|
|
if (_walkSoundId >= 0) {
|
2018-03-24 17:20:27 +01:00
|
|
|
_audioPlayer->playAud(_gameInfo->getSfxTrack(_walkSoundId), _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0);
|
2016-09-20 00:33:06 +02:00
|
|
|
_walkSoundId = -1;
|
|
|
|
}
|
|
|
|
|
2019-01-24 17:00:27 +01:00
|
|
|
if (_debugger->_isDebuggerOverlay) {
|
|
|
|
_debugger->drawDebuggerOverlay();
|
2017-04-02 18:17:43 +02:00
|
|
|
}
|
2019-01-24 17:00:27 +01:00
|
|
|
|
2018-05-07 19:17:13 +02:00
|
|
|
if (_debugger->_viewObstacles) {
|
|
|
|
_obstacles->draw();
|
|
|
|
}
|
2018-07-02 10:45:17 +03:00
|
|
|
|
2018-06-18 14:10:00 +03:00
|
|
|
_subtitles->tick(_surfaceFront);
|
2018-07-02 10:45:17 +03:00
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
blitToScreen(_surfaceFront);
|
2014-05-25 15:01:06 +02:00
|
|
|
_system->delayMillis(10);
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-20 22:55:31 +01:00
|
|
|
void BladeRunnerEngine::actorsUpdate() {
|
|
|
|
int actorCount = (int)_gameInfo->getActorCount();
|
|
|
|
int setId = _scene->getSetId();
|
|
|
|
|
2018-02-13 23:08:37 +01:00
|
|
|
if (setId != kSetUG18 || _gameVars[kVariableChapter] != 4 || !_gameFlags->query(670) || !_aiScripts->isInsideScript()) {
|
2017-03-20 22:55:31 +01:00
|
|
|
for (int i = 0; i < actorCount; i++) {
|
|
|
|
Actor *actor = _actors[i];
|
2018-02-25 19:31:52 +01:00
|
|
|
if (actor->getSetId() == setId || i == _actorUpdateCounter) {
|
2018-02-10 20:34:28 +01:00
|
|
|
_aiScripts->update(i);
|
2018-02-18 22:18:41 +01:00
|
|
|
actor->timersUpdate();
|
2017-03-20 22:55:31 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-25 19:31:52 +01:00
|
|
|
++_actorUpdateCounter;
|
|
|
|
if (_actorUpdateCounter >= actorCount) {
|
|
|
|
_actorUpdateCounter = 0;
|
|
|
|
}
|
2017-03-20 22:55:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::walkingReset() {
|
|
|
|
_mouseClickTimeLast = 0;
|
|
|
|
_mouseClickTimeDiff = 0;
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_isInsideScriptExit = false;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_isInsideScriptRegion = false;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_isInsideScriptObject = false;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_isInsideScriptItem = false;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToEmptyX = 0;
|
|
|
|
_walkingToEmptyY = 0;
|
|
|
|
_isInsideScriptEmpty = false;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
_isInsideScriptActor = false;
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
void BladeRunnerEngine::handleEvents() {
|
2016-09-10 18:16:17 +02:00
|
|
|
if (shouldQuit()) {
|
|
|
|
_gameIsRunning = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
Common::Event event;
|
|
|
|
Common::EventManager *eventMan = _system->getEventManager();
|
|
|
|
while (eventMan->pollEvent(event)) {
|
2016-09-10 18:16:17 +02:00
|
|
|
switch (event.type) {
|
2017-08-24 23:43:47 +02:00
|
|
|
case Common::EVENT_KEYUP:
|
|
|
|
handleKeyUp(event);
|
|
|
|
break;
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
handleKeyDown(event);
|
|
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONUP:
|
|
|
|
handleMouseAction(event.mouse.x, event.mouse.y, true, false);
|
|
|
|
break;
|
|
|
|
case Common::EVENT_RBUTTONUP:
|
|
|
|
case Common::EVENT_MBUTTONUP:
|
|
|
|
handleMouseAction(event.mouse.x, event.mouse.y, false, false);
|
|
|
|
break;
|
2016-10-03 12:38:43 +02:00
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
2017-08-24 23:43:47 +02:00
|
|
|
handleMouseAction(event.mouse.x, event.mouse.y, true, true);
|
|
|
|
break;
|
2016-10-03 12:38:43 +02:00
|
|
|
case Common::EVENT_RBUTTONDOWN:
|
2017-08-24 23:43:47 +02:00
|
|
|
case Common::EVENT_MBUTTONDOWN:
|
|
|
|
handleMouseAction(event.mouse.x, event.mouse.y, false, true);
|
|
|
|
break;
|
2016-10-03 12:38:43 +02:00
|
|
|
default:
|
2017-08-24 23:43:47 +02:00
|
|
|
; // nothing to do
|
2016-09-10 18:16:17 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-24 23:43:47 +02:00
|
|
|
void BladeRunnerEngine::handleKeyUp(Common::Event &event) {
|
|
|
|
if (event.kbd.keycode == Common::KEYCODE_RETURN) {
|
|
|
|
_speechSkipped = true;
|
|
|
|
}
|
2018-01-14 12:12:06 +01:00
|
|
|
|
2018-03-27 23:43:38 +02:00
|
|
|
if (_vqaIsPlaying) {
|
|
|
|
_vqaStopIsRequested = true;
|
|
|
|
_vqaIsPlaying = false;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
// TODO:
|
2018-01-14 12:12:06 +01:00
|
|
|
if (!playerHasControl() /*|| ActorInWalkingLoop*/) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_kia->isOpen()) {
|
2018-01-14 12:12:06 +01:00
|
|
|
_kia->handleKeyUp(event.kbd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_spinner->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_elevator->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_esper->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
if (_vk->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_dialogueMenu->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-25 16:52:48 +02:00
|
|
|
if (_scores->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
switch (event.kbd.keycode) {
|
|
|
|
case Common::KEYCODE_TAB:
|
|
|
|
_kia->openLastOpened();
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_ESCAPE:
|
|
|
|
_kia->open(kKIASectionSettings);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_SPACE:
|
|
|
|
// TODO: combat::switchCombatMode(&Combat);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
2017-08-24 23:43:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
|
2018-02-25 19:31:52 +01:00
|
|
|
if ((event.kbd.keycode == Common::KEYCODE_d) && (event.kbd.flags & Common::KBD_CTRL)) {
|
2019-01-09 23:06:10 +01:00
|
|
|
_time->pause();
|
2018-02-25 19:31:52 +01:00
|
|
|
getDebugger()->attach();
|
|
|
|
getDebugger()->onFrame();
|
2019-01-09 23:06:10 +01:00
|
|
|
|
|
|
|
_time->resume();
|
|
|
|
|
|
|
|
if (!_kia->isOpen() && !_spinner->isOpen() && !_elevator->isOpen() && !_esper->isOpen() && !_dialogueMenu->isOpen() && !_scores->isOpen()) {
|
|
|
|
_scene->resume();
|
|
|
|
}
|
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
//TODO:
|
2018-02-10 20:34:28 +01:00
|
|
|
if (!playerHasControl() /* || ActorWalkingLoop || ActorSpeaking || VqaIsPlaying */) {
|
2018-01-31 00:37:19 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_kia->isOpen()) {
|
2018-01-14 12:12:06 +01:00
|
|
|
_kia->handleKeyDown(event.kbd);
|
2018-12-05 18:18:13 +01:00
|
|
|
return;
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
2018-01-31 00:37:19 +01:00
|
|
|
|
|
|
|
if (_spinner->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_elevator->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_esper->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_dialogueMenu->isOpen()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-25 16:52:48 +02:00
|
|
|
if (_scores->isOpen()) {
|
2018-03-26 00:38:58 +02:00
|
|
|
_scores->handleKeyDown(event.kbd);
|
2018-03-25 16:52:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-01-31 00:37:19 +01:00
|
|
|
|
|
|
|
switch (event.kbd.keycode) {
|
|
|
|
case Common::KEYCODE_F1:
|
|
|
|
_kia->open(kKIASectionHelp);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F2:
|
|
|
|
_kia->open(kKIASectionSave);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F3:
|
|
|
|
_kia->open(kKIASectionLoad);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F4:
|
|
|
|
_kia->open(kKIASectionCrimes);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F5:
|
|
|
|
_kia->open(kKIASectionSuspects);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F6:
|
|
|
|
_kia->open(kKIASectionClues);
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_F10:
|
|
|
|
_kia->open(kKIASectionQuit);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-08-24 23:43:47 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseAction(int x, int y, bool mainButton, bool buttonDown) {
|
2018-03-06 00:07:42 +01:00
|
|
|
x = CLIP(x, 0, 639);
|
|
|
|
y = CLIP(y, 0, 479);
|
|
|
|
|
2018-12-15 22:40:07 +01:00
|
|
|
int timeNow = _time->current();
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (buttonDown) {
|
|
|
|
_mouseClickTimeDiff = timeNow - _mouseClickTimeLast;
|
|
|
|
_mouseClickTimeLast = timeNow;
|
|
|
|
}
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
if (!playerHasControl() || _mouse->isDisabled()) {
|
2016-09-10 18:16:17 +02:00
|
|
|
return;
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
|
|
|
|
2018-01-31 00:37:19 +01:00
|
|
|
if (_kia->isOpen()) {
|
2018-01-14 12:12:06 +01:00
|
|
|
if (buttonDown) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_kia->handleMouseDown(x, y, mainButton);
|
2018-01-14 12:12:06 +01:00
|
|
|
} else {
|
2018-02-18 22:18:41 +01:00
|
|
|
_kia->handleMouseUp(x, y, mainButton);
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2017-07-31 00:11:00 +02:00
|
|
|
if (_spinner->isOpen()) {
|
|
|
|
if (buttonDown) {
|
|
|
|
_spinner->handleMouseDown(x, y);
|
|
|
|
} else {
|
|
|
|
_spinner->handleMouseUp(x, y);
|
2018-01-31 00:37:19 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_esper->isOpen()) {
|
|
|
|
if (buttonDown) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_esper->handleMouseDown(x, y, mainButton);
|
2018-01-31 00:37:19 +01:00
|
|
|
} else {
|
2018-02-18 22:18:41 +01:00
|
|
|
_esper->handleMouseUp(x, y, mainButton);
|
2017-07-31 00:11:00 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-10 20:34:28 +01:00
|
|
|
if (_vk->isOpen()) {
|
|
|
|
if (buttonDown) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_vk->handleMouseDown(x, y, mainButton);
|
2018-02-10 20:34:28 +01:00
|
|
|
} else {
|
2018-02-18 22:18:41 +01:00
|
|
|
_vk->handleMouseUp(x, y, mainButton);
|
2018-02-10 20:34:28 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-24 22:34:40 +02:00
|
|
|
if (_elevator->isOpen()) {
|
|
|
|
if (buttonDown) {
|
|
|
|
_elevator->handleMouseDown(x, y);
|
|
|
|
} else {
|
|
|
|
_elevator->handleMouseUp(x, y);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-26 00:09:01 +02:00
|
|
|
if (_scores->isOpen()) {
|
|
|
|
if (buttonDown) {
|
|
|
|
_scores->handleMouseDown(x, y);
|
|
|
|
} else {
|
|
|
|
_scores->handleMouseUp(x, y);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-22 18:57:50 +02:00
|
|
|
if (_dialogueMenu->waitingForInput()) {
|
2018-02-18 22:18:41 +01:00
|
|
|
if (mainButton && !buttonDown) {
|
2017-08-22 18:57:50 +02:00
|
|
|
_dialogueMenu->mouseUp();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
if (mainButton) {
|
2017-09-10 20:19:02 +02:00
|
|
|
Vector3 scenePosition = _mouse->getXYZ(x, y);
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2018-02-05 18:46:09 +01:00
|
|
|
bool isClickable;
|
|
|
|
bool isObstacle;
|
|
|
|
bool isTarget;
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, scenePosition, true, false, true);
|
2017-08-24 23:43:47 +02:00
|
|
|
int exitIndex = _scene->_exits->getRegionAtXY(x, y);
|
2018-02-18 22:18:41 +01:00
|
|
|
int regionIndex = _scene->_regions->getRegionAtXY(x, y);
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2018-05-06 11:19:38 +02:00
|
|
|
if ((sceneObjectId < kSceneObjectOffsetActors || sceneObjectId >= kSceneObjectOffsetItems) && exitIndex >= 0) {
|
2018-02-18 22:18:41 +01:00
|
|
|
handleMouseClickExit(exitIndex, x, y, buttonDown);
|
|
|
|
} else if (regionIndex >= 0) {
|
|
|
|
handleMouseClickRegion(regionIndex, x, y, buttonDown);
|
|
|
|
} else if (sceneObjectId == -1) {
|
|
|
|
handleMouseClickEmpty(x, y, scenePosition, buttonDown);
|
|
|
|
} else if (sceneObjectId >= kSceneObjectOffsetActors && sceneObjectId < kSceneObjectOffsetItems) {
|
|
|
|
handleMouseClickActor(sceneObjectId - kSceneObjectOffsetActors, mainButton, buttonDown, scenePosition, x, y);
|
|
|
|
} else if (sceneObjectId >= kSceneObjectOffsetItems && sceneObjectId < kSceneObjectOffsetObjects) {
|
|
|
|
handleMouseClickItem(sceneObjectId - kSceneObjectOffsetItems, buttonDown);
|
|
|
|
} else if (sceneObjectId >= kSceneObjectOffsetObjects && sceneObjectId <= 293) {
|
|
|
|
handleMouseClick3DObject(sceneObjectId - kSceneObjectOffsetObjects, buttonDown, isClickable, isTarget);
|
2017-08-24 23:43:47 +02:00
|
|
|
}
|
2018-02-18 22:18:41 +01:00
|
|
|
} else if (buttonDown) {
|
2019-02-01 00:01:22 +01:00
|
|
|
if (_playerActor->mustReachWalkDestination()) {
|
2019-01-08 17:29:28 +01:00
|
|
|
if (!_isWalkingInterruptible) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-18 22:18:41 +01:00
|
|
|
_playerActor->stopWalking(false);
|
2019-01-08 17:29:28 +01:00
|
|
|
_interruptWalking = true;
|
2017-08-24 23:43:47 +02:00
|
|
|
}
|
2018-02-18 22:18:41 +01:00
|
|
|
_combat->change();
|
|
|
|
}
|
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClickExit(int exitId, int x, int y, bool buttonDown) {
|
|
|
|
debug("clicked on exit %d %d %d", exitId, x, y);
|
|
|
|
|
|
|
|
if (_isWalkingInterruptible && exitId != _walkingToExitId) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToExitId = exitId;
|
|
|
|
return;
|
2016-09-10 18:16:17 +02:00
|
|
|
}
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (buttonDown) {
|
|
|
|
return;
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
if (_isInsideScriptExit && exitId == _walkingToExitId) {
|
|
|
|
_playerActor->run();
|
|
|
|
if (_mouseClickTimeDiff <= 10000) {
|
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_walkingToExitId = exitId;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
|
|
|
|
_isInsideScriptExit = true;
|
|
|
|
_sceneScript->clickedOnExit(exitId);
|
|
|
|
_isInsideScriptExit = false;
|
|
|
|
}
|
2016-09-10 18:33:04 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClickRegion(int regionId, int x, int y, bool buttonDown) {
|
|
|
|
debug("clicked on region %d %d %d", regionId, x, y);
|
|
|
|
|
|
|
|
if (_isWalkingInterruptible && regionId != _walkingToRegionId) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToRegionId = regionId;
|
|
|
|
return;
|
|
|
|
}
|
2016-09-10 18:33:04 +02:00
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
if (buttonDown || _mouse->isInactive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInsideScriptRegion && regionId == _walkingToRegionId) {
|
|
|
|
_playerActor->run();
|
|
|
|
if (_mouseClickTimeDiff <= 10000) {
|
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_walkingToRegionId = regionId;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
|
|
|
|
_isInsideScriptRegion = true;
|
|
|
|
_sceneScript->clickedOn2DRegion(regionId);
|
|
|
|
_isInsideScriptRegion = false;
|
|
|
|
}
|
2016-09-10 18:33:04 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, bool isClickable, bool isTarget) {
|
2018-03-24 17:20:27 +01:00
|
|
|
const Common::String &objectName = _scene->objectGetName(objectId);
|
|
|
|
debug("Clicked on object %s", objectName.c_str());
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (_isWalkingInterruptible && objectId != _walkingToObjectId) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToObjectId = objectId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse->isInactive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_combat->isActive()) {
|
|
|
|
if (buttonDown || !isClickable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInsideScriptObject && objectId == _walkingToObjectId) {
|
|
|
|
_playerActor->run();
|
|
|
|
if (_mouseClickTimeDiff <= 10000) {
|
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_walkingToObjectId = objectId;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
|
|
|
|
_isInsideScriptObject = true;
|
2018-03-24 17:20:27 +01:00
|
|
|
_sceneScript->clickedOn3DObject(objectName.c_str(), false);
|
2018-02-18 22:18:41 +01:00
|
|
|
_isInsideScriptObject = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!buttonDown || !isTarget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_playerActor->stopWalking(false);
|
|
|
|
_playerActor->faceObject(objectName, false);
|
2018-03-17 16:40:33 +01:00
|
|
|
_playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
|
2018-02-18 22:18:41 +01:00
|
|
|
_settings->decreaseAmmo();
|
|
|
|
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
|
|
|
|
|
2018-03-25 03:02:56 +02:00
|
|
|
_mouse->setMouseJitterUp();
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
_isInsideScriptObject = true;
|
2018-03-24 17:20:27 +01:00
|
|
|
_sceneScript->clickedOn3DObject(objectName.c_str(), true);
|
2018-02-18 22:18:41 +01:00
|
|
|
_isInsideScriptObject = false;
|
|
|
|
}
|
2016-09-10 18:33:04 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClickEmpty(int x, int y, Vector3 &scenePosition, bool buttonDown) {
|
|
|
|
debug("Clicked on nothing %f, %f, %f", scenePosition.x, scenePosition.y, scenePosition.z);
|
|
|
|
|
|
|
|
if (_isWalkingInterruptible) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_isInsideScriptEmpty = true;
|
2018-02-10 20:34:28 +01:00
|
|
|
bool sceneMouseClick = _sceneScript->mouseClick(x, y);
|
2018-02-18 22:18:41 +01:00
|
|
|
_isInsideScriptEmpty = false;
|
2017-09-10 20:19:02 +02:00
|
|
|
|
|
|
|
if (sceneMouseClick) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
int actorId = Actor::findTargetUnderMouse(this, x, y);
|
|
|
|
int itemId = _items->findTargetUnderMouse(x, y);
|
|
|
|
|
2018-02-19 22:04:44 +01:00
|
|
|
if (_combat->isActive() && buttonDown && (actorId > 0 || itemId > 0)) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_playerActor->stopWalking(false);
|
|
|
|
if (actorId > 0) {
|
|
|
|
_playerActor->faceActor(actorId, false);
|
|
|
|
} else {
|
|
|
|
_playerActor->faceItem(itemId, false);
|
|
|
|
}
|
2018-03-17 16:40:33 +01:00
|
|
|
_playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
|
2018-02-18 22:18:41 +01:00
|
|
|
_settings->decreaseAmmo();
|
|
|
|
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getMissSound()), 100, 0, 0, 90, 0);
|
|
|
|
|
2018-03-25 03:02:56 +02:00
|
|
|
_mouse->setMouseJitterUp();
|
2018-02-18 22:18:41 +01:00
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
if (actorId > 0) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_aiScripts->shotAtAndMissed(actorId);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (buttonDown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_walkingToEmpty = true;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
|
|
|
|
if (_combat->isActive() && (actorId > 0 || itemId > 0)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int xDist = abs(_walkingToEmptyX - x);
|
|
|
|
int yDist = abs(_walkingToEmptyY - y);
|
|
|
|
|
|
|
|
_walkingToEmptyX = x;
|
|
|
|
_walkingToEmptyY = y;
|
|
|
|
|
|
|
|
bool inWalkbox = false;
|
|
|
|
float altitude = _scene->_set->getAltitudeAtXZ(scenePosition.x, scenePosition.z, &inWalkbox);
|
|
|
|
|
|
|
|
if (!inWalkbox || scenePosition.y >= altitude + 6.0f) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-18 22:44:28 +01:00
|
|
|
bool shouldRun = _playerActor->isRunning();
|
2018-02-18 22:18:41 +01:00
|
|
|
if (_mouseClickTimeDiff <= 10000 && xDist < 10 && yDist < 10) {
|
2018-02-18 22:44:28 +01:00
|
|
|
shouldRun = true;
|
2018-02-18 22:18:41 +01:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:44:28 +01:00
|
|
|
_playerActor->walkTo(shouldRun, scenePosition, false);
|
2018-02-18 22:18:41 +01:00
|
|
|
|
2018-02-18 22:44:28 +01:00
|
|
|
if (shouldRun && _playerActor->isWalking()) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
}
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClickItem(int itemId, bool buttonDown) {
|
2016-09-10 18:33:04 +02:00
|
|
|
debug("Clicked on item %d", itemId);
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (_isWalkingInterruptible && itemId != _walkingToItemId) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToItemId = itemId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse->isInactive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_combat->isActive()) {
|
|
|
|
if (buttonDown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInsideScriptItem && itemId == _walkingToItemId) {
|
|
|
|
_playerActor->run();
|
|
|
|
if (_mouseClickTimeDiff <= 10000) {
|
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_walkingToItemId = itemId;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToActorId = -1;
|
|
|
|
|
|
|
|
_isInsideScriptItem = true;
|
|
|
|
_sceneScript->clickedOnItem(itemId, false);
|
|
|
|
_isInsideScriptItem = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!buttonDown || !_items->isTarget(itemId) /* || _mouse->isRandomized() */) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_playerActor->stopWalking(false);
|
|
|
|
_playerActor->faceItem(itemId, false);
|
2018-03-17 16:40:33 +01:00
|
|
|
_playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
|
2018-02-18 22:18:41 +01:00
|
|
|
_settings->decreaseAmmo();
|
|
|
|
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
|
|
|
|
|
2018-03-25 03:02:56 +02:00
|
|
|
_mouse->setMouseJitterUp();
|
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
_isInsideScriptItem = true;
|
|
|
|
_sceneScript->clickedOnItem(itemId, true);
|
|
|
|
_isInsideScriptItem = false;
|
|
|
|
}
|
2016-09-10 18:33:04 +02:00
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
|
2018-02-18 22:18:41 +01:00
|
|
|
void BladeRunnerEngine::handleMouseClickActor(int actorId, bool mainButton, bool buttonDown, Vector3 &scenePosition, int x, int y) {
|
2016-09-10 18:33:04 +02:00
|
|
|
debug("Clicked on actor %d", actorId);
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (_isWalkingInterruptible && actorId != _walkingToActorId) {
|
|
|
|
_isWalkingInterruptible = false;
|
|
|
|
_interruptWalking = true;
|
|
|
|
walkingReset();
|
|
|
|
_walkingToActorId = actorId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouse->isInactive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!buttonDown) {
|
|
|
|
if (actorId == kActorMcCoy) {
|
|
|
|
if (mainButton) {
|
|
|
|
if (!_combat->isActive()) {
|
|
|
|
_kia->openLastOpened();
|
|
|
|
}
|
2019-02-01 00:01:22 +01:00
|
|
|
} else if (!_playerActor->mustReachWalkDestination()) {
|
2018-02-18 22:18:41 +01:00
|
|
|
_combat->change();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInsideScriptActor && actorId == _walkingToActorId) {
|
|
|
|
_playerActor->run();
|
|
|
|
if (_mouseClickTimeDiff <= 10000) {
|
|
|
|
_playerActor->increaseFPS();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_walkingToExitId = -1;
|
|
|
|
_walkingToRegionId = -1;
|
|
|
|
_walkingToObjectId = -1;
|
|
|
|
_walkingToItemId = -1;
|
|
|
|
_walkingToEmpty = false;
|
|
|
|
_walkingToActorId = actorId;
|
|
|
|
|
|
|
|
_isInsideScriptActor = true;
|
|
|
|
bool processedBySceneScript = _sceneScript->clickedOnActor(actorId);
|
|
|
|
_isInsideScriptActor = false;
|
|
|
|
|
|
|
|
if (!_combat->isActive() && !processedBySceneScript) {
|
|
|
|
_aiScripts->clickedByPlayer(actorId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2018-03-17 16:40:33 +01:00
|
|
|
Actor *actor = _actors[actorId];
|
|
|
|
|
|
|
|
if (!_combat->isActive() || actorId == kActorMcCoy || !actor->isTarget() || actor->isRetired() /*|| _mouse->isRandomized()*/) {
|
2018-02-18 22:18:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_playerActor->stopWalking(false);
|
|
|
|
_playerActor->faceActor(actorId, false);
|
2018-03-17 16:40:33 +01:00
|
|
|
_playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
|
2018-02-18 22:18:41 +01:00
|
|
|
_settings->decreaseAmmo();
|
|
|
|
|
2018-03-17 16:40:33 +01:00
|
|
|
bool missed = _playerActor->isObstacleBetween(actor->getXYZ());
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
_audioPlayer->playAud(_gameInfo->getSfxTrack(missed ? _combat->getMissSound() : _combat->getHitSound()), 100, 0, 0, 90, 0);
|
|
|
|
|
2018-03-25 03:02:56 +02:00
|
|
|
_mouse->setMouseJitterUp();
|
2018-02-18 22:18:41 +01:00
|
|
|
|
|
|
|
if (missed) {
|
|
|
|
_aiScripts->shotAtAndMissed(actorId);
|
|
|
|
} else {
|
|
|
|
_isInsideScriptActor = true;
|
|
|
|
bool canShoot = _aiScripts->shotAtAndHit(actorId);
|
|
|
|
_isInsideScriptActor = false;
|
|
|
|
if (!canShoot) {
|
|
|
|
_combat->shoot(actorId, scenePosition, x);
|
|
|
|
}
|
|
|
|
}
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
}
|
|
|
|
|
2015-09-19 01:43:38 +02:00
|
|
|
void BladeRunnerEngine::gameWaitForActive() {
|
2016-10-12 23:00:33 +02:00
|
|
|
while (!_windowIsActive) {
|
2015-09-19 01:43:38 +02:00
|
|
|
handleEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 19:33:35 +01:00
|
|
|
void BladeRunnerEngine::loopActorSpeaking() {
|
2017-08-24 23:43:47 +02:00
|
|
|
if (!_audioSpeech->isPlaying()) {
|
2015-02-10 19:33:35 +01:00
|
|
|
return;
|
2017-08-24 23:43:47 +02:00
|
|
|
}
|
2015-02-10 19:33:35 +01:00
|
|
|
|
2015-05-01 10:13:30 +02:00
|
|
|
playerLosesControl();
|
2015-02-10 19:33:35 +01:00
|
|
|
|
|
|
|
do {
|
|
|
|
gameTick();
|
2016-09-10 18:16:17 +02:00
|
|
|
} while (_gameIsRunning && _audioSpeech->isPlaying());
|
2015-02-10 19:33:35 +01:00
|
|
|
|
2015-05-01 10:13:30 +02:00
|
|
|
playerGainsControl();
|
2015-02-10 19:33:35 +01:00
|
|
|
}
|
|
|
|
|
2014-05-17 17:13:49 +02:00
|
|
|
void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
|
2014-05-16 21:58:49 +02:00
|
|
|
Common::String name = _gameInfo->getOuttake(id);
|
|
|
|
|
2014-05-17 17:13:49 +02:00
|
|
|
OuttakePlayer player(this);
|
2014-05-16 21:58:49 +02:00
|
|
|
|
2015-02-06 15:31:43 +01:00
|
|
|
player.play(name, noLocalization, container);
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool BladeRunnerEngine::openArchive(const Common::String &name) {
|
2018-01-28 11:14:29 +01:00
|
|
|
int i;
|
2014-05-16 21:58:49 +02:00
|
|
|
|
|
|
|
// If archive is already open, return true
|
|
|
|
for (i = 0; i != kArchiveCount; ++i) {
|
2018-01-14 12:12:06 +01:00
|
|
|
if (_archives[i].isOpen() && _archives[i].getName() == name) {
|
2014-05-16 21:58:49 +02:00
|
|
|
return true;
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find first available slot
|
|
|
|
for (i = 0; i != kArchiveCount; ++i) {
|
2018-01-14 12:12:06 +01:00
|
|
|
if (!_archives[i].isOpen()) {
|
2014-05-16 21:58:49 +02:00
|
|
|
break;
|
2018-01-14 12:12:06 +01:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
if (i == kArchiveCount) {
|
|
|
|
/* TODO: BLADE.EXE retires the least recently used
|
|
|
|
* archive when it runs out of slots. */
|
|
|
|
|
|
|
|
error("openArchive: No more archive slots");
|
|
|
|
}
|
|
|
|
|
|
|
|
_archives[i].open(name);
|
|
|
|
return _archives[i].isOpen();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BladeRunnerEngine::closeArchive(const Common::String &name) {
|
2018-01-28 11:14:29 +01:00
|
|
|
for (int i = 0; i != kArchiveCount; ++i) {
|
2016-10-12 23:00:33 +02:00
|
|
|
if (_archives[i].isOpen() && _archives[i].getName() == name) {
|
2014-05-16 21:58:49 +02:00
|
|
|
_archives[i].close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug("closeArchive: Archive %s not open.", name.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-14 12:12:06 +01:00
|
|
|
bool BladeRunnerEngine::isArchiveOpen(const Common::String &name) const {
|
2018-01-28 11:14:29 +01:00
|
|
|
for (int i = 0; i != kArchiveCount; ++i) {
|
2016-10-12 23:00:33 +02:00
|
|
|
if (_archives[i].isOpen() && _archives[i].getName() == name)
|
2014-05-16 21:58:49 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-02 10:45:17 +03:00
|
|
|
void BladeRunnerEngine::syncSoundSettings() {
|
|
|
|
Engine::syncSoundSettings();
|
|
|
|
|
|
|
|
_subtitlesEnabled = ConfMan.getBool("subtitles");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BladeRunnerEngine::isSubtitlesEnabled() {
|
|
|
|
return _subtitlesEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::setSubtitlesEnabled(bool newVal) {
|
|
|
|
ConfMan.setBool("subtitles", newVal);
|
2018-07-02 10:58:24 +03:00
|
|
|
syncSoundSettings();
|
2018-07-02 10:45:17 +03:00
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::String &name) {
|
2018-01-28 11:14:29 +01:00
|
|
|
for (int i = 0; i != kArchiveCount; ++i) {
|
2017-09-10 20:19:02 +02:00
|
|
|
if (!_archives[i].isOpen()) {
|
2014-05-16 21:58:49 +02:00
|
|
|
continue;
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2018-04-07 22:22:21 +02:00
|
|
|
|
2017-09-10 20:19:02 +02:00
|
|
|
if (false) {
|
2014-05-16 21:58:49 +02:00
|
|
|
debug("getResource: Searching archive %s for %s.", _archives[i].getName().c_str(), name.c_str());
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2018-04-07 22:22:21 +02:00
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
Common::SeekableReadStream *stream = _archives[i].createReadStreamForMember(name);
|
2017-09-10 20:19:02 +02:00
|
|
|
if (stream) {
|
2014-05-16 21:58:49 +02:00
|
|
|
return stream;
|
2017-09-10 20:19:02 +02:00
|
|
|
}
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2018-03-06 00:07:42 +01:00
|
|
|
warning("getResource: Resource %s not found", name.c_str());
|
2017-08-24 23:43:47 +02:00
|
|
|
return nullptr;
|
2014-05-16 21:58:49 +02:00
|
|
|
}
|
|
|
|
|
2015-05-01 10:13:30 +02:00
|
|
|
bool BladeRunnerEngine::playerHasControl() {
|
|
|
|
return _playerLosesControlCounter == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::playerLosesControl() {
|
|
|
|
if (++_playerLosesControlCounter == 1) {
|
|
|
|
_mouse->disable();
|
|
|
|
}
|
2016-09-10 18:16:17 +02:00
|
|
|
// debug("Player Lost Control (%d)", _playerLosesControlCounter);
|
2015-05-01 10:13:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::playerGainsControl() {
|
|
|
|
if (_playerLosesControlCounter == 0) {
|
|
|
|
warning("Unbalanced call to BladeRunnerEngine::playerGainsControl");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_playerLosesControlCounter > 0)
|
|
|
|
--_playerLosesControlCounter;
|
|
|
|
|
2016-09-10 18:16:17 +02:00
|
|
|
// debug("Player Gained Control (%d)", _playerLosesControlCounter);
|
2015-05-01 10:13:30 +02:00
|
|
|
|
|
|
|
if (_playerLosesControlCounter == 0) {
|
|
|
|
_mouse->enable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-08 19:25:27 +01:00
|
|
|
void BladeRunnerEngine::playerDied() {
|
|
|
|
playerLosesControl();
|
|
|
|
|
|
|
|
int timeWaitEnd = _time->current() + 5000;
|
|
|
|
while (_time->current() < timeWaitEnd) {
|
|
|
|
gameTick();
|
|
|
|
}
|
|
|
|
|
|
|
|
_actorDialogueQueue->flush(1, false);
|
|
|
|
|
|
|
|
while (_playerLosesControlCounter > 0) {
|
|
|
|
playerGainsControl();
|
|
|
|
}
|
|
|
|
|
|
|
|
_kia->_forceOpen = true;
|
|
|
|
_kia->open(kKIASectionLoad);
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const Graphics::Surface &thumbnail) {
|
2018-03-17 16:14:48 +01:00
|
|
|
if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-11-24 08:55:21 +01:00
|
|
|
Common::MemoryWriteStreamDynamic memoryStream(DisposeAfterUse::YES);
|
2018-11-21 23:16:15 +01:00
|
|
|
SaveFileWriteStream s(memoryStream);
|
2018-03-17 16:14:48 +01:00
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
s.write(thumbnail.getPixels(), SaveFileManager::kThumbnailSize);
|
2018-11-21 23:16:15 +01:00
|
|
|
s.writeFloat(1.0f);
|
2018-03-17 16:14:48 +01:00
|
|
|
_settings->save(s);
|
|
|
|
_scene->save(s);
|
|
|
|
_scene->_exits->save(s);
|
|
|
|
_scene->_regions->save(s);
|
|
|
|
_scene->_set->save(s);
|
|
|
|
for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) {
|
2018-03-24 17:20:27 +01:00
|
|
|
s.writeInt(_gameVars[i]);
|
2018-03-17 16:14:48 +01:00
|
|
|
}
|
2018-03-24 17:20:27 +01:00
|
|
|
_music->save(s);
|
2018-03-17 16:14:48 +01:00
|
|
|
// _audioPlayer->save(s) // zero func
|
|
|
|
// _audioSpeech->save(s) // zero func
|
|
|
|
_combat->save(s);
|
|
|
|
_gameFlags->save(s);
|
|
|
|
_items->save(s);
|
|
|
|
_sceneObjects->save(s);
|
|
|
|
_ambientSounds->save(s);
|
|
|
|
_overlays->save(s);
|
|
|
|
_spinner->save(s);
|
2018-03-25 16:52:48 +02:00
|
|
|
_scores->save(s);
|
2018-03-17 16:14:48 +01:00
|
|
|
_dialogueMenu->save(s);
|
|
|
|
_obstacles->save(s);
|
|
|
|
_actorDialogueQueue->save(s);
|
|
|
|
_waypoints->save(s);
|
|
|
|
|
|
|
|
for (uint i = 0; i != _gameInfo->getActorCount(); ++i) {
|
|
|
|
_actors[i]->save(s);
|
|
|
|
|
2018-03-24 17:20:27 +01:00
|
|
|
int animationState, animationFrame, animationStateNext, nextAnimation;
|
|
|
|
_aiScripts->queryAnimationState(i, &animationState, &animationFrame, &animationStateNext, &nextAnimation);
|
|
|
|
s.writeInt(animationState);
|
|
|
|
s.writeInt(animationFrame);
|
|
|
|
s.writeInt(animationStateNext);
|
|
|
|
s.writeInt(nextAnimation);
|
2018-03-17 16:14:48 +01:00
|
|
|
}
|
|
|
|
_actors[kActorVoiceOver]->save(s);
|
|
|
|
_policeMaze->save(s);
|
|
|
|
_crimesDatabase->save(s);
|
|
|
|
|
|
|
|
s.finalize();
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
stream.writeUint32LE(memoryStream.size() + 4);
|
|
|
|
stream.write(memoryStream.getData(), memoryStream.size());
|
|
|
|
stream.flush();
|
2018-03-24 17:20:27 +01:00
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
return true;
|
2018-03-17 16:14:48 +01:00
|
|
|
}
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
bool BladeRunnerEngine::loadGame(Common::SeekableReadStream &stream) {
|
2018-03-24 17:20:27 +01:00
|
|
|
if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
|
2018-11-21 23:16:15 +01:00
|
|
|
return false;
|
2018-03-24 17:20:27 +01:00
|
|
|
}
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
SaveFileReadStream s(stream);
|
2018-03-24 17:20:27 +01:00
|
|
|
|
|
|
|
_ambientSounds->removeAllNonLoopingSounds(true);
|
|
|
|
_ambientSounds->removeAllLoopingSounds(1);
|
|
|
|
_music->stop(2);
|
|
|
|
_audioSpeech->stopSpeech();
|
|
|
|
_actorDialogueQueue->flush(true, false);
|
2018-11-21 23:16:15 +01:00
|
|
|
_screenEffects->_entries.clear();
|
2018-03-24 17:20:27 +01:00
|
|
|
|
|
|
|
int size = s.readInt();
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
if (size != s.size() - s.pos() + 4) {
|
|
|
|
_gameIsLoading = false;
|
|
|
|
return false;
|
2018-03-24 17:20:27 +01:00
|
|
|
}
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
_gameIsLoading = true;
|
|
|
|
_settings->setLoadingGame();
|
2018-11-25 21:47:00 +01:00
|
|
|
s.skip(SaveFileManager::kThumbnailSize); // skip the thumbnail
|
2018-11-21 23:16:15 +01:00
|
|
|
s.skip(4);// always float 1.0, but never used
|
2018-03-24 17:20:27 +01:00
|
|
|
_settings->load(s);
|
|
|
|
_scene->load(s);
|
|
|
|
_scene->_exits->load(s);
|
|
|
|
_scene->_regions->load(s);
|
|
|
|
_scene->_set->load(s);
|
|
|
|
for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) {
|
|
|
|
_gameVars[i] = s.readInt();
|
|
|
|
}
|
|
|
|
_music->load(s);
|
|
|
|
// _audioPlayer->load(s) // zero func
|
|
|
|
// _audioSpeech->load(s) // zero func
|
|
|
|
_combat->load(s);
|
|
|
|
_gameFlags->load(s);
|
|
|
|
_items->load(s);
|
|
|
|
_sceneObjects->load(s);
|
|
|
|
_ambientSounds->load(s);
|
|
|
|
_overlays->load(s);
|
|
|
|
_spinner->load(s);
|
2018-03-25 16:52:48 +02:00
|
|
|
_scores->load(s);
|
2018-03-24 17:20:27 +01:00
|
|
|
_dialogueMenu->load(s);
|
|
|
|
_obstacles->load(s);
|
|
|
|
_actorDialogueQueue->load(s);
|
|
|
|
_waypoints->load(s);
|
|
|
|
for (uint i = 0; i != _gameInfo->getActorCount(); ++i) {
|
|
|
|
_actors[i]->load(s);
|
|
|
|
|
|
|
|
int animationState = s.readInt();
|
|
|
|
int animationFrame = s.readInt();
|
|
|
|
int animationStateNext = s.readInt();
|
|
|
|
int nextAnimation = s.readInt();
|
|
|
|
_aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation);
|
|
|
|
}
|
|
|
|
_actors[kActorVoiceOver]->load(s);
|
|
|
|
_policeMaze->load(s);
|
|
|
|
_crimesDatabase->load(s);
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
_gameIsLoading = false;
|
|
|
|
|
2018-03-24 17:20:27 +01:00
|
|
|
_settings->setNewSetAndScene(_settings->getSet(), _settings->getScene());
|
|
|
|
_settings->setChapter(_settings->getChapter());
|
2018-11-21 23:16:15 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::newGame(int difficulty) {
|
|
|
|
_settings->reset();
|
|
|
|
_combat->reset();
|
|
|
|
|
|
|
|
for (uint i = 0; i < _gameInfo->getActorCount(); ++i) {
|
|
|
|
_actors[i]->setup(i);
|
|
|
|
}
|
|
|
|
_actors[kActorVoiceOver]->setup(99);
|
|
|
|
|
|
|
|
for (uint i = 0; i < _gameInfo->getSuspectCount(); ++i) {
|
|
|
|
_suspectsDatabase->get(i)->reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
_gameFlags->clear();
|
|
|
|
|
|
|
|
_gameInfo->getGlobalVarCount();
|
|
|
|
|
|
|
|
for (uint i = 0; i < _gameInfo->getGlobalVarCount(); ++i) {
|
|
|
|
_gameVars[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_items->reset();
|
|
|
|
_scores->reset();
|
|
|
|
_kia->reset();
|
|
|
|
_dialogueMenu->clear();
|
|
|
|
_scene->_exits->enable();
|
|
|
|
|
|
|
|
if (difficulty >= 0 && difficulty < 3) {
|
|
|
|
_settings->setDifficulty(difficulty);
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
InitScript initScript(this);
|
|
|
|
initScript.SCRIPT_Initialize_Game();
|
|
|
|
initChapterAndScene();
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
_settings->setStartingGame();
|
2018-03-24 17:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void BladeRunnerEngine::ISez(const Common::String &str) {
|
|
|
|
debug("\t%s", str.c_str());
|
2014-05-25 19:56:03 +02:00
|
|
|
}
|
|
|
|
|
2018-11-21 23:16:15 +01:00
|
|
|
void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) const {
|
2017-08-04 21:40:09 +02:00
|
|
|
_system->copyRectToScreen(src.getPixels(), src.pitch, 0, 0, src.w, src.h);
|
|
|
|
_system->updateScreen();
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
Graphics::Surface BladeRunnerEngine::generateThumbnail() const {
|
|
|
|
Graphics::Surface thumbnail;
|
|
|
|
thumbnail.create(640 / 8, 480 / 8, createRGB555());
|
|
|
|
|
|
|
|
for (int y = 0; y < thumbnail.h; ++y) {
|
|
|
|
for (int x = 0; x < thumbnail.w; ++x) {
|
|
|
|
uint16 *dstPixel = (uint16 *)thumbnail.getBasePtr(x, y);
|
|
|
|
const uint16 *srcPixel = (const uint16 *)_surfaceFront.getBasePtr(x * 8, y * 8);
|
2018-11-21 23:16:15 +01:00
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
*dstPixel = *srcPixel;
|
2018-11-21 23:16:15 +01:00
|
|
|
}
|
|
|
|
}
|
2018-11-25 21:47:00 +01:00
|
|
|
|
|
|
|
return thumbnail;
|
2018-11-21 23:16:15 +01:00
|
|
|
}
|
|
|
|
|
2018-02-25 19:31:52 +01:00
|
|
|
GUI::Debugger *BladeRunnerEngine::getDebugger() {
|
|
|
|
return _debugger;
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:47:00 +01:00
|
|
|
Common::String BladeRunnerEngine::getTargetName() const {
|
|
|
|
return _targetName;
|
|
|
|
}
|
|
|
|
|
2017-08-04 21:40:09 +02:00
|
|
|
void blit(const Graphics::Surface &src, Graphics::Surface &dst) {
|
|
|
|
dst.copyRectToSurface(src.getPixels(), src.pitch, 0, 0, src.w, src.h);
|
|
|
|
}
|
|
|
|
|
2014-05-16 21:58:49 +02:00
|
|
|
} // End of namespace BladeRunner
|