From 0e7823cedd3629667154ad410c2260ebdf663bcc Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Wed, 28 Feb 2024 15:03:27 -0500 Subject: [PATCH] LegoGameState player functions (#603) * LegoGameState player functions * Style * use sizeof --------- Co-authored-by: Christian Semmler --- .../legoomni/include/legobuildingmanager.h | 5 +- LEGO1/lego/legoomni/include/legogamestate.h | 23 +- .../lego/legoomni/include/legoplantmanager.h | 5 +- .../legoomni/include/legounksavedatawriter.h | 2 +- .../legoomni/src/common/legogamestate.cpp | 249 ++++++++++++++---- 5 files changed, 223 insertions(+), 61 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 2c50c027..c8351413 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -2,7 +2,7 @@ #define LEGOBUILDINGMANAGER_H #include "decomp.h" -#include "lego/sources/misc/legostorage.h" +#include "misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6f50 @@ -24,6 +24,7 @@ public: static void configureLegoBuildingManager(MxS32); static void SetCustomizeAnimFile(const char* p_value); + void Init(); void FUN_1002fa00(); void FUN_1002fb30(); MxResult Save(LegoStorage* p_storage); @@ -36,8 +37,6 @@ public: private: static char* g_customizeAnimFile; - void Init(); - undefined m_unk0x08[0x28]; // 0x08 }; diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index d35c0764..7358df5f 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -90,8 +90,11 @@ public: // SIZE 0x0c struct Username { Username(); + inline Username(Username& p_other) { Set(p_other); } + inline void Set(Username& p_other) { memcpy(m_letters, p_other.m_letters, sizeof(m_letters)); } + MxResult ReadWrite(LegoStorage* p_storage); - Username* operator=(const Username* p_other); + Username& operator=(const Username& p_other); MxS16 m_letters[7]; // 0x00 }; @@ -120,19 +123,29 @@ public: LegoGameState(); ~LegoGameState(); + void SetActor(MxU8 p_actorId); + void RemoveActor(); + void ResetROI(); + MxResult Save(MxULong); MxResult DeleteState(); MxResult Load(MxULong); - void SerializePlayersInfo(MxS16); + + void SerializePlayersInfo(MxS16 p_flags); + MxResult AddPlayer(Username& p_player); + void SwitchPlayer(MxS16 p_playerId); + MxS16 FindPlayer(Username& p_player); + void SerializeScoreHistory(MxS16 p_flags); void SetSavePath(char*); LegoState* GetState(const char* p_stateName); LegoState* CreateState(const char* p_stateName); - void GetFileSavePath(MxString* p_outPath, MxULong p_slotn); + void GetFileSavePath(MxString* p_outPath, MxU8 p_slotn); void StopArea(Area p_area); void SwitchArea(Area p_area); + void Init(); inline MxU8 GetActorId() { return m_actorId; } inline Act GetCurrentAct() { return m_currentAct; } @@ -152,8 +165,6 @@ public: void SetCurrentAct(Act p_currentAct); void FindLoadedAct(); - void SetActor(MxU8 p_actorId); - void ResetROI(); private: void RegisterState(LegoState* p_state); @@ -173,7 +184,7 @@ private: LegoBackgroundColor* m_tempBackgroundColor; // 0x1c LegoFullScreenMovie* m_fullScreenMovie; // 0x20 MxU16 m_unk0x24; // 0x24 - undefined2 m_unk0x26; // 0x26 + MxS16 m_playerCount; // 0x26 Username m_players[9]; // 0x28 History m_history; // 0xa6 undefined2 m_unk0x41a; // 0x41a diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 622eb500..581ec7b4 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -2,7 +2,7 @@ #define LEGOPLANTMANAGER_H #include "decomp.h" -#include "lego/sources/misc/legostorage.h" +#include "misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6758 @@ -21,6 +21,7 @@ public: return "LegoPlantManager"; } + void Init(); void FUN_10026360(MxS32 p_scriptIndex); void FUN_100263a0(undefined4 p_und); void Save(LegoStorage* p_storage); @@ -35,8 +36,6 @@ public: private: static char* g_customizeAnimFile; - void Init(); - undefined m_unk0x08[0x24]; // 0x08 }; diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 482ecd9e..9f3d1235 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -59,7 +59,7 @@ public: MxResult ReadSaveData3(LegoStorage* p_storage); LegoROI* FUN_10083500(const char*, MxBool); - static void InitSaveData(); + void InitSaveData(); static void SetCustomizeAnimFile(const char* p_value); static MxBool FUN_10084c00(const LegoChar*); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 9c794f97..ccd0a445 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -2,8 +2,12 @@ #include "act1state.h" #include "define.h" +#include "dunebuggy.h" +#include "helicopter.h" #include "infocenterstate.h" +#include "isle.h" #include "islepathactor.h" +#include "jetski.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" #include "legonavcontroller.h" @@ -18,6 +22,7 @@ #include "mxobjectfactory.h" #include "mxstring.h" #include "mxvariabletable.h" +#include "racecar.h" #include "roi/legoroi.h" #include @@ -90,7 +95,7 @@ LegoGameState::LegoGameState() m_currentArea = e_noArea; m_previousArea = e_noArea; m_unk0x42c = e_noArea; - m_unk0x26 = 0; + m_playerCount = 0; m_isDirty = FALSE; m_loadedAct = e_actNotFound; SetCurrentAct(e_act1); @@ -158,6 +163,15 @@ void LegoGameState::SetActor(MxU8 p_actorId) SetCurrentActor(newActor); } +// FUNCTION: LEGO1 0x10039910 +void LegoGameState::RemoveActor() +{ + IslePathActor* actor = CurrentActor(); + SetCurrentActor(NULL); + delete actor; + m_actorId = 0; +} + // FUNCTION: LEGO1 0x10039940 void LegoGameState::ResetROI() { @@ -185,7 +199,7 @@ MxResult LegoGameState::Save(MxULong p_slot) } MxResult result = FAILURE; - LegoFile fileStream; + LegoFile fileStorage; MxVariableTable* variableTable = VariableTable(); MxS16 count = 0; MxU32 i; @@ -195,32 +209,32 @@ MxResult LegoGameState::Save(MxULong p_slot) MxString savePath; GetFileSavePath(&savePath, p_slot); - if (fileStream.Open(savePath.GetData(), LegoFile::c_write) == FAILURE) { + if (fileStorage.Open(savePath.GetData(), LegoFile::c_write) == FAILURE) { goto done; } - Write(&fileStream, 0x1000c); - Write(&fileStream, m_unk0x24); - Write(&fileStream, (MxU16) m_currentAct); - Write(&fileStream, m_actorId); + Write(&fileStorage, 0x1000c); + Write(&fileStorage, m_unk0x24); + Write(&fileStorage, (MxU16) m_currentAct); + Write(&fileStorage, m_actorId); for (i = 0; i < _countof(g_colorSaveData); i++) { - if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { goto done; } } - if (WriteVariable(&fileStream, variableTable, "backgroundcolor") == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, "backgroundcolor") == FAILURE) { goto done; } - if (WriteVariable(&fileStream, variableTable, "lightposition") == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, "lightposition") == FAILURE) { goto done; } - WriteEndOfVariables(&fileStream); - UnkSaveDataWriter()->WriteSaveData3(&fileStream); - PlantManager()->Save(&fileStream); - result = BuildingManager()->Save(&fileStream); + WriteEndOfVariables(&fileStorage); + UnkSaveDataWriter()->WriteSaveData3(&fileStorage); + PlantManager()->Save(&fileStorage); + result = BuildingManager()->Save(&fileStorage); for (j = 0; j < m_stateCount; j++) { if (m_stateArray[j]->VTable0x14()) { @@ -228,16 +242,16 @@ MxResult LegoGameState::Save(MxULong p_slot) } } - Write(&fileStream, count); + Write(&fileStorage, count); for (j = 0; j < m_stateCount; j++) { if (m_stateArray[j]->VTable0x14()) { - m_stateArray[j]->VTable0x1c(&fileStream); + m_stateArray[j]->VTable0x1c(&fileStorage); } } area = m_unk0x42c; - Write(&fileStream, (MxU16) area); + Write(&fileStorage, (MxU16) area); SerializeScoreHistory(2); m_isDirty = FALSE; @@ -272,13 +286,13 @@ MxResult LegoGameState::DeleteState() MxResult LegoGameState::Load(MxULong p_slot) { MxResult result = FAILURE; - LegoFile fileStream; + LegoFile fileStorage; MxVariableTable* variableTable = VariableTable(); MxString savePath; GetFileSavePath(&savePath, p_slot); - if (fileStream.Open(savePath.GetData(), LegoFile::c_read) == FAILURE) { + if (fileStorage.Open(savePath.GetData(), LegoFile::c_read) == FAILURE) { goto done; } @@ -286,25 +300,25 @@ MxResult LegoGameState::Load(MxULong p_slot) MxS16 count, area, act; const char* lightPosition; - Read(&fileStream, &version); + Read(&fileStorage, &version); if (version != 0x1000c) { OmniError("Saved game version mismatch", 0); goto done; } - Read(&fileStream, &m_unk0x24); + Read(&fileStorage, &m_unk0x24); - Read(&fileStream, &act); + Read(&fileStorage, &act); SetCurrentAct((Act) act); - Read(&fileStream, &m_actorId); + Read(&fileStorage, &m_actorId); if (m_actorId) { SetActor(m_actorId); } do { - status = ReadVariable(&fileStream, variableTable); + status = ReadVariable(&fileStorage, variableTable); if (status == 1) { goto done; } @@ -317,13 +331,13 @@ MxResult LegoGameState::Load(MxULong p_slot) SetLightPosition(atoi(lightPosition)); } - if (UnkSaveDataWriter()->ReadSaveData3(&fileStream) == FAILURE) { + if (UnkSaveDataWriter()->ReadSaveData3(&fileStorage) == FAILURE) { goto done; } - if (PlantManager()->Load(&fileStream) == FAILURE) { + if (PlantManager()->Load(&fileStorage) == FAILURE) { goto done; } - if (BuildingManager()->Load(&fileStream) == FAILURE) { + if (BuildingManager()->Load(&fileStorage) == FAILURE) { goto done; } if (DeleteState() != SUCCESS) { @@ -331,13 +345,13 @@ MxResult LegoGameState::Load(MxULong p_slot) } char stateName[80]; - Read(&fileStream, &count); + Read(&fileStorage, &count); if (count) { for (MxS16 i = 0; i < count; i++) { MxS16 stateNameLength; - Read(&fileStream, &stateNameLength); - Read(&fileStream, stateName, (MxULong) stateNameLength); + Read(&fileStorage, &stateNameLength); + Read(&fileStorage, stateName, (MxULong) stateNameLength); stateName[stateNameLength] = 0; LegoState* state = GetState(stateName); @@ -349,11 +363,11 @@ MxResult LegoGameState::Load(MxULong p_slot) } } - state->VTable0x1c(&fileStream); + state->VTable0x1c(&fileStorage); } } - Read(&fileStream, &area); + Read(&fileStorage, &area); if (m_currentAct == 0) { m_unk0x42c = e_noArea; @@ -397,11 +411,11 @@ MxResult LegoGameState::WriteVariable(LegoStorage* p_storage, MxVariableTable* p if (variableValue) { MxU8 length = strlen(p_variableName); - if (p_storage->Write((char*) &length, 1) == SUCCESS) { + if (p_storage->Write(&length, sizeof(length)) == SUCCESS) { if (p_storage->Write(p_variableName, length) == SUCCESS) { length = strlen(variableValue); - if (p_storage->Write((char*) &length, 1) == SUCCESS) { - result = p_storage->Write((char*) variableValue, length); + if (p_storage->Write(&length, sizeof(length)) == SUCCESS) { + result = p_storage->Write(variableValue, length); } } } @@ -415,22 +429,20 @@ MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_storage) { MxU8 len = strlen(g_endOfVariables); - if (p_storage->Write(&len, 1) == SUCCESS) { + if (p_storage->Write(&len, sizeof(len)) == SUCCESS) { return p_storage->Write(g_endOfVariables, len); } return FAILURE; } -// 95% match, just some instruction ordering differences on the call to -// MxVariableTable::SetVariable at the end. // FUNCTION: LEGO1 0x1003a080 MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) { MxS32 result = 1; MxU8 length; - if (p_storage->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read(&length, sizeof(length)) == SUCCESS) { char nameBuffer[256]; if (p_storage->Read(nameBuffer, length) == SUCCESS) { nameBuffer[length] = '\0'; @@ -439,12 +451,12 @@ MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) result = 2; } else { - if (p_storage->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read(&length, sizeof(length)) == SUCCESS) { char valueBuffer[256]; if (p_storage->Read(valueBuffer, length) == SUCCESS) { - result = 0; valueBuffer[length] = '\0'; p_to->SetVariable(nameBuffer, valueBuffer); + result = SUCCESS; } } } @@ -455,7 +467,7 @@ MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) } // FUNCTION: LEGO1 0x1003a170 -void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) +void LegoGameState::GetFileSavePath(MxString* p_outPath, MxU8 p_slotn) { char baseForSlot[2] = "0"; char path[1024] = ""; @@ -475,10 +487,97 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) *p_outPath = MxString(path); } -// STUB: LEGO1 0x1003a2e0 -void LegoGameState::SerializePlayersInfo(MxS16) +// FUNCTION: LEGO1 0x1003a2e0 +void LegoGameState::SerializePlayersInfo(MxS16 p_flags) { - // TODO + LegoFile fileStorage; + MxString playersGSI = MxString(m_savePath); + + playersGSI += "\\"; + playersGSI += g_playersGSI; + + if (fileStorage.Open(playersGSI.GetData(), p_flags) == SUCCESS) { + if (fileStorage.IsReadMode()) { + Read(&fileStorage, &m_playerCount); + } + else if (fileStorage.IsWriteMode()) { + Write(&fileStorage, m_playerCount); + } + + for (MxS16 i = 0; i < m_playerCount; i++) { + m_players[i].ReadWrite(&fileStorage); + } + } +} + +// FUNCTION: LEGO1 0x1003a3f0 +MxResult LegoGameState::AddPlayer(Username& p_player) +{ + MxString from, to; + + if (m_playerCount == 9) { + GetFileSavePath(&from, 8); + DeleteFile(from.GetData()); + m_playerCount--; + } + + for (MxS16 i = m_playerCount; i > 0; i--) { + m_players[i] = m_players[i - 1]; + GetFileSavePath(&from, i - 1); + GetFileSavePath(&to, i); + MoveFile(from.GetData(), to.GetData()); + } + + m_playerCount++; + m_players[0].Set(p_player); + m_unk0x24 = m_history.m_unk0x372; + m_history.m_unk0x372 = m_unk0x24 + 1; + m_history.WriteScoreHistory(); + SetCurrentAct(e_act1); + + return DeleteState(); +} + +// FUNCTION: LEGO1 0x1003a540 +void LegoGameState::SwitchPlayer(MxS16 p_playerId) +{ + if (p_playerId > 0) { + MxString from, temp, to; + + GetFileSavePath(&from, p_playerId); + GetFileSavePath(&temp, 36); + + Username selectedName(m_players[p_playerId]); + + MoveFile(from.GetData(), temp.GetData()); + + for (MxS16 i = p_playerId; i > 0; i--) { + m_players[i] = m_players[i - 1]; + GetFileSavePath(&from, i - 1); + GetFileSavePath(&to, i); + MoveFile(from.GetData(), to.GetData()); + } + + m_players[0] = selectedName; + GetFileSavePath(&from, 0); + MoveFile(temp.GetData(), from.GetData()); + } + + if (Load(0) != SUCCESS) { + Init(); + } +} + +// FUNCTION: LEGO1 0x1003a6e0 +MxS16 LegoGameState::FindPlayer(Username& p_player) +{ + for (MxS16 i = 0; i < m_playerCount; i++) { + if (memcmp(&m_players[i], &p_player, sizeof(p_player)) == 0) { + return i; + } + } + + return -1; } // FUNCTION: LEGO1 0x1003a720 @@ -939,6 +1038,60 @@ void LegoGameState::RegisterState(LegoState* p_state) m_stateArray[targetIndex] = p_state; } +// FUNCTION: LEGO1 0x1003bd00 +void LegoGameState::Init() +{ + m_backgroundColor->SetValue("set 56 54 68"); + m_backgroundColor->SetLights(); + m_tempBackgroundColor->SetValue("set 56 54 68"); + VariableTable()->SetVariable("lightposition", "2"); + SetLightPosition(2); + PlantManager()->Init(); + BuildingManager()->Init(); + UnkSaveDataWriter()->InitSaveData(); + AnimationManager()->FUN_1005ee80(TRUE); + SetColors(); + RemoveActor(); + DeleteState(); + m_isDirty = FALSE; + FindLoadedAct(); + SetCurrentAct(e_act1); + + if (m_loadedAct == e_act1) { + Isle* isle = (Isle*) FindWorld(*g_isleScript, 0); + + Helicopter* copter = (Helicopter*) isle->Find(*g_copterScript, 1); + if (copter) { + isle->FUN_1001fc80(copter); + isle->VTable0x6c(copter); + delete copter; + } + + DuneBuggy* dunebuggy = (DuneBuggy*) isle->Find(*g_dunecarScript, 2); + if (dunebuggy) { + isle->FUN_1001fc80(dunebuggy); + isle->VTable0x6c(dunebuggy); + delete dunebuggy; + } + + Jetski* jetski = (Jetski*) isle->Find(*g_jetskiScript, 3); + if (jetski) { + isle->FUN_1001fc80(jetski); + isle->VTable0x6c(jetski); + delete jetski; + } + + RaceCar* racecar = (RaceCar*) isle->Find(*g_racecarScript, 4); + if (racecar) { + isle->FUN_1001fc80(racecar); + isle->VTable0x6c(racecar); + delete racecar; + } + } + + m_unk0x42c = e_noArea; +} + // FUNCTION: LEGO1 0x1003c670 LegoGameState::Username::Username() { @@ -964,10 +1117,10 @@ MxResult LegoGameState::Username::ReadWrite(LegoStorage* p_storage) } // FUNCTION: LEGO1 0x1003c710 -LegoGameState::Username* LegoGameState::Username::operator=(const Username* p_other) +LegoGameState::Username& LegoGameState::Username::operator=(const Username& p_other) { - memcpy(m_letters, p_other->m_letters, sizeof(m_letters)); - return this; + memcpy(m_letters, p_other.m_letters, sizeof(m_letters)); + return *this; } // FUNCTION: LEGO1 0x1003c830