BLADERUNNER: Make the cut content a runtime option

Player can choose to use or not the restored cut content.
Does not affect fixed bugs in original game.
This commit is contained in:
Peter Kohaut 2019-04-25 23:39:31 +02:00
parent 620864293d
commit ee2dcf6375
13 changed files with 774 additions and 766 deletions

View file

@ -111,6 +111,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
_sitcomMode = false;
_shortyMode = false;
_cutContent = true;
_playerLosesControlCounter = 0;
@ -443,6 +444,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
_sitcomMode = ConfMan.getBool("sitcom");
_shortyMode = ConfMan.getBool("shorty");
_cutContent = ConfMan.getBool("cutcontent");
_items = new Items(this);

View file

@ -39,8 +39,6 @@
#define BLADERUNNER_DEBUG_CONSOLE 0
#define BLADERUNNER_ORIGINAL_SETTINGS 0
#define BLADERUNNER_ORIGINAL_BUGS 0
#define BLADERUNNER_RESTORED_CUT_CONTENT 1
namespace Common {
struct Event;
@ -113,9 +111,10 @@ public:
static const int kActorCount = 100;
static const int kActorVoiceOver = kActorCount - 1;
bool _gameIsRunning;
bool _windowIsActive;
int _playerLosesControlCounter;
bool _gameIsRunning;
bool _windowIsActive;
int _playerLosesControlCounter;
Common::String _languageCode;
Common::Language _language;
@ -203,6 +202,7 @@ public:
bool _subtitlesEnabled; // tracks the state of whether subtitles are enabled or disabled from ScummVM GUI option or KIA checkbox (the states are synched)
bool _sitcomMode;
bool _shortyMode;
bool _cutContent;
int _walkSoundId;
int _walkSoundVolume;

View file

@ -59,6 +59,15 @@ static const ADExtraGuiOptionsMap optionsList[] = {
false
}
},
{
GAMEOPTION_CUT_CONTENT,
{
_s("Restore cut content"),
_s("Restore content which was cut from the original game"),
"cutcontent",
true
}
},
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};

View file

@ -27,6 +27,7 @@
#define GAMEOPTION_SITCOM GUIO_GAMEOPTIONS1
#define GAMEOPTION_SHORTY GUIO_GAMEOPTIONS2
#define GAMEOPTION_CUT_CONTENT GUIO_GAMEOPTIONS3
namespace BladeRunner {
@ -39,7 +40,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
// BladeRunner (German)
@ -50,7 +51,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
// BladeRunner (French) - Bug #9722
@ -61,7 +62,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
// BladeRunner (Italian)
@ -72,7 +73,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
// BladeRunner (Russian)
@ -83,7 +84,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
// BladeRunner (Russian - alternate version)
@ -94,7 +95,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
@ -106,7 +107,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO2(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY)
GUIO3(GAMEOPTION_SITCOM, GAMEOPTION_SHORTY, GAMEOPTION_CUT_CONTENT)
},
AD_TABLE_END_MARKER

View file

@ -191,11 +191,9 @@ bool AIScriptMoraji::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case kGoalMorajiDie:
// Added check here to have Moraji death speech SFX
// when shot by McCoy outside the Dermo Design Lab
if (Game_Flag_Query(kFlagDR04McCoyShotMoraji)) {
#if BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent && Game_Flag_Query(kFlagDR04McCoyShotMoraji)) {
// original code used no voice here
Sound_Play_Speech_Line(kActorMoraji, 9020, 50, 0, 50); // Use Moraji's death SPCHSFX, also lower volume
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
}
_animationFrame = -1;
_animationState = 13;

View file

@ -1180,10 +1180,10 @@ bool AIScriptZuben::ChangeAnimationMode(int mode) {
break;
case kAnimationModeDie:
Actor_Set_Targetable(kActorZuben, false);
#if BLADERUNNER_RESTORED_CUT_CONTENT
// original code used no voice here
Sound_Play_Speech_Line(kActorZuben, 9020, 75, 0, 99); // add Zuben's death rattle here
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
// original code used no voice here
Sound_Play_Speech_Line(kActorZuben, 9020, 75, 0, 99); // add Zuben's death rattle here
}
switch (_animationState) {
case 2:
case 4:

View file

@ -2247,9 +2247,9 @@ void InitScript::Init_SDB() {
SDB_Add_Whereabouts_Clue(kSuspectClovis, kClueChewInterview);
SDB_Add_Replicant_Clue(kSuspectClovis, kClueOfficersStatement);
SDB_Add_Replicant_Clue(kSuspectClovis, kClueDoorForced2);
#if BLADERUNNER_RESTORED_CUT_CONTENT
SDB_Add_Replicant_Clue(kSuspectClovis, kClueDoorForced1);
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
SDB_Add_Replicant_Clue(kSuspectClovis, kClueDoorForced1);
}
SDB_Add_Replicant_Clue(kSuspectClovis, kClueMorajiInterview);
SDB_Add_Replicant_Clue(kSuspectClovis, kClueZubenTalksAboutLucy1);
SDB_Add_Replicant_Clue(kSuspectClovis, kClueZubenTalksAboutLucy2);
@ -2278,9 +2278,9 @@ void InitScript::Init_SDB() {
SDB_Add_Whereabouts_Clue(kSuspectZuben, kClueRuncitersViewB);
SDB_Add_Replicant_Clue(kSuspectZuben, kClueOfficersStatement);
SDB_Add_Replicant_Clue(kSuspectZuben, kClueDoorForced2);
#if BLADERUNNER_RESTORED_CUT_CONTENT
SDB_Add_Replicant_Clue(kSuspectZuben, kClueDoorForced1);
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
SDB_Add_Replicant_Clue(kSuspectZuben, kClueDoorForced1);
}
SDB_Add_Replicant_Clue(kSuspectZuben, kClueHowieLeeInterview);
SDB_Add_Replicant_Clue(kSuspectZuben, kClueZubenRunsAway);
SDB_Add_Replicant_Clue(kSuspectZuben, kClueZuben);
@ -2490,9 +2490,9 @@ void InitScript::Init_CDB() {
CDB_Set_Clue_Asset_Type(kClueOfficersStatement, kClueTypeAudioRecording);
CDB_Set_Clue_Asset_Type(kClueDoorForced2, kClueTypeAudioRecording);
#if BLADERUNNER_RESTORED_CUT_CONTENT
CDB_Set_Clue_Asset_Type(kClueDoorForced1, kClueTypeAudioRecording);
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
CDB_Set_Clue_Asset_Type(kClueDoorForced1, kClueTypeAudioRecording);
}
CDB_Set_Clue_Asset_Type(kClueLimpingFootprints, kClueTypeAudioRecording);
CDB_Set_Clue_Asset_Type(kClueGracefulFootprints, kClueTypeAudioRecording);
CDB_Set_Clue_Asset_Type(kClueShellCasings, kClueTypeObject);

View file

@ -45,11 +45,11 @@ void KIAScript::SCRIPT_KIA_DLL_Play_Clue_Asset_Script(int notUsed, int clueId) {
case kClueDoorForced2:
KIA_Play_Actor_Dialogue(kActorOfficerLeary, 0);
break;
#if BLADERUNNER_RESTORED_CUT_CONTENT
case kClueDoorForced1:
KIA_Play_Actor_Dialogue(kActorVoiceOver, 1870);
if (_vm->_cutContent) {
KIA_Play_Actor_Dialogue(kActorVoiceOver, 1870);
}
break;
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
case kClueLimpingFootprints:
KIA_Play_Actor_Dialogue(kActorVoiceOver, 1970);
KIA_Play_Actor_Dialogue(kActorVoiceOver, 1980);

View file

@ -63,25 +63,25 @@ void SceneScriptCT01::InitializeScene() {
}
}
} else if (Game_Flag_Query(kFlagSpinnerAtCT01)) {
#if BLADERUNNER_RESTORED_CUT_CONTENT
// 0. This scene is not available in chapters 4 and 5
// 1. Add open/close spinner door animation and sound
// 2. Keep walkers from messing about with the scene (popping up or overlapping with landing) until spinner has landed
// Note: kFlagSpinnerAtCT01 reset (original) is not handled the same was as in NR01 but it still works
// Note 2: Gordo sitting at the diner overlaps with the counter bar in front of him
// so the loop will be prevented from playing when he is there.
if ( Global_Variable_Query(kVariableChapter) < 4
&& Actor_Query_Which_Set_In(kActorGordo) != kSetCT01_CT12
&& Random_Query(1, 3) == 1
){
Scene_Loop_Start_Special(kSceneLoopModeLoseControl, kCT01LoopInshot, false);
if (_vm->_cutContent) {
// 0. This scene is not available in chapters 4 and 5
// 1. Add open/close spinner door animation and sound
// 2. Keep walkers from messing about with the scene (popping up or overlapping with landing) until spinner has landed
// Note: kFlagSpinnerAtCT01 reset (original) is not handled the same was as in NR01 but it still works
// Note 2: Gordo sitting at the diner overlaps with the counter bar in front of him
// so the loop will be prevented from playing when he is there.
if ( Global_Variable_Query(kVariableChapter) < 4
&& Actor_Query_Which_Set_In(kActorGordo) != kSetCT01_CT12
&& Random_Query(1, 3) == 1
){
Scene_Loop_Start_Special(kSceneLoopModeLoseControl, kCT01LoopInshot, false);
}
// Pause generic walkers outside special loop
// so that they're always paused when McCoy enters (less chance to collide with him)
// There's also another flag called kFlagUnpauseGenWalkers
// but the usage of that flag seems more obscure and dubious for this purpose
Game_Flag_Set(kFlagGenericWalkerWaiting);
}
// Pause generic walkers outside special loop
// so that they're always paused when McCoy enters (less chance to collide with him)
// There's also another flag called kFlagUnpauseGenWalkers
// but the usage of that flag seems more obscure and dubious for this purpose
Game_Flag_Set(kFlagGenericWalkerWaiting);
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
Setup_Scene_Information(-530.0f, -6.5f, 241.0f, 506);
Game_Flag_Set(kFlagArrivedFromSpinner1);
} else {
@ -292,14 +292,14 @@ bool SceneScriptCT01::ClickedOnExit(int exitId) {
Game_Flag_Reset(kFlagMcCoyInTyrellBuilding);
Game_Flag_Reset(kFlagMcCoyInDNARow);
Game_Flag_Reset(kFlagMcCoyInBradburyBuilding);
//#if BLADERUNNER_RESTORED_CUT_CONTENT
//if (_vm->_cutContent) {
// // Restored spinner door opens/ closes, so we disable this for now
// // NOTE: Reverted this cut content since this might be annoying
// as it slows down the pacing...
// int spinnerDest = Spinner_Interface_Choose_Dest(kCT01LoopDoorAnim, false);
//#else
//} else {
int spinnerDest = Spinner_Interface_Choose_Dest(-1, false);
//#endif // BLADERUNNER_RESTORED_CUT_CONTENT
//}
switch (spinnerDest) {
case kSpinnerDestinationPoliceStation:
@ -407,15 +407,15 @@ void SceneScriptCT01::SceneFrameAdvanced(int frame) {
Ambient_Sounds_Play_Sound(kSfxCARDOWN3, 40, 99, 0, 0);
}
#if BLADERUNNER_RESTORED_CUT_CONTENT
if (frame == 136 || frame == 258) {
Sound_Play(kSfxSPINOPN4, 100, 80, 80, 50);
}
if (_vm->_cutContent) {
if (frame == 136 || frame == 258) {
Sound_Play(kSfxSPINOPN4, 100, 80, 80, 50);
}
if (frame == 183 || frame == 303) {
Sound_Play(kSfxSPINCLS1, 100, 80, 80, 50);
if (frame == 183 || frame == 303) {
Sound_Play(kSfxSPINCLS1, 100, 80, 80, 50);
}
}
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (frame == 316) {
Ambient_Sounds_Play_Sound(kSfxCARUP3B, 50, -50, 100, 99);
@ -456,14 +456,14 @@ void SceneScriptCT01::PlayerWalkedIn() {
return;
}
Loop_Actor_Walk_To_XYZ(kActorMcCoy, -330.0f, -6.5f, 221.0f, 0, false, false, 0);
#if BLADERUNNER_RESTORED_CUT_CONTENT
// unpause generic walkers here, less chance to collide with McCOy while he enters the scene
if( Game_Flag_Query(kFlagArrivedFromSpinner1)
&& Game_Flag_Query(kFlagGenericWalkerWaiting)
) {
Game_Flag_Reset(kFlagGenericWalkerWaiting);
if (_vm->_cutContent) {
// unpause generic walkers here, less chance to collide with McCOy while he enters the scene
if( Game_Flag_Query(kFlagArrivedFromSpinner1)
&& Game_Flag_Query(kFlagGenericWalkerWaiting)
) {
Game_Flag_Reset(kFlagGenericWalkerWaiting);
}
}
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
Loop_Actor_Walk_To_XYZ(kActorMcCoy, -314.0f, -6.5f, 326.0f, 0, false, false, 0);
if (!Game_Flag_Query(kFlagCT01Visited)) {

View file

@ -176,13 +176,36 @@ void SceneScriptPS04::dialogueWithGuzza() {
case 120: // MONEY
Actor_Says(kActorMcCoy, 4000, 18);
#if BLADERUNNER_RESTORED_CUT_CONTENT
// Using cut content we have two cases:
// 1. Guzza can accept the loan (as in ORIGINAL)
// 2. Guzza can refuse the loan (CUT)
// Basically, if McCoy hasn't retired Zuben or if he drunk away his money at the bar
// then he'll have a small amount of chinyen and Guzza should accept the loan
if (Global_Variable_Query(kVariableChinyen) <= 100) {
if (_vm->_cutContent) {
// Using cut content we have two cases:
// 1. Guzza can accept the loan (as in ORIGINAL)
// 2. Guzza can refuse the loan (CUT)
// Basically, if McCoy hasn't retired Zuben or if he drunk away his money at the bar
// then he'll have a small amount of chinyen and Guzza should accept the loan
if (Global_Variable_Query(kVariableChinyen) <= 100) {
Actor_Clue_Acquire(kActorMcCoy, kClueGuzzasCash, true, kActorGuzza);
Actor_Says(kActorGuzza, 520, 33);
Actor_Says(kActorMcCoy, 4055, 13);
Actor_Says(kActorGuzza, 530, 31);
Actor_Says(kActorMcCoy, 4060, 13);
Actor_Says(kActorGuzza, 540, 31);
Actor_Says(kActorGuzza, 550, 32);
Actor_Says(kActorMcCoy, 4065, 18);
Actor_Says(kActorGuzza, 560, 34);
if (Query_Difficulty_Level() != kGameDifficultyEasy) {
Global_Variable_Increment(kVariableChinyen, 100);
}
} else {
// McCoy has plenty cash already - Guzza denies the loan
Actor_Says(kActorGuzza, 470, 33); // Hey, I'd love to be your own personal ATM but the department's strapped right now.
Actor_Says(kActorGuzza, 480, 31);
Actor_Says(kActorGuzza, 490, 31);
Actor_Says(kActorGuzza, 500, 32);
Actor_Says(kActorMcCoy, 4045, 16);
Actor_Says(kActorGuzza, 510, 31); // Hey, you track down a Rep, you get an advance.
Actor_Says(kActorMcCoy, 4050, 18);
}
} else {
Actor_Clue_Acquire(kActorMcCoy, kClueGuzzasCash, true, kActorGuzza);
Actor_Says(kActorGuzza, 520, 33);
Actor_Says(kActorMcCoy, 4055, 13);
@ -195,30 +218,7 @@ void SceneScriptPS04::dialogueWithGuzza() {
if (Query_Difficulty_Level() != kGameDifficultyEasy) {
Global_Variable_Increment(kVariableChinyen, 100);
}
} else {
// McCoy has plenty cash already - Guzza denies the loan
Actor_Says(kActorGuzza, 470, 33); // Hey, I'd love to be your own personal ATM but the department's strapped right now.
Actor_Says(kActorGuzza, 480, 31);
Actor_Says(kActorGuzza, 490, 31);
Actor_Says(kActorGuzza, 500, 32);
Actor_Says(kActorMcCoy, 4045, 16);
Actor_Says(kActorGuzza, 510, 31); // Hey, you track down a Rep, you get an advance.
Actor_Says(kActorMcCoy, 4050, 18);
}
#else
Actor_Clue_Acquire(kActorMcCoy, kClueGuzzasCash, true, kActorGuzza);
Actor_Says(kActorGuzza, 520, 33);
Actor_Says(kActorMcCoy, 4055, 13);
Actor_Says(kActorGuzza, 530, 31);
Actor_Says(kActorMcCoy, 4060, 13);
Actor_Says(kActorGuzza, 540, 31);
Actor_Says(kActorGuzza, 550, 32);
Actor_Says(kActorMcCoy, 4065, 18);
Actor_Says(kActorGuzza, 560, 34);
if (Query_Difficulty_Level() != kGameDifficultyEasy) {
Global_Variable_Increment(kVariableChinyen, 100);
}
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
break;
case 130: // REPORT IN

View file

@ -271,11 +271,11 @@ bool SceneScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
#if BLADERUNNER_ORIGINAL_BUGS
#else
else if (!Actor_Clue_Query(kActorMcCoy, kClueDoorForced2) && !Actor_Clue_Query(kActorMcCoy, kClueDoorForced1) && !Actor_Query_In_Set(kActorOfficerLeary, kSetRC01) && Global_Variable_Query(kVariableChapter) == 1) {
#if BLADERUNNER_RESTORED_CUT_CONTENT
Actor_Voice_Over(1870, kActorVoiceOver);
#else
Actor_Says(kActorMcCoy, 8570, 14);
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
Actor_Voice_Over(1870, kActorVoiceOver);
} else {
Actor_Says(kActorMcCoy, 8570, 14);
}
Actor_Clue_Acquire(kActorMcCoy, kClueDoorForced1, true, -1);
}
#endif // BLADERUNNER_ORIGINAL_BUGS

View file

@ -145,9 +145,9 @@ void SceneScriptRC02::dialogueWithRunciter() {
) {
DM_Add_To_List_Never_Repeat_Once_Selected(20, 6, 4, 5); // REFERENCE
}
#if BLADERUNNER_RESTORED_CUT_CONTENT
DM_Add_To_List_Never_Repeat_Once_Selected(200, -1, 3, 6); // VK - TEST
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
if (_vm->_cutContent) {
DM_Add_To_List_Never_Repeat_Once_Selected(200, -1, 3, 6); // VK - TEST
}
Dialogue_Menu_Add_DONE_To_List(30); // DONE
Dialogue_Menu_Appear(320, 240);
@ -210,17 +210,17 @@ void SceneScriptRC02::dialogueWithRunciter() {
Actor_Clue_Acquire(kActorMcCoy, kClueReferenceLetter, true, kActorRunciter);
break;
#if BLADERUNNER_RESTORED_CUT_CONTENT // scene 16 79
case 200:
Actor_Face_Actor(kActorMcCoy, kActorRunciter, true);
Actor_Says(kActorMcCoy, 395, 14);
Actor_Face_Actor(kActorRunciter, kActorMcCoy, true);
Actor_Says(kActorRunciter, 1680, 13);
Actor_Says(kActorMcCoy, 400, 14);
Voight_Kampff_Activate(kActorRunciter, 20);
Actor_Modify_Friendliness_To_Other(kActorRunciter, kActorMcCoy, -10);
if (_vm->_cutContent) { // scene 16 79
Actor_Face_Actor(kActorMcCoy, kActorRunciter, true);
Actor_Says(kActorMcCoy, 395, 14);
Actor_Face_Actor(kActorRunciter, kActorMcCoy, true);
Actor_Says(kActorRunciter, 1680, 13);
Actor_Says(kActorMcCoy, 400, 14);
Voight_Kampff_Activate(kActorRunciter, 20);
Actor_Modify_Friendliness_To_Other(kActorRunciter, kActorMcCoy, -10);
}
break;
#endif // BLADERUNNER_RESTORED_CUT_CONTENT
case 30: // DONE
Actor_Says(kActorMcCoy, 4595, 14);

File diff suppressed because it is too large Load diff