From 64b28c073052535cd0ce444292bdfda1629a45d8 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 1 Mar 2020 14:18:10 +0300 Subject: save/load --- src/control/Script.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++++++++- src/control/Script.h | 8 +++ 2 files changed, 173 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/control/Script.cpp b/src/control/Script.cpp index dab68e5a..b4041f2e 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11199,8 +11199,170 @@ void CTheScripts::RenderTheScriptDebugLines() RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0); } -WRAPPER void CTheScripts::SaveAllScripts(uint8*, uint32*) { EAXJMP(0x4535E0); } -WRAPPER void CTheScripts::LoadAllScripts(uint8*, uint32) { EAXJMP(0x453B30); } +#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) + sizeof(CTheScripts::BaseBriefIdForContact) + sizeof(CTheScripts::OnAMissionForContactFlag) +\ + sizeof(CTheScripts::CollectiveArray) + 4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32) + +void CTheScripts::SaveAllScripts(uint8* buf, uint32* size) +{ +INITSAVEBUF + uint32 var_space = ScriptSpace[6] << 24 | ScriptSpace[5] << 16 | ScriptSpace[4] << 8 | ScriptSpace[3]; + // = *(uint32*)&ScriptSpace[3]; + uint32 running_scripts = 0; + for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) + running_scripts++; + *size = sizeof(CRunningScript) * running_scripts + var_space + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32); + WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE); + WriteSaveBuf(buf, var_space); + for (uint32 i = 0; i < var_space; i++) + WriteSaveBuf(buf, ScriptSpace[i]); + static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts"); + uint32 script_data_size = SCRIPT_DATA_SIZE; + WriteSaveBuf(buf, script_data_size); + WriteSaveBuf(buf, OnAMissionFlag); + for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { + WriteSaveBuf(buf, OnAMissionForContactFlag[i]); + WriteSaveBuf(buf, BaseBriefIdForContact[i]); + } + for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) + WriteSaveBuf(buf, CollectiveArray[i]); + WriteSaveBuf(buf, NextFreeCollectiveIndex); + for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + CBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding; + uint32 type, handle; + if (!pBuilding) { + type = 0; + handle = 0; + } else if (pBuilding->GetIsATreadable()) { + type = 1; + handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pBuilding) + 1; + } else { + type = 2; + handle = CPools::GetBuildingPool()->GetJustIndex(pBuilding) + 1; + } + WriteSaveBuf(buf, type); + WriteSaveBuf(buf, handle); + WriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel); + WriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel); + } + for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + CEntity* pEntity = InvisibilitySettingArray[i]; + uint32 type, handle; + if (!pEntity) { + type = 0; + handle = 0; + } else { + switch (pEntity->m_type) { + case ENTITY_TYPE_BUILDING: + if (((CBuilding*)pEntity)->GetIsATreadable()) { + type = 1; + handle = CPools::GetTreadablePool()->GetJustIndex((CTreadable*)pEntity) + 1; + } else { + type = 2; + handle = CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pEntity) + 1; + } + break; + case ENTITY_TYPE_OBJECT: + type = 3; + handle = CPools::GetObjectPool()->GetJustIndex((CObject*)pEntity) + 1; + break; + case ENTITY_TYPE_DUMMY: + type = 4; + handle = CPools::GetDummyPool()->GetJustIndex((CDummy*)pEntity) + 1; + } + } + WriteSaveBuf(buf, type); + WriteSaveBuf(buf, handle); + } + WriteSaveBuf(buf, bUsingAMultiScriptFile); + WriteSaveBuf(buf, (uint8)0); + WriteSaveBuf(buf, (uint16)0); + WriteSaveBuf(buf, MainScriptSize); + WriteSaveBuf(buf, LargestMissionScriptSize); + WriteSaveBuf(buf, NumberOfMissionScripts); + WriteSaveBuf(buf, (uint16)0); + WriteSaveBuf(buf, running_scripts); + for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) + WriteSaveBuf(buf, *pScript); +VALIDATESAVEBUF(*size) +} + +void CTheScripts::LoadAllScripts(uint8* buf, uint32 size) +{ + Init(); +INITSAVEBUF + CheckSaveHeader(buf, 'S', 'C', 'R', '\0', size - SAVE_HEADER_SIZE); + uint32 var_space = ReadSaveBuf(buf); + for (uint32 i = 0; i < var_space; i++) + ScriptSpace[i] = ReadSaveBuf(buf); + assert(ReadSaveBuf(buf) == SCRIPT_DATA_SIZE); + OnAMissionFlag = ReadSaveBuf(buf); + for (uint32 i = 0; i < MAX_NUM_CONTACTS; i++) { + OnAMissionForContactFlag[i] = ReadSaveBuf(buf); + BaseBriefIdForContact[i] = ReadSaveBuf(buf); + } + for (uint32 i = 0; i < MAX_NUM_COLLECTIVES; i++) + CollectiveArray[i] = ReadSaveBuf(buf); + NextFreeCollectiveIndex = ReadSaveBuf(buf); + for (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) { + uint32 type = ReadSaveBuf(buf); + uint32 handle = ReadSaveBuf(buf); + switch (type) { + case 0: + BuildingSwapArray[i].m_pBuilding = nil; + break; + case 1: + BuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1); + break; + case 2: + BuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1); + break; + default: + assert(false); + } + BuildingSwapArray[i].m_nNewModel = ReadSaveBuf(buf); + BuildingSwapArray[i].m_nOldModel = ReadSaveBuf(buf); + if (BuildingSwapArray[i].m_pBuilding) + BuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel); + } + for (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) { + uint32 type = ReadSaveBuf(buf); + uint32 handle = ReadSaveBuf(buf); + switch (type) { + case 0: + InvisibilitySettingArray[i] = nil; + break; + case 1: + InvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1); + break; + case 2: + InvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1); + break; + case 3: + InvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1); + break; + case 4: + InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1); + default: + assert(false); + } + if (InvisibilitySettingArray[i]) + InvisibilitySettingArray[i]->bIsVisible = false; + assert(ReadSaveBuf(buf) == bUsingAMultiScriptFile); + ReadSaveBuf(buf); + ReadSaveBuf(buf); + assert(ReadSaveBuf(buf) == MainScriptSize); + assert(ReadSaveBuf(buf) == LargestMissionScriptSize); + assert(ReadSaveBuf(buf) == NumberOfMissionScripts); + ReadSaveBuf(buf); + uint32 running_scripts = ReadSaveBuf(buf); + for (uint32 i = 0; i < running_scripts; i++) + StartNewScript(0)->BuildFromSaved(ReadSaveBuf(buf)); + } +VALIDATESAVEBUF(size) +} + +#undef SCRIPT_DATA_SIZE + WRAPPER void CTheScripts::ClearSpaceForMissionEntity(const CVector&, CEntity*) { EAXJMP(0x454060); } WRAPPER void CTheScripts::HighlightImportantArea(uint32, float, float, float, float, float) { EAXJMP(0x454320); } WRAPPER void CTheScripts::HighlightImportantAngledArea(uint32, float, float, float, float, float, float, float, float, float) { EAXJMP(0x454430); } @@ -11228,7 +11390,7 @@ InjectHook(0x44FD10, &CTheScripts::UndoBuildingSwaps, PATCH_JUMP); InjectHook(0x44FD60, &CTheScripts::UndoEntityVisibilitySettings, PATCH_JUMP); InjectHook(0x4534E0, &CTheScripts::ScriptDebugLine3D, PATCH_JUMP); InjectHook(0x453550, &CTheScripts::RenderTheScriptDebugLines, PATCH_JUMP); -//InjectHook(0x4535E0, &CTheScripts::SaveAllScripts, PATCH_JUMP); +InjectHook(0x4535E0, &CTheScripts::SaveAllScripts, PATCH_JUMP); //InjectHook(0x453B30, &CTheScripts::LoadAllScripts, PATCH_JUMP); //InjectHook(0x454060, &CTheScripts::ClearSpaceForMissionEntity, PATCH_JUMP); ENDPATCHES diff --git a/src/control/Script.h b/src/control/Script.h index 18d148bf..5f3175f0 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -382,6 +382,14 @@ class CRunningScript public: void SetIP(uint32 ip) { m_nIp = ip; } CRunningScript* GetNext() const { return next; } + void BuildFromSaved(const CRunningScript& pSaved) + { + CRunningScript* n = next; + CRunningScript* p = prev; + *this = pSaved; + next = n; + prev = p; + } void UpdateTimers(float timeStep) { m_anLocalVariables[NUM_LOCAL_VARS] += timeStep; m_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep; -- cgit v1.2.3