From 70080f1fdbafe5ecd11c573d4d9fba522a5d8235 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 1 Aug 2021 12:54:05 +0300 Subject: mission replay --- src/control/GameLogic.cpp | 9 ++ src/control/Script.cpp | 217 ++++++++++++++++++++++++++++++++++------------ src/control/Script.h | 12 ++- src/control/Script3.cpp | 7 +- src/control/Script5.cpp | 4 +- src/control/Script6.cpp | 25 ++++-- src/control/Script8.cpp | 3 + 7 files changed, 214 insertions(+), 63 deletions(-) (limited to 'src/control') diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 11df7b43..63c685d1 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -102,6 +102,15 @@ CGameLogic::Update() CVector vecRestartPos; float fRestartFloat; +#ifdef MISSION_REPLAY + // what a place to check! + if (gbTryingPorn4Again) { + CRunningScript* pScript = CTheScripts::pActiveScripts; + if (pScript && !CGeneral::faststricmp(pScript->m_abScriptName, "porno4")) + gbTryingPorn4Again = false; + } +#endif + if (CCutsceneMgr::IsCutsceneProcessing()) return; UpdateShortCut(); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 76ab9471..09c68958 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -116,7 +116,97 @@ static const char* nonMissionScripts[] = { "rc4", "hj", "usj", - "mayhem" + "mayhem", + "range", + "race", + "pizza", + "rcheli", + "rcplne1", + "rcrace1", + "cokerun", + "buypro1", + "carbuy1", + "buypro2", + "icecut", + "icecre1", + "buypro3", + "buypro4", + "buypro5", + "buypro6", + "buypro7", + "buypro8", + "buypro9", + "buypro10", + "buypro11", + "ovalrng", + "mm", + "kickst", + "heli1sc", + "heli2sc", + "heli3sc", + "heli4sc", + "carpark_1", + "bmx_1", + "bmx_2" +}; + +static const char* MissionScripts[] = { + "LAWYER1", + "LAWYER2", + "LAWYER3", + "LAWYER4", + "GENERL1", + "COL2", + "GENERL3", + "COL_4", + "COL_5", + "baron1", + "baron2", + "baron3", + "baron4", + "kent1", + "baron5", + "serg1", + "serg2", + "serg3", + "bankjo1", + "bankjo2", + "bankjo3", + "bankjo4", + "phil1", + "phil2", + "porno1", + "porno2", + "porno3", + "porno4", + "protec1", + "protec2", + "protec3", + "count1", + "count2", + "CAP_1", + "FIN_1", + "bike1", + "bike2", + "bike3", + "rockb1", + "rockb2", + "rockb3", + "cuban1", + "cuban2", + "cuban3", + "cuban4", + "hait1", + "hait2", + "hait3", + "assin1", + "assin2", + "assin3", + "assin4", + "assin5", + "taxwar1", + "taxwar2", + "taxwar3" }; int AllowMissionReplay; @@ -132,6 +222,11 @@ bool gbTryingPorn4Again; int IsInAmmunation; int MissionSkipLevel; +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT +bool UsingMobileScript; +bool AlreadySavedGame; +#endif + #endif #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT @@ -2313,6 +2408,10 @@ void CTheScripts::Init() PrintToLog(init_msg); CFileMgr::SetDir(""); #endif +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + UsingMobileScript = false; + AlreadySavedGame = false; +#endif } void CTheScripts::RemoveScriptTextureDictionary() @@ -2383,6 +2482,7 @@ void CTheScripts::Process() #ifdef MISSION_REPLAY static uint32 TimeToWaitTill; + static bool AlreadyResetHealth; switch (AllowMissionReplay) { case 2: AllowMissionReplay = 3; @@ -2398,9 +2498,19 @@ void CTheScripts::Process() break; case 6: AllowMissionReplay = 7; + AlreadyResetHealth = false; TimeToWaitTill = CTimer::GetTimeInMilliseconds() + 500; break; case 7: + if (!AlreadyResetHealth) { + AlreadyResetHealth = true; + CPlayerPed* pPlayerPed = FindPlayerPed(); + if (pPlayerPed) { + CPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed(); + if (pPlayerInfo) + pPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth; + } + } if (TimeToWaitTill < CTimer::GetTimeInMilliseconds()) { AllowMissionReplay = 0; return; @@ -2560,44 +2670,49 @@ int8 CRunningScript::ProcessOneCommand() retval = ProcessCommands1300To1399(command); else if (command < 1500) retval = ProcessCommands1400To1499(command); +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + if (!AlreadySavedGame) // we need to ignore first "fake" command which actually just saves the game +#endif + { #ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT - if (command < ARRAY_SIZE(commands)) { - if (commands[command].cond || commands[command].output[0] != ARGTYPE_NONE) { - strcat(commandInfo, " ->"); - if (commands[command].cond) - strcat(commandInfo, m_bCondResult ? " TRUE" : " FALSE"); - uint32 t = m_nIp; - m_nIp = ip; - ip = t; - for (int i = 0; commands[command].output[i] != ARGTYPE_NONE; i++) { - char tmp[32]; - switch (commands[command].output[i]) { - case ARGTYPE_INT: - case ARGTYPE_PED_HANDLE: - case ARGTYPE_VEHICLE_HANDLE: - case ARGTYPE_OBJECT_HANDLE: GetStoredParameterForDebug(commandInfo); sprintf(tmp, " (%d)", ScriptParams[i]); strcat(commandInfo, tmp); break; - case ARGTYPE_FLOAT: GetStoredParameterForDebug(commandInfo); sprintf(tmp, " (%8.3f)", *(float*)&ScriptParams[i]); strcat(commandInfo, tmp); break; - default: script_assert(0 && "Script only returns INTs and FLOATs"); + if (command < ARRAY_SIZE(commands)) { + if (commands[command].cond || commands[command].output[0] != ARGTYPE_NONE) { + strcat(commandInfo, " ->"); + if (commands[command].cond) + strcat(commandInfo, m_bCondResult ? " TRUE" : " FALSE"); + uint32 t = m_nIp; + m_nIp = ip; + ip = t; + for (int i = 0; commands[command].output[i] != ARGTYPE_NONE; i++) { + char tmp[32]; + switch (commands[command].output[i]) { + case ARGTYPE_INT: + case ARGTYPE_PED_HANDLE: + case ARGTYPE_VEHICLE_HANDLE: + case ARGTYPE_OBJECT_HANDLE: GetStoredParameterForDebug(commandInfo); sprintf(tmp, " (%d)", ScriptParams[i]); strcat(commandInfo, tmp); break; + case ARGTYPE_FLOAT: GetStoredParameterForDebug(commandInfo); sprintf(tmp, " (%8.3f)", *(float*)&ScriptParams[i]); strcat(commandInfo, tmp); break; + default: script_assert(0 && "Script only returns INTs and FLOATs"); + } } + m_nIp = ip; } - m_nIp = ip; - } - PrintToLog("%s\n", commandInfo); - if (m_bMissionFlag) { - for (int i = 0; commandInfo[i]; i++) { - if (commandInfo[i] == '_') - commandInfo[i] = ' '; + PrintToLog("%s\n", commandInfo); + if (m_bMissionFlag) { + for (int i = 0; commandInfo[i]; i++) { + if (commandInfo[i] == '_') + commandInfo[i] = ' '; + } + CDebug::DebugAddText(commandInfo); } - CDebug::DebugAddText(commandInfo); } - } #elif defined USE_BASIC_SCRIPT_DEBUG_OUTPUT - if (m_bMissionFlag) { - char tmp[128]; - sprintf(tmp, "Comm %d Cmp %d", command, m_bCondResult); - CDebug::DebugAddText(tmp); - } + if (m_bMissionFlag) { + char tmp[128]; + sprintf(tmp, "Comm %d Cmp %d", command, m_bCondResult); + CDebug::DebugAddText(tmp); + } #endif + } return retval; } @@ -4049,14 +4164,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CollectParameters(&m_nIp, 2); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); script_assert(car); -#if defined MISSION_REPLAY && defined SIMPLIER_MISSIONS - car->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1]; - if (missionRetryScriptIndex == 40 && car->GetModelIndex() == MI_CHEETAH) // Turismo - car->AutoPilot.m_nCruiseSpeed = 8 * car->AutoPilot.m_nCruiseSpeed / 10; - car->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity); -#else car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity); -#endif return 0; } case COMMAND_SET_CAR_DRIVING_STYLE: @@ -4125,8 +4233,12 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) { wchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp); #ifdef MISSION_REPLAY - if (strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], "M_FAIL") == 0 && CanAllowMissionReplay()) - AllowMissionReplay = 1; + if (strcmp((char*)&CTheScripts::ScriptSpace[m_nIp - KEY_LENGTH_IN_SCRIPT], "M_FAIL") == 0) { + if (AllowMissionReplay == 7) + AllowMissionReplay = 0; + if (CanAllowMissionReplay()) + AllowMissionReplay = 1; + } #endif CollectParameters(&m_nIp, 2); CMessages::AddBigMessage(key, ScriptParams[0], ScriptParams[1] - 1); @@ -4774,21 +4886,15 @@ bool CRunningScript::CanAllowMissionReplay() { if (AllowMissionReplay) return false; - if (CStats::LastMissionPassedName[0] == '\0') - return false; - for (int i = 0; i < ARRAY_SIZE(nonMissionScripts); i++) { - if (strcmp(m_abScriptName, nonMissionScripts[i]) == 0) - return false; + for (int i = 0; i < ARRAY_SIZE(MissionScripts); i++) { + if (!CGeneral::faststricmp(m_abScriptName, MissionScripts[i])) + return true; } - return true; + return false; } uint32 AddExtraDeathDelay() { - if (missionRetryScriptIndex == 63) - return 7000; - if (missionRetryScriptIndex == 64) - return 4000; return 1000; } @@ -4796,7 +4902,7 @@ void RetryMission(int type, int unk) { if (type == 0) { doingMissionRetry = true; - FrontEndMenuManager.m_nCurrScreen = 57; // MENUPAGE_MISSION_RETRY + FrontEndMenuManager.m_nCurrScreen = MENUPAGE_MISSION_RETRY; FrontEndMenuManager.RequestFrontEndStartUp(); } else if (type == 2) { @@ -4834,8 +4940,11 @@ CTheScripts::SwitchToMission(int32 mission) #ifdef MISSION_REPLAY missionRetryScriptIndex = mission; - if (missionRetryScriptIndex == 19) - CStats::LastMissionPassedName[0] = '\0'; +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + if (CTheScripts::MissionSupportsMissionReplay(missionRetryScriptIndex)) { + SaveGameForPause(4); + } +#endif #endif CTimer::Suspend(); int offset = CTheScripts::MultiScriptArray[mission]; diff --git a/src/control/Script.h b/src/control/Script.h index 80c05363..0c23de5b 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -575,13 +575,18 @@ public: static void SetObjectiveForAllPedsInCollective(int, eObjective); #endif +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + static bool MissionSupportsMissionReplay(int index) + { + return index >= 3 && index <= 35 || index >= 51 && index <= 65 || index >= 67 && index <= 74 || index >= 83 && index <= 87; + } +#endif }; #ifdef USE_DEBUG_SCRIPT_LOADER extern int scriptToLoad; #endif #ifdef MISSION_REPLAY -static_assert(false, "Mission replay is not supported"); extern int AllowMissionReplay; extern uint32 WaitForMissionActivate; extern uint32 WaitForSave; @@ -592,6 +597,11 @@ extern bool gbTryingPorn4Again; extern int IsInAmmunation; extern int MissionSkipLevel; +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT +extern bool UsingMobileScript; +extern bool AlreadySavedGame; +#endif + uint32 AddExtraDeathDelay(); void RetryMission(int, int); #endif diff --git a/src/control/Script3.cpp b/src/control/Script3.cpp index acd3988f..f831645e 100644 --- a/src/control/Script3.cpp +++ b/src/control/Script3.cpp @@ -149,7 +149,12 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) } case COMMAND_ADD_EXPLOSION: CollectParameters(&m_nIp, 4); - CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true); +#ifdef SIMPLER_MISSIONS + if (!CGeneral::faststricmp(m_abScriptName, "hait2")) + CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true, 11.25f); + else +#endif + CExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true); return 0; case COMMAND_IS_CAR_UPRIGHT: diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index f65724c2..fc258f0c 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -1379,8 +1379,10 @@ void CRunningScript::DoDeatharrestCheck() if (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest()) return; #ifdef MISSION_REPLAY - if (AllowMissionReplay != 0) + if (AllowMissionReplay != 7 && AllowMissionReplay != 0) return; + if (AllowMissionReplay == 7) + AllowMissionReplay = 0; if (CanAllowMissionReplay()) AllowMissionReplay = 1; #endif diff --git a/src/control/Script6.cpp b/src/control/Script6.cpp index 4d7121f2..a9b750bf 100644 --- a/src/control/Script6.cpp +++ b/src/control/Script6.cpp @@ -125,10 +125,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) case COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE: { CollectParameters(&m_nIp, 1); -#ifdef MISSION_REPLAY - AllowMissionReplay = 0; - SaveGameForPause(3); -#endif CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]]; CPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE); pPlayerInfo->MakePlayerSafe(true); @@ -372,14 +368,28 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) return 0; case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL: { +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + uint32 oldIp = m_nIp; +#endif CollectParameters(&m_nIp, 1); if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2) return 0; #ifdef MISSION_REPLAY missionRetryScriptIndex = ScriptParams[0]; - if (missionRetryScriptIndex == 19) - CStats::LastMissionPassedName[0] = '\0'; +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + if (!UsingMobileScript && CTheScripts::MissionSupportsMissionReplay(missionRetryScriptIndex)){ + if (!AlreadySavedGame) { + m_nIp = oldIp - 2; + SaveGameForPause(4); + AlreadySavedGame = true; + return 0; + } + else { + AlreadySavedGame = false; + } + } +#endif #endif CTimer::Suspend(); int offset = CTheScripts::MultiScriptArray[ScriptParams[0]]; @@ -1075,6 +1085,9 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) } case COMMAND_FAIL_CURRENT_MISSION: CTheScripts::FailCurrentMission = 2; +#ifdef MISSION_REPLAY + MissionSkipLevel = 0; +#endif return 0; case COMMAND_GET_CLOSEST_OBJECT_OF_TYPE: { diff --git a/src/control/Script8.cpp b/src/control/Script8.cpp index 56d7ed90..98f69737 100644 --- a/src/control/Script8.cpp +++ b/src/control/Script8.cpp @@ -576,6 +576,9 @@ int8 CRunningScript::ProcessCommands1400To1499(int32 command) return 0; case COMMAND_DO_SAVE_GAME: CollectParameters(&m_nIp, 1); +#ifdef USE_MISSION_REPLAY_OVERRIDE_FOR_NON_MOBILE_SCRIPT + UsingMobileScript = true; +#endif #ifdef MISSION_REPLAY SaveGameForPause(ScriptParams[0]); #endif -- cgit v1.2.3