diff --git a/TR5Main/Game/gameflow.cpp b/TR5Main/Game/gameflow.cpp index defff2d32..421f9aedc 100644 --- a/TR5Main/Game/gameflow.cpp +++ b/TR5Main/Game/gameflow.cpp @@ -17,7 +17,7 @@ int LoadSavegameInfos() for (int i = 0; i < MAX_SAVEGAMES; i++) { - g_NewSavegameInfos[i].Present = false; + g_NewSavegameInfos[i].present = false; } // try to load the savegame @@ -31,7 +31,7 @@ int LoadSavegameInfos() continue; fclose(savegamePtr); - g_NewSavegameInfos[i].Present = true; + g_NewSavegameInfos[i].present = true; SaveGame::LoadHeader(fileName, &g_NewSavegameInfos[i]); fclose(savegamePtr); diff --git a/TR5Main/Game/savegame.cpp b/TR5Main/Game/savegame.cpp index 3b8f32e1a..d35dba4a1 100644 --- a/TR5Main/Game/savegame.cpp +++ b/TR5Main/Game/savegame.cpp @@ -18,419 +18,242 @@ #include "itemdata/creature_info.h" #include "Game/effects/lara_burn.h" #include "Specific/savegame/flatbuffers/ten_savegame_generated.h" + using namespace TEN::Effects::Fire; using namespace TEN::Entities::Switches; +using namespace flatbuffers; + namespace Save = TEN::Save; using std::string; using std::vector; + FileStream* SaveGame::m_stream; -ChunkReader* SaveGame::m_reader; -ChunkWriter* SaveGame::m_writer; vector SaveGame::m_luaVariables; int SaveGame::LastSaveGame; -std::unique_ptr SaveGame::m_chunkGameStatus; -std::unique_ptr SaveGame::m_chunkItems; -std::unique_ptr SaveGame::m_chunkItem; -std::unique_ptr SaveGame::m_chunkLara; -std::unique_ptr SaveGame::m_chunkLuaVariable; -std::unique_ptr SaveGame::m_chunkStaticFlags; -std::unique_ptr SaveGame::m_chunkVehicle; -std::unique_ptr SaveGame::m_chunkSequenceSwitch; -std::unique_ptr SaveGame::m_chunkFlybyFlags; -std::unique_ptr SaveGame::m_chunkCdFlags; -std::unique_ptr SaveGame::m_chunkCamera; -std::unique_ptr SaveGame::m_chunkFlipStats; -std::unique_ptr SaveGame::m_chunkFlipMap; -std::unique_ptr SaveGame::m_chunkItemDummy; -std::unique_ptr SaveGame::m_chunkStatistics; -std::unique_ptr SaveGame::m_chunkItemAnims; -std::unique_ptr SaveGame::m_chunkItemMeshes; -std::unique_ptr SaveGame::m_chunkItemFlags; -std::unique_ptr SaveGame::m_chunkItemHitPoints; -std::unique_ptr SaveGame::m_chunkItemPosition; -std::unique_ptr SaveGame::m_chunkItemIntelligentData; -std::unique_ptr SaveGame::m_chunkSpecialItemBurningTorch; -std::unique_ptr SaveGame::m_chunkSpecialItemChaff; -std::unique_ptr SaveGame::m_chunkSpecialItemTorpedo; -std::unique_ptr SaveGame::m_chunkSpecialItemCrossbowBolt; -std::unique_ptr SaveGame::m_chunkSpecialItemFlare; -std::unique_ptr SaveGame::m_chunkItemQuadInfo; -std::unique_ptr SaveGame::m_chunkBats; -std::unique_ptr SaveGame::m_chunkRats; -std::unique_ptr SaveGame::m_chunkSpiders; -std::unique_ptr SaveGame::m_chunkLaraExtraInfo; -std::unique_ptr SaveGame::m_chunkWeaponInfo; -std::unique_ptr SaveGame::m_chunkPuzzle; -std::unique_ptr SaveGame::m_chunkKey; -std::unique_ptr SaveGame::m_chunkPickup; -std::unique_ptr SaveGame::m_chunkExamine; -std::unique_ptr SaveGame::m_chunkPuzzleCombo; -std::unique_ptr SaveGame::m_chunkKeyCombo; -std::unique_ptr SaveGame::m_chunkPickupCombo; -std::unique_ptr SaveGame::m_chunkExamineCombo; -std::unique_ptr SaveGame::m_chunkWeaponItem; - SAVEGAME_INFO Savegame; -//extern vector SoundTracks; - -void SaveGame::saveItems() -{ - // Save level items - for (int i = 0; i < g_Level.NumItems; i++) - m_writer->WriteChunkWithChildren(m_chunkItem.get(), &saveItem, i, 0); - - // Save items created at runtime (flares, missiles...) - for (int i = g_Level.NumItems; i < NUM_ITEMS; i++) - { - ITEM_INFO* item = &g_Level.Items[i]; - if (item->active) - { - // Some items are very special and are saved in specific functions, all the others use the general function - if (item->objectNumber == ID_BURNING_TORCH_ITEM) - m_writer->WriteChunk(m_chunkSpecialItemBurningTorch.get(), &saveBurningTorch, i, 1); - else if (item->objectNumber == ID_CHAFF) - m_writer->WriteChunk(m_chunkSpecialItemChaff.get(), &saveChaff, i, 1); - else if (item->objectNumber == ID_TORPEDO) - m_writer->WriteChunk(m_chunkSpecialItemTorpedo.get(), &saveTorpedo, i, 1); - else if (item->objectNumber == ID_CROSSBOW_BOLT) - m_writer->WriteChunk(m_chunkSpecialItemCrossbowBolt.get(), &saveCrossbowBolt, i, 1); - else if (item->objectNumber == ID_FLARE_ITEM) - m_writer->WriteChunk(m_chunkSpecialItemFlare.get(), &saveFlare, i, 1); - else - m_writer->WriteChunkWithChildren(m_chunkItem.get(), &saveItem, i, 1); - } - } - - // Save special items - if (Objects[ID_BATS_EMITTER].loaded) - for (int i = 0; i < NUM_BATS; i++) - if (Bats[i].on) - m_writer->WriteChunk(m_chunkBats.get(), &saveBats, i, 0); - - if (Objects[ID_RATS_EMITTER].loaded) - for (int i = 0; i < NUM_RATS; i++) - if (Rats[i].on) - m_writer->WriteChunk(m_chunkRats.get(), &saveRats, i, 0); - - if (Objects[ID_SPIDERS_EMITTER].loaded) - for (int i = 0; i < NUM_SPIDERS; i++) - if (Spiders[i].on) - m_writer->WriteChunk(m_chunkSpiders.get(), &saveSpiders, i, 0); -} - -void SaveGame::saveItem(int itemNumber, int runtimeItem) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - OBJECT_INFO* obj = &Objects[item->objectNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, runtimeItem); - - bool hasData = true; - - if (item->flags & IFLAG_KILLED) - { - LEB128::Write(m_stream, 0x2000); - hasData = false; - } - else if (item->flags & (IFLAG_ACTIVATION_MASK | IFLAG_INVISIBLE | 0x20) - || item->objectNumber == ID_LARA) - { - LEB128::Write(m_stream, 0x8000); - hasData = true; - } - else - { - LEB128::Write(m_stream, 0x0000); - hasData = false; - } - - LEB128::Write(m_stream, item->objectNumber); - - if (hasData) - { - m_writer->WriteChunkInt(m_chunkItemDummy.get(), 1); - - if (obj->saveAnim) - m_writer->WriteChunk(m_chunkItemAnims.get(), &saveItemAnims, itemNumber, 0); - - if (obj->savePosition) - m_writer->WriteChunk(m_chunkItemPosition.get(), &saveItemPosition, itemNumber, 0); - - if (obj->saveHitpoints) - m_writer->WriteChunk(m_chunkItemHitPoints.get(), &saveItemHitPoints, itemNumber, 0); - - if (obj->saveFlags) - m_writer->WriteChunkWithChildren(m_chunkItemFlags.get(), &saveItemFlags, itemNumber, 0); - - if (obj->saveMesh) - m_writer->WriteChunk(m_chunkItemMeshes.get(), &saveItemMesh, itemNumber, 0); - - if (obj->intelligent && item->data != NULL) - m_writer->WriteChunk(m_chunkItemIntelligentData.get(), &saveItemIntelligentData, itemNumber, 0); - } - else - { - m_writer->WriteChunkInt(m_chunkItemDummy.get(), 1); - } -} - -void SaveGame::saveGameStatus(int arg1, int arg2) -{ - /*LEB128::Write(m_stream, FlipStatus); -#ifndef NEW_INV - LEB128::Write(m_stream, LastInventoryItem); -#endif - LEB128::Write(m_stream, FlipEffect); - LEB128::Write(m_stream, FlipTimer); - //LEB128::Write(m_stream, CurrentLoopedSoundTrack); - LEB128::Write(m_stream, CurrentSequence); - - // Now the sub-chunks - for (int i = 0; i < g_Level.Rooms.size(); i++) - for (int j = 0; j < g_Level.Rooms[i].mesh.size(); j++) - m_writer->WriteChunk(m_chunkStaticFlags.get(), &saveStaticFlag, i, j); - - for (int i = 0; i < 6; i++) - m_writer->WriteChunk(m_chunkSequenceSwitch.get(), &saveSequenceSwitch, i, SequenceUsed[i]); - - for (int i = 0; i < NumberSpotcams; i++) - m_writer->WriteChunk(m_chunkFlybyFlags.get(), &saveFlybyFlags, i, SpotCam[i].flags); - - for (int i = 0; i < SoundTracks.size(); i++) - m_writer->WriteChunk(m_chunkCdFlags.get(), &saveCdFlags, i, SoundTracks[i].Mask); - - for (int i = 0; i < NumberCameras; i++) - m_writer->WriteChunk(m_chunkCamera.get(), &saveCamera, i, FixedCameras[i].flags); - - for (int i = 0; i < 255; i++) - m_writer->WriteChunk(m_chunkFlipStats.get(), &saveFlipStats, i, FlipStats[i]); - - for (int i = 0; i < 255; i++) - m_writer->WriteChunk(m_chunkFlipMap.get(), &saveFlipMap, i, FlipMap[i]);*/ -} - -void SaveGame::saveLara(int arg1, int arg2) -{ - // LARA_INFO struct dumped to savegame - LaraInfo lara; - memcpy(&lara, &Lara, sizeof(Lara)); - - //lara.leftArm.frameBase = (short*)((char *)lara.leftArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase); - //lara.rightArm.frameBase = (short*)((char *)lara.rightArm.frameBase - (ptrdiff_t)Objects[ID_LARA].frameBase); - //lara.generalPtr = (char *)lara.generalPtr - (ptrdiff_t)malloc_buffer; - - m_stream->Write(reinterpret_cast(&lara), sizeof(Lara)); - - // Lara weapon data - if (Lara.weaponItem != NO_ITEM) - m_writer->WriteChunk(m_chunkWeaponItem.get(), &saveWeaponItem, Lara.weaponItem, 0); - - // Save Lara extra info - m_writer->WriteChunk(m_chunkLaraExtraInfo.get(), &saveLaraExtraInfo, 0, 0); - - // Save carried weapons - for (int i = 0; i < NUM_WEAPONS; i++) - { - m_writer->WriteChunk(m_chunkWeaponInfo.get(), &saveWeaponInfo, i, 0); - } - - // Save carried puzzles, keys, pickups and examines - for (int i = 0; i < NUM_PUZZLES; i++) - { - if (Lara.Puzzles[i] > 0) - m_writer->WriteChunk(m_chunkPuzzle.get(), &savePuzzle, i, Lara.Puzzles[i]); - } - - for (int i = 0; i < NUM_PUZZLES * 2; i++) - { - if (Lara.PuzzlesCombo[i] > 0) - m_writer->WriteChunk(m_chunkPuzzleCombo.get(), &savePuzzle, i, Lara.PuzzlesCombo[i]); - } - - for (int i = 0; i < NUM_KEYS; i++) - { - if (Lara.Keys[i] > 0) - m_writer->WriteChunk(m_chunkKey.get(), &savePuzzle, i, Lara.Keys[i]); - } - - for (int i = 0; i < NUM_KEYS * 2; i++) - { - if (Lara.KeysCombo[i] > 0) - m_writer->WriteChunk(m_chunkKeyCombo.get(), &savePuzzle, i, Lara.KeysCombo[i]); - } - - for (int i = 0; i < NUM_PICKUPS; i++) - { - if (Lara.Pickups[i] > 0) - m_writer->WriteChunk(m_chunkPickup.get(), &savePuzzle, i, Lara.Pickups[i]); - } - - for (int i = 0; i < NUM_PICKUPS * 2; i++) - { - if (Lara.PickupsCombo[i] > 0) - m_writer->WriteChunk(m_chunkPickupCombo.get(), &savePuzzle, i, Lara.PickupsCombo[i]); - } - - for (int i = 0; i < NUM_EXAMINES; i++) - { - if (Lara.Examines[i] > 0) - m_writer->WriteChunk(m_chunkExamine.get(), &savePuzzle, i, Lara.Examines[i]); - } - - for (int i = 0; i < NUM_EXAMINES * 2; i++) - { - if (Lara.ExaminesCombo[i] > 0) - m_writer->WriteChunk(m_chunkExamineCombo.get(), &savePuzzle, i, Lara.ExaminesCombo[i]); - } -} - -void SaveGame::saveWeaponItem(int arg1, int arg2) -{ - ITEM_INFO* weaponItem = &g_Level.Items[arg1]; - - LEB128::Write(m_stream, weaponItem->objectNumber); - LEB128::Write(m_stream, weaponItem->animNumber); - LEB128::Write(m_stream, weaponItem->frameNumber); - LEB128::Write(m_stream, weaponItem->currentAnimState); - LEB128::Write(m_stream, weaponItem->goalAnimState); - LEB128::Write(m_stream, weaponItem->requiredAnimState); -} - -void SaveGame::saveLaraExtraInfo(int arg1, int arg2) -{ - LEB128::Write(m_stream, (Lara.Binoculars ? 1 : 0)); - LEB128::Write(m_stream, (Lara.Lasersight ? 1 : 0)); - LEB128::Write(m_stream, (Lara.Crowbar ? 1 : 0)); - LEB128::Write(m_stream, (Lara.Silencer ? 1 : 0)); - LEB128::Write(m_stream, (Lara.Torch ? 1 : 0)); - LEB128::Write(m_stream, Lara.Secrets); - LEB128::Write(m_stream, Lara.ExtraAnim); - LEB128::Write(m_stream, Lara.Vehicle); - LEB128::Write(m_stream, Lara.mineL); - LEB128::Write(m_stream, Lara.mineR); - LEB128::Write(m_stream, Lara.NumFlares); - LEB128::Write(m_stream, Lara.NumLargeMedipacks); - LEB128::Write(m_stream, Lara.NumSmallMedipacks); -} - -void SaveGame::savePuzzle(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); // ID - LEB128::Write(m_stream, arg2); // Quantity -} - -void SaveGame::saveWeaponInfo(int arg1, int arg2) -{ - CarriedWeaponInfo* weapon = &Lara.Weapons[arg1]; - - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, weapon->Present); - LEB128::Write(m_stream, weapon->SelectedAmmo); - LEB128::Write(m_stream, weapon->Ammo[WEAPON_AMMO1]); - LEB128::Write(m_stream, weapon->Ammo[WEAPON_AMMO2]); - LEB128::Write(m_stream, weapon->Ammo[WEAPON_AMMO3]); - LEB128::Write(m_stream, weapon->HasSilencer); - LEB128::Write(m_stream, weapon->HasLasersight); -} - -void SaveGame::saveVariables() -{ - m_luaVariables.clear(); - //g_GameScript->GetVariables(&m_luaVariables); - for (int i = 0; i < m_luaVariables.size(); i++) - m_writer->WriteChunk(m_chunkLuaVariable.get(), &saveVariable, i, 0); -} - -void SaveGame::saveVariable(int arg1, int arg2) -{ - LuaVariable variable = m_luaVariables[arg1]; - - LEB128::Write(m_stream, variable.IsGlobal == 1); - LEB128::Write(m_stream, variable.Type); - m_stream->WriteString((char*)variable.Name.c_str()); - - /*if (variable.Type == LUA_VARIABLE_TYPE_BOOL) - m_stream->WriteBool(variable.BoolValue); - else if (variable.Type == LUA_VARIABLE_TYPE_INT) - m_stream->WriteInt32(variable.IntValue); - else if (variable.Type == LUA_VARIABLE_TYPE_STRING) - m_stream->WriteString((char*)variable.StringValue.c_str()); - else if (variable.Type == LUA_VARIABLE_TYPE_FLOAT) - m_stream->WriteFloat(variable.FloatValue);*/ -} - -void SaveGame::Start() -{ - m_chunkGameStatus = ChunkId::FromString("TR5MSgGameStatus"); - m_chunkItems = ChunkId::FromString("TR5MSgItems"); - m_chunkItem = ChunkId::FromString("TR5MSgItem"); - m_chunkLara = ChunkId::FromString("TR5MSgLara"); - m_chunkLuaVariable = ChunkId::FromString("TR5MSgLuaVar"); - m_chunkStaticFlags = ChunkId::FromString("TR5MSgStFl"); - m_chunkVehicle = ChunkId::FromString("TR5MSgLaraVeh"); - m_chunkSequenceSwitch = ChunkId::FromString("TR5MSgSeqSw"); - m_chunkFlybyFlags = ChunkId::FromString("TR5MSgFlybyF"); - m_chunkCdFlags = ChunkId::FromString("TR5MSgCdF"); - m_chunkCamera = ChunkId::FromString("TR5MSgCam"); - m_chunkFlipStats = ChunkId::FromString("TR5MSgFlS"); - m_chunkFlipMap = ChunkId::FromString("TR5MSgFlM"); - m_chunkItemDummy = ChunkId::FromString("TR5MSgItemDummy"); - m_chunkStatistics = ChunkId::FromString("TR5MSgStats"); - m_chunkItemAnims = ChunkId::FromString("TR5MSgItAnms"); - m_chunkItemMeshes = ChunkId::FromString("TR5MSgItMsh"); - m_chunkItemFlags = ChunkId::FromString("TR5MSgItFl"); - m_chunkItemHitPoints = ChunkId::FromString("TR5MSgItHP"); - m_chunkItemPosition = ChunkId::FromString("TR5MSgItPos"); - m_chunkItemIntelligentData = ChunkId::FromString("TR5MSgItIntell"); - m_chunkSpecialItemBurningTorch = ChunkId::FromString("TR5MSgItTorch"); - m_chunkSpecialItemChaff = ChunkId::FromString("TR5MSgItChaff"); - m_chunkSpecialItemTorpedo = ChunkId::FromString("TR5MSgItTorpedo"); - m_chunkSpecialItemCrossbowBolt = ChunkId::FromString("TR5MSgItBolt"); - m_chunkSpecialItemFlare = ChunkId::FromString("TR5MSgItFlare"); - m_chunkItemQuadInfo = ChunkId::FromString("TR5MSgQuadInfo"); - m_chunkBats = ChunkId::FromString("TR5MSgBats"); - m_chunkRats = ChunkId::FromString("TR5MSgRats"); - m_chunkSpiders = ChunkId::FromString("TR5MSgSpiders"); - m_chunkLaraExtraInfo = ChunkId::FromString("TR5MSgLaraExtraInfo"); - m_chunkWeaponInfo = ChunkId::FromString("TR5MSgWeapon"); - m_chunkPuzzle = ChunkId::FromString("TR5MSgPuzzle"); - m_chunkPuzzleCombo = ChunkId::FromString("TR5MSgPuzzleC"); - m_chunkKey = ChunkId::FromString("TR5MSgKey"); - m_chunkKeyCombo = ChunkId::FromString("TR5MSgKeyC"); - m_chunkPickup = ChunkId::FromString("TR5MSgPickup"); - m_chunkPickupCombo = ChunkId::FromString("TR5MSgPickupC"); - m_chunkExamine = ChunkId::FromString("TR5MSgExamine"); - m_chunkExamineCombo = ChunkId::FromString("TR5MSgExamineC"); - m_chunkWeaponItem = ChunkId::FromString("TR5MSgWeaponItem"); - - LastSaveGame = 0; -} - -void SaveGame::End() -{ -} bool SaveGame::Save(char* fileName) { - using namespace flatbuffers; - - ITEM_INFO itemToSerialize{}; FlatBufferBuilder fbb{}; Save::SaveGameBuilder sgb = Save::SaveGameBuilder(fbb); std::vector> serializedItems{}; + // Serialize Lara + /*Save::LaraT serializedLara; + + for (int i = 0; i < NUM_PUZZLES; i++) + serializedLara.puzzles.push_back(Lara.Puzzles[i]); + + for (int i = 0; i < NUM_PUZZLES * 2; i++) + serializedLara.puzzles_combo.push_back(Lara.PuzzlesCombo[i]); + + for (int i = 0; i < NUM_KEYS; i++) + serializedLara.keys.push_back(Lara.Keys[i]); + + for (int i = 0; i < NUM_KEYS * 2; i++) + serializedLara.keys_combo.push_back(Lara.KeysCombo[i]); + + for (int i = 0; i < NUM_PICKUPS; i++) + serializedLara.pickups.push_back(Lara.Pickups[i]); + + for (int i = 0; i < NUM_PICKUPS * 2; i++) + serializedLara.pickups_combo.push_back(Lara.PickupsCombo[i]); + + for (int i = 0; i < 15; i++) + serializedLara.mesh_ptrs.push_back(Lara.meshPtrs[i]); + + for (int i = 0; i < 15; i++) + serializedLara.wet.push_back(Lara.wet[i] == 1); + + auto arm = Save::CreateLaraArmInfo(fbb, 0, 0, 0, 0, 0, 0, 0, 0); + + serializedLara.left_arm = std::make_unique(new Save::LaraArmInfoT()); + Save::LaraArmInfoT* leftArm = serializedLara.left_arm.get(); + leftArm->anim_number = Lara.leftArm.animNumber; + leftArm->flash_gun = Lara.leftArm.flash_gun; + leftArm->frame_base = Lara.leftArm.frameBase; + leftArm->frame_number = Lara.leftArm.frameNumber; + leftArm->lock = Lara.leftArm.lock; + leftArm->x_rot = Lara.leftArm.xRot; + leftArm->y_rot = Lara.leftArm.yRot; + leftArm->z_rot = Lara.leftArm.zRot; + + serializedLara.right_arm = std::make_unique(new Save::LaraArmInfoT()); + Save::LaraArmInfoT* rightArm = serializedLara.right_arm.get(); + rightArm->anim_number = Lara.rightArm.animNumber; + rightArm->flash_gun = Lara.rightArm.flash_gun; + rightArm->frame_base = Lara.rightArm.frameBase; + rightArm->frame_number = Lara.rightArm.frameNumber; + rightArm->lock = Lara.rightArm.lock; + rightArm->x_rot = Lara.rightArm.xRot; + rightArm->y_rot = Lara.rightArm.yRot; + rightArm->z_rot = Lara.rightArm.zRot; + + serializedLara.air = Lara.air; + serializedLara.beetle_life = Lara.BeetleLife; + serializedLara.big_waterskin = Lara.big_waterskin; + serializedLara.binoculars = Lara.Binoculars; + serializedLara.burn = Lara.burn; + serializedLara.burn_blue = Lara.burnBlue; + serializedLara.burn_count = Lara.burnCount; + serializedLara.burn_smoke = Lara.burnSmoke; + serializedLara.busy = Lara.busy; + serializedLara.calc_fall_speed = Lara.calcFallSpeed; + serializedLara.can_monkey_swing = Lara.canMonkeySwing; + serializedLara.climb_status = Lara.climbStatus; + serializedLara.corner_x = Lara.cornerX; + serializedLara.corner_z = Lara.cornerZ; + serializedLara.crowbar = Lara.Crowbar; + serializedLara.current_active = Lara.currentActive; + serializedLara.current_x_vel = Lara.currentXvel; + serializedLara.current_y_vel = Lara.currentYvel; + serializedLara.current_z_vel = Lara.currentZvel; + serializedLara.death_count = Lara.deathCount; + serializedLara.dive_count = Lara.diveCount; + serializedLara.extra_anim = Lara.ExtraAnim; + //serializedLara.fall_speed = Lara.fallSpeed; + serializedLara.fired = Lara.fired; + serializedLara.flare_age = Lara.flareAge; + serializedLara.flare_control_left = Lara.flareControlLeft; + serializedLara.flare_frame = Lara.flareFrame; + serializedLara.gun_status = Lara.gunStatus; + serializedLara.gun_type = Lara.gunType; + serializedLara.has_beetle_things = Lara.hasBeetleThings; + serializedLara.has_fired = Lara.hasFired; + serializedLara.head_x_rot = Lara.headXrot; + serializedLara.head_y_rot = Lara.headYrot; + serializedLara.head_z_rot = Lara.headZrot; + serializedLara.highest_location = Lara.highestLocation; + serializedLara.hit_direction = Lara.hitDirection; + serializedLara.hit_frame = Lara.hitFrame; + serializedLara.interacted_item = Lara.interactedItem; + serializedLara.is_climbing = Lara.isClimbing; + serializedLara.is_ducked = Lara.isDucked; + serializedLara.is_moving = Lara.isMoving; + serializedLara.item_number = Lara.itemNumber; + serializedLara.keep_ducked = Lara.keepDucked; + serializedLara.lasersight = Lara.Lasersight; + serializedLara.last_gun_type = Lara.lastGunType; + Save::Vector3 lastPos = Save::Vector3(Lara.lastPos.x, Lara.lastPos.y, Lara.lastPos.z); + serializedLara.last_position = std::make_unique(&lastPos); + serializedLara.lit_torch = Lara.litTorch; + serializedLara.location = Lara.location; + serializedLara.location_pad = Lara.locationPad; + serializedLara.look = Lara.look; + serializedLara.mine_l = Lara.mineL; + serializedLara.mine_r = Lara.mineR; + serializedLara.move_angle = Lara.moveAngle; + serializedLara.move_count = Lara.moveCount; + serializedLara.num_flares = Lara.NumFlares; + serializedLara.num_small_medipacks = Lara.NumSmallMedipacks; + serializedLara.num_large_medipacks = Lara.NumLargeMedipacks; + serializedLara.old_busy = Lara.oldBusy; + serializedLara.poisoned = Lara.poisoned; + serializedLara.pose_count = Lara.poseCount; + serializedLara.request_gun_type = Lara.requestGunType; + serializedLara.rope_arc_back = Lara.ropeArcBack; + serializedLara.rope_arc_front = Lara.ropeArcFront; + serializedLara.rope_dframe = Lara.ropeDFrame; + serializedLara.rope_direction = Lara.ropeDirection; + serializedLara.rope_down_vel = Lara.ropeDownVel; + serializedLara.rope_flag = Lara.ropeFlag; + serializedLara.rope_framerate = Lara.ropeFrameRate; + serializedLara.rope_frame = Lara.ropeFrame; + serializedLara.rope_last_x = Lara.ropeLastX; + serializedLara.rope_max_x_backward = Lara.ropeMaxXBackward; + serializedLara.rope_max_x_forward = Lara.ropeMaxXForward; + serializedLara.rope_offset = Lara.ropeOffset; + serializedLara.rope_ptr = Lara.ropePtr; + serializedLara.rope_segment = Lara.ropeSegment; + serializedLara.rope_y = Lara.ropeY; + serializedLara.secrets = Lara.Secrets; + serializedLara.silencer = Lara.Silencer; + serializedLara.small_waterskin = Lara.small_waterskin; + serializedLara.spaz_effect_count = Lara.spazEffectCount; + serializedLara.target_angles.push_back(Lara.targetAngles[0]); + serializedLara.target_angles.push_back(Lara.targetAngles[1]); + serializedLara.target_item_number = Lara.target - g_Level.Items.data(); + //serializedLara.tightrope = Lara.air; + serializedLara.torch = Lara.Torch; + serializedLara.torso_x_rot = Lara.torsoXrot; + serializedLara.torso_y_rot = Lara.torsoYrot; + serializedLara.torso_z_rot = Lara.torsoZrot; + serializedLara.turn_rate = Lara.turnRate; + serializedLara.uncontrollable = Lara.uncontrollable; + serializedLara.vehicle = Lara.Vehicle; + serializedLara.water_status = Lara.waterStatus; + serializedLara.water_surface_dist = Lara.waterSurfaceDist; + serializedLara.weapon_item = Lara.weaponItem; + */ + + Save::SaveGameT sg; + + // Create the savegame header + Save::SaveGameHeaderT* header = sg.header.get(); + header->level_name = g_GameFlow->GetString(g_GameFlow->GetLevel(CurrentLevel)->NameStringKey.c_str()); + header->days = (GameTimer / 30) / 86400; + header->hours = ((GameTimer / 30) % 86400) / 3600; + header->minutes = ((GameTimer / 30) / 60) % 6; + header->seconds = (GameTimer / 30) % 60; + header->level = CurrentLevel; + header->level = GameTimer; + header->level = ++LastSaveGame; + + Save::SaveGameStatisticsT* levelStatistics = sg.level.get(); + levelStatistics->ammo_hits = Savegame.Level.AmmoHits; + levelStatistics->ammo_used = Savegame.Level.AmmoUsed; + levelStatistics->kills = Savegame.Level.Kills; + levelStatistics->medipacks_used = Savegame.Level.HealthUsed; + levelStatistics->distance = Savegame.Level.Distance; + levelStatistics->secrets = Savegame.Level.Secrets; + levelStatistics->timer = Savegame.Level.Timer; + + Save::SaveGameStatisticsT* gameStatistics = sg.game.get(); + gameStatistics->ammo_hits = Savegame.Game.AmmoHits; + gameStatistics->ammo_used = Savegame.Game.AmmoUsed; + gameStatistics->kills = Savegame.Game.Kills; + gameStatistics->medipacks_used = Savegame.Game.HealthUsed; + gameStatistics->distance = Savegame.Game.Distance; + gameStatistics->secrets = Savegame.Game.Secrets; + gameStatistics->timer = Savegame.Game.Timer; + for (const auto& itemToSerialize : g_Level.Items) { Save::ItemT serializedItem{}; + serializedItem.anim_number = itemToSerialize.animNumber; + serializedItem.after_death = itemToSerialize.afterDeath; + serializedItem.box_number = itemToSerialize.boxNumber; + serializedItem.carried_item = itemToSerialize.carriedItem; + serializedItem.current_anim_state = itemToSerialize.currentAnimState; + serializedItem.fall_speed = itemToSerialize.fallspeed; + serializedItem.fired_weapon = itemToSerialize.firedWeapon; + serializedItem.flags = itemToSerialize.flags; + serializedItem.floor = itemToSerialize.floor; + serializedItem.frame_number = itemToSerialize.frameNumber; + serializedItem.goal_anim_state = itemToSerialize.goalAnimState; + serializedItem.hit_points = itemToSerialize.hitPoints; + for (int i = 0; i < 7; i++) + serializedItem.item_flags.push_back(itemToSerialize.itemFlags[i]); + serializedItem.mesh_bits = itemToSerialize.meshBits; + serializedItem.object_id = itemToSerialize.objectNumber; + serializedItem.required_anim_state = itemToSerialize.requiredAnimState; + serializedItem.room_number = itemToSerialize.roomNumber; + serializedItem.speed = itemToSerialize.speed; + serializedItem.timer = itemToSerialize.timer; + serializedItem.touch_bits = itemToSerialize.touchBits; + serializedItem.trigger_flags = itemToSerialize.triggerFlags; + //serialize Items here serializedItems.push_back(Save::CreateItem(fbb, &serializedItem)); } - sgb.add_ambient_track(4) // serialize single field - sgb.add_items(fbb.CreateVector(serializedItems)); - auto serializedSave = sgb.Finish(); + + //sgb.add_ambient_track(4); + //sgb.add_items(fbb.CreateVector(serializedItems)); + + //auto serializedSave = sgb.Finish(); + fbb.Finish(Save::SaveGame::Pack(fbb, &sg)); auto bufferToSerialize = fbb.GetBufferPointer(); auto bufferSize = fbb.GetSize(); @@ -438,186 +261,10 @@ bool SaveGame::Save(char* fileName) fileOut.open(fileName, std::ios_base::binary | std::ios_base::out); fileOut.write((char*)bufferToSerialize, bufferSize); fileOut.close(); -} - - -bool SaveGame::readGameStatus() -{ - FlipStatus = LEB128::ReadInt32(m_stream); -#ifndef NEW_INV - LastInventoryItem = LEB128::ReadInt32(m_stream); -#endif - FlipEffect = LEB128::ReadInt32(m_stream); - CurrentLoopedSoundTrack = LEB128::ReadByte(m_stream); - CurrentSequence = LEB128::ReadByte(m_stream); - - m_reader->ReadChunks(&readGameStatusChunks, 0); return true; } -bool SaveGame::readLara() -{ - // Read dumped LARA_INFO struct - char* buffer = (char*)malloc(sizeof(LaraInfo)); - m_stream->Read(buffer, sizeof(LaraInfo)); - LaraInfo* lara = reinterpret_cast(buffer); - memcpy(&Lara, lara, sizeof(LaraInfo)); - free(buffer); - - //Lara.leftArm.frameBase = AddPtr(Lara.leftArm.frameBase, short, Objects[ID_LARA].frameBase); - //Lara.rightArm.frameBase = AddPtr(Lara.rightArm.frameBase, short, Objects[ID_LARA].frameBase); - - Lara.target = NULL; - Lara.spazEffect = NULL; - //Lara.generalPtr = AddPtr(Lara.generalPtr, char, malloc_buffer); - Lara.weaponItem = NO_ITEM; - - // Is Lara burning? - if (Lara.burn) - { - Lara.burn = false; - bool smokeFlag = false; - if (Lara.burnSmoke) - { - Lara.burnSmoke = false; - smokeFlag = true; - } - - LaraBurn(); - if (smokeFlag) - Lara.burnSmoke = true; - } - - m_reader->ReadChunks(&readLaraChunks, 0); - return true; -} - -bool SaveGame::readItem() -{ - short itemNumber = LEB128::ReadInt16(m_stream); - short runtimeItem = LEB128::ReadByte(m_stream); - short itemKind = LEB128::ReadInt16(m_stream); - - // Runtime items must be allocated dynamically - if (runtimeItem) - itemNumber = CreateItem(); - - ITEM_INFO* item = &g_Level.Items[itemNumber]; - item->objectNumber = from_underlying(LEB128::ReadInt16(m_stream)); - - OBJECT_INFO* obj = &Objects[item->objectNumber]; - - // Runtime items must be initialised - // TODO: test test test!!! - if (runtimeItem) - { - InitialiseItem(itemNumber); - AddActiveItem(itemNumber); - } - - if (itemKind == 0x2000) - { - m_reader->ReadChunks(&readItemChunks, itemNumber); - DisableBaddieAI(itemNumber); - KillItem(itemNumber); - item->status = ITEM_DEACTIVATED; - item->flags |= ONESHOT; - item->afterDeath = 128; - } - else if (itemKind == 0x8000) - { - m_reader->ReadChunks(&readItemChunks, itemNumber); - } - else - { - m_reader->ReadChunks(&readItemChunks, itemNumber); - } - - // Some post-processing things - if (obj->isPuzzleHole && (item->status == ITEM_DEACTIVATED || item->status == ITEM_ACTIVE)) - item->objectNumber += GAME_OBJECT_ID{ NUM_PUZZLES }; - - if (item->objectNumber >= ID_SMASH_OBJECT1 && item->objectNumber <= ID_SMASH_OBJECT8 && (item->flags & ONESHOT)) - item->meshBits = 0x100; - - if (item->objectNumber == ID_RAISING_BLOCK1 && item->itemFlags[1]) - { - //if (item->triggerFlags == -1) - // AlterFloorHeight(item, -255); - //else if (item->triggerFlags == -3) - // AlterFloorHeight(item, -1023); - //else - // AlterFloorHeight(item, -1024); - } - - //if (item->objectNumber == ID_RAISING_BLOCK2 && item->itemFlags[1]) - // AlterFloorHeight(item, -2048); - - return true; -} - -bool SaveGame::readVariable() -{ - LuaVariable variable; - - variable.IsGlobal = LEB128::ReadByte(m_stream) == 1; - variable.Type = LEB128::ReadInt32(m_stream); - - char* variableName; - m_stream->ReadString(&variableName); - variable.Name = string(variableName); - free(variableName); - - /*if (variable.Type == LUA_VARIABLE_TYPE_BOOL) - m_stream->ReadBool(&variable.BoolValue); - else if (variable.Type == LUA_VARIABLE_TYPE_INT) - m_stream->ReadInt32(&variable.IntValue); - else if (variable.Type == LUA_VARIABLE_TYPE_FLOAT) - m_stream->ReadFloat(&variable.FloatValue); - else if (variable.Type == LUA_VARIABLE_TYPE_STRING) - { - char* variableValue; - m_stream->ReadString(&variableValue); - variable.StringValue = string(variableValue); - free(variableValue); - }*/ - - return true; -} - -bool SaveGame::readSavegameChunks(ChunkId* chunkId, int maxSize, int arg) -{ - if (chunkId->EqualsTo(m_chunkGameStatus.get())) - return readGameStatus(); - else if (chunkId->EqualsTo(m_chunkLara.get())) - return readLara(); - else if (chunkId->EqualsTo(m_chunkItem.get())) - return readItem(); - else if (chunkId->EqualsTo(m_chunkLuaVariable.get())) - return readVariable(); - else if (chunkId->EqualsTo(m_chunkStatistics.get())) - return readStatistics(); - else if (chunkId->EqualsTo(m_chunkSpecialItemBurningTorch.get())) - return readBurningTorch(); - else if (chunkId->EqualsTo(m_chunkSpecialItemChaff.get())) - return readChaff(); - else if (chunkId->EqualsTo(m_chunkSpecialItemTorpedo.get())) - return readTorpedo(); - else if (chunkId->EqualsTo(m_chunkSpecialItemCrossbowBolt.get())) - return readCrossbowBolt(); - else if (chunkId->EqualsTo(m_chunkSpecialItemFlare.get())) - return readFlare(); - else if (chunkId->EqualsTo(m_chunkBats.get())) - return readBats(); - else if (chunkId->EqualsTo(m_chunkRats.get())) - return readRats(); - else if (chunkId->EqualsTo(m_chunkSpiders.get())) - return readSpiders(); - - return false; -} - bool SaveGame::Load(char* fileName) { std::ifstream file; @@ -636,888 +283,40 @@ bool SaveGame::Load(char* fileName) //g_Level.Items.begin() -> replaces Items in g_Level with new ones until SaveGame Vector reaches and (possible out of bounds since g_Level Items has size of 1024, but logically impossible) // std::back_inserter(g_Level.Items) would append! - std::transform(s->items()->begin(), s->items()->end(),g_Level.Items.begin(), [](const Save::Item& savedItem) { - + /*std::transform(s->items()->begin(), s->items()->end(), g_Level.Items.begin(), [](const Save::Item& savedItem) { + //transform savegame item into game item ITEM_INFO i{}; i.hitPoints = savedItem.hit_points(); i.animNumber = savedItem.anim_number(); // and so on; return i; - }); - + });*/ + + return true; } bool SaveGame::LoadHeader(char* fileName, SaveGameHeader* header) { - m_stream = new FileStream(fileName, true, false); - m_reader = new ChunkReader(0x4D355254, m_stream); + std::ifstream file; + file.open(fileName, std::ios_base::app | std::ios_base::binary); + file.seekg(0, std::ios::end); + size_t length = file.tellg(); + file.seekg(0, std::ios::beg); + std::unique_ptr buffer = std::make_unique(length); + file.read(buffer.get(), length); + file.close(); - // Header must be here - char* levelName; - m_stream->ReadString(&levelName); - header->LevelName = string(levelName); - free(levelName); + const Save::SaveGame* s = Save::GetSaveGame(buffer.get()); - // Skip timer - header->Days = LEB128::ReadInt32(m_stream); - header->Hours = LEB128::ReadInt32(m_stream); - header->Minutes = LEB128::ReadInt32(m_stream); - header->Seconds = LEB128::ReadInt32(m_stream); - - header->Level = LEB128::ReadByte(m_stream); - header->Timer = LEB128::ReadInt32(m_stream); - header->Count = LEB128::ReadInt32(m_stream); - - // Close the stream - m_stream->Close(); - //delete m_writer; - //delete m_stream; + header->levelName = s->header()->level_name()->str(); + header->days = s->header()->days(); + header->hours = s->header()->hours(); + header->minutes = s->header()->minutes(); + header->seconds = s->header()->seconds(); + header->level = s->header()->level(); + header->timer = s->header()->timer(); + header->count = s->header()->count(); return true; } - -void SaveGame::saveStaticFlag(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); - LEB128::Write(m_stream, g_Level.Rooms[arg1].mesh[arg2].flags); -} - -bool SaveGame::readLaraChunks(ChunkId* chunkId, int maxSize, int arg) -{ - if (chunkId->EqualsTo(m_chunkLaraExtraInfo.get())) - { - Lara.Binoculars = LEB128::ReadByte(m_stream); - Lara.Lasersight = LEB128::ReadByte(m_stream); - Lara.Crowbar = LEB128::ReadByte(m_stream); - Lara.Silencer = LEB128::ReadByte(m_stream); - Lara.Torch = LEB128::ReadByte(m_stream); - Lara.Secrets = LEB128::ReadInt32(m_stream); - Lara.ExtraAnim = LEB128::ReadInt16(m_stream); - Lara.Vehicle = LEB128::ReadInt16(m_stream); - Lara.mineL = LEB128::ReadByte(m_stream); - Lara.mineR = LEB128::ReadByte(m_stream); - Lara.NumFlares = LEB128::ReadInt32(m_stream); - Lara.NumLargeMedipacks = LEB128::ReadInt32(m_stream); - Lara.NumSmallMedipacks = LEB128::ReadInt32(m_stream); - - return true; - } - else if (chunkId->EqualsTo(m_chunkWeaponInfo.get())) - { - int id = LEB128::ReadInt32(m_stream); - CarriedWeaponInfo* weapon = &Lara.Weapons[id]; - - weapon->Present = LEB128::ReadByte(m_stream); - weapon->SelectedAmmo = LEB128::ReadByte(m_stream); - weapon->Ammo[WEAPON_AMMO1] = LEB128::ReadInt16(m_stream); - weapon->Ammo[WEAPON_AMMO2] = LEB128::ReadInt16(m_stream); - weapon->Ammo[WEAPON_AMMO3] = LEB128::ReadInt16(m_stream); - weapon->HasSilencer = LEB128::ReadByte(m_stream); - weapon->HasLasersight = LEB128::ReadByte(m_stream); - } - else if (chunkId->EqualsTo(m_chunkPuzzle.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.Puzzles[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkPuzzleCombo.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.PuzzlesCombo[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkKey.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.Keys[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkKeyCombo.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.KeysCombo[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkPickup.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.Pickups[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkPickupCombo.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.PickupsCombo[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkExamine.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.Examines[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkExamineCombo.get())) - { - int id = LEB128::ReadInt32(m_stream); - int quantity = LEB128::ReadInt32(m_stream); - Lara.ExaminesCombo[id] = quantity; - } - else if (chunkId->EqualsTo(m_chunkWeaponItem.get())) - { - short weaponItemNum = CreateItem(); - Lara.weaponItem = weaponItemNum; - - ITEM_INFO* weaponItem = &g_Level.Items[Lara.weaponItem]; - - weaponItem->objectNumber = from_underlying(LEB128::ReadInt16(m_stream)); - weaponItem->animNumber = LEB128::ReadInt16(m_stream); - weaponItem->frameNumber = LEB128::ReadInt16(m_stream); - weaponItem->currentAnimState = LEB128::ReadInt16(m_stream); - weaponItem->goalAnimState = LEB128::ReadInt16(m_stream); - weaponItem->requiredAnimState = LEB128::ReadInt16(m_stream); - weaponItem->roomNumber = 255; - } - - return false; -} - -bool SaveGame::readGameStatusChunks(ChunkId* chunkId, int maxSize, int arg) -{ - if (chunkId->EqualsTo(m_chunkStaticFlags.get())) - { - short roomIndex = LEB128::ReadInt16(m_stream); - short staticIndex = LEB128::ReadInt16(m_stream); - short flags = LEB128::ReadInt16(m_stream); - g_Level.Rooms[roomIndex].mesh[staticIndex].flags = flags; - - if (!flags) - { - FLOOR_INFO* floor = GetFloor(g_Level.Rooms[roomIndex].mesh[staticIndex].pos.xPos, - g_Level.Rooms[roomIndex].mesh[staticIndex].pos.yPos, - g_Level.Rooms[roomIndex].mesh[staticIndex].pos.zPos, - &roomIndex); - - TestTriggers(g_Level.Rooms[roomIndex].mesh[staticIndex].pos.xPos, - g_Level.Rooms[roomIndex].mesh[staticIndex].pos.yPos, - g_Level.Rooms[roomIndex].mesh[staticIndex].pos.zPos, roomIndex, true); - - floor->Stopper = false; - } - - return true; - } - else if (chunkId->EqualsTo(m_chunkFlipStats.get())) - { - short index = LEB128::ReadInt16(m_stream); - short value = LEB128::ReadInt16(m_stream); - //FlipStats[index] = value; - return true; - } - else if (chunkId->EqualsTo(m_chunkFlipMap.get())) - { - short index = LEB128::ReadInt16(m_stream); - short value = LEB128::ReadInt16(m_stream); - FlipMap[index] = value; - if ((value & 0x3E00) == 0x3E00) - DoFlipMap(index); - return true; - } - /*else if (chunkId->EqualsTo(m_chunkCdFlags.get())) - { - short index = LEB128::ReadInt16(m_stream); - printf("Index: %d\n", index); - short value = LEB128::ReadInt16(m_stream); - if (index < SoundTracks.size()) - SoundTracks[index].Mask = value; - return true; - }*/ - else if (chunkId->EqualsTo(m_chunkCamera.get())) - { - short index = LEB128::ReadInt16(m_stream); - short value = LEB128::ReadInt16(m_stream); - g_Level.Cameras[index].flags = value; - return true; - } - else if (chunkId->EqualsTo(m_chunkSequenceSwitch.get())) - { - short index = LEB128::ReadInt16(m_stream); - short value = LEB128::ReadInt16(m_stream); - SequenceUsed[index] = value; - return true; - } - else if (chunkId->EqualsTo(m_chunkFlybyFlags.get())) - { - int index = LEB128::ReadInt16(m_stream); - int value = LEB128::ReadInt16(m_stream); - SpotCam[index].flags = value; - return true; - } - return false; -} - -void SaveGame::saveCamera(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -void SaveGame::saveSequenceSwitch(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -void SaveGame::saveFlybyFlags(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -void SaveGame::saveFlipMap(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -void SaveGame::saveFlipStats(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -void SaveGame::saveCdFlags(int arg1, int arg2) -{ - LEB128::Write(m_stream, arg1); - LEB128::Write(m_stream, arg2); -} - -bool SaveGame::readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - if (chunkId->EqualsTo(m_chunkItemDummy.get())) - return m_reader->ReadChunkInt32(maxSize); - else if (chunkId->EqualsTo(m_chunkItemAnims.get())) - { - item->currentAnimState = LEB128::ReadInt16(m_stream); - item->goalAnimState = LEB128::ReadInt16(m_stream); - item->requiredAnimState = LEB128::ReadInt16(m_stream); - item->animNumber = LEB128::ReadInt16(m_stream); - item->frameNumber = LEB128::ReadInt16(m_stream); - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemPosition.get())) - { - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - - short roomNumber = LEB128::ReadInt16(m_stream); - if (item->roomNumber != roomNumber) - ItemNewRoom(itemNumber, roomNumber); - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemHitPoints.get())) - { - item->hitPoints = LEB128::ReadInt16(m_stream); - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemFlags.get())) - { - item->flags = LEB128::ReadInt16(m_stream); - byte active = LEB128::ReadByte(m_stream); - item->status = LEB128::ReadByte(m_stream); - item->gravityStatus = LEB128::ReadByte(m_stream); - item->hitStatus = LEB128::ReadByte(m_stream); - item->collidable = LEB128::ReadByte(m_stream); - item->lookedAt = LEB128::ReadByte(m_stream); - item->dynamicLight = LEB128::ReadByte(m_stream); - item->poisoned = LEB128::ReadByte(m_stream); - item->aiBits = LEB128::ReadByte(m_stream); - item->reallyActive = LEB128::ReadByte(m_stream); - item->triggerFlags = LEB128::ReadInt16(m_stream); - item->timer = LEB128::ReadByte(m_stream); - item->itemFlags[0] = LEB128::ReadInt16(m_stream); - item->itemFlags[1] = LEB128::ReadInt16(m_stream); - item->itemFlags[2] = LEB128::ReadInt16(m_stream); - item->itemFlags[3] = LEB128::ReadInt16(m_stream); - - if (active && !item->active) - AddActiveItem(itemNumber); - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemIntelligentData.get())) - { - EnableBaddieAI(itemNumber, 1); - - OBJECT_INFO* obj = &Objects[item->objectNumber]; - CREATURE_INFO* creature = (CREATURE_INFO*)item->data; - - creature->jointRotation[0] = LEB128::ReadInt16(m_stream); - creature->jointRotation[1] = LEB128::ReadInt16(m_stream); - creature->jointRotation[2] = LEB128::ReadInt16(m_stream); - creature->jointRotation[3] = LEB128::ReadInt16(m_stream); - creature->maximumTurn = LEB128::ReadInt16(m_stream); - creature->flags = LEB128::ReadInt16(m_stream); - creature->alerted = LEB128::ReadByte(m_stream); - creature->headLeft = LEB128::ReadByte(m_stream); - creature->headRight = LEB128::ReadByte(m_stream); - creature->reachedGoal = LEB128::ReadByte(m_stream); - creature->hurtByLara = LEB128::ReadByte(m_stream); - creature->patrol2 = LEB128::ReadByte(m_stream); - creature->jumpAhead = LEB128::ReadByte(m_stream); - creature->monkeyAhead = LEB128::ReadByte(m_stream); - creature->mood = (MOOD_TYPE)LEB128::ReadInt32(m_stream); - - ITEM_INFO* enemy = (ITEM_INFO*)LEB128::ReadLong(m_stream); - //creature->enemy = AddPtr(enemy, ITEM_INFO, malloc_buffer); - - creature->aiTarget.objectNumber = from_underlying(LEB128::ReadInt16(m_stream)); - creature->aiTarget.roomNumber = LEB128::ReadInt16(m_stream); - creature->aiTarget.boxNumber = LEB128::ReadInt16(m_stream); - creature->aiTarget.flags = LEB128::ReadInt16(m_stream); - creature->aiTarget.pos.xPos = LEB128::ReadInt32(m_stream); - creature->aiTarget.pos.yPos = LEB128::ReadInt32(m_stream); - creature->aiTarget.pos.zPos = LEB128::ReadInt32(m_stream); - creature->aiTarget.pos.xRot = LEB128::ReadInt16(m_stream); - creature->aiTarget.pos.yRot = LEB128::ReadInt16(m_stream); - creature->aiTarget.pos.zRot = LEB128::ReadInt16(m_stream); - - creature->LOT.canJump = LEB128::ReadByte(m_stream); - creature->LOT.canMonkey = LEB128::ReadByte(m_stream); - creature->LOT.isAmphibious = LEB128::ReadByte(m_stream); - creature->LOT.isJumping = LEB128::ReadByte(m_stream); - creature->LOT.isMonkeying = LEB128::ReadByte(m_stream); - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemQuadInfo.get())) - { - //QUAD_INFO* quadInfo = game_malloc(); - //m_stream->ReadBytes(reinterpret_cast(quadInfo), sizeof(QUAD_INFO)); - //if (item->objectNumber == ID_QUAD) - // item->data = quadInfo; - - return true; - } - else if (chunkId->EqualsTo(m_chunkItemMeshes.get())) - { - item->meshBits = LEB128::ReadInt32(m_stream); - item->swapMeshFlags = LEB128::ReadInt32(m_stream); - - return true; - } - - return false; -} - -void SaveGame::saveStatistics(int arg1, int arg2) -{ - LEB128::Write(m_stream, Savegame.Game.AmmoHits); - LEB128::Write(m_stream, Savegame.Game.AmmoUsed); - LEB128::Write(m_stream, Savegame.Game.Distance); - LEB128::Write(m_stream, Savegame.Game.HealthUsed); - LEB128::Write(m_stream, Savegame.Game.Kills); - LEB128::Write(m_stream, Savegame.Game.Secrets); - LEB128::Write(m_stream, Savegame.Game.Timer); - - LEB128::Write(m_stream, Savegame.Level.AmmoHits); - LEB128::Write(m_stream, Savegame.Level.AmmoUsed); - LEB128::Write(m_stream, Savegame.Level.Distance); - LEB128::Write(m_stream, Savegame.Level.HealthUsed); - LEB128::Write(m_stream, Savegame.Level.Kills); - LEB128::Write(m_stream, Savegame.Level.Secrets); - LEB128::Write(m_stream, Savegame.Level.Timer); -} - -bool SaveGame::readStatistics() -{ - Savegame.Game.AmmoHits = LEB128::ReadInt32(m_stream); - Savegame.Game.AmmoUsed = LEB128::ReadInt32(m_stream); - Savegame.Game.Distance = LEB128::ReadInt32(m_stream); - Savegame.Game.HealthUsed = LEB128::ReadByte(m_stream); - Savegame.Game.Kills = LEB128::ReadInt16(m_stream); - Savegame.Game.Secrets = LEB128::ReadByte(m_stream); - Savegame.Game.Timer = LEB128::ReadInt32(m_stream); - - Savegame.Level.AmmoHits = LEB128::ReadInt32(m_stream); - Savegame.Level.AmmoUsed = LEB128::ReadInt32(m_stream); - Savegame.Level.Distance = LEB128::ReadInt32(m_stream); - Savegame.Level.HealthUsed = LEB128::ReadByte(m_stream); - Savegame.Level.Kills = LEB128::ReadInt16(m_stream); - Savegame.Level.Secrets = LEB128::ReadByte(m_stream); - Savegame.Level.Timer = LEB128::ReadInt32(m_stream); - - return true; -} - -void SaveGame::saveItemFlags(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - OBJECT_INFO* obj = &Objects[item->objectNumber]; - - LEB128::Write(m_stream, item->flags); - LEB128::Write(m_stream, item->active); - LEB128::Write(m_stream, item->status); - LEB128::Write(m_stream, item->gravityStatus); - LEB128::Write(m_stream, item->hitStatus); - LEB128::Write(m_stream, item->collidable); - LEB128::Write(m_stream, item->lookedAt); - LEB128::Write(m_stream, item->dynamicLight); - LEB128::Write(m_stream, item->poisoned); - LEB128::Write(m_stream, item->aiBits); - LEB128::Write(m_stream, item->reallyActive); - LEB128::Write(m_stream, item->triggerFlags); - LEB128::Write(m_stream, item->timer); - LEB128::Write(m_stream, item->itemFlags[0]); - LEB128::Write(m_stream, item->itemFlags[1]); - LEB128::Write(m_stream, item->itemFlags[2]); - LEB128::Write(m_stream, item->itemFlags[3]); -} - -void SaveGame::saveItemIntelligentData(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - OBJECT_INFO* obj = &Objects[item->objectNumber]; - CREATURE_INFO* creature = (CREATURE_INFO*)item->data; - - ITEM_INFO* enemy = (ITEM_INFO*)((char*)creature->enemy); - - LEB128::Write(m_stream, creature->jointRotation[0]); - LEB128::Write(m_stream, creature->jointRotation[1]); - LEB128::Write(m_stream, creature->jointRotation[2]); - LEB128::Write(m_stream, creature->jointRotation[3]); - LEB128::Write(m_stream, creature->maximumTurn); - LEB128::Write(m_stream, creature->flags); - LEB128::Write(m_stream, creature->alerted); - LEB128::Write(m_stream, creature->headLeft); - LEB128::Write(m_stream, creature->headRight); - LEB128::Write(m_stream, creature->reachedGoal); - LEB128::Write(m_stream, creature->hurtByLara); - LEB128::Write(m_stream, creature->patrol2); - LEB128::Write(m_stream, creature->jumpAhead); - LEB128::Write(m_stream, creature->monkeyAhead); - LEB128::Write(m_stream, creature->mood); - LEB128::Write(m_stream, (int)enemy); - - LEB128::Write(m_stream, creature->aiTarget.objectNumber); - LEB128::Write(m_stream, creature->aiTarget.roomNumber); - LEB128::Write(m_stream, creature->aiTarget.boxNumber); - LEB128::Write(m_stream, creature->aiTarget.flags); - LEB128::Write(m_stream, creature->aiTarget.pos.xPos); - LEB128::Write(m_stream, creature->aiTarget.pos.yPos); - LEB128::Write(m_stream, creature->aiTarget.pos.zPos); - LEB128::Write(m_stream, creature->aiTarget.pos.xRot); - LEB128::Write(m_stream, creature->aiTarget.pos.yRot); - LEB128::Write(m_stream, creature->aiTarget.pos.zRot); - - LEB128::Write(m_stream, creature->LOT.canJump); - LEB128::Write(m_stream, creature->LOT.canMonkey); - LEB128::Write(m_stream, creature->LOT.isAmphibious); - LEB128::Write(m_stream, creature->LOT.isJumping); - LEB128::Write(m_stream, creature->LOT.isMonkeying); -} - -void SaveGame::saveItemHitPoints(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - - LEB128::Write(m_stream, item->hitPoints); -} - -void SaveGame::saveItemPosition(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); -} - -void SaveGame::saveItemMesh(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - - LEB128::Write(m_stream, item->meshBits); - LEB128::Write(m_stream, item->swapMeshFlags); -} - -void SaveGame::saveItemAnims(int arg1, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[arg1]; - - LEB128::Write(m_stream, item->currentAnimState); - LEB128::Write(m_stream, item->goalAnimState); - LEB128::Write(m_stream, item->requiredAnimState); - LEB128::Write(m_stream, item->animNumber); - LEB128::Write(m_stream, item->frameNumber); -} - -void SaveGame::saveBurningTorch(int itemNumber, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); - - LEB128::Write(m_stream, item->itemFlags[2]); -} - -void SaveGame::saveChaff(int itemNumber, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); - - LEB128::Write(m_stream, item->itemFlags[0]); - LEB128::Write(m_stream, item->itemFlags[1]); -} - -void SaveGame::saveTorpedo(int itemNumber, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); - - LEB128::Write(m_stream, item->itemFlags[0]); - LEB128::Write(m_stream, item->itemFlags[1]); - LEB128::Write(m_stream, item->currentAnimState); - LEB128::Write(m_stream, item->goalAnimState); - LEB128::Write(m_stream, item->requiredAnimState); -} - -void SaveGame::saveCrossbowBolt(int itemNumber, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); -} - -void SaveGame::saveFlare(int itemNumber, int arg2) -{ - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - LEB128::Write(m_stream, itemNumber); - LEB128::Write(m_stream, item->pos.xPos); - LEB128::Write(m_stream, item->pos.yPos); - LEB128::Write(m_stream, item->pos.zPos); - LEB128::Write(m_stream, item->pos.xRot); - LEB128::Write(m_stream, item->pos.yRot); - LEB128::Write(m_stream, item->pos.zRot); - LEB128::Write(m_stream, item->roomNumber); - LEB128::Write(m_stream, item->speed); - LEB128::Write(m_stream, item->fallspeed); - - // Flare age - LEB128::Write(m_stream, (int)item->data); -} - -bool SaveGame::readBurningTorch() -{ - LEB128::ReadInt16(m_stream); - - short itemNumber = CreateItem(); - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - item->objectNumber = ID_BURNING_TORCH_ITEM; - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - item->roomNumber = LEB128::ReadInt16(m_stream); - - short oldXrot = item->pos.xRot; - short oldYrot = item->pos.yRot; - short oldZrot = item->pos.zRot; - - InitialiseItem(itemNumber); - - item->pos.xRot = oldXrot; - item->pos.yRot = oldYrot; - item->pos.zRot = oldZrot; - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - AddActiveItem(itemNumber); - - item->itemFlags[2] = LEB128::ReadInt16(m_stream); - - return true; -} - -bool SaveGame::readChaff() -{ - LEB128::ReadInt16(m_stream); - - short itemNumber = CreateItem(); - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - item->objectNumber = ID_CHAFF; - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - item->roomNumber = LEB128::ReadInt16(m_stream); - - short oldXrot = item->pos.xRot; - short oldYrot = item->pos.yRot; - short oldZrot = item->pos.zRot; - - InitialiseItem(itemNumber); - - item->pos.xRot = oldXrot; - item->pos.yRot = oldYrot; - item->pos.zRot = oldZrot; - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - AddActiveItem(itemNumber); - - item->itemFlags[0] = LEB128::ReadInt16(m_stream); - item->itemFlags[1] = LEB128::ReadInt16(m_stream); - - return true; -} - -bool SaveGame::readCrossbowBolt() -{ - LEB128::ReadInt16(m_stream); - - short itemNumber = CreateItem(); - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - item->objectNumber = ID_CROSSBOW_BOLT; - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - item->roomNumber = LEB128::ReadInt16(m_stream); - - short oldXrot = item->pos.xRot; - short oldYrot = item->pos.yRot; - short oldZrot = item->pos.zRot; - - InitialiseItem(itemNumber); - - item->pos.xRot = oldXrot; - item->pos.yRot = oldYrot; - item->pos.zRot = oldZrot; - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - AddActiveItem(itemNumber); - - return true; -} - -bool SaveGame::readFlare() -{ - LEB128::ReadInt16(m_stream); - - short itemNumber = CreateItem(); - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - item->objectNumber = ID_FLARE_ITEM; - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - item->roomNumber = LEB128::ReadInt16(m_stream); - - short oldXrot = item->pos.xRot; - short oldYrot = item->pos.yRot; - short oldZrot = item->pos.zRot; - - InitialiseItem(itemNumber); - - item->pos.xRot = oldXrot; - item->pos.yRot = oldYrot; - item->pos.zRot = oldZrot; - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - AddActiveItem(itemNumber); - - // Flare age - item->data = LEB128::ReadInt32(m_stream); - - return true; -} - -bool SaveGame::readTorpedo() -{ - LEB128::ReadInt16(m_stream); - - short itemNumber = CreateItem(); - ITEM_INFO* item = &g_Level.Items[itemNumber]; - - item->objectNumber = ID_TORPEDO; - item->pos.xPos = LEB128::ReadInt32(m_stream); - item->pos.yPos = LEB128::ReadInt32(m_stream); - item->pos.zPos = LEB128::ReadInt32(m_stream); - item->pos.xRot = LEB128::ReadInt16(m_stream); - item->pos.yRot = LEB128::ReadInt16(m_stream); - item->pos.zRot = LEB128::ReadInt16(m_stream); - item->roomNumber = LEB128::ReadInt16(m_stream); - - short oldXrot = item->pos.xRot; - short oldYrot = item->pos.yRot; - short oldZrot = item->pos.zRot; - - InitialiseItem(itemNumber); - - item->pos.xRot = oldXrot; - item->pos.yRot = oldYrot; - item->pos.zRot = oldZrot; - - item->speed = LEB128::ReadInt16(m_stream); - item->fallspeed = LEB128::ReadInt16(m_stream); - - AddActiveItem(itemNumber); - - item->itemFlags[0] = LEB128::ReadInt16(m_stream); - item->itemFlags[1] = LEB128::ReadInt16(m_stream); - item->currentAnimState = LEB128::ReadInt16(m_stream); - item->goalAnimState = LEB128::ReadInt16(m_stream); - item->requiredAnimState = LEB128::ReadInt16(m_stream); - - return true; -} - -void SaveGame::saveItemQuadInfo(int itemNumber, int arg2) -{ - - //m_stream->WriteBytes(reinterpret_cast(g_Level.Items[itemNumber].data), sizeof(QUAD_INFO)); -} - -void SaveGame::saveRats(int arg1, int arg2) -{ - RAT_STRUCT buffer; - memcpy(&buffer, &Rats[arg1], sizeof(RAT_STRUCT)); - LEB128::Write(m_stream, arg1); - m_stream->Write(reinterpret_cast(&buffer), sizeof(RAT_STRUCT)); -} - -void SaveGame::saveBats(int arg1, int arg2) -{ - BAT_STRUCT buffer; - memcpy(&buffer, &Bats[arg1], sizeof(BAT_STRUCT)); - LEB128::Write(m_stream, arg1); - m_stream->Write(reinterpret_cast(&buffer), sizeof(BAT_STRUCT)); -} - -void SaveGame::saveSpiders(int arg1, int arg2) -{ - SPIDER_STRUCT buffer; - memcpy(&buffer, &Spiders[arg1], sizeof(SPIDER_STRUCT)); - LEB128::Write(m_stream, arg1); - m_stream->Write(reinterpret_cast(&buffer), sizeof(SPIDER_STRUCT)); -} - -bool SaveGame::readBats() -{ - int index = LEB128::ReadInt16(m_stream); - - BAT_STRUCT* bats = &Bats[index]; - - char* buffer = (char*)malloc(sizeof(BAT_STRUCT)); - m_stream->Read(buffer, sizeof(BAT_STRUCT)); - memcpy(bats, buffer, sizeof(BAT_STRUCT)); - free(buffer); - - return true; -} - -bool SaveGame::readRats() -{ - int index = LEB128::ReadInt16(m_stream); - - RAT_STRUCT* rats = &Rats[index]; - - char* buffer = (char*)malloc(sizeof(RAT_STRUCT)); - m_stream->Read(buffer, sizeof(RAT_STRUCT)); - memcpy(rats, buffer, sizeof(RAT_STRUCT)); - free(buffer); - - return true; -} - -bool SaveGame::readSpiders() -{ - int index = LEB128::ReadInt16(m_stream); - - SPIDER_STRUCT* spiders = &Spiders[index]; - - char* buffer = (char*)malloc(sizeof(SPIDER_STRUCT)); - m_stream->Read(buffer, sizeof(SPIDER_STRUCT)); - memcpy(spiders, buffer, sizeof(SPIDER_STRUCT)); - free(buffer); - - return true; -} \ No newline at end of file diff --git a/TR5Main/Game/savegame.h b/TR5Main/Game/savegame.h index 40c76b746..3ed6a9f37 100644 --- a/TR5Main/Game/savegame.h +++ b/TR5Main/Game/savegame.h @@ -47,15 +47,15 @@ struct SAVEGAME_INFO struct SaveGameHeader { - std::string LevelName; - int Days; - int Hours; - int Minutes; - int Seconds; - int Level; - int Timer; - int Count; - bool Present; + std::string levelName; + int days; + int hours; + int minutes; + int seconds; + int level; + int timer; + int count; + bool present; }; extern SAVEGAME_INFO Savegame; @@ -63,109 +63,11 @@ extern SAVEGAME_INFO Savegame; class SaveGame { private: static FileStream* m_stream; - static ChunkReader* m_reader; - static ChunkWriter* m_writer; static std::vector m_luaVariables; - - static std::unique_ptr m_chunkGameStatus; - static std::unique_ptr m_chunkItems; - static std::unique_ptr m_chunkItem; - static std::unique_ptr m_chunkLara; - static std::unique_ptr m_chunkLuaVariable; - static std::unique_ptr m_chunkStaticFlags; - static std::unique_ptr m_chunkVehicle; - static std::unique_ptr m_chunkSequenceSwitch; - static std::unique_ptr m_chunkFlybyFlags; - static std::unique_ptr m_chunkCdFlags; - static std::unique_ptr m_chunkCamera; - static std::unique_ptr m_chunkFlipStats; - static std::unique_ptr m_chunkFlipMap; - static std::unique_ptr m_chunkItemDummy; - static std::unique_ptr m_chunkStatistics; - static std::unique_ptr m_chunkItemAnims; - static std::unique_ptr m_chunkItemMeshes; - static std::unique_ptr m_chunkItemFlags; - static std::unique_ptr m_chunkItemHitPoints; - static std::unique_ptr m_chunkItemPosition; - static std::unique_ptr m_chunkItemIntelligentData; - static std::unique_ptr m_chunkSpecialItemBurningTorch; - static std::unique_ptr m_chunkSpecialItemChaff; - static std::unique_ptr m_chunkSpecialItemTorpedo; - static std::unique_ptr m_chunkSpecialItemCrossbowBolt; - static std::unique_ptr m_chunkSpecialItemFlare; - static std::unique_ptr m_chunkItemQuadInfo; - static std::unique_ptr m_chunkRats; - static std::unique_ptr m_chunkSpiders; - static std::unique_ptr m_chunkBats; - static std::unique_ptr m_chunkLaraExtraInfo; - static std::unique_ptr m_chunkWeaponInfo; - static std::unique_ptr m_chunkPuzzle; - static std::unique_ptr m_chunkKey; - static std::unique_ptr m_chunkPickup; - static std::unique_ptr m_chunkExamine; - static std::unique_ptr m_chunkPuzzleCombo; - static std::unique_ptr m_chunkKeyCombo; - static std::unique_ptr m_chunkPickupCombo; - static std::unique_ptr m_chunkExamineCombo; - static std::unique_ptr m_chunkWeaponItem; - - static void saveGameStatus(int arg1, int arg2); - static void saveLara(int arg1, int arg2); - static void saveItem(int arg1, int arg2); - static void saveBurningTorch(int arg1, int arg2); - static void saveChaff(int arg1, int arg2); - static void saveTorpedo(int arg1, int arg2); - static void saveCrossbowBolt(int arg1, int arg2); - static void saveFlare(int arg1, int arg2); - static void saveItems(); - static void saveVariables(); - static void saveVariable(int arg1, int arg2); - static void saveStaticFlag(int arg1, int arg2); - static void saveCamera(int arg1, int arg2); - static void saveSequenceSwitch(int arg1, int arg2); - static void saveFlybyFlags(int arg1, int arg2); - static void saveFlipMap(int arg1, int arg2); - static void saveFlipStats(int arg1, int arg2); - static void saveCdFlags(int arg1, int arg2); - static void saveStatistics(int arg1, int arg2); - static void saveItemFlags(int arg1, int arg2); - static void saveItemHitPoints(int arg1, int arg2); - static void saveItemPosition(int arg1, int arg2); - static void saveItemMesh(int arg1, int arg2); - static void saveItemAnims(int arg1, int arg2); - static void saveItemIntelligentData(int arg1, int arg2); - static void saveItemQuadInfo(int arg1, int arg2); - static void saveRats(int arg1, int arg2); - static void saveBats(int arg1, int arg2); - static void saveSpiders(int arg1, int arg2); - static void saveLaraExtraInfo(int arg1, int arg2); - static void savePuzzle(int arg1, int arg2); - static void saveWeaponInfo(int arg1, int arg2); - static void saveWeaponItem(int arg1, int arg2); - - static bool readGameStatus(); - static bool readLara(); - static bool readItem(); - static bool readBurningTorch(); - static bool readChaff(); - static bool readCrossbowBolt(); - static bool readFlare(); - static bool readTorpedo(); - static bool readBats(); - static bool readRats(); - static bool readSpiders(); - static bool readStatistics(); - static bool readVariable(); - static bool readSavegameChunks(ChunkId* chunkId, int maxSize, int arg); - static bool readLaraChunks(ChunkId* chunkId, int maxSize, int arg); - static bool readGameStatusChunks(ChunkId* chunkId, int maxSize, int arg); - static bool readItemChunks(ChunkId* chunkId, int maxSize, int itemNumber); public: static int LastSaveGame; - static void Start(); - static void End(); static bool Load(char* fileName); static bool LoadHeader(char* fileName, SaveGameHeader* header); static bool Save(char* fileName); diff --git a/TR5Main/Renderer/Renderer11Draw.cpp b/TR5Main/Renderer/Renderer11Draw.cpp index 7626cf406..409caf670 100644 --- a/TR5Main/Renderer/Renderer11Draw.cpp +++ b/TR5Main/Renderer/Renderer11Draw.cpp @@ -558,17 +558,17 @@ namespace TEN::Renderer { int n2 = n - 1; - if (!g_NewSavegameInfos[n - 1].Present) + if (!g_NewSavegameInfos[n - 1].present) drawString(400, y, g_GameFlow->GetString(STRING_UNUSED), D3DCOLOR_ARGB(255, 255, 255, 255), PRINTSTRING_CENTER | PRINTSTRING_OUTLINE | (title_selected_option & (1 << (n2 + 1)) ? PRINTSTRING_BLINK : 0)); else { - sprintf(stringBuffer, "%05d", g_NewSavegameInfos[n-1].Count); + sprintf(stringBuffer, "%05d", g_NewSavegameInfos[n-1].count); drawString(200, y, stringBuffer, D3DCOLOR_ARGB(255, 255, 255, 255), PRINTSTRING_OUTLINE | (title_selected_option & (1 << (n2 + 1)) ? PRINTSTRING_BLINK | PRINTSTRING_DONT_UPDATE_BLINK : 0)); - drawString(250, y, (char*)g_NewSavegameInfos[n-1].LevelName.c_str(), D3DCOLOR_ARGB(255, 255, 255, 255), PRINTSTRING_OUTLINE | (title_selected_option & (1 << (n2 + 1)) ? PRINTSTRING_BLINK | PRINTSTRING_DONT_UPDATE_BLINK : 0)); + drawString(250, y, (char*)g_NewSavegameInfos[n-1].levelName.c_str(), D3DCOLOR_ARGB(255, 255, 255, 255), PRINTSTRING_OUTLINE | (title_selected_option & (1 << (n2 + 1)) ? PRINTSTRING_BLINK | PRINTSTRING_DONT_UPDATE_BLINK : 0)); - sprintf(stringBuffer, g_GameFlow->GetString(STRING_SAVEGAME_TIMESTAMP), g_NewSavegameInfos[n-1].Days, g_NewSavegameInfos[n-1].Hours, g_NewSavegameInfos[n-1].Minutes, g_NewSavegameInfos[n-1].Seconds); + sprintf(stringBuffer, g_GameFlow->GetString(STRING_SAVEGAME_TIMESTAMP), g_NewSavegameInfos[n-1].days, g_NewSavegameInfos[n-1].hours, g_NewSavegameInfos[n-1].minutes, g_NewSavegameInfos[n-1].seconds); drawString(475, y, stringBuffer, D3DCOLOR_ARGB(255, 255, 255, 255), PRINTSTRING_OUTLINE | (title_selected_option & (1 << (n2 + 1)) ? PRINTSTRING_BLINK : 0)); } diff --git a/TR5Main/Scripting/GameFlowScript.cpp b/TR5Main/Scripting/GameFlowScript.cpp index 9fa4a95b6..8ee27747b 100644 --- a/TR5Main/Scripting/GameFlowScript.cpp +++ b/TR5Main/Scripting/GameFlowScript.cpp @@ -287,7 +287,7 @@ bool GameFlow::DoGameflow() SaveGame::LoadHeader(fileName, &header); // Load level - CurrentLevel = header.Level; + CurrentLevel = header.level; loadFromSavegame = true; break; diff --git a/TR5Main/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TR5Main/Specific/savegame/flatbuffers/ten_savegame_generated.h index 88091d026..2f11700a2 100644 --- a/TR5Main/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TR5Main/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -73,6 +73,14 @@ struct BatInfo; struct BatInfoBuilder; struct BatInfoT; +struct SaveGameHeader; +struct SaveGameHeaderBuilder; +struct SaveGameHeaderT; + +struct SaveGameStatistics; +struct SaveGameStatisticsBuilder; +struct SaveGameStatisticsT; + struct SaveGame; struct SaveGameBuilder; struct SaveGameT; @@ -3477,8 +3485,294 @@ struct BatInfo::Traits { flatbuffers::Offset CreateBatInfo(flatbuffers::FlatBufferBuilder &_fbb, const BatInfoT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct SaveGameHeaderT : public flatbuffers::NativeTable { + typedef SaveGameHeader TableType; + std::string level_name{}; + int32_t days = 0; + int32_t hours = 0; + int32_t minutes = 0; + int32_t seconds = 0; + int32_t level = 0; + int32_t timer = 0; + int32_t count = 0; +}; + +struct SaveGameHeader FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SaveGameHeaderT NativeTableType; + typedef SaveGameHeaderBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LEVEL_NAME = 4, + VT_DAYS = 6, + VT_HOURS = 8, + VT_MINUTES = 10, + VT_SECONDS = 12, + VT_LEVEL = 14, + VT_TIMER = 16, + VT_COUNT = 18 + }; + const flatbuffers::String *level_name() const { + return GetPointer(VT_LEVEL_NAME); + } + int32_t days() const { + return GetField(VT_DAYS, 0); + } + int32_t hours() const { + return GetField(VT_HOURS, 0); + } + int32_t minutes() const { + return GetField(VT_MINUTES, 0); + } + int32_t seconds() const { + return GetField(VT_SECONDS, 0); + } + int32_t level() const { + return GetField(VT_LEVEL, 0); + } + int32_t timer() const { + return GetField(VT_TIMER, 0); + } + int32_t count() const { + return GetField(VT_COUNT, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_LEVEL_NAME) && + verifier.VerifyString(level_name()) && + VerifyField(verifier, VT_DAYS) && + VerifyField(verifier, VT_HOURS) && + VerifyField(verifier, VT_MINUTES) && + VerifyField(verifier, VT_SECONDS) && + VerifyField(verifier, VT_LEVEL) && + VerifyField(verifier, VT_TIMER) && + VerifyField(verifier, VT_COUNT) && + verifier.EndTable(); + } + SaveGameHeaderT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SaveGameHeaderT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameHeaderT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SaveGameHeaderBuilder { + typedef SaveGameHeader Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_level_name(flatbuffers::Offset level_name) { + fbb_.AddOffset(SaveGameHeader::VT_LEVEL_NAME, level_name); + } + void add_days(int32_t days) { + fbb_.AddElement(SaveGameHeader::VT_DAYS, days, 0); + } + void add_hours(int32_t hours) { + fbb_.AddElement(SaveGameHeader::VT_HOURS, hours, 0); + } + void add_minutes(int32_t minutes) { + fbb_.AddElement(SaveGameHeader::VT_MINUTES, minutes, 0); + } + void add_seconds(int32_t seconds) { + fbb_.AddElement(SaveGameHeader::VT_SECONDS, seconds, 0); + } + void add_level(int32_t level) { + fbb_.AddElement(SaveGameHeader::VT_LEVEL, level, 0); + } + void add_timer(int32_t timer) { + fbb_.AddElement(SaveGameHeader::VT_TIMER, timer, 0); + } + void add_count(int32_t count) { + fbb_.AddElement(SaveGameHeader::VT_COUNT, count, 0); + } + explicit SaveGameHeaderBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSaveGameHeader( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset level_name = 0, + int32_t days = 0, + int32_t hours = 0, + int32_t minutes = 0, + int32_t seconds = 0, + int32_t level = 0, + int32_t timer = 0, + int32_t count = 0) { + SaveGameHeaderBuilder builder_(_fbb); + builder_.add_count(count); + builder_.add_timer(timer); + builder_.add_level(level); + builder_.add_seconds(seconds); + builder_.add_minutes(minutes); + builder_.add_hours(hours); + builder_.add_days(days); + builder_.add_level_name(level_name); + return builder_.Finish(); +} + +struct SaveGameHeader::Traits { + using type = SaveGameHeader; + static auto constexpr Create = CreateSaveGameHeader; +}; + +inline flatbuffers::Offset CreateSaveGameHeaderDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *level_name = nullptr, + int32_t days = 0, + int32_t hours = 0, + int32_t minutes = 0, + int32_t seconds = 0, + int32_t level = 0, + int32_t timer = 0, + int32_t count = 0) { + auto level_name__ = level_name ? _fbb.CreateString(level_name) : 0; + return TEN::Save::CreateSaveGameHeader( + _fbb, + level_name__, + days, + hours, + minutes, + seconds, + level, + timer, + count); +} + +flatbuffers::Offset CreateSaveGameHeader(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameHeaderT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SaveGameStatisticsT : public flatbuffers::NativeTable { + typedef SaveGameStatistics TableType; + int32_t ammo_hits = 0; + int32_t ammo_used = 0; + int32_t medipacks_used = 0; + int32_t distance = 0; + int32_t kills = 0; + int32_t secrets = 0; + int32_t timer = 0; +}; + +struct SaveGameStatistics FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SaveGameStatisticsT NativeTableType; + typedef SaveGameStatisticsBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_AMMO_HITS = 4, + VT_AMMO_USED = 6, + VT_MEDIPACKS_USED = 8, + VT_DISTANCE = 10, + VT_KILLS = 12, + VT_SECRETS = 14, + VT_TIMER = 16 + }; + int32_t ammo_hits() const { + return GetField(VT_AMMO_HITS, 0); + } + int32_t ammo_used() const { + return GetField(VT_AMMO_USED, 0); + } + int32_t medipacks_used() const { + return GetField(VT_MEDIPACKS_USED, 0); + } + int32_t distance() const { + return GetField(VT_DISTANCE, 0); + } + int32_t kills() const { + return GetField(VT_KILLS, 0); + } + int32_t secrets() const { + return GetField(VT_SECRETS, 0); + } + int32_t timer() const { + return GetField(VT_TIMER, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_AMMO_HITS) && + VerifyField(verifier, VT_AMMO_USED) && + VerifyField(verifier, VT_MEDIPACKS_USED) && + VerifyField(verifier, VT_DISTANCE) && + VerifyField(verifier, VT_KILLS) && + VerifyField(verifier, VT_SECRETS) && + VerifyField(verifier, VT_TIMER) && + verifier.EndTable(); + } + SaveGameStatisticsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SaveGameStatisticsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameStatisticsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SaveGameStatisticsBuilder { + typedef SaveGameStatistics Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_ammo_hits(int32_t ammo_hits) { + fbb_.AddElement(SaveGameStatistics::VT_AMMO_HITS, ammo_hits, 0); + } + void add_ammo_used(int32_t ammo_used) { + fbb_.AddElement(SaveGameStatistics::VT_AMMO_USED, ammo_used, 0); + } + void add_medipacks_used(int32_t medipacks_used) { + fbb_.AddElement(SaveGameStatistics::VT_MEDIPACKS_USED, medipacks_used, 0); + } + void add_distance(int32_t distance) { + fbb_.AddElement(SaveGameStatistics::VT_DISTANCE, distance, 0); + } + void add_kills(int32_t kills) { + fbb_.AddElement(SaveGameStatistics::VT_KILLS, kills, 0); + } + void add_secrets(int32_t secrets) { + fbb_.AddElement(SaveGameStatistics::VT_SECRETS, secrets, 0); + } + void add_timer(int32_t timer) { + fbb_.AddElement(SaveGameStatistics::VT_TIMER, timer, 0); + } + explicit SaveGameStatisticsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSaveGameStatistics( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t ammo_hits = 0, + int32_t ammo_used = 0, + int32_t medipacks_used = 0, + int32_t distance = 0, + int32_t kills = 0, + int32_t secrets = 0, + int32_t timer = 0) { + SaveGameStatisticsBuilder builder_(_fbb); + builder_.add_timer(timer); + builder_.add_secrets(secrets); + builder_.add_kills(kills); + builder_.add_distance(distance); + builder_.add_medipacks_used(medipacks_used); + builder_.add_ammo_used(ammo_used); + builder_.add_ammo_hits(ammo_hits); + return builder_.Finish(); +} + +struct SaveGameStatistics::Traits { + using type = SaveGameStatistics; + static auto constexpr Create = CreateSaveGameStatistics; +}; + +flatbuffers::Offset CreateSaveGameStatistics(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameStatisticsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct SaveGameT : public flatbuffers::NativeTable { typedef SaveGame TableType; + std::unique_ptr header{}; + std::unique_ptr game{}; + std::unique_ptr level{}; std::unique_ptr lara{}; std::unique_ptr active_weapon{}; std::vector> items{}; @@ -3502,23 +3796,35 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef SaveGameBuilder Builder; struct Traits; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_LARA = 4, - VT_ACTIVE_WEAPON = 6, - VT_ITEMS = 8, - VT_FIXED_CAMERAS = 10, - VT_SINKS = 12, - VT_STATIC_MESHES = 14, - VT_RATS = 16, - VT_SPIDERS = 18, - VT_SCARABS = 20, - VT_BATS = 22, - VT_FLIP_MAPS = 24, - VT_FLIP_EFFECT = 26, - VT_FLIP_TIMER = 28, - VT_FLIP_STATUS = 30, - VT_AMBIENT_TRACK = 32, - VT_CD_FLAGS = 34 + VT_HEADER = 4, + VT_GAME = 6, + VT_LEVEL = 8, + VT_LARA = 10, + VT_ACTIVE_WEAPON = 12, + VT_ITEMS = 14, + VT_FIXED_CAMERAS = 16, + VT_SINKS = 18, + VT_STATIC_MESHES = 20, + VT_RATS = 22, + VT_SPIDERS = 24, + VT_SCARABS = 26, + VT_BATS = 28, + VT_FLIP_MAPS = 30, + VT_FLIP_EFFECT = 32, + VT_FLIP_TIMER = 34, + VT_FLIP_STATUS = 36, + VT_AMBIENT_TRACK = 38, + VT_CD_FLAGS = 40 }; + const TEN::Save::SaveGameHeader *header() const { + return GetPointer(VT_HEADER); + } + const TEN::Save::SaveGameStatistics *game() const { + return GetPointer(VT_GAME); + } + const TEN::Save::SaveGameStatistics *level() const { + return GetPointer(VT_LEVEL); + } const TEN::Save::Lara *lara() const { return GetPointer(VT_LARA); } @@ -3569,6 +3875,12 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_HEADER) && + verifier.VerifyTable(header()) && + VerifyOffset(verifier, VT_GAME) && + verifier.VerifyTable(game()) && + VerifyOffset(verifier, VT_LEVEL) && + verifier.VerifyTable(level()) && VerifyOffset(verifier, VT_LARA) && verifier.VerifyTable(lara()) && VerifyOffset(verifier, VT_ACTIVE_WEAPON) && @@ -3616,6 +3928,15 @@ struct SaveGameBuilder { typedef SaveGame Table; flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; + void add_header(flatbuffers::Offset header) { + fbb_.AddOffset(SaveGame::VT_HEADER, header); + } + void add_game(flatbuffers::Offset game) { + fbb_.AddOffset(SaveGame::VT_GAME, game); + } + void add_level(flatbuffers::Offset level) { + fbb_.AddOffset(SaveGame::VT_LEVEL, level); + } void add_lara(flatbuffers::Offset lara) { fbb_.AddOffset(SaveGame::VT_LARA, lara); } @@ -3677,6 +3998,9 @@ struct SaveGameBuilder { inline flatbuffers::Offset CreateSaveGame( flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset header = 0, + flatbuffers::Offset game = 0, + flatbuffers::Offset level = 0, flatbuffers::Offset lara = 0, flatbuffers::Offset active_weapon = 0, flatbuffers::Offset>> items = 0, @@ -3710,6 +4034,9 @@ inline flatbuffers::Offset CreateSaveGame( builder_.add_items(items); builder_.add_active_weapon(active_weapon); builder_.add_lara(lara); + builder_.add_level(level); + builder_.add_game(game); + builder_.add_header(header); return builder_.Finish(); } @@ -3720,6 +4047,9 @@ struct SaveGame::Traits { inline flatbuffers::Offset CreateSaveGameDirect( flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset header = 0, + flatbuffers::Offset game = 0, + flatbuffers::Offset level = 0, flatbuffers::Offset lara = 0, flatbuffers::Offset active_weapon = 0, const std::vector> *items = nullptr, @@ -3748,6 +4078,9 @@ inline flatbuffers::Offset CreateSaveGameDirect( auto cd_flags__ = cd_flags ? _fbb.CreateVector(*cd_flags) : 0; return TEN::Save::CreateSaveGame( _fbb, + header, + game, + level, lara, active_weapon, items__, @@ -4710,6 +5043,97 @@ inline flatbuffers::Offset CreateBatInfo(flatbuffers::FlatBufferBuilder _counter); } +inline SaveGameHeaderT *SaveGameHeader::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SaveGameHeader::UnPackTo(SaveGameHeaderT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = level_name(); if (_e) _o->level_name = _e->str(); } + { auto _e = days(); _o->days = _e; } + { auto _e = hours(); _o->hours = _e; } + { auto _e = minutes(); _o->minutes = _e; } + { auto _e = seconds(); _o->seconds = _e; } + { auto _e = level(); _o->level = _e; } + { auto _e = timer(); _o->timer = _e; } + { auto _e = count(); _o->count = _e; } +} + +inline flatbuffers::Offset SaveGameHeader::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameHeaderT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSaveGameHeader(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSaveGameHeader(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameHeaderT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SaveGameHeaderT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _level_name = _o->level_name.empty() ? _fbb.CreateSharedString("") : _fbb.CreateString(_o->level_name); + auto _days = _o->days; + auto _hours = _o->hours; + auto _minutes = _o->minutes; + auto _seconds = _o->seconds; + auto _level = _o->level; + auto _timer = _o->timer; + auto _count = _o->count; + return TEN::Save::CreateSaveGameHeader( + _fbb, + _level_name, + _days, + _hours, + _minutes, + _seconds, + _level, + _timer, + _count); +} + +inline SaveGameStatisticsT *SaveGameStatistics::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SaveGameStatistics::UnPackTo(SaveGameStatisticsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = ammo_hits(); _o->ammo_hits = _e; } + { auto _e = ammo_used(); _o->ammo_used = _e; } + { auto _e = medipacks_used(); _o->medipacks_used = _e; } + { auto _e = distance(); _o->distance = _e; } + { auto _e = kills(); _o->kills = _e; } + { auto _e = secrets(); _o->secrets = _e; } + { auto _e = timer(); _o->timer = _e; } +} + +inline flatbuffers::Offset SaveGameStatistics::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameStatisticsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSaveGameStatistics(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSaveGameStatistics(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameStatisticsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SaveGameStatisticsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _ammo_hits = _o->ammo_hits; + auto _ammo_used = _o->ammo_used; + auto _medipacks_used = _o->medipacks_used; + auto _distance = _o->distance; + auto _kills = _o->kills; + auto _secrets = _o->secrets; + auto _timer = _o->timer; + return TEN::Save::CreateSaveGameStatistics( + _fbb, + _ammo_hits, + _ammo_used, + _medipacks_used, + _distance, + _kills, + _secrets, + _timer); +} + inline SaveGameT *SaveGame::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -4719,6 +5143,9 @@ inline SaveGameT *SaveGame::UnPack(const flatbuffers::resolver_function_t *_reso inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; + { auto _e = header(); if (_e) _o->header = std::unique_ptr(_e->UnPack(_resolver)); } + { auto _e = game(); if (_e) _o->game = std::unique_ptr(_e->UnPack(_resolver)); } + { auto _e = level(); if (_e) _o->level = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = lara(); if (_e) _o->lara = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = active_weapon(); if (_e) _o->active_weapon = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = items(); if (_e) { _o->items.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->items[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } @@ -4745,6 +5172,9 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild (void)_rehasher; (void)_o; struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SaveGameT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _header = _o->header ? CreateSaveGameHeader(_fbb, _o->header.get(), _rehasher) : 0; + auto _game = _o->game ? CreateSaveGameStatistics(_fbb, _o->game.get(), _rehasher) : 0; + auto _level = _o->level ? CreateSaveGameStatistics(_fbb, _o->level.get(), _rehasher) : 0; auto _lara = _o->lara ? CreateLara(_fbb, _o->lara.get(), _rehasher) : 0; auto _active_weapon = _o->active_weapon ? CreateWeaponInfo(_fbb, _o->active_weapon.get(), _rehasher) : 0; auto _items = _fbb.CreateVector> (_o->items.size(), [](size_t i, _VectorArgs *__va) { return CreateItem(*__va->__fbb, __va->__o->items[i].get(), __va->__rehasher); }, &_va ); @@ -4763,6 +5193,9 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild auto _cd_flags = _fbb.CreateVector(_o->cd_flags); return TEN::Save::CreateSaveGame( _fbb, + _header, + _game, + _level, _lara, _active_weapon, _items, diff --git a/TR5Main/Specific/winmain.cpp b/TR5Main/Specific/winmain.cpp index fa670663b..412d22ab2 100644 --- a/TR5Main/Specific/winmain.cpp +++ b/TR5Main/Specific/winmain.cpp @@ -184,9 +184,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine throw; } - // Initialise chunks for savegames - SaveGame::Start(); - INITCOMMONCONTROLSEX commCtrlInit; commCtrlInit.dwSize = sizeof(INITCOMMONCONTROLSEX); commCtrlInit.dwICC = ICC_USEREX_CLASSES | ICC_STANDARD_CLASSES; @@ -303,6 +300,4 @@ void WinClose() delete g_GameFlow; ShutdownTENLog(); - - SaveGame::End(); } \ No newline at end of file