99#include " SatisfactorySave/GameTypes/Properties/ObjectProperty.h"
1010#include " SatisfactorySave/GameTypes/Properties/StructProperty.h"
1111#include " SatisfactorySave/GameTypes/Structs/PropertyStruct.h"
12+ #include " SatisfactorySave/GameTypes/Structs/RotatorStruct.h"
13+ #include " SatisfactorySave/GameTypes/Structs/VectorStruct.h"
1214#include " SatisfactorySave/GameTypes/UE/Engine/GameFramework/Actor.h"
1315
1416Satisfactory3DMap::MapLODReader::MapLODReader (const std::shared_ptr<s::PakManager>& pakManager) {
@@ -24,8 +26,56 @@ Satisfactory3DMap::MapLODReader::MapLODReader(const std::shared_ptr<s::PakManage
2426 throw std::runtime_error (" ClassIndex missing for /Script/Engine/WorldPartitionHLOD!" );
2527 }
2628
29+ // Water Mesh
30+ if (!pakManager->containsAssetFilename (" Game/FactoryGame/World/Environment/Water/Mesh/WaterPlane.uasset" )) {
31+ throw std::runtime_error (" Missing WaterPlane asset!" );
32+ }
33+ auto waterPlaneAsset =
34+ pakManager->readAsset (" Game/FactoryGame/World/Environment/Water/Mesh/WaterPlane.uasset" );
35+ auto waterPlaneMeshExp = waterPlaneAsset.getExportObjectByName (" WaterPlane" );
36+ if (waterPlaneMeshExp == nullptr ) {
37+ throw std::runtime_error (" Invalid WaterPlane asset!" );
38+ }
39+ waterPlaneMesh_ = waterPlaneMeshExp->cast_object <s::UStaticMesh>();
40+ if (waterPlaneMesh_ == nullptr ) {
41+ throw std::runtime_error (" Invalid WaterPlane mesh!" );
42+ }
43+
44+ // BP_Water instances
45+ if (!pakManager->containsAssetFilename (" Game/FactoryGame/World/Environment/Water/BP/BP_Water.uasset" )) {
46+ throw std::runtime_error (" Missing BP_Water asset!" );
47+ }
48+ auto waterAsset = pakManager->readAsset (" Game/FactoryGame/World/Environment/Water/BP/BP_Water.uasset" );
49+ const auto bpWaterCIndices = waterAsset.getExportMapIndicesByName (" BP_Water_C" );
50+ if (bpWaterCIndices.size () != 1 ) {
51+ throw std::runtime_error (" Missing BP_Water_C object!" );
52+ }
53+ const auto bpWaterHash = waterAsset.exportMap ()[bpWaterCIndices[0 ]].PublicExportHash ;
54+ const auto waterClassIdx = mapAsset.getPackageObjectIndexByImportedPackageNameAndHash (
55+ s::FName (" /Game/FactoryGame/World/Environment/Water/BP/BP_Water" ), bpWaterHash);
56+
57+ // BP_TranslucentWater instances
58+ if (!pakManager->containsAssetFilename (
59+ " Game/FactoryGame/World/Environment/Water/Translucent/BP_TranslucentWater.uasset" )) {
60+ throw std::runtime_error (" Missing BP_TranslucentWater asset!" );
61+ }
62+ auto tWaterAsset = pakManager->readAsset (
63+ " Game/FactoryGame/World/Environment/Water/Translucent/BP_TranslucentWater.uasset" );
64+ const auto bpTWaterCIndices = tWaterAsset.getExportMapIndicesByName (" BP_TranslucentWater_C" );
65+ if (bpTWaterCIndices.size () != 1 ) {
66+ throw std::runtime_error (" Missing BP_TranslucentWater_C object!" );
67+ }
68+ const auto bpTWaterHash = tWaterAsset.exportMap ()[bpTWaterCIndices[0 ]].PublicExportHash ;
69+ const auto tWaterClassIdx = mapAsset.getPackageObjectIndexByImportedPackageNameAndHash (
70+ s::FName (" /Game/FactoryGame/World/Environment/Water/Translucent/BP_TranslucentWater" ), bpTWaterHash);
71+
2772 for (std::size_t i = 0 ; i < mapAsset.exportMap ().size (); i++) {
2873 const auto & exp = mapAsset.exportMap ()[i];
74+
75+ if (exp.ClassIndex == waterClassIdx || exp.ClassIndex == tWaterClassIdx) {
76+ readWaterInstance (mapAsset, i);
77+ }
78+
2979 if (exp.ClassIndex != WPHLODClassIndex.value ()) {
3080 continue ;
3181 }
@@ -118,3 +168,25 @@ Satisfactory3DMap::MapLODReader::MapLODReader(const std::shared_ptr<s::PakManage
118168 }
119169 }
120170}
171+
172+ void Satisfactory3DMap::MapLODReader::readWaterInstance (s::AssetFile& mapAsset, std::size_t i) {
173+ const auto & waterExp = mapAsset.getExportObjectByIdx (i);
174+ const auto & surfaceRef = waterExp->Object ->Properties .get <s::ObjectProperty>(" WaterSurface" ).Value ;
175+ if (surfaceRef.pakValue () < 0 ) {
176+ throw std::runtime_error (" Water surface reference < 0 not implemented!" );
177+ }
178+ const auto & surfaceExp = mapAsset.getExportObjectByIdx (surfaceRef.pakValue () - 1 );
179+ const auto properties = surfaceExp->Object ->Properties ;
180+ WaterInstance inst;
181+ try {
182+ inst.location = properties.get <s::StructProperty>(" RelativeLocation" ).get <s::VectorStruct>().Data ;
183+ } catch (const std::exception& ex) {}
184+ try {
185+ inst.rotation = properties.get <s::StructProperty>(" RelativeRotation" ).get <s::RotatorStruct>().Data ;
186+ } catch (const std::exception& ex) {}
187+ try {
188+ inst.scale = properties.get <s::StructProperty>(" RelativeScale3D" ).get <s::VectorStruct>().Data ;
189+ } catch (const std::exception& ex) {}
190+
191+ waterInstances_.push_back (inst);
192+ }
0 commit comments