├── About ├── Version.txt ├── PublishedFileId.txt ├── Preview.png └── About.xml ├── .gitattributes ├── AddOn └── BiomeTransitions │ ├── About │ ├── PublishedFileId.txt │ ├── Preview.png │ └── About.xml │ ├── 1.3 │ └── Languages │ │ ├── Korean (한국어) │ │ └── Keyed │ │ │ └── Keys.xml │ │ └── English │ │ └── Keyed │ │ └── Keys.xml │ ├── 1.4 │ └── Languages │ │ ├── Korean (한국어) │ │ └── Keyed │ │ │ └── Keys.xml │ │ └── English │ │ └── Keyed │ │ └── Keys.xml │ ├── 1.5 │ └── Languages │ │ ├── Korean (한국어) │ │ └── Keyed │ │ │ └── Keys.xml │ │ └── English │ │ └── Keyed │ │ └── Keys.xml │ ├── 1.6 │ ├── Languages │ │ ├── Korean (한국어) │ │ │ └── Keyed │ │ │ │ └── Keys.xml │ │ └── English │ │ │ └── Keyed │ │ │ └── Keys.xml │ └── Defs │ │ └── TileMutators.xml │ └── LoadFolders.xml ├── .gitignore ├── 1.4 ├── Lunar │ ├── Manifest.lfc │ ├── Components │ │ ├── HarmonyLib.dll │ │ ├── HarmonyLib.lfc │ │ ├── MapPreview.dll │ │ ├── MapPreview.lfc │ │ ├── TerrainGraph.dll │ │ ├── TerrainGraph.lfc │ │ ├── LunarFramework.dll │ │ ├── LunarFramework.lfc │ │ ├── GeologicalLandforms.dll │ │ ├── GeologicalLandforms.lfc │ │ ├── GeologicalLandformsMod.dll │ │ └── GeologicalLandformsMod.lfc │ ├── README.md │ └── Manifest.xml ├── Assemblies │ └── LunarLoader.dll ├── Textures │ ├── LoadingIndicatorStaticGL.png │ └── World │ │ └── Landforms │ │ ├── Sinkhole.png │ │ ├── SurfaceCave.png │ │ ├── CaveEntrance.png │ │ └── SecludedValley.png └── Languages │ └── English │ └── Keyed │ └── GLFCore.xml ├── 1.5 ├── Lunar │ ├── Manifest.lfc │ ├── Components │ │ ├── HarmonyLib.dll │ │ ├── HarmonyLib.lfc │ │ ├── MapPreview.dll │ │ ├── MapPreview.lfc │ │ ├── TerrainGraph.dll │ │ ├── TerrainGraph.lfc │ │ ├── LunarFramework.dll │ │ ├── LunarFramework.lfc │ │ ├── GeologicalLandforms.dll │ │ ├── GeologicalLandforms.lfc │ │ ├── GeologicalLandformsMod.dll │ │ └── GeologicalLandformsMod.lfc │ ├── README.md │ └── Manifest.xml ├── Assemblies │ └── LunarLoader.dll ├── Textures │ ├── LoadingIndicatorStaticGL.png │ └── World │ │ └── Landforms │ │ ├── Sinkhole.png │ │ ├── SurfaceCave.png │ │ ├── CaveEntrance.png │ │ └── SecludedValley.png └── Languages │ ├── English │ └── Keyed │ │ └── GLFCore.xml │ └── Russian │ └── Keyed │ └── GLFCore.xml ├── 1.6 ├── Lunar │ ├── Manifest.lfc │ ├── Components │ │ ├── HarmonyLib.dll │ │ ├── HarmonyLib.lfc │ │ ├── MapPreview.dll │ │ ├── MapPreview.lfc │ │ ├── TerrainGraph.dll │ │ ├── TerrainGraph.lfc │ │ ├── LunarFramework.dll │ │ ├── LunarFramework.lfc │ │ ├── GeologicalLandforms.dll │ │ ├── GeologicalLandforms.lfc │ │ ├── GeologicalLandformsMod.dll │ │ └── GeologicalLandformsMod.lfc │ ├── Manifest.xml │ └── README.md ├── Assemblies │ └── LunarLoader.dll ├── Textures │ ├── LoadingIndicatorStaticGL.png │ └── World │ │ └── Landforms │ │ ├── Sinkhole.png │ │ ├── SurfaceCave.png │ │ ├── CaveEntrance.png │ │ └── SecludedValley.png └── Languages │ ├── English │ └── Keyed │ │ └── GLFCore.xml │ └── Russian │ └── Keyed │ └── GLFCore.xml ├── AssetBundles ├── terraingraph └── terraingraph.manifest ├── 1.3 └── Assemblies │ ├── 0_TerrainGraph.dll │ └── 1_GeologicalLandforms.dll ├── .gitmodules ├── Sources ├── GeologicalLandforms │ ├── XML │ │ ├── PocketMapProperties.cs │ │ ├── XmlDynamicValueContexts.cs │ │ ├── BiomeWorkerConfig.cs │ │ └── BiomeVariantDef.cs │ ├── GraphEditor │ │ ├── Connections │ │ │ ├── RoofFunctionConnection.cs │ │ │ ├── BiomeFunctionConnection.cs │ │ │ ├── TerrainFunctionConnection.cs │ │ │ ├── BiomeGridFunctionConnection.cs │ │ │ ├── RoofGridFunctionConnection.cs │ │ │ ├── TerrainGridFunctionConnection.cs │ │ │ └── DefFunctionConnection.cs │ │ ├── Nodes │ │ │ ├── Output │ │ │ │ ├── NodeOutputBase.cs │ │ │ │ ├── NodeOutputRoofGrid.cs │ │ │ │ ├── NodeOutputCaves.cs │ │ │ │ ├── NodeOutputFertility.cs │ │ │ │ ├── NodeOutputScatterers.cs │ │ │ │ ├── NodeOutputElevation.cs │ │ │ │ ├── NodeOutputTerrain.cs │ │ │ │ ├── NodeOutputWaterFlow.cs │ │ │ │ └── NodeOutputTerrainPatches.cs │ │ │ ├── Value │ │ │ │ ├── NodeValueMapSize.cs │ │ │ │ └── NodeValueRiversAndRoads.cs │ │ │ ├── Custom │ │ │ │ └── NodeApplyLayer.cs │ │ │ ├── UI │ │ │ │ ├── NodeUIBase.cs │ │ │ │ ├── NodeUILayerConfig.cs │ │ │ │ ├── NodeUILandformManifest.cs │ │ │ │ └── NodeUIWorldTileGraphic.cs │ │ │ ├── Input │ │ │ │ ├── NodeInputElevation.cs │ │ │ │ ├── NodeInputFertility.cs │ │ │ │ ├── NodeInputTerrain.cs │ │ │ │ ├── NodeInputBiomeGrid.cs │ │ │ │ └── NodeInputCaves.cs │ │ │ ├── TerrainGrid │ │ │ │ └── NodeTerrainGridNaturalRock.cs │ │ │ ├── RoofGrid │ │ │ │ └── NodeRoofGridPreview.cs │ │ │ ├── BiomeGrid │ │ │ │ └── NodeBiomeGridPreview.cs │ │ │ ├── Grid │ │ │ │ └── NodeGridTransformByMapSize.cs │ │ │ └── Def │ │ │ │ ├── NodeDefConst.cs │ │ │ │ ├── NodeValueSelectDef.cs │ │ │ │ └── NodeGridSelectDef.cs │ │ └── LandformPreviewScheduler.cs │ ├── Patches │ │ ├── Patch_RimWorld_GenStep_Animals.cs │ │ ├── Patch_RimWorld_LearningReadout.cs │ │ ├── Patch_Verse_MemoryUtility.cs │ │ ├── Patch_Verse_RoofCollapseUtility.cs │ │ ├── Patch_RimWorld_WeatherEvent_LightningStrike.cs │ │ ├── Patch_RimWorld_WorldDrawLayer_Landmarks.cs │ │ ├── Patch_RimWorld_QuestNode_SpawnMechCluster.cs │ │ ├── Patch_Verse_Map.cs │ │ ├── Patch_RimWorld_WorldLandmarks.cs │ │ ├── Patch_RimWorld_WorldObjectsHolder.cs │ │ ├── Patch_RimWorld_IncidentWorker.cs │ │ ├── Patch_RimWorld_RaidStrategyWorker.cs │ │ ├── Patch_RimWorld_PawnsArrivalModeWorker.cs │ │ ├── Patch_RimWorld_MapGenUtility.cs │ │ ├── Legacy │ │ │ ├── Patch_RimWorld_GenStep_Caves.cs │ │ │ ├── Patch_RimWorld_GenStep_CavesTerrain.cs │ │ │ ├── Patch_Verse_Command_SetPlantToGrow.cs │ │ │ ├── Patch_Verse_AnimalPenManager.cs │ │ │ ├── Patch_RimWorld_CompAutoCutWindTurbine.cs │ │ │ └── Patch_RimWorld_GenStep_Plants.cs │ │ ├── Patch_RimWorld_SurfaceLayer.cs │ │ ├── Patch_RimWorld_TerrainPatchMaker.cs │ │ ├── Patch_Verse_MapPlantGrowthRateCalculator.cs │ │ ├── Patch_RimWorld_Dialog_WorldSearch.cs │ │ ├── Patch_RimWorld_ExpandableLandmarksUtility.cs │ │ ├── Patch_RimWorld_WalkPathFinder.cs │ │ ├── Patch_RimWorld_GenStep_Scatterer.cs │ │ ├── Patch_RimWorld_GenStep_CaveHives.cs │ │ ├── Patch_RimWorld_GenStep_RocksFromGrid.cs │ │ ├── Patch_RimWorld_TileFinder.cs │ │ ├── Patch_Verse_MapGenerator.cs │ │ └── Patch_RimWorld_WorldPathGrid.cs │ ├── Compatibility │ │ ├── ModCompat_DubsMintMenus.cs │ │ ├── ModCompat_RimWar.cs │ │ ├── ModCompat_RealisticPlanets.cs │ │ ├── ModCompat_RocketMan.cs │ │ ├── ModCompat_BiomesCore.cs │ │ └── ModCompat_RoadsOfTheRim.cs │ ├── World │ │ ├── Topology.cs │ │ ├── WorldTileInfoPrimer.cs │ │ ├── IWorldTileInfo.cs │ │ └── WorldGenStep_Landforms.cs │ └── Utility │ │ ├── CompatUtils.cs │ │ ├── TerrainPriority.cs │ │ └── WorldTileTraverser.cs ├── GeologicalLandformsMod │ ├── FloatMenuOptionProvider_PathingDebug.cs │ └── Patches │ │ ├── Patch_RimWorld_FloatMenuMakerMap.cs │ │ ├── Patch_Verse_Root_Play.cs │ │ └── Patch_Verse_WaterInfo.cs ├── GeologicalLandforms.sln └── Directory.Build.props ├── LoadFolders.xml └── .github └── workflows ├── prerelease.yml └── release.yml /About/Version.txt: -------------------------------------------------------------------------------- 1 | 1.7.11 2 | -------------------------------------------------------------------------------- /About/PublishedFileId.txt: -------------------------------------------------------------------------------- 1 | 2773943594 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.xml text eol=crlf 2 | *.lfc binary 3 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/About/PublishedFileId.txt: -------------------------------------------------------------------------------- 1 | 2814391846 -------------------------------------------------------------------------------- /About/Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/About/Preview.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/ 3 | obj/ 4 | *.pdb 5 | *.DotSettings.user 6 | _PublisherPlus.xml 7 | packages/ 8 | -------------------------------------------------------------------------------- /1.4/Lunar/Manifest.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Manifest.lfc -------------------------------------------------------------------------------- /1.5/Lunar/Manifest.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Manifest.lfc -------------------------------------------------------------------------------- /1.6/Lunar/Manifest.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Manifest.lfc -------------------------------------------------------------------------------- /AssetBundles/terraingraph: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/AssetBundles/terraingraph -------------------------------------------------------------------------------- /1.4/Assemblies/LunarLoader.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Assemblies/LunarLoader.dll -------------------------------------------------------------------------------- /1.5/Assemblies/LunarLoader.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Assemblies/LunarLoader.dll -------------------------------------------------------------------------------- /1.6/Assemblies/LunarLoader.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Assemblies/LunarLoader.dll -------------------------------------------------------------------------------- /1.3/Assemblies/0_TerrainGraph.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.3/Assemblies/0_TerrainGraph.dll -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Sources/TerrainGraph"] 2 | path = Sources/TerrainGraph 3 | url = https://github.com/m00nl1ght-dev/TerrainGraph 4 | -------------------------------------------------------------------------------- /1.4/Lunar/Components/HarmonyLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/HarmonyLib.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/HarmonyLib.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/HarmonyLib.lfc -------------------------------------------------------------------------------- /1.4/Lunar/Components/MapPreview.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/MapPreview.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/MapPreview.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/MapPreview.lfc -------------------------------------------------------------------------------- /1.4/Lunar/Components/TerrainGraph.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/TerrainGraph.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/TerrainGraph.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/TerrainGraph.lfc -------------------------------------------------------------------------------- /1.5/Lunar/Components/HarmonyLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/HarmonyLib.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/HarmonyLib.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/HarmonyLib.lfc -------------------------------------------------------------------------------- /1.5/Lunar/Components/MapPreview.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/MapPreview.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/MapPreview.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/MapPreview.lfc -------------------------------------------------------------------------------- /1.5/Lunar/Components/TerrainGraph.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/TerrainGraph.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/TerrainGraph.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/TerrainGraph.lfc -------------------------------------------------------------------------------- /1.6/Lunar/Components/HarmonyLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/HarmonyLib.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/HarmonyLib.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/HarmonyLib.lfc -------------------------------------------------------------------------------- /1.6/Lunar/Components/MapPreview.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/MapPreview.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/MapPreview.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/MapPreview.lfc -------------------------------------------------------------------------------- /1.6/Lunar/Components/TerrainGraph.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/TerrainGraph.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/TerrainGraph.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/TerrainGraph.lfc -------------------------------------------------------------------------------- /1.4/Lunar/Components/LunarFramework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/LunarFramework.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/LunarFramework.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/LunarFramework.lfc -------------------------------------------------------------------------------- /1.5/Lunar/Components/LunarFramework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/LunarFramework.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/LunarFramework.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/LunarFramework.lfc -------------------------------------------------------------------------------- /1.6/Lunar/Components/LunarFramework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/LunarFramework.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/LunarFramework.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/LunarFramework.lfc -------------------------------------------------------------------------------- /1.3/Assemblies/1_GeologicalLandforms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.3/Assemblies/1_GeologicalLandforms.dll -------------------------------------------------------------------------------- /1.4/Textures/LoadingIndicatorStaticGL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Textures/LoadingIndicatorStaticGL.png -------------------------------------------------------------------------------- /1.4/Textures/World/Landforms/Sinkhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Textures/World/Landforms/Sinkhole.png -------------------------------------------------------------------------------- /1.5/Textures/LoadingIndicatorStaticGL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Textures/LoadingIndicatorStaticGL.png -------------------------------------------------------------------------------- /1.5/Textures/World/Landforms/Sinkhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Textures/World/Landforms/Sinkhole.png -------------------------------------------------------------------------------- /1.6/Textures/LoadingIndicatorStaticGL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Textures/LoadingIndicatorStaticGL.png -------------------------------------------------------------------------------- /1.6/Textures/World/Landforms/Sinkhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Textures/World/Landforms/Sinkhole.png -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/About/Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/AddOn/BiomeTransitions/About/Preview.png -------------------------------------------------------------------------------- /1.4/Lunar/Components/GeologicalLandforms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/GeologicalLandforms.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/GeologicalLandforms.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/GeologicalLandforms.lfc -------------------------------------------------------------------------------- /1.4/Textures/World/Landforms/SurfaceCave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Textures/World/Landforms/SurfaceCave.png -------------------------------------------------------------------------------- /1.5/Lunar/Components/GeologicalLandforms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/GeologicalLandforms.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/GeologicalLandforms.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/GeologicalLandforms.lfc -------------------------------------------------------------------------------- /1.5/Textures/World/Landforms/SurfaceCave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Textures/World/Landforms/SurfaceCave.png -------------------------------------------------------------------------------- /1.6/Lunar/Components/GeologicalLandforms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/GeologicalLandforms.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/GeologicalLandforms.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/GeologicalLandforms.lfc -------------------------------------------------------------------------------- /1.6/Textures/World/Landforms/SurfaceCave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Textures/World/Landforms/SurfaceCave.png -------------------------------------------------------------------------------- /1.4/Lunar/Components/GeologicalLandformsMod.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/GeologicalLandformsMod.dll -------------------------------------------------------------------------------- /1.4/Lunar/Components/GeologicalLandformsMod.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Lunar/Components/GeologicalLandformsMod.lfc -------------------------------------------------------------------------------- /1.4/Textures/World/Landforms/CaveEntrance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Textures/World/Landforms/CaveEntrance.png -------------------------------------------------------------------------------- /1.4/Textures/World/Landforms/SecludedValley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.4/Textures/World/Landforms/SecludedValley.png -------------------------------------------------------------------------------- /1.5/Lunar/Components/GeologicalLandformsMod.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/GeologicalLandformsMod.dll -------------------------------------------------------------------------------- /1.5/Lunar/Components/GeologicalLandformsMod.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Lunar/Components/GeologicalLandformsMod.lfc -------------------------------------------------------------------------------- /1.5/Textures/World/Landforms/CaveEntrance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Textures/World/Landforms/CaveEntrance.png -------------------------------------------------------------------------------- /1.5/Textures/World/Landforms/SecludedValley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.5/Textures/World/Landforms/SecludedValley.png -------------------------------------------------------------------------------- /1.6/Lunar/Components/GeologicalLandformsMod.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/GeologicalLandformsMod.dll -------------------------------------------------------------------------------- /1.6/Lunar/Components/GeologicalLandformsMod.lfc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Lunar/Components/GeologicalLandformsMod.lfc -------------------------------------------------------------------------------- /1.6/Textures/World/Landforms/CaveEntrance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Textures/World/Landforms/CaveEntrance.png -------------------------------------------------------------------------------- /1.6/Textures/World/Landforms/SecludedValley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m00nl1ght-dev/GeologicalLandforms/HEAD/1.6/Textures/World/Landforms/SecludedValley.png -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.3/Languages/Korean (한국어)/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 생물 군계 혼합 4 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.4/Languages/Korean (한국어)/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 생물 군계 혼합 4 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.5/Languages/Korean (한국어)/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 생물 군계 혼합 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.6/Languages/Korean (한국어)/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 생물 군계 혼합 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.3/Languages/English/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | biome transitions 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.4/Languages/English/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | biome transitions 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.5/Languages/English/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | biome transitions 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.6/Languages/English/Keyed/Keys.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | biome transitions 4 | 5 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/LoadFolders.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
  • 1.3
  • 5 |
    6 | 7 |
  • 1.4
  • 8 |
    9 | 10 |
  • 1.5
  • 11 |
    12 | 13 |
  • 1.6
  • 14 |
    15 |
    16 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/1.6/Defs/TileMutators.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GL_BiomeTransitions 7 | -1 8 | 240 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/XML/PocketMapProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using LunarFramework.XML; 3 | using Verse; 4 | 5 | namespace GeologicalLandforms; 6 | 7 | public class PocketMapProperties : DefModExtension 8 | { 9 | public XmlDynamicValue, ICtxTile> landforms; 10 | public XmlDynamicValue, ICtxTile> biomeVariants; 11 | } 12 | -------------------------------------------------------------------------------- /LoadFolders.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
  • 1.3
  • 5 |
  • /
  • 6 |
    7 | 8 |
  • 1.4
  • 9 |
  • /
  • 10 |
    11 | 12 |
  • 1.5
  • 13 |
  • /
  • 14 |
    15 | 16 |
  • 1.6
  • 17 |
  • /
  • 18 |
    19 |
    20 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/RoofFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Verse; 3 | 4 | namespace GeologicalLandforms.GraphEditor; 5 | 6 | public class RoofFunctionConnection : DefFunctionConnection 7 | { 8 | public static readonly RoofFunctionConnection Instance = new(); 9 | 10 | public const string Id = "RoofFunc"; 11 | 12 | public override string Identifier => Id; 13 | public override Color Color => new(1.2F, 0.7F, 0.44F); 14 | } 15 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/BiomeFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using RimWorld; 2 | using UnityEngine; 3 | 4 | namespace GeologicalLandforms.GraphEditor; 5 | 6 | public class BiomeFunctionConnection : DefFunctionConnection 7 | { 8 | public static readonly BiomeFunctionConnection Instance = new(); 9 | 10 | public const string Id = "BiomeFunc"; 11 | 12 | public override string Identifier => Id; 13 | public override Color Color => new(1.5f, 1.5f, 0f); 14 | } 15 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/TerrainFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Verse; 3 | 4 | namespace GeologicalLandforms.GraphEditor; 5 | 6 | public class TerrainFunctionConnection : DefFunctionConnection 7 | { 8 | public static readonly TerrainFunctionConnection Instance = new(); 9 | 10 | public const string Id = "TerrainFunc"; 11 | 12 | public override string Identifier => Id; 13 | public override Color Color => new(1.5f, 0f, 0f); 14 | } 15 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/BiomeGridFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using RimWorld; 4 | using TerrainGraph; 5 | using UnityEngine; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | public class BiomeGridFunctionConnection : ValueConnectionType 10 | { 11 | public const string Id = "BiomeGridFunc"; 12 | 13 | public override string Identifier => Id; 14 | public override Color Color => new(2f, 1f, 0f); 15 | public override Type Type => typeof(ISupplier>); 16 | } 17 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/RoofGridFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | public class RoofGridFunctionConnection : ValueConnectionType 10 | { 11 | public const string Id = "RoofGridFunc"; 12 | 13 | public override string Identifier => Id; 14 | public override Color Color => new(0.9F, 0.45F, 0.21F); 15 | public override Type Type => typeof(ISupplier>); 16 | } 17 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/TerrainGridFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | public class TerrainGridFunctionConnection : ValueConnectionType 10 | { 11 | public const string Id = "TerrainGridFunc"; 12 | 13 | public override string Identifier => Id; 14 | public override Color Color => new(1.25f, 0f, 2.5f); 15 | public override Type Type => typeof(ISupplier>); 16 | } 17 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_GenStep_Animals.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.Patches; 7 | 8 | [PatchGroup("Main")] 9 | [HarmonyPatch(typeof(GenStep_Animals))] 10 | internal static class Patch_RimWorld_GenStep_Animals 11 | { 12 | [HarmonyPrefix] 13 | [HarmonyPatch("Generate")] 14 | [HarmonyPriority(Priority.High)] 15 | private static void Generate_Prefix(Map map) 16 | { 17 | map.BiomeGrid()?.UpdateOpenGroundFraction(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_LearningReadout.cs: -------------------------------------------------------------------------------- 1 | using GeologicalLandforms.GraphEditor; 2 | using HarmonyLib; 3 | using LunarFramework.Patching; 4 | using RimWorld; 5 | 6 | namespace GeologicalLandforms.Patches; 7 | 8 | [PatchGroup("Main")] 9 | [HarmonyPatch(typeof(LearningReadout))] 10 | internal static class Patch_RimWorld_LearningReadout 11 | { 12 | [HarmonyPrefix] 13 | [HarmonyPatch("LearningReadoutOnGUI")] 14 | [HarmonyPriority(Priority.High)] 15 | private static bool LearningReadoutOnGUI() 16 | { 17 | return !LandformGraphEditor.IsEditorOpen; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_Verse_MemoryUtility.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using Verse.Profile; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(MemoryUtility))] 9 | internal static class Patch_Verse_MemoryUtility 10 | { 11 | [HarmonyPostfix] 12 | [HarmonyPatch("ClearAllMapsAndWorld")] 13 | private static void ClearAllMapsAndWorld() 14 | { 15 | #if RW_1_6_OR_GREATER 16 | TileMutatorsCustomization.Disable(); 17 | #endif 18 | 19 | ExtensionUtils.ClearCaches(); 20 | WorldTileInfo.RemoveCache(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_Verse_RoofCollapseUtility.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using Verse; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(RoofCollapseUtility))] 9 | internal static class Patch_Verse_RoofCollapseUtility 10 | { 11 | [HarmonyPrefix] 12 | [HarmonyPatch("WithinRangeOfRoofHolder")] 13 | [HarmonyPriority(Priority.High)] 14 | private static bool WithinRangeOfRoofHolder(IntVec3 c, Map map, ref bool __result) 15 | { 16 | if (c.GetRoof(map) is not { isThickRoof: true } || !map.HasStableCaveRoofs()) return true; 17 | __result = true; 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WeatherEvent_LightningStrike.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld; 4 | using RimWorld.Planet; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.Patches; 8 | 9 | /// 10 | /// Reduce frequency of lightning strikes on impassable world tiles. 11 | /// 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(WeatherEvent_LightningStrike))] 14 | internal static class Patch_RimWorld_WeatherEvent_LightningStrike 15 | { 16 | [HarmonyPrefix] 17 | [HarmonyPatch("FireEvent")] 18 | private static bool FireEvent(Map ___map) 19 | { 20 | return ___map.TileInfo.hilliness != Hilliness.Impassable || Rand.Value < 0.3f; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WorldDrawLayer_Landmarks.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using HarmonyLib; 4 | using LunarFramework.Patching; 5 | using RimWorld; 6 | using RimWorld.Planet; 7 | 8 | namespace GeologicalLandforms.Patches; 9 | 10 | /// 11 | /// Hide landmarks on the world map which have been disabled by the user via customization settings. 12 | /// 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(WorldDrawLayer_Landmarks))] 15 | internal static class Patch_RimWorld_WorldDrawLayer_Landmarks 16 | { 17 | [HarmonyPrefix] 18 | [HarmonyPatch("DrawStandard")] 19 | private static bool DrawStandard_Prefix(Landmark landmark) 20 | { 21 | return !TileMutatorsCustomization.IsLandmarkDisabled(landmark.def); 22 | } 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_QuestNode_SpawnMechCluster.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld.Planet; 4 | using RimWorld.QuestGen; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.Patches; 8 | 9 | /// 10 | /// Prevent quests with mech cluster on impassable world tiles. 11 | /// 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(QuestNode_SpawnMechCluster))] 14 | internal static class Patch_RimWorld_QuestNode_SpawnMechCluster 15 | { 16 | [HarmonyPostfix] 17 | [HarmonyPatch("TestRunInt")] 18 | private static void TestRunInt(Slate slate, ref bool __result) 19 | { 20 | if (__result && slate.Get("map").TileInfo.hilliness == Hilliness.Impassable) 21 | { 22 | __result = false; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_Verse_Map.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(Map))] 14 | internal static class Patch_Verse_Map 15 | { 16 | [HarmonyPrefix] 17 | [PatchTargetPotentiallyInlined] 18 | [HarmonyPatch(nameof(Map.Biomes), MethodType.Getter)] 19 | private static bool GetBiomes_Prefix(Map __instance, ref IEnumerable __result) 20 | { 21 | var biomeGrid = __instance.BiomeGrid(); 22 | if (biomeGrid is not { Enabled: true }) return true; 23 | 24 | __result = biomeGrid.Entries.Select(e => e.Biome); 25 | return false; 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | public abstract class NodeOutputBase : NodeBase 10 | { 11 | public Landform Landform => (Landform) canvas; 12 | 13 | public virtual ValueConnectionKnob InputKnobRef => null; 14 | public virtual ValueConnectionKnob OutputKnobRef => null; 15 | 16 | public override void NodeGUI() 17 | { 18 | GUILayout.BeginVertical(BoxStyle); 19 | 20 | GUILayout.BeginHorizontal(BoxStyle); 21 | GUILayout.Label(InputKnobRef.name, BoxLayout); 22 | GUILayout.EndHorizontal(); 23 | InputKnobRef.SetPosition(); 24 | OutputKnobRef?.SetPosition(); 25 | 26 | GUILayout.EndVertical(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WorldLandmarks.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using HarmonyLib; 4 | using LunarFramework.Patching; 5 | using RimWorld; 6 | using RimWorld.Planet; 7 | 8 | namespace GeologicalLandforms.Patches; 9 | 10 | /// 11 | /// Transiently filter out landmarks which have been disabled by the user via customization settings. 12 | /// 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(WorldLandmarks))] 15 | internal static class Patch_RimWorld_WorldLandmarks 16 | { 17 | [HarmonyPostfix] 18 | [PatchTargetPotentiallyInlined] 19 | [HarmonyPatch("get_Item", typeof(PlanetTile))] 20 | private static void GetItem_Postfix(ref Landmark __result) 21 | { 22 | if (__result != null && TileMutatorsCustomization.Enabled && TileMutatorsCustomization.IsLandmarkDisabled(__result.def)) 23 | { 24 | __result = null; 25 | } 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WorldObjectsHolder.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld.Planet; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(WorldObjectsHolder))] 9 | internal static class Patch_RimWorld_WorldObjectsHolder 10 | { 11 | [HarmonyPostfix] 12 | [HarmonyPatch(nameof(WorldObjectsHolder.Add))] 13 | private static void Add_Postfix(WorldObject o) 14 | { 15 | #if RW_1_6_OR_GREATER 16 | if (!o.Tile.Layer.IsRootSurface) return; 17 | #endif 18 | 19 | WorldTileInfo.InvalidateCache(o.Tile.tileId); 20 | } 21 | 22 | [HarmonyPostfix] 23 | [HarmonyPatch(nameof(WorldObjectsHolder.Remove))] 24 | private static void Remove_Postfix(WorldObject o) 25 | { 26 | #if RW_1_6_OR_GREATER 27 | if (!o.Tile.Layer.IsRootSurface) return; 28 | #endif 29 | 30 | WorldTileInfo.InvalidateCache(o.Tile.tileId); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_DubsMintMenus.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using GeologicalLandforms.Patches; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.Compatibility; 9 | 10 | [HarmonyPatch] 11 | internal class ModCompat_DubsMintMenus : ModCompat 12 | { 13 | public override string TargetAssemblyName => "DubsMintMenus"; 14 | public override string DisplayName => "Dubs Mint Menus"; 15 | 16 | [HarmonyPrefix] 17 | [HarmonyPatch("DubsMintMenus.Dialog_FancyDanPlantSetterBob", "IsPlantAvailable")] 18 | private static bool Dialog_FancyDanPlantSetterBob_IsPlantAvailable(ThingDef plantDef, Map map, ref bool __result) 19 | { 20 | var biomeGrid = map.BiomeGrid(); 21 | if (biomeGrid is not { Enabled: true }) return true; 22 | 23 | __result = Patch_Verse_Command_SetPlantToGrow.IsPlantAvailable_LocalBiomeAware(plantDef, map, biomeGrid); 24 | return false; 25 | } 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Value/NodeValueMapSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GeologicalLandforms.GraphEditor; 3 | using NodeEditorFramework; 4 | using UnityEngine; 5 | 6 | namespace TerrainGraph; 7 | 8 | [Serializable] 9 | [Node(false, "Value/Map Size", 1001)] 10 | public class NodeValueMapSize : NodeBase 11 | { 12 | public const string ID = "mapSize"; 13 | public override string GetID => ID; 14 | 15 | public override Vector2 DefaultSize => new(100, 55); 16 | public override bool AutoLayout => false; 17 | 18 | public override string Title => "Map Size"; 19 | 20 | [ValueConnectionKnob("Output", Direction.Out, ValueFunctionConnection.Id)] 21 | public ValueConnectionKnob OutputKnob; 22 | 23 | public override void NodeGUI() 24 | { 25 | OutputKnob.SetPosition(FirstKnobPosition); 26 | } 27 | 28 | public override bool Calculate() 29 | { 30 | OutputKnob.SetValue>(Supplier.Of(Landform.GeneratingMapSizeMin)); 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_RimWar.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using Verse; 4 | 5 | namespace GeologicalLandforms.Compatibility; 6 | 7 | /// 8 | /// Delays the WorldReachability patch in RimWar until the world has finished generating. 9 | /// 10 | [HarmonyPatch] 11 | public class ModCompat_RimWar : ModCompat 12 | { 13 | public override string TargetAssemblyName => "RimWar"; 14 | public override string DisplayName => "RimWar"; 15 | 16 | protected override bool OnApply() 17 | { 18 | return AccessTools.TypeByName("RimWar.WorldReachability_CanReach_Patch") != null; 19 | } 20 | 21 | [HarmonyPrefix] 22 | [HarmonyPatch("RimWar.WorldReachability_CanReach_Patch", "Prefix")] 23 | private static bool WorldReachability_CanReach_Patch(ref bool __result) 24 | { 25 | if (!Find.World.HasFinishedGenerating()) 26 | { 27 | __result = true; 28 | return false; 29 | } 30 | 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /1.6/Lunar/Manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Geological Landforms 4 | m00nl1ght.GeologicalLandforms 5 | m00nl1ght 6 | 1.6 7 | 8 |
  • 9 | MapPreview 10 |
  • 11 |
  • 12 | TerrainGraph 13 |
  • 14 |
  • 15 | GeologicalLandforms 16 | 17 |
  • MapPreview
  • 18 |
  • TerrainGraph
  • 19 | 20 | 21 |
  • 22 | GeologicalLandformsMod 23 | 24 |
  • GeologicalLandforms
  • 25 | 26 | 27 |
    28 | 29 | 30 |
  • 31 | m00nl1ght.MapPreview 32 | 1.10.0 33 |
  • 34 |
    35 | 36 | 37 |
    38 |
    39 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_IncidentWorker.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(IncidentWorker))] 9 | internal static class Patch_RimWorld_IncidentWorker 10 | { 11 | [HarmonyPostfix] 12 | [HarmonyPatch("CanFireNow")] 13 | [HarmonyPriority(Priority.Low)] 14 | private static void CanFireNow(IncidentWorker __instance, IncidentParms parms, ref bool __result) 15 | { 16 | if (__result && parms.target != null && parms.target.Tile >= 0) 17 | { 18 | var tileInfo = WorldTileInfo.Get(parms.target.Tile); 19 | if (tileInfo.HasLandforms()) 20 | { 21 | foreach (var landform in tileInfo.Landforms) 22 | { 23 | var mapIncidents = landform.MapIncidents; 24 | if (mapIncidents != null && !mapIncidents.CanHaveIncidentNow(__instance)) 25 | { 26 | __result = false; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_RaidStrategyWorker.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(RaidStrategyWorker))] 9 | internal static class Patch_RimWorld_RaidStrategyWorker 10 | { 11 | [HarmonyPostfix] 12 | [HarmonyPatch("CanUseWith")] 13 | [HarmonyPriority(Priority.Low)] 14 | private static void CanUseWith(RaidStrategyWorker __instance, IncidentParms parms, ref bool __result) 15 | { 16 | if (__result && parms.target != null && parms.target.Tile >= 0) 17 | { 18 | var tileInfo = WorldTileInfo.Get(parms.target.Tile); 19 | if (tileInfo.HasLandforms()) 20 | { 21 | foreach (var landform in tileInfo.Landforms) 22 | { 23 | var mapIncidents = landform.MapIncidents; 24 | if (mapIncidents != null && !mapIncidents.CanUseRaidStrategyNow(__instance)) 25 | { 26 | __result = false; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_PawnsArrivalModeWorker.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using LunarFramework.Patching; 3 | using RimWorld; 4 | 5 | namespace GeologicalLandforms.Patches; 6 | 7 | [PatchGroup("Main")] 8 | [HarmonyPatch(typeof(PawnsArrivalModeWorker))] 9 | internal static class Patch_RimWorld_PawnsArrivalModeWorker 10 | { 11 | [HarmonyPostfix] 12 | [HarmonyPatch("CanUseWith")] 13 | [HarmonyPriority(Priority.Low)] 14 | private static void CanUseWith(PawnsArrivalModeWorker __instance, IncidentParms parms, ref bool __result) 15 | { 16 | if (__result && parms.target != null && parms.target.Tile >= 0) 17 | { 18 | var tileInfo = WorldTileInfo.Get(parms.target.Tile); 19 | if (tileInfo.HasLandforms()) 20 | { 21 | foreach (var landform in tileInfo.Landforms) 22 | { 23 | var mapIncidents = landform.MapIncidents; 24 | if (mapIncidents != null && !mapIncidents.CanUseArrivalModeNow(__instance)) 25 | { 26 | __result = false; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_MapGenUtility.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using HarmonyLib; 4 | using LunarFramework.Patching; 5 | using RimWorld; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.Patches; 9 | 10 | [PatchGroup("Main")] 11 | [HarmonyPatch(typeof(MapGenUtility))] 12 | internal static class Patch_RimWorld_MapGenUtility 13 | { 14 | [HarmonyPrefix] 15 | [HarmonyPriority(Priority.High)] 16 | [HarmonyPatch(nameof(MapGenUtility.BiomeAt))] 17 | private static bool BiomeAt_Prefix(Map map, IntVec3 c, ref BiomeDef __result) 18 | { 19 | var biomeGrid = map.BiomeGrid(); 20 | if (biomeGrid is not { Enabled: true }) return true; 21 | 22 | __result = biomeGrid.BiomeAt(c); 23 | return false; 24 | } 25 | 26 | [HarmonyPrefix] 27 | [HarmonyPriority(Priority.High)] 28 | [HarmonyPatch(nameof(MapGenUtility.IsMixedBiome))] 29 | private static bool IsMixedBiome_Prefix(Map map, ref bool __result) 30 | { 31 | var biomeGrid = map.BiomeGrid(); 32 | if (biomeGrid is not { Enabled: true }) return true; 33 | 34 | __result = biomeGrid.Entries.Count > 1; 35 | return false; 36 | } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputRoofGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Output/Roof Grid", 407)] 10 | public class NodeOutputRoofGrid : NodeOutputBase 11 | { 12 | public const string ID = "outputRoofGrid"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Roof Output"; 16 | 17 | public override ValueConnectionKnob InputKnobRef => InputKnob; 18 | 19 | [ValueConnectionKnob("Roof Grid", Direction.In, RoofGridFunctionConnection.Id)] 20 | public ValueConnectionKnob InputKnob; 21 | 22 | public override void OnCreate(bool fromGUI) 23 | { 24 | var exiting = Landform.OutputRoofGrid; 25 | if (exiting != null && exiting != this && canvas.nodes.Contains(exiting)) exiting.Delete(); 26 | Landform.OutputRoofGrid = this; 27 | } 28 | 29 | protected override void OnDelete() 30 | { 31 | if (Landform.OutputRoofGrid == this) Landform.OutputRoofGrid = null; 32 | } 33 | 34 | public IGridFunction Get() 35 | { 36 | return InputKnob.GetValue>>()?.ResetAndGet(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_RimWorld_GenStep_Caves.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using GeologicalLandforms.GraphEditor; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.Patches; 10 | 11 | [PatchGroup("Main")] 12 | [HarmonyPatch(typeof(GenStep_Caves))] 13 | internal static class Patch_RimWorld_GenStep_Caves 14 | { 15 | [HarmonyPrefix] 16 | [HarmonyPatch("Generate")] 17 | [HarmonyPriority(Priority.VeryHigh)] 18 | [HarmonyBefore("com.configurablemaps.rimworld.mod")] 19 | private static bool Generate_Prefix(Map map, GenStepParams parms) 20 | { 21 | // if there is no landform on this tile, let vanilla gen or other mods handle it 22 | if (!Landform.AnyGenerating) return true; 23 | 24 | var cavesModule = Landform.GetFeatureScaled(l => l.OutputCaves?.Get()); 25 | 26 | if (cavesModule == null) return true; 27 | 28 | var elevation = MapGenerator.Elevation; 29 | var caves = MapGenerator.Caves; 30 | 31 | foreach (var cell in map.AllCells) 32 | { 33 | caves[cell] = elevation[cell] > 0.7f ? (float) cavesModule.ValueAt(cell.x, cell.z) : 0f; 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_RealisticPlanets.cs: -------------------------------------------------------------------------------- 1 | using GeologicalLandforms.Patches; 2 | using HarmonyLib; 3 | using LunarFramework.Patching; 4 | 5 | namespace GeologicalLandforms.Compatibility; 6 | 7 | [HarmonyPatch] 8 | public class ModCompat_RealisticPlanets : ModCompat 9 | { 10 | public override string TargetAssemblyName => "Realistic_Planets_Continued"; 11 | public override string DisplayName => "Realistic Planets Continued"; 12 | 13 | private static float _originPos; 14 | 15 | protected override bool OnApply() 16 | { 17 | _originPos = 520f; 18 | 19 | if (AccessTools.TypeByName("WorldGenRules.MyLittlePlanet") != null) 20 | { 21 | _originPos += 40f; 22 | } 23 | 24 | return true; 25 | } 26 | 27 | [HarmonyPostfix] 28 | [HarmonyPatch("Planets_Code.Planets_CreateWorldParams", "DoWindowContents")] 29 | private static void Planets_CreateWorldParams_DoWindowContents() 30 | { 31 | Patch_RimWorld_Page_CreateWorldParams.DoExtraSliders(_originPos, 200f); 32 | } 33 | 34 | [HarmonyPostfix] 35 | [HarmonyPatch("Planets_Code.Planets_CreateWorldParams", "Reset")] 36 | internal static void Reset() 37 | { 38 | Patch_RimWorld_Page_CreateWorldParams.Reset(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_SurfaceLayer.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using HarmonyLib; 7 | using LunarFramework.Patching; 8 | using RimWorld; 9 | using RimWorld.Planet; 10 | 11 | namespace GeologicalLandforms.Patches; 12 | 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(SurfaceLayer))] 15 | internal static class Patch_RimWorld_SurfaceLayer 16 | { 17 | private static readonly Type Self = typeof(Patch_RimWorld_SurfaceLayer); 18 | 19 | [HarmonyTranspiler] 20 | [HarmonyPatch("SerializeMutators")] 21 | private static IEnumerable SerializeMutators_Transpiler(IEnumerable instructions) 22 | { 23 | var pattern = TranspilerPattern.Build("SerializeMutators") 24 | .MatchCall(typeof(Tile), "get_Mutators").Remove() 25 | .MatchCall(typeof(Enumerable), nameof(Enumerable.ToList), null, [typeof(TileMutatorDef)]).Remove() 26 | .Insert(CodeInstruction.Call(Self, nameof(TileMutatorsForSaving))); 27 | 28 | return TranspilerPattern.Apply(instructions, pattern); 29 | } 30 | 31 | private static List TileMutatorsForSaving(Tile tile) 32 | { 33 | return tile.mutatorsNullable ?? []; 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_RocketMan.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using HarmonyLib; 3 | using LunarFramework.Patching; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.Compatibility; 7 | 8 | /// 9 | /// Delays the WorldReachability patch in RocketMan until the world has finished generating. 10 | /// 11 | [HarmonyPatch] 12 | public class ModCompat_RocketMan : ModCompat 13 | { 14 | public override string TargetAssemblyName => "Cosmodrome"; 15 | public override string DisplayName => "RocketMan"; 16 | 17 | private static MethodInfo _targetMethod; 18 | 19 | protected override bool OnApply() 20 | { 21 | var baseType = AccessTools.TypeByName("RocketMan.Optimizations.WorldReachability_Patch"); 22 | var nestedType = baseType?.GetNestedType("WorldReachability_CanReach_Patch"); 23 | _targetMethod = AccessTools.Method(nestedType, "Prefix"); 24 | return _targetMethod != null; 25 | } 26 | 27 | [HarmonyTargetMethod] 28 | private static MethodBase TargetMethod() => _targetMethod; 29 | 30 | [HarmonyPrefix] 31 | private static bool WorldReachability_CanReach_Patch(ref bool __result) 32 | { 33 | if (!Find.World.HasFinishedGenerating()) 34 | { 35 | __result = true; 36 | return false; 37 | } 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_TerrainPatchMaker.cs: -------------------------------------------------------------------------------- 1 | using GeologicalLandforms.GraphEditor; 2 | using HarmonyLib; 3 | using LunarFramework.Patching; 4 | using RimWorld; 5 | using Verse.Noise; 6 | 7 | namespace GeologicalLandforms.Patches; 8 | 9 | [PatchGroup("Main")] 10 | [HarmonyPatch(typeof(TerrainPatchMaker))] 11 | internal static class Patch_RimWorld_TerrainPatchMaker 12 | { 13 | [HarmonyPostfix] 14 | [HarmonyPatch("Init")] 15 | private static void Init(ref ModuleBase ___noise) 16 | { 17 | if (!Landform.AnyGenerating) return; 18 | 19 | var offsetFunc = Landform.GetFeatureScaled(l => l.OutputTerrainPatches?.GetOffset()); 20 | var frequencyFactor = Landform.GetFeature(l => l.OutputTerrainPatches?.GetFrequencyFactor()) ?? 1d; 21 | var lacunarityFactor = Landform.GetFeature(l => l.OutputTerrainPatches?.GetLacunarityFactor()) ?? 1d; 22 | var persistenceFactor = Landform.GetFeature(l => l.OutputTerrainPatches?.GetPersistenceFactor()) ?? 1d; 23 | 24 | if (___noise is Perlin perlin) 25 | { 26 | perlin.Frequency *= frequencyFactor; 27 | perlin.Lacunarity *= lacunarityFactor; 28 | perlin.Persistence *= persistenceFactor; 29 | } 30 | 31 | if (offsetFunc != null) 32 | { 33 | ___noise = new Add(___noise, offsetFunc.AsModule()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_RimWorld_GenStep_CavesTerrain.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using GeologicalLandforms.GraphEditor; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.Patches; 10 | 11 | [PatchGroup("Main")] 12 | [HarmonyPatch(typeof(GenStep_CavesTerrain))] 13 | internal static class Patch_RimWorld_GenStep_CavesTerrain 14 | { 15 | [HarmonyPrefix] 16 | [HarmonyPatch("Generate")] 17 | [HarmonyPriority(Priority.VeryHigh)] 18 | private static bool Generate_Prefix(Map map, GenStepParams parms) 19 | { 20 | // if there is no landform on this tile, let vanilla gen or other mods handle it 21 | if (!Landform.AnyGenerating) return true; 22 | 23 | var cavesTerrainModule = Landform.GetFeatureScaled(l => l.OutputTerrain?.GetCave()); 24 | 25 | if (cavesTerrainModule == null) return true; 26 | 27 | var caves = MapGenerator.Caves; 28 | 29 | foreach (var cell in map.AllCells) 30 | { 31 | if (caves[cell] > 0.0 && !cell.GetTerrain(map).IsRiver) 32 | { 33 | var terrainDef = cavesTerrainModule.ValueAt(cell.x, cell.z); 34 | if (terrainDef != null) map.terrainGrid.SetTerrain(cell, terrainDef); 35 | } 36 | } 37 | 38 | return false; 39 | } 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Connections/DefFunctionConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NodeEditorFramework; 4 | using TerrainGraph; 5 | using UnityEngine; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | public abstract class DefFunctionConnection : ValueConnectionType where T : Def 11 | { 12 | public override Type Type => typeof(ISupplier); 13 | 14 | public void SelectorUI(NodeBase node, string current, bool enabled, Action onSelected, GUILayoutOption[] layout = null) 15 | { 16 | GUI.enabled = enabled; 17 | 18 | layout ??= node.BoxLayout; 19 | 20 | if (GUILayout.Button(DisplayName(FromString(current)), GUI.skin.box, layout)) 21 | { 22 | NodeBase.Dropdown(new[] { (T) null }.Concat(DefDatabase.AllDefsListForReading).ToList(), onSelected, DisplayName); 23 | } 24 | 25 | GUI.enabled = true; 26 | } 27 | 28 | public string DisplayName(T def) 29 | { 30 | return def == null ? "None" : def.label.CapitalizeFirst(); 31 | } 32 | 33 | public string ToString(T def) 34 | { 35 | return def == null ? "None" : def.defName; 36 | } 37 | 38 | public T FromString(string defName) 39 | { 40 | return string.IsNullOrEmpty(defName) || defName.EqualsIgnoreCase("None") ? null 41 | : DefDatabase.GetNamed(defName, false); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /1.4/Lunar/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Lunar Framework 3 | 4 | ### What is this? 5 | 6 | I created this framework to make my mods more modular and fully self-contained. This way, they have no hard dependencies and can be used standalone, but also work when installed together with my other mods. 7 | Basically each mod consist of individual components, and if multiple mods are present that contain the same component, only the newer version of that component is loaded. 8 | In addition, the framework also contains some common code that is used by all my mods. 9 | 10 | If you have any questions or would like to use the framework for your own mods, you can contact me on Discord: m00nl1ght#6339 11 | 12 | ### What are the .lfc files and why are they needed? 13 | 14 | Those files contain a simple checksum that is used to verify the integrity of the mod on startup. 15 | The reason for this is that Steam sometimes messes up when updating mods, for example by randomly stopping half way through, or leaving behind some old files. 16 | This can cause mods to break in unpredictable ways, especially when the assembly files are affected. 17 | To detect issues like this, Lunar Framework uses the checksum files to verify that no files are broken. 18 | If there are, it displays a warning to the user, asking them to redownload/resubscribe the mod. 19 | Unsubscribing and then resubscribing forces Steam to delete and then redownload the mod's files, which fixes the issue. 20 | -------------------------------------------------------------------------------- /1.5/Lunar/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Lunar Framework 3 | 4 | ### What is this? 5 | 6 | I created this framework to make my mods more modular and fully self-contained. This way, they have no hard dependencies and can be used standalone, but also work when installed together with my other mods. 7 | Basically each mod consist of individual components, and if multiple mods are present that contain the same component, only the newer version of that component is loaded. 8 | In addition, the framework also contains some common code that is used by all my mods. 9 | 10 | If you have any questions or would like to use the framework for your own mods, you can contact me on Discord: m00nl1ght#6339 11 | 12 | ### What are the .lfc files and why are they needed? 13 | 14 | Those files contain a simple checksum that is used to verify the integrity of the mod on startup. 15 | The reason for this is that Steam sometimes messes up when updating mods, for example by randomly stopping half way through, or leaving behind some old files. 16 | This can cause mods to break in unpredictable ways, especially when the assembly files are affected. 17 | To detect issues like this, Lunar Framework uses the checksum files to verify that no files are broken. 18 | If there are, it displays a warning to the user, asking them to redownload/resubscribe the mod. 19 | Unsubscribing and then resubscribing forces Steam to delete and then redownload the mod's files, which fixes the issue. 20 | -------------------------------------------------------------------------------- /1.6/Lunar/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Lunar Framework 3 | 4 | ### What is this? 5 | 6 | I created this framework to make my mods more modular and fully self-contained. This way, they have no hard dependencies and can be used standalone, but also work when installed together with my other mods. 7 | Basically each mod consist of individual components, and if multiple mods are present that contain the same component, only the newer version of that component is loaded. 8 | In addition, the framework also contains some common code that is used by all my mods. 9 | 10 | If you have any questions or would like to use the framework for your own mods, you can contact me on Discord: m00nl1ght#6339 11 | 12 | ### What are the .lfc files and why are they needed? 13 | 14 | Those files contain a simple checksum that is used to verify the integrity of the mod on startup. 15 | The reason for this is that Steam sometimes messes up when updating mods, for example by randomly stopping half way through, or leaving behind some old files. 16 | This can cause mods to break in unpredictable ways, especially when the assembly files are affected. 17 | To detect issues like this, Lunar Framework uses the checksum files to verify that no files are broken. 18 | If there are, it displays a warning to the user, asking them to redownload/resubscribe the mod. 19 | Unsubscribing and then resubscribing forces Steam to delete and then redownload the mod's files, which fixes the issue. 20 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_Verse_MapPlantGrowthRateCalculator.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_5_OR_GREATER 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld.Planet; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(MapPlantGrowthRateCalculator))] 14 | internal static class Patch_Verse_MapPlantGrowthRateCalculator 15 | { 16 | internal static readonly Type Self = typeof(Patch_Verse_MapPlantGrowthRateCalculator); 17 | 18 | [HarmonyTranspiler] 19 | [HarmonyPatch("BuildFor", typeof(Map))] 20 | private static IEnumerable BuildFor_Transpiler(IEnumerable instructions) 21 | { 22 | var pattern = TranspilerPattern.Build("BuildFor") 23 | .MatchCall(typeof(Map), "get_Tile").Remove() 24 | .Insert(CodeInstruction.Call(Self, nameof(TileForMap))); 25 | 26 | return TranspilerPattern.Apply(instructions, pattern); 27 | } 28 | 29 | #if RW_1_6_OR_GREATER 30 | private static PlanetTile TileForMap(Map map) 31 | #else 32 | private static int TileForMap(Map map) 33 | #endif 34 | { 35 | return map.Tile < 0 && map.Parent is PocketMapParent { sourceMap: not null } parent && parent.sourceMap.Tile >= 0 36 | ? parent.sourceMap.Tile 37 | : map.Tile; 38 | } 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /1.5/Lunar/Manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Geological Landforms 4 | m00nl1ght.GeologicalLandforms 5 | m00nl1ght 6 | 1.5 7 | 8 | 9 | MapPreview 10 | 11 | 12 | TerrainGraph 13 | 14 | 0_TerrainGraph 15 | 16 | 17 | 18 | GeologicalLandforms 19 | 20 | 1_GeologicalLandforms 21 | 22 | 23 | MapPreview 24 | TerrainGraph 25 | 26 | 27 | 28 | GeologicalLandformsMod 29 | 30 | 2_GeologicalLandformsMod 31 | 32 | 33 | GeologicalLandforms 34 | 35 | 36 | 37 | 38 | 39 | 40 | m00nl1ght.MapPreview 41 | 1.10.0 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /AddOn/BiomeTransitions/About/About.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | m00nl1ght.GeologicalLandforms.BiomeTransitions 4 | https://github.com/m00nl1ght-dev/GeologicalLandforms 5 | Biome Transitions 6 | m00nl1ght-dev 7 | Add-on for Geological Landforms that generates maps with multiple mixing biomes on them when you settle on a world tile that has different biomes adjacent to it. 8 | 9 |
  • 1.3
  • 10 |
  • 1.4
  • 11 |
  • 1.5
  • 12 |
  • 1.6
  • 13 |
    14 | 15 |
  • 16 | m00nl1ght.GeologicalLandforms 17 | Geological Landforms 18 | steam://url/CommunityFilePage/2773943594 19 | https://github.com/m00nl1ght-dev/GeologicalLandforms/releases/latest 20 |
  • 21 |
    22 | 23 |
  • Ludeon.RimWorld
  • 24 |
  • Ludeon.RimWorld.Royalty
  • 25 |
  • Ludeon.RimWorld.Ideology
  • 26 |
  • Ludeon.RimWorld.Biotech
  • 27 |
  • Ludeon.RimWorld.Anomaly
  • 28 |
  • Ludeon.RimWorld.Odyssey
  • 29 |
  • brrainz.harmony
  • 30 |
  • m00nl1ght.GeologicalLandforms
  • 31 |
    32 | 33 | 34 |
    35 | -------------------------------------------------------------------------------- /1.4/Lunar/Manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Geological Landforms 4 | m00nl1ght.GeologicalLandforms 5 | m00nl1ght 6 | 1.4.3613 7 | 8 | 9 | MapPreview 10 | 11 | 12 | TerrainGraph 13 | 14 | 0_TerrainGraph 15 | 16 | 17 | 18 | GeologicalLandforms 19 | 20 | 1_GeologicalLandforms 21 | 22 | 23 | MapPreview 24 | TerrainGraph 25 | 26 | 27 | 28 | GeologicalLandformsMod 29 | 30 | 2_GeologicalLandformsMod 31 | 32 | 33 | GeologicalLandforms 34 | 35 | 36 | 37 | 38 | 39 | 40 | m00nl1ght.MapPreview 41 | 1.10.0 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_Dialog_WorldSearch.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | 8 | namespace GeologicalLandforms.Patches; 9 | 10 | [PatchGroup("Main")] 11 | [HarmonyPatch(typeof(Dialog_WorldSearch))] 12 | internal static class Patch_RimWorld_Dialog_WorldSearch 13 | { 14 | [HarmonyPostfix] 15 | [HarmonyPatch("InitializeSearchSet")] 16 | private static void InitializeSearchSet_Postfix(List ___searchSet) 17 | { 18 | foreach (var element in ___searchSet) 19 | { 20 | if (element.tile.Layer.IsRootSurface && element.tile.tileId >= 0) 21 | { 22 | element.mutators = TileMutatorsCustomization.Get(element.tile.tileId, element.mutators) as List; 23 | 24 | if (element.landmark != null) 25 | { 26 | foreach (var mutatorChance in element.landmark.def.mutatorChances) 27 | { 28 | // Ignore landmarks if their required tile mutator is disabled by the user via mod settings 29 | if (mutatorChance.required && (element.mutators == null || !element.mutators.Contains(mutatorChance.mutator))) 30 | { 31 | element.landmark = null; 32 | break; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_BiomesCore.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using GeologicalLandforms.GraphEditor; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.Compatibility; 10 | 11 | [HarmonyPatch] 12 | public class ModCompat_BiomesCore : ModCompat 13 | { 14 | public override string TargetAssemblyName => "BiomesCore"; 15 | public override string DisplayName => "Biomes! Core"; 16 | 17 | [HarmonyPrefix] 18 | [HarmonyPatch("BiomesCore.MapGeneration.GenStep_Island", "Generate")] 19 | private static bool GenStep_Island_Prefix() => Landform.GetFeature(lf => lf.OutputFertility?.Get()) == null; 20 | 21 | [HarmonyPrefix] 22 | [HarmonyPatch("BiomesCore.MapGeneration.GenStep_IslandElevation", "Generate")] 23 | private static bool GenStep_IslandElevation_Prefix() => Landform.GetFeature(lf => lf.OutputElevation?.Get()) == null; 24 | 25 | [HarmonyPrefix] 26 | [HarmonyPatch("BiomesCore.MapGeneration.GenStep_Cavern", "Generate")] 27 | private static bool GenStep_Cavern_Prefix() => Landform.GetFeature(lf => lf.OutputElevation?.Get()) == null; 28 | 29 | [HarmonyPrefix] 30 | [HarmonyPatch("BiomesCore.Patches.LocalBiomeExtensionPoint", "LocalBiome")] 31 | private static bool LocalBiomeExtensionPoint(Map map, IntVec3 pos, ref BiomeDef __result) 32 | { 33 | var biomeGrid = map.BiomeGrid(); 34 | if (biomeGrid is not { Enabled: true }) return true; 35 | __result = biomeGrid.BiomeAt(pos); 36 | return false; 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputCaves.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | 5 | namespace GeologicalLandforms.GraphEditor; 6 | 7 | [Serializable] 8 | [Node(false, "Output/Caves", 405)] 9 | public class NodeOutputCaves : NodeOutputBase 10 | { 11 | public const string ID = "outputCaves"; 12 | public override string GetID => ID; 13 | 14 | public override string Title => "Caves Output"; 15 | 16 | public override ValueConnectionKnob InputKnobRef => InputKnob; 17 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 18 | 19 | [ValueConnectionKnob("Caves", Direction.In, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob InputKnob; 21 | 22 | [ValueConnectionKnob("CavesOutput", Direction.Out, GridFunctionConnection.Id)] 23 | public ValueConnectionKnob OutputKnob; 24 | 25 | public override void OnCreate(bool fromGUI) 26 | { 27 | var exiting = Landform.OutputCaves; 28 | if (exiting != null && exiting != this && canvas.nodes.Contains(exiting)) exiting.Delete(); 29 | Landform.OutputCaves = this; 30 | } 31 | 32 | protected override void OnDelete() 33 | { 34 | if (Landform.OutputCaves == this) Landform.OutputCaves = null; 35 | } 36 | 37 | public IGridFunction Get() 38 | { 39 | return InputKnob.GetValue>>()?.ResetAndGet(); 40 | } 41 | 42 | public override bool Calculate() 43 | { 44 | OutputKnob.SetValue(InputKnob.GetValue>>()); 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AssetBundles/terraingraph.manifest: -------------------------------------------------------------------------------- 1 | ManifestFileVersion: 0 2 | CRC: 370444400 3 | Hashes: 4 | AssetFileHash: 5 | serializedVersion: 2 6 | Hash: 88946e967017e86e6734150da716ffc3 7 | TypeTreeHash: 8 | serializedVersion: 2 9 | Hash: 24e4188fe4e4eb280bf8a24ddc4be5ea 10 | HashAppended: 0 11 | ClassTypes: 12 | - Class: 28 13 | Script: {instanceID: 0} 14 | - Class: 48 15 | Script: {instanceID: 0} 16 | - Class: 213 17 | Script: {instanceID: 0} 18 | SerializeReferenceClassIdentifiers: [] 19 | Assets: 20 | - Assets/GL_NodeEditorFramework/Resources/Textures/expandRight.png 21 | - Assets/GL_NodeEditorFramework/Resources/Textures/Out_Knob.png 22 | - Assets/GL_NodeEditorFramework/Resources/Textures/Icon_Light.png 23 | - Assets/GL_NodeEditorFramework/Resources/Textures/AALine.png 24 | - Assets/GL_NodeEditorFramework/Resources/Shader/LineShader.shader 25 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_SelectedBG.png 26 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_ToolbarLabel.png 27 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_Toolbar.png 28 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_Button_Hover.png 29 | - Assets/GL_NodeEditorFramework/Resources/Textures/Icon_Dark.png 30 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_Button.png 31 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_ToolbarButton.png 32 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_Button_Selected.png 33 | - Assets/GL_NodeEditorFramework/Resources/Textures/NE_Box.png 34 | - Assets/GL_NodeEditorFramework/Resources/Textures/In_Knob.png 35 | - Assets/GL_NodeEditorFramework/Resources/Textures/background.png 36 | Dependencies: [] 37 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Custom/NodeApplyLayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NodeEditorFramework; 4 | using TerrainGraph; 5 | using UnityEngine; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | [Serializable] 11 | [Node(false, "Other/Apply Layer", 9001)] 12 | public class NodeApplyLayer : NodeBase 13 | { 14 | public const string ID = "applyLayer"; 15 | public override string GetID => ID; 16 | 17 | public override string Title => "Apply Layer"; 18 | 19 | public Landform Landform => (Landform) canvas; 20 | 21 | public string LayerId = ""; 22 | 23 | public override void NodeGUI() 24 | { 25 | GUILayout.BeginVertical(BoxStyle); 26 | GUILayout.BeginHorizontal(BoxStyle); 27 | 28 | if (GUILayout.Button(LayerId, GUI.skin.box, FullBoxLayout)) 29 | { 30 | var options = LandformManager.LandformsById.Values.Where(lf => lf.IsLayer && lf.WorldTileReq == null); 31 | Dropdown(options.ToList(), OnLandformSelected, t => t.Id); 32 | } 33 | 34 | GUILayout.EndHorizontal(); 35 | GUILayout.EndVertical(); 36 | 37 | if (GUI.changed) 38 | canvas.OnNodeChange(this); 39 | } 40 | 41 | private void OnLandformSelected(Landform landform) 42 | { 43 | LayerId = landform.Id; 44 | canvas.OnNodeChange(this); 45 | } 46 | 47 | public override void OnCreate(bool fromGUI) 48 | { 49 | Landform.ApplyLayers.AddDistinct(this); 50 | } 51 | 52 | protected override void OnDelete() 53 | { 54 | Landform.ApplyLayers.Remove(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_ExpandableLandmarksUtility.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection.Emit; 6 | using HarmonyLib; 7 | using LunarFramework.Patching; 8 | using RimWorld.Planet; 9 | using Verse; 10 | 11 | namespace GeologicalLandforms.Patches; 12 | 13 | /// 14 | /// Hide expandable items for landmarks which have been disabled by the user via customization settings. 15 | /// 16 | [PatchGroup("Main")] 17 | [HarmonyPatch(typeof(ExpandableLandmarksUtility))] 18 | internal static class Patch_RimWorld_ExpandableLandmarksUtility 19 | { 20 | private static readonly Type Self = typeof(Patch_RimWorld_ExpandableLandmarksUtility); 21 | 22 | [HarmonyTranspiler] 23 | [HarmonyPatch("get_LandmarksToShow")] 24 | private static IEnumerable GetLandmarksToShow_Transpiler(IEnumerable instructions) 25 | { 26 | var pattern = TranspilerPattern.Build("LandmarksToShow") 27 | .MatchCall(typeof(List), "Add") 28 | .Replace(OpCodes.Call, AccessTools.Method(Self, nameof(AddIfNotDisabled))); 29 | 30 | return TranspilerPattern.Apply(instructions, pattern); 31 | } 32 | 33 | private static void AddIfNotDisabled(List list, PlanetTile tile) 34 | { 35 | if (Find.World.landmarks.landmarks.TryGetValue(tile, out var landmark)) 36 | { 37 | if (landmark != null && !TileMutatorsCustomization.IsLandmarkDisabled(landmark.def)) 38 | { 39 | list.Add(tile); 40 | } 41 | } 42 | } 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputFertility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | 5 | namespace GeologicalLandforms.GraphEditor; 6 | 7 | [Serializable] 8 | [Node(false, "Output/Fertility", 401)] 9 | public class NodeOutputFertility : NodeOutputBase 10 | { 11 | public const string ID = "outputFertility"; 12 | public override string GetID => ID; 13 | 14 | public override string Title => "Fertility Output"; 15 | 16 | public override ValueConnectionKnob InputKnobRef => InputKnob; 17 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 18 | 19 | [ValueConnectionKnob("Fertility", Direction.In, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob InputKnob; 21 | 22 | [ValueConnectionKnob("FertilityOutput", Direction.Out, GridFunctionConnection.Id)] 23 | public ValueConnectionKnob OutputKnob; 24 | 25 | public override void OnCreate(bool fromGUI) 26 | { 27 | var exiting = Landform.OutputFertility; 28 | if (exiting != null && exiting != this && canvas.nodes.Contains(exiting)) exiting.Delete(); 29 | Landform.OutputFertility = this; 30 | } 31 | 32 | protected override void OnDelete() 33 | { 34 | if (Landform.OutputFertility == this) Landform.OutputFertility = null; 35 | } 36 | 37 | public IGridFunction Get() 38 | { 39 | return InputKnob.GetValue>>()?.ResetAndGet(); 40 | } 41 | 42 | public override bool Calculate() 43 | { 44 | OutputKnob.SetValue(InputKnob.GetValue>>()); 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/GeologicalLandformsMod/FloatMenuOptionProvider_PathingDebug.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | #if DEBUG 3 | 4 | using System.Collections.Generic; 5 | using RimWorld; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms; 9 | 10 | public class FloatMenuOptionProvider_PathingDebug : FloatMenuOptionProvider 11 | { 12 | protected override bool Drafted => true; 13 | 14 | protected override bool Undrafted => true; 15 | 16 | protected override bool Multiselect => false; 17 | 18 | protected override bool CanSelfTarget => true; 19 | 20 | public override IEnumerable GetOptionsFor(Pawn clickedPawn, FloatMenuContext context) 21 | { 22 | if (clickedPawn != context.FirstSelectedPawn) 23 | yield break; 24 | 25 | void ActionBest() 26 | { 27 | if (!RCellFinder.TryFindBestExitSpot(clickedPawn, out var dest1)) 28 | dest1 = clickedPawn.Position; 29 | var job1 = JobMaker.MakeJob(JobDefOf.Goto, dest1); 30 | job1.exitMapOnArrival = false; 31 | clickedPawn.jobs.TryTakeOrderedJob(job1); 32 | } 33 | 34 | void ActionRandom() 35 | { 36 | if (!RCellFinder.TryFindRandomExitSpot(clickedPawn, out var dest1)) 37 | dest1 = clickedPawn.Position; 38 | var job1 = JobMaker.MakeJob(JobDefOf.Goto, dest1); 39 | job1.exitMapOnArrival = false; 40 | clickedPawn.jobs.TryTakeOrderedJob(job1); 41 | } 42 | 43 | yield return new FloatMenuOption("[debug] Find best map exit", ActionBest); 44 | yield return new FloatMenuOption("[debug] Find random map exit", ActionRandom); 45 | } 46 | } 47 | 48 | #endif 49 | #endif 50 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Compatibility/ModCompat_RoadsOfTheRim.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using System.Linq; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld.Planet; 7 | 8 | namespace GeologicalLandforms.Compatibility; 9 | 10 | [HarmonyPatch] 11 | public class ModCompat_RoadsOfTheRim : ModCompat 12 | { 13 | public override string TargetAssemblyName => "RoadsOfTheRim"; 14 | public override string DisplayName => "Roads Of The Rim"; 15 | 16 | [HarmonyPostfix] 17 | [HarmonyPatch("RoadsOfTheRim.DefModExtension_RotR_RoadDef", "ImpassableAllowed")] 18 | private static void ImpassableAllowed_Postfix(int tile, ref bool __result) 19 | { 20 | if (!__result) 21 | { 22 | var tileInfo = WorldTileInfo.Get(tile); 23 | if (tileInfo.HasLandforms() && tileInfo.Landforms.Any(lf => !lf.IsLayer)) 24 | { 25 | __result = true; 26 | } 27 | } 28 | } 29 | } 30 | 31 | [HarmonyPatch] 32 | public class ModCompat_RailsAndRoadsOfTheRim : ModCompat 33 | { 34 | public override string TargetAssemblyName => "RailsAndRoadsOfTheRim"; 35 | public override string DisplayName => "Rails And Roads Of The Rim"; 36 | 37 | [HarmonyPostfix] 38 | [HarmonyPatch("RailsAndRoadsOfTheRim.DefModExtension_RotR_RoadDef", "ImpassableAllowed")] 39 | private static void ImpassableAllowed_Postfix(PlanetTile tile, ref bool __result) 40 | { 41 | if (!__result) 42 | { 43 | var tileInfo = WorldTileInfo.Get(tile.tileId); 44 | if (tileInfo.HasLandforms() && tileInfo.Landforms.Any(lf => !lf.IsLayer)) 45 | { 46 | __result = true; 47 | } 48 | } 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/UI/NodeUIBase.cs: -------------------------------------------------------------------------------- 1 | using LunarFramework.GUI; 2 | using TerrainGraph; 3 | using UnityEngine; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | public abstract class NodeUIBase : NodeBase 9 | { 10 | public Landform Landform => (Landform) canvas; 11 | 12 | public override bool AutoLayout => false; 13 | 14 | protected virtual float Margin => 15f; 15 | 16 | private readonly LayoutRect _layout = new(GeologicalLandformsAPI.LunarAPI); 17 | 18 | public override void NodeGUI() 19 | { 20 | var inner = GUILayoutUtility.GetRect(rect.width, rect.height); 21 | 22 | _layout.PushChanged(); 23 | 24 | _layout.BeginRoot(inner, new LayoutParams { Margin = new(Margin) }); 25 | DoWindowContents(_layout); 26 | _layout.End(); 27 | 28 | if (_layout.PopChanged()) TerrainCanvas.OnNodeChange(this); 29 | } 30 | 31 | protected abstract void DoWindowContents(LayoutRect layout); 32 | 33 | protected static void DoCheckbox(Rect rect, ref bool value, string label) 34 | { 35 | var before = value; 36 | LunarGUI.HighlightOnHover(rect); 37 | var preAnchor = Text.Anchor; 38 | Text.Anchor = TextAnchor.MiddleLeft; 39 | var labelRect = rect; 40 | labelRect.xMax -= 24f; 41 | Widgets.Label(labelRect, label); 42 | if (GUI.enabled && Widgets.ButtonInvisible(rect)) value = !value; 43 | Widgets.CheckboxDraw(rect.x + rect.width - 24, rect.y + (rect.height - 24) / 2f, value, !GUI.enabled); 44 | Text.Anchor = preAnchor; 45 | if (value != before) GUI.changed = true; 46 | } 47 | 48 | public override bool Calculate() 49 | { 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/World/Topology.cs: -------------------------------------------------------------------------------- 1 | using static GeologicalLandforms.Topology; 2 | 3 | namespace GeologicalLandforms; 4 | 5 | public enum Topology : byte 6 | { 7 | Any, 8 | Inland, 9 | CoastOneSide, 10 | CoastTwoSides, 11 | CoastLandbridge, 12 | CoastThreeSides, 13 | CoastAllSides, 14 | CliffOneSide, 15 | CliffTwoSides, 16 | CliffValley, 17 | CliffThreeSides, 18 | CliffAllSides, 19 | CliffAndCoast, 20 | CaveEntrance, 21 | CaveTunnel, 22 | Ocean 23 | } 24 | 25 | public static class TopologyExtensions 26 | { 27 | public static bool IsCoast(this Topology topology, bool includeSpecial = false) 28 | { 29 | return topology is CoastOneSide or CoastTwoSides or CoastThreeSides or CliffAndCoast 30 | || (includeSpecial && topology is CoastLandbridge or CoastAllSides); 31 | } 32 | 33 | public static bool IsCliff(this Topology topology, bool includeSpecial = false) 34 | { 35 | return topology is CliffOneSide or CliffTwoSides or CliffThreeSides or CliffAllSides 36 | || (includeSpecial && topology is CliffValley or CliffAndCoast); 37 | } 38 | 39 | public static bool IsCommon(this Topology topology) 40 | { 41 | return topology is CliffOneSide or CliffTwoSides or CoastOneSide or CoastTwoSides; 42 | } 43 | 44 | public static bool IsCompatible(this Topology req, Topology tile, bool lenient) 45 | { 46 | if (req == Any || tile == req) return true; 47 | if (!lenient) return false; 48 | if (req.IsCoast() && tile.IsCoast(true)) return true; 49 | if (req.IsCliff() && tile.IsCliff(true)) return true; 50 | if (req == Inland && tile.IsCliff(true)) return true; 51 | return false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Input/NodeInputElevation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Input/Elevation", 350)] 10 | public class NodeInputElevation : NodeInputBase 11 | { 12 | public const string ID = "inputElevation"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Elevation Input"; 16 | 17 | public override ValueConnectionKnob KnobRef => Knob; 18 | 19 | [ValueConnectionKnob("Elevation", Direction.Out, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob Knob; 21 | 22 | public override void OnCreate(bool fromGUI) 23 | { 24 | var existing = Landform.InputElevation; 25 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 26 | Landform.InputElevation = this; 27 | } 28 | 29 | protected override void OnDelete() 30 | { 31 | if (Landform.InputElevation == this) Landform.InputElevation = null; 32 | } 33 | 34 | public override bool Calculate() 35 | { 36 | #if RW_1_6_OR_GREATER 37 | 38 | if (MapGenerator.mapBeingGenerated is {} map) 39 | { 40 | Knob.SetValue(Supplier.From(() => Landform.TransformIntoNodeSpace(new DiscreteFloatGridWrapper(MapGenerator.Elevation, map.Size, 1d)))); 41 | return true; 42 | } 43 | 44 | #endif 45 | 46 | var supplier = GetFromBelowStack(Landform, l => l.OutputElevation?.InputKnob.GetValue>>()); 47 | supplier ??= BuildVanillaElevationGridSupplier(); 48 | Knob.SetValue(supplier); 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Input/NodeInputFertility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Input/Fertility", 351)] 10 | public class NodeInputFertility : NodeInputBase 11 | { 12 | public const string ID = "inputFertility"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Fertility Input"; 16 | 17 | public override ValueConnectionKnob KnobRef => Knob; 18 | 19 | [ValueConnectionKnob("Fertility", Direction.Out, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob Knob; 21 | 22 | public override void OnCreate(bool fromGUI) 23 | { 24 | var existing = Landform.InputFertility; 25 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 26 | Landform.InputFertility = this; 27 | } 28 | 29 | protected override void OnDelete() 30 | { 31 | if (Landform.InputFertility == this) Landform.InputFertility = null; 32 | } 33 | 34 | public override bool Calculate() 35 | { 36 | #if RW_1_6_OR_GREATER 37 | 38 | if (MapGenerator.mapBeingGenerated is {} map) 39 | { 40 | Knob.SetValue(Supplier.From(() => Landform.TransformIntoNodeSpace(new DiscreteFloatGridWrapper(MapGenerator.Fertility, map.Size, 0d)))); 41 | return true; 42 | } 43 | 44 | #endif 45 | 46 | var supplier = GetFromBelowStack(Landform, l => l.OutputFertility?.InputKnob.GetValue>>()); 47 | supplier ??= BuildVanillaFertilityGridSupplier(); 48 | Knob.SetValue(supplier); 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WalkPathFinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | using RimWorld.Planet; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(WalkPathFinder))] 14 | internal static class Patch_RimWorld_WalkPathFinder 15 | { 16 | private static readonly Type Self = typeof(Patch_RimWorld_WalkPathFinder); 17 | 18 | [HarmonyTargetMethod] 19 | private static MethodBase TargetMethod() 20 | { 21 | #if RW_1_6_OR_GREATER 22 | return AccessTools.FindIncludingInnerTypes(typeof(WalkPathFinder), type => AccessTools.FirstMethod(type, method => 23 | method.Name.Contains("") && method.Name.Contains("ValidCell") && method.ReturnType == typeof(bool) 24 | )); 25 | #else 26 | return AccessTools.Method(typeof(WalkPathFinder), "TryFindWalkPath"); 27 | #endif 28 | } 29 | 30 | [HarmonyTranspiler] 31 | [HarmonyPriority(Priority.Low)] 32 | private static IEnumerable TryFindWalkPath_Transpiler(IEnumerable instructions) 33 | { 34 | var pattern = TranspilerPattern.Build("TryFindWalkPath") 35 | .MatchCall(typeof(GridsUtility), "Roofed", [typeof(IntVec3), typeof(Map)]).Remove() 36 | .Insert(CodeInstruction.Call(Self, nameof(RoofedAndTileNotImpassable))); 37 | 38 | return TranspilerPattern.Apply(instructions, pattern); 39 | } 40 | 41 | private static bool RoofedAndTileNotImpassable(IntVec3 pos, Map map) 42 | { 43 | return pos.Roofed(map) && map.TileInfo.hilliness != Hilliness.Impassable; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Input/NodeInputTerrain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Input/Terrain", 352)] 10 | public class NodeInputTerrain : NodeInputBase 11 | { 12 | public const string ID = "inputTerrain"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Terrain Input"; 16 | 17 | public override ValueConnectionKnob KnobRef => Knob; 18 | 19 | [ValueConnectionKnob("Base", Direction.Out, TerrainGridFunctionConnection.Id)] 20 | public ValueConnectionKnob Knob; 21 | 22 | public override void OnCreate(bool fromGUI) 23 | { 24 | var existing = Landform.InputTerrain; 25 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 26 | Landform.InputTerrain = this; 27 | } 28 | 29 | protected override void OnDelete() 30 | { 31 | if (Landform.InputTerrain == this) Landform.InputTerrain = null; 32 | } 33 | 34 | public override bool Calculate() 35 | { 36 | #if RW_1_6_OR_GREATER 37 | 38 | if (MapGenerator.mapBeingGenerated is { terrainGrid: not null } map) 39 | { 40 | Knob.SetValue(Supplier.From(() => Landform.TransformIntoNodeSpace(new DiscreteTerrainGridWrapper(map.terrainGrid, map.Size, null)))); 41 | return true; 42 | } 43 | 44 | #endif 45 | 46 | var supplier = GetFromBelowStack(Landform, l => l.OutputTerrain?.BaseKnob.GetValue>>()); 47 | supplier ??= Supplier.Of(GridFunction.Of(null)); 48 | Knob.SetValue(supplier); 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/TerrainGrid/NodeTerrainGridNaturalRock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using RimWorld; 4 | using TerrainGraph; 5 | using UnityEngine; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | [Serializable] 11 | [Node(false, "Terrain/Grid/Natural Rock", 315)] 12 | public class NodeTerrainGridNaturalRock : NodeBase 13 | { 14 | public const string ID = "terrainGridNaturalRock"; 15 | public override string GetID => ID; 16 | 17 | public override Vector2 MinSize => new(100, 10); 18 | 19 | public override string Title => "Natural Rock"; 20 | 21 | [ValueConnectionKnob("Output", Direction.Out, TerrainGridFunctionConnection.Id)] 22 | public ValueConnectionKnob OutputKnob; 23 | 24 | public override void NodeGUI() 25 | { 26 | GUILayout.BeginVertical(BoxStyle); 27 | 28 | GUILayout.BeginHorizontal(BoxStyle); 29 | GUILayout.Label("Rock Grid", DoubleBoxLayout); 30 | GUILayout.EndHorizontal(); 31 | OutputKnob.SetPosition(); 32 | 33 | GUILayout.EndVertical(); 34 | } 35 | 36 | public override bool Calculate() 37 | { 38 | OutputKnob.SetValue>>(Supplier.Of>(new RockGridFunction())); 39 | return true; 40 | } 41 | 42 | private class RockGridFunction : IGridFunction 43 | { 44 | public TerrainDef ValueAt(double x, double z) 45 | { 46 | if (RockNoises.rockNoises == null) return ThingDefOf.Sandstone.building.naturalTerrain; 47 | return GenStep_RocksFromGrid.RockDefAt(new IntVec3((int) Math.Round(x, 0), 0, (int) Math.Round(z, 0))).building.naturalTerrain; 48 | } 49 | 50 | public override string ToString() => "ROCK GRID {}"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_Verse_Command_SetPlantToGrow.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(Command_SetPlantToGrow))] 14 | internal static class Patch_Verse_Command_SetPlantToGrow 15 | { 16 | [HarmonyPrefix] 17 | [HarmonyPatch("IsPlantAvailable")] 18 | [HarmonyPriority(Priority.VeryLow)] 19 | private static bool IsPlantAvailable_Prefix(ThingDef plantDef, Map map, ref bool __result) 20 | { 21 | var biomeGrid = map.BiomeGrid(); 22 | if (biomeGrid is not { Enabled: true }) return true; 23 | 24 | __result = IsPlantAvailable_LocalBiomeAware(plantDef, map, biomeGrid); 25 | return false; 26 | } 27 | 28 | [HarmonyPatch("IsPlantAvailable")] 29 | [HarmonyReversePatch(HarmonyReversePatchType.Snapshot)] 30 | [HarmonyPriority(Priority.VeryLow + 1)] 31 | internal static bool IsPlantAvailable_LocalBiomeAware(ThingDef plantDef, Map map, BiomeGrid biomeGrid) 32 | { 33 | IEnumerable Transpiler(IEnumerable instructions) 34 | { 35 | var pattern = TranspilerPattern.Build("AllWildPlants") 36 | .Match(OpCodes.Ldarg_1).Replace(OpCodes.Ldarg_2) 37 | .MatchCall(typeof(Map), "get_Biome").Remove() 38 | .MatchCall(typeof(BiomeDef), "get_AllWildPlants").Remove() 39 | .Insert(CodeInstruction.Call(typeof(BiomeGrid), "get_AllPotentialPlants")); 40 | 41 | return TranspilerPattern.Apply(instructions, pattern); 42 | } 43 | 44 | _ = Transpiler(null); 45 | return false; 46 | } 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Utility/CompatUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.CompilerServices; 3 | using System.Threading; 4 | using RimWorld.Planet; 5 | using Unity.Collections; 6 | using UnityEngine; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms; 10 | 11 | public static class CompatUtils 12 | { 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static int Length(this NativeArray array) where T : struct => array.Length; 15 | 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public static int Length(this List list) where T : struct => list.Count; 18 | 19 | #if RW_1_6_OR_GREATER 20 | 21 | public static NativeArray ExtNbValues(this WorldGrid grid) => grid.UnsafeTileIDToNeighbors_values; 22 | public static NativeArray ExtNbOffsets(this WorldGrid grid) => grid.UnsafeTileIDToNeighbors_offsets; 23 | public static NativeArray ExtVertValues(this WorldGrid grid) => grid.UnsafeVerts; 24 | public static NativeArray ExtVertOffsets(this WorldGrid grid) => grid.UnsafeTileIDToVerts_offsets; 25 | 26 | #else 27 | 28 | public static List ExtNbValues(this WorldGrid grid) => grid.tileIDToNeighbors_values; 29 | public static List ExtNbOffsets(this WorldGrid grid) => grid.tileIDToNeighbors_offsets; 30 | public static List ExtVertValues(this WorldGrid grid) => grid.verts; 31 | public static List ExtVertOffsets(this WorldGrid grid) => grid.tileIDToVerts_offsets; 32 | 33 | #endif 34 | 35 | public static bool IsMainOrLongEventThread() 36 | { 37 | if (UnityData.IsInMainThread) 38 | return true; 39 | 40 | if (LongEventHandler.eventThread == null) 41 | return false; 42 | 43 | return Thread.CurrentThread.ManagedThreadId == LongEventHandler.eventThread.ManagedThreadId; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeologicalLandforms", "GeologicalLandforms\GeologicalLandforms.csproj", "{3D0DE44D-4410-4F16-8E49-85FE38D12051}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerrainGraph", "TerrainGraph\TerrainGraph.csproj", "{B6FBAC5C-B4DB-411A-885B-FE710846011F}" 6 | EndProject 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeologicalLandformsMod", "GeologicalLandformsMod\GeologicalLandformsMod.csproj", "{B0D7D213-E636-4516-B545-D4C22FDD2F80}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {3D0DE44D-4410-4F16-8E49-85FE38D12051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {3D0DE44D-4410-4F16-8E49-85FE38D12051}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {3D0DE44D-4410-4F16-8E49-85FE38D12051}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {3D0DE44D-4410-4F16-8E49-85FE38D12051}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {B6FBAC5C-B4DB-411A-885B-FE710846011F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {B6FBAC5C-B4DB-411A-885B-FE710846011F}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {B6FBAC5C-B4DB-411A-885B-FE710846011F}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {B6FBAC5C-B4DB-411A-885B-FE710846011F}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {B0D7D213-E636-4516-B545-D4C22FDD2F80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {B0D7D213-E636-4516-B545-D4C22FDD2F80}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {B0D7D213-E636-4516-B545-D4C22FDD2F80}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {B0D7D213-E636-4516-B545-D4C22FDD2F80}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/XML/XmlDynamicValueContexts.cs: -------------------------------------------------------------------------------- 1 | using GeologicalLandforms.GraphEditor; 2 | using RimWorld.Planet; 3 | using Verse; 4 | 5 | namespace GeologicalLandforms; 6 | 7 | public interface ICtxEarlyTile 8 | { 9 | public int TileId { get; } 10 | public Tile Tile { get; } 11 | public World World { get; } 12 | } 13 | 14 | public readonly struct CtxEarlyTile : ICtxEarlyTile 15 | { 16 | public int TileId { get; } 17 | public Tile Tile { get; } 18 | public World World { get; } 19 | 20 | public CtxEarlyTile(int tileId, Tile tile, World world) 21 | { 22 | TileId = tileId; 23 | Tile = tile; 24 | World = world; 25 | } 26 | } 27 | 28 | public interface ICtxTile 29 | { 30 | public IWorldTileInfo TileInfo { get; } 31 | } 32 | 33 | public readonly struct CtxTile : ICtxTile 34 | { 35 | public IWorldTileInfo TileInfo { get; } 36 | 37 | public CtxTile(IWorldTileInfo tileInfo) 38 | { 39 | TileInfo = tileInfo; 40 | } 41 | } 42 | 43 | public interface ICtxMapCell : ICtxTile 44 | { 45 | public Map Map { get; } 46 | public IntVec3 MapCell { get; } 47 | } 48 | 49 | public readonly struct CtxMapCell : ICtxMapCell 50 | { 51 | public IWorldTileInfo TileInfo { get; } 52 | 53 | public Map Map { get; } 54 | public IntVec3 MapCell { get; } 55 | 56 | public CtxMapCell(IWorldTileInfo tileInfo, Map map, IntVec3 mapCell) 57 | { 58 | TileInfo = tileInfo; 59 | Map = map; 60 | MapCell = mapCell; 61 | } 62 | } 63 | 64 | public interface ICtxMapGenCell : ICtxMapCell; 65 | 66 | public readonly struct CtxMapGenCell : ICtxMapGenCell 67 | { 68 | public IWorldTileInfo TileInfo => Landform.GeneratingTile; 69 | public Map Map => MapGenerator.mapBeingGenerated; 70 | 71 | public IntVec3 MapCell { get; } 72 | 73 | public CtxMapGenCell(IntVec3 mapCell) 74 | { 75 | MapCell = mapCell; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Input/NodeInputBiomeGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using RimWorld; 4 | using TerrainGraph; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | [Serializable] 10 | [Node(false, "Input/Biome Grid", 353)] 11 | public class NodeInputBiomeGrid : NodeInputBase 12 | { 13 | public const string ID = "inputBiomeGrid"; 14 | public override string GetID => ID; 15 | 16 | public override string Title => "Biome Input"; 17 | 18 | public override ValueConnectionKnob KnobRef => Knob; 19 | 20 | [ValueConnectionKnob("Biome Grid", Direction.Out, BiomeGridFunctionConnection.Id)] 21 | public ValueConnectionKnob Knob; 22 | 23 | public override void OnCreate(bool fromGUI) 24 | { 25 | var existing = Landform.InputBiomeGrid; 26 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 27 | Landform.InputBiomeGrid = this; 28 | } 29 | 30 | protected override void OnDelete() 31 | { 32 | if (Landform.InputBiomeGrid == this) Landform.InputBiomeGrid = null; 33 | } 34 | 35 | public override bool Calculate() 36 | { 37 | #if RW_1_6_OR_GREATER 38 | 39 | if (MapGenerator.mapBeingGenerated != null) 40 | { 41 | var biomeGrid = MapGenerator.mapBeingGenerated.BiomeGrid(); 42 | if (biomeGrid != null) 43 | { 44 | Knob.SetValue(Supplier.From(() => Landform.TransformIntoNodeSpace(new DiscreteBiomeGridWrapper(biomeGrid)))); 45 | return true; 46 | } 47 | } 48 | 49 | #endif 50 | 51 | var supplier = GetFromBelowStack(Landform, l => l.OutputBiomeGrid?.BiomeGridKnob.GetValue>>()); 52 | supplier ??= Supplier.Of(GridFunction.Of(Landform.GeneratingTile.Biome)); 53 | Knob.SetValue(supplier); 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/UI/NodeUILayerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LunarFramework.GUI; 3 | using NodeEditorFramework; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | [Serializable] 10 | [Node(false, "Other/Layer Config", 9000)] 11 | public class NodeUILayerConfig : NodeUIBase 12 | { 13 | public const string ID = "layerConfig"; 14 | public override string GetID => ID; 15 | 16 | public override string Title => "Layer Config"; 17 | public override Vector2 DefaultSize => new(400, 115); 18 | 19 | public string LayerId = ""; 20 | public int Priority; 21 | 22 | private string _priorityEdit; 23 | 24 | protected override void DoWindowContents(LayoutRect layout) 25 | { 26 | layout.PushEnabled(Landform.IsCustom); 27 | 28 | layout.BeginAbs(28f); 29 | LunarGUI.Label(layout.Rel(0.3f), "GeologicalLandforms.Settings.Landform.LayerId".Translate()); 30 | LunarGUI.TextField(layout, ref LayerId); 31 | layout.End(); 32 | 33 | layout.Abs(10f); 34 | 35 | layout.BeginAbs(28f); 36 | LunarGUI.Label(layout.Rel(0.3f), "GeologicalLandforms.Settings.Landform.Priority".Translate()); 37 | LunarGUI.IntField(layout, ref Priority, ref _priorityEdit, -999, 999); 38 | layout.End(); 39 | 40 | layout.PopEnabled(); 41 | 42 | LayerId = LayerId.ToLower(); 43 | } 44 | 45 | public override void DrawNode() 46 | { 47 | if (Landform.Id != null) base.DrawNode(); 48 | } 49 | 50 | public override void OnCreate(bool fromGUI) 51 | { 52 | var existing = Landform.LayerConfig; 53 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 54 | Landform.LayerConfig = this; 55 | } 56 | 57 | protected override void OnDelete() 58 | { 59 | if (Landform.LayerConfig == this) Landform.LayerConfig = null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_Verse_AnimalPenManager.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(AnimalPenManager))] 14 | internal static class Patch_Verse_AnimalPenManager 15 | { 16 | [HarmonyPrefix] 17 | [HarmonyPatch("GetFixedAutoCutFilter")] 18 | [HarmonyPriority(Priority.VeryLow)] 19 | private static bool GetFixedAutoCutFilter_Prefix(AnimalPenManager __instance, Map ___map, ref ThingFilter __result) 20 | { 21 | var biomeGrid = ___map.BiomeGrid(); 22 | if (biomeGrid is not { Enabled: true }) return true; 23 | 24 | __result = GetFixedAutoCutFilter_LocalBiomeAware(__instance, biomeGrid); 25 | return false; 26 | } 27 | 28 | [HarmonyPatch("GetFixedAutoCutFilter")] 29 | [HarmonyReversePatch(HarmonyReversePatchType.Snapshot)] 30 | [HarmonyPriority(Priority.VeryLow + 1)] 31 | private static ThingFilter GetFixedAutoCutFilter_LocalBiomeAware(AnimalPenManager instance, BiomeGrid biomeGrid) 32 | { 33 | IEnumerable Transpiler(IEnumerable instructions) 34 | { 35 | var pattern = TranspilerPattern.Build("AllWildPlants") 36 | .Match(OpCodes.Ldarg_0).Replace(OpCodes.Ldarg_1) 37 | .MatchLoad(typeof(AnimalPenManager), "map").Remove() 38 | .MatchCall(typeof(Map), "get_Biome").Remove() 39 | .MatchCall(typeof(BiomeDef), "get_AllWildPlants").Remove() 40 | .Insert(CodeInstruction.Call(typeof(BiomeGrid), "get_AllPotentialPlants")); 41 | 42 | return TranspilerPattern.Apply(instructions, pattern); 43 | } 44 | 45 | _ = Transpiler(null); 46 | return null; 47 | } 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Input/NodeInputCaves.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using Verse; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Input/Caves", 354)] 10 | public class NodeInputCaves : NodeInputBase 11 | { 12 | public const string ID = "inputCaves"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Caves Input"; 16 | 17 | public override ValueConnectionKnob KnobRef => Knob; 18 | 19 | [ValueConnectionKnob("Caves", Direction.Out, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob Knob; 21 | 22 | public override void OnCreate(bool fromGUI) 23 | { 24 | var existing = Landform.InputCaves; 25 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 26 | Landform.InputCaves = this; 27 | } 28 | 29 | protected override void OnDelete() 30 | { 31 | if (Landform.InputCaves == this) Landform.InputCaves = null; 32 | } 33 | 34 | public override bool Calculate() 35 | { 36 | #if RW_1_6_OR_GREATER 37 | 38 | if (MapGenerator.mapBeingGenerated is {} map) 39 | { 40 | Knob.SetValue(Supplier.From(() => Landform.TransformIntoNodeSpace(new DiscreteFloatGridWrapper(MapGenerator.Caves, map.Size, 0d)))); 41 | return true; 42 | } 43 | 44 | #endif 45 | 46 | var supplier = GetFromBelowStack(Landform, l => l.OutputCaves?.InputKnob.GetValue>>()); 47 | if (supplier != null) 48 | { 49 | Knob.SetValue(supplier); 50 | return true; 51 | } 52 | 53 | if (!Landform.GeneratingTile.HasCaves) 54 | { 55 | Knob.SetValue(Supplier.Of(GridFunction.Zero)); 56 | return true; 57 | } 58 | 59 | Knob.SetValue(BuildVanillaCaveGridSupplier()); 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputScatterers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Output/Scatterers", 406)] 10 | public class NodeOutputScatterers : NodeOutputBase 11 | { 12 | public const string ID = "outputScatterers"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Scatterers"; 16 | 17 | [ValueConnectionKnob("Mineables", Direction.In, ValueFunctionConnection.Id)] 18 | public ValueConnectionKnob MineablesKnob; 19 | 20 | [ValueConnectionKnob("Cave Hives", Direction.In, ValueFunctionConnection.Id)] 21 | public ValueConnectionKnob CaveHivesKnob; 22 | 23 | public override void NodeGUI() 24 | { 25 | GUILayout.BeginVertical(BoxStyle); 26 | 27 | GUILayout.BeginHorizontal(BoxStyle); 28 | GUILayout.Label(MineablesKnob.name, BoxLayout); 29 | GUILayout.EndHorizontal(); 30 | MineablesKnob.SetPosition(); 31 | 32 | GUILayout.BeginHorizontal(BoxStyle); 33 | GUILayout.Label(CaveHivesKnob.name, BoxLayout); 34 | GUILayout.EndHorizontal(); 35 | CaveHivesKnob.SetPosition(); 36 | 37 | GUILayout.EndVertical(); 38 | } 39 | 40 | public override void OnCreate(bool fromGUI) 41 | { 42 | var existing = Landform.OutputScatterers; 43 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 44 | Landform.OutputScatterers = this; 45 | } 46 | 47 | protected override void OnDelete() 48 | { 49 | if (Landform.OutputScatterers == this) Landform.OutputScatterers = null; 50 | } 51 | 52 | public double? GetMineables() 53 | { 54 | return MineablesKnob.GetValue>()?.ResetAndGet(); 55 | } 56 | 57 | public double? GetCaveHives() 58 | { 59 | return CaveHivesKnob.GetValue>()?.ResetAndGet(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /About/About.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | m00nl1ght.GeologicalLandforms 4 | https://github.com/m00nl1ght-dev/GeologicalLandforms 5 | Geological Landforms 6 | m00nl1ght 7 | Adds 44 landforms to the game, which generate biome-independently. The goal of this mod is to make map generation more interesting and varied, compared to the vanilla experience of simply having either a cliff or a coast on one edge of your map. 8 | 9 |
  • 1.3
  • 10 |
  • 1.4
  • 11 |
  • 1.5
  • 12 |
  • 1.6
  • 13 |
    14 | 15 | 16 |
  • 17 | brrainz.harmony 18 | Harmony 19 | steam://url/CommunityFilePage/2009463077 20 | https://github.com/pardeike/HarmonyRimWorld/releases/latest 21 |
  • 22 |
    23 | 24 | 25 | 26 | 27 |
    28 | 29 | 34 |
  • rwmt.multiplayer
  • 35 |
    36 | 37 |
  • Ludeon.RimWorld
  • 38 |
  • Ludeon.RimWorld.Royalty
  • 39 |
  • Ludeon.RimWorld.Ideology
  • 40 |
  • Ludeon.RimWorld.Biotech
  • 41 |
  • Ludeon.RimWorld.Anomaly
  • 42 |
  • Ludeon.RimWorld.Odyssey
  • 43 |
  • brrainz.harmony
  • 44 |
    45 | 46 | 47 |
    48 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/RoofGrid/NodeRoofGridPreview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using NodeEditorFramework; 4 | using TerrainGraph; 5 | using UnityEngine; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | [Serializable] 11 | [Node(false, "Roof/Grid/Preview", 336)] 12 | public class NodeRoofGridPreview : NodeDiscreteGridPreview 13 | { 14 | public const string ID = "roofGridPreview"; 15 | public override string GetID => ID; 16 | 17 | public override string Title => "Preview"; 18 | 19 | public override ValueConnectionKnob InputKnobRef => InputKnob; 20 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 21 | 22 | protected override IGridFunction Default => GridFunction.Of(null); 23 | 24 | [ValueConnectionKnob("Input", Direction.In, RoofGridFunctionConnection.Id)] 25 | public ValueConnectionKnob InputKnob; 26 | 27 | [ValueConnectionKnob("Output", Direction.Out, RoofGridFunctionConnection.Id)] 28 | public ValueConnectionKnob OutputKnob; 29 | 30 | private readonly List _colorIdxCache = []; 31 | 32 | public override bool Calculate() 33 | { 34 | _colorIdxCache.Clear(); 35 | 36 | OutputKnob.SetValue(InputKnob.GetValue>>()); 37 | return true; 38 | } 39 | 40 | protected override string MakeTooltip(RoofDef value, double x, double y) 41 | { 42 | var displayName = RoofFunctionConnection.Instance.DisplayName(value); 43 | return $"{displayName} ( {Math.Round(x, 0)} | {Math.Round(y, 0)} )"; 44 | } 45 | 46 | protected override Color GetColor(RoofDef value) 47 | { 48 | if (value == null) return Color.black; 49 | 50 | var idx = _colorIdxCache.IndexOf(value); 51 | 52 | if (idx < 0) 53 | { 54 | idx = _colorIdxCache.Count; 55 | _colorIdxCache.Add(value); 56 | } 57 | 58 | return NodeGridPreview.FixedColors[idx % NodeGridPreview.FixedColors.Count]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_RimWorld_CompAutoCutWindTurbine.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(CompAutoCutWindTurbine))] 14 | internal static class Patch_RimWorld_CompAutoCutWindTurbine 15 | { 16 | [HarmonyPrefix] 17 | [HarmonyPatch("GetFixedAutoCutFilter")] 18 | [HarmonyPriority(Priority.VeryLow)] 19 | private static bool GetFixedAutoCutFilter_Prefix(CompAutoCutWindTurbine __instance, ThingWithComps ___parent, ref ThingFilter __result) 20 | { 21 | var biomeGrid = ___parent.Map.BiomeGrid(); 22 | if (biomeGrid is not { Enabled: true }) return true; 23 | 24 | __result = GetFixedAutoCutFilter_LocalBiomeAware(__instance, biomeGrid); 25 | return false; 26 | } 27 | 28 | [HarmonyPatch("GetFixedAutoCutFilter")] 29 | [HarmonyReversePatch(HarmonyReversePatchType.Snapshot)] 30 | [HarmonyPriority(Priority.VeryLow + 1)] 31 | private static ThingFilter GetFixedAutoCutFilter_LocalBiomeAware(CompAutoCutWindTurbine instance, BiomeGrid biomeGrid) 32 | { 33 | IEnumerable Transpiler(IEnumerable instructions) 34 | { 35 | var pattern = TranspilerPattern.Build("AllWildPlants") 36 | .Match(OpCodes.Ldarg_0).Replace(OpCodes.Ldarg_1) 37 | .MatchLoad(typeof(ThingComp), "parent").Remove() 38 | .MatchCall(typeof(Thing), "get_Map").Remove() 39 | .MatchCall(typeof(Map), "get_Biome").Remove() 40 | .MatchCall(typeof(BiomeDef), "get_AllWildPlants").Remove() 41 | .Insert(CodeInstruction.Call(typeof(BiomeGrid), "get_AllPotentialPlants")); 42 | 43 | return TranspilerPattern.Apply(instructions, pattern); 44 | } 45 | 46 | _ = Transpiler(null); 47 | return null; 48 | } 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/LandformPreviewScheduler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LunarFramework.GUI; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | public class LandformPreviewScheduler : AsyncPreviewScheduler 10 | { 11 | public static readonly LandformPreviewScheduler Instance = new(); 12 | 13 | private readonly Texture2D _loadingIndicator; 14 | 15 | private LandformPreviewScheduler() 16 | { 17 | _loadingIndicator = ContentFinder.Get("LoadingIndicatorStaticGL"); 18 | } 19 | 20 | protected override void RunOnMainThread(Action action) 21 | { 22 | GeologicalLandformsAPI.LunarAPI.LifecycleHooks.DoOnce(action); 23 | } 24 | 25 | protected override void OnError(PreviewTask task, Exception exception) 26 | { 27 | GeologicalLandformsAPI.Logger.Warn("Error occured while generating preview for node: " + task.Node.name, exception); 28 | } 29 | 30 | private const float IndSize = 50f; 31 | 32 | public override void DrawLoadingIndicator(NodeBase node, Rect rect) 33 | { 34 | if (node.OngoingPreviewTask is { Exception: not null }) 35 | { 36 | LunarGUI.DrawQuad(rect, new Color(0f, 0f, 0f, 0.65f)); 37 | var prevColor = GUI.color; 38 | GUI.color = new Color(1, 0, 0, 1); 39 | GUI.DrawTexture(rect.ScaledBy(0.5f), TexButton.CloseXSmall); 40 | GUI.color = prevColor; 41 | } 42 | else if (node.OngoingPreviewTask is not { TimeSinceCreated: < 0.1f, WasIdleBefore: true }) 43 | { 44 | LunarGUI.DrawQuad(rect, new Color(0f, 0f, 0f, 0.65f)); 45 | var alpha = 1f - (1 + Mathf.Sin(Time.time * 3f)) * 0.4f; 46 | var cRect = new Rect(rect.center.x - IndSize / 2f, rect.center.y - IndSize / 2f, IndSize, IndSize); 47 | var prevColor = GUI.color; 48 | GUI.color = new Color(1, 1, 1, alpha); 49 | GUI.DrawTexture(cRect, _loadingIndicator); 50 | GUI.color = prevColor; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/BiomeGrid/NodeBiomeGridPreview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using NodeEditorFramework; 4 | using RimWorld; 5 | using TerrainGraph; 6 | using UnityEngine; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | [Serializable] 11 | [Node(false, "Biome/Grid/Preview", 346)] 12 | public class NodeBiomeGridPreview : NodeDiscreteGridPreview 13 | { 14 | public const string ID = "biomeGridPreview"; 15 | public override string GetID => ID; 16 | 17 | public override string Title => "Preview"; 18 | 19 | public override ValueConnectionKnob InputKnobRef => InputKnob; 20 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 21 | 22 | protected override IGridFunction Default => GridFunction.Of(null); 23 | 24 | [ValueConnectionKnob("Input", Direction.In, BiomeGridFunctionConnection.Id)] 25 | public ValueConnectionKnob InputKnob; 26 | 27 | [ValueConnectionKnob("Output", Direction.Out, BiomeGridFunctionConnection.Id)] 28 | public ValueConnectionKnob OutputKnob; 29 | 30 | private readonly List _colorIdxCache = []; 31 | 32 | public override bool Calculate() 33 | { 34 | _colorIdxCache.Clear(); 35 | 36 | OutputKnob.SetValue(InputKnob.GetValue>>()); 37 | return true; 38 | } 39 | 40 | protected override string MakeTooltip(BiomeDef value, double x, double y) 41 | { 42 | var displayName = BiomeFunctionConnection.Instance.DisplayName(value); 43 | return $"{displayName} ( {Math.Round(x, 0)} | {Math.Round(y, 0)} )"; 44 | } 45 | 46 | protected override Color GetColor(BiomeDef value) 47 | { 48 | if (value == null) return Color.black; 49 | 50 | var idx = _colorIdxCache.IndexOf(value); 51 | 52 | if (idx < 0) 53 | { 54 | idx = _colorIdxCache.Count; 55 | _colorIdxCache.Add(value); 56 | } 57 | 58 | return NodeGridPreview.FixedColors[idx % NodeGridPreview.FixedColors.Count]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputElevation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Output/Elevation", 400)] 10 | public class NodeOutputElevation : NodeOutputBase 11 | { 12 | public const string ID = "outputElevation"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Elevation Output"; 16 | 17 | public override ValueConnectionKnob InputKnobRef => InputKnob; 18 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 19 | 20 | [ValueConnectionKnob("Elevation", Direction.In, GridFunctionConnection.Id)] 21 | public ValueConnectionKnob InputKnob; 22 | 23 | [ValueConnectionKnob("ElevationOutput", Direction.Out, GridFunctionConnection.Id)] 24 | public ValueConnectionKnob OutputKnob; 25 | 26 | public override void OnCreate(bool fromGUI) 27 | { 28 | var existing = Landform.OutputElevation; 29 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 30 | Landform.OutputElevation = this; 31 | } 32 | 33 | protected override void OnDelete() 34 | { 35 | if (Landform.OutputElevation == this) Landform.OutputElevation = null; 36 | } 37 | 38 | public IGridFunction Get() 39 | { 40 | return InputKnob.GetValue>>()?.ResetAndGet(); 41 | } 42 | 43 | public override bool Calculate() 44 | { 45 | OutputKnob.SetValue(InputKnob.GetValue>>()); 46 | return true; 47 | } 48 | 49 | public class ElevationPreviewModel : NodeGridPreview.IPreviewModel 50 | { 51 | public Color GetColorFor(float val, int x, int y) 52 | { 53 | if (val >= 0.7f) return Color.white; 54 | if (val >= 0.61f) return new Color(0.4f, 0.4f, 0.4f); 55 | if (val >= 0.55f) return new Color(0.2f, 0.2f, 0.2f); 56 | return Color.black; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_GenStep_Scatterer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GeologicalLandforms.GraphEditor; 3 | using HarmonyLib; 4 | using LunarFramework.Patching; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.Patches; 8 | 9 | [PatchGroup("Main")] 10 | [HarmonyPatch(typeof(GenStep_Scatterer))] 11 | internal static class Patch_RimWorld_GenStep_Scatterer 12 | { 13 | [HarmonyPrefix] 14 | [HarmonyPatch("Generate")] 15 | [HarmonyPriority(Priority.High)] 16 | private static void Generate_Prefix(GenStep_Scatterer __instance, ref State __state) 17 | { 18 | if (Landform.AnyGeneratingNonLayer) 19 | { 20 | __state.hasData = true; 21 | 22 | __state.minEdgeDist = __instance.minEdgeDist; 23 | __state.minEdgeDistPct = __instance.minEdgeDistPct; 24 | 25 | __state.minDistToPlayerStart = __instance.minDistToPlayerStart; 26 | __state.minDistToPlayerStartPct = __instance.minDistToPlayerStartPct; 27 | 28 | __instance.minEdgeDist = Math.Min(__instance.minEdgeDist, 10); 29 | __instance.minEdgeDistPct = Math.Min(__instance.minEdgeDistPct, 0.1f); 30 | 31 | __instance.minDistToPlayerStart = 0; 32 | __instance.minDistToPlayerStartPct = 0f; 33 | } 34 | } 35 | 36 | [HarmonyPostfix] 37 | [HarmonyPatch("Generate")] 38 | [HarmonyPriority(Priority.Low)] 39 | private static void Generate_Postfix(GenStep_Scatterer __instance, State __state) 40 | { 41 | if (__state.hasData) 42 | { 43 | __instance.minEdgeDist = __state.minEdgeDist; 44 | __instance.minEdgeDistPct = __state.minEdgeDistPct; 45 | 46 | __instance.minDistToPlayerStart = __state.minDistToPlayerStart; 47 | __instance.minDistToPlayerStartPct = __state.minDistToPlayerStartPct; 48 | } 49 | } 50 | 51 | private struct State 52 | { 53 | public bool hasData; 54 | 55 | public int minEdgeDist; 56 | public float minEdgeDistPct; 57 | 58 | public int minDistToPlayerStart; 59 | public float minDistToPlayerStartPct; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_GenStep_CaveHives.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection.Emit; 4 | using GeologicalLandforms.GraphEditor; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(GenStep_CaveHives))] 14 | internal static class Patch_RimWorld_GenStep_CaveHives 15 | { 16 | private const float VanillaCaveCellsPerHive = 1000f; 17 | 18 | internal static readonly Type Self = typeof(Patch_RimWorld_GenStep_CaveHives); 19 | 20 | [HarmonyTranspiler] 21 | [HarmonyPatch("Generate")] 22 | [HarmonyPriority(Priority.VeryLow)] 23 | [PatchExcludedFromConflictCheck] 24 | private static IEnumerable Generate_Transpiler(IEnumerable instructions) 25 | { 26 | var pattern = TranspilerPattern.Build("AdjustCaveHiveCount") 27 | .MatchLdloc().Keep() 28 | .Match(OpCodes.Conv_R4).Keep() 29 | .Match(OpCodes.Ldc_R4).Remove() 30 | .Insert(CodeInstruction.Call(Self, nameof(CaveCellsPerHive))) 31 | .Match(OpCodes.Div).Keep() 32 | .Match(OpCodes.Call).Keep() 33 | .MatchStloc().Keep() 34 | .Insert(OpCodes.Ldarg_1) 35 | .Insert(OpCodes.Ldarg_0) 36 | .Insert(CodeInstruction.LoadField(typeof(GenStep_CaveHives), "rockCells")) 37 | .Insert(CodeInstruction.Call(Self, nameof(RemoveWaterCells))); 38 | 39 | return TranspilerPattern.Apply(instructions, pattern); 40 | } 41 | 42 | private static float CaveCellsPerHive() 43 | { 44 | if (!Landform.AnyGenerating) return VanillaCaveCellsPerHive; 45 | 46 | double? value = Landform.GetFeature(l => l.OutputScatterers?.GetCaveHives()); 47 | return value.HasValue ? VanillaCaveCellsPerHive / (float) value.Value : VanillaCaveCellsPerHive; 48 | } 49 | 50 | private static void RemoveWaterCells(Map map, List cells) 51 | { 52 | cells.RemoveAll(c => map.terrainGrid.TerrainAt(c).IsWater); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/GeologicalLandformsMod/Patches/Patch_RimWorld_FloatMenuMakerMap.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | #if !RW_1_6_OR_GREATER 3 | 4 | using System.Collections.Generic; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using UnityEngine; 9 | using Verse; 10 | 11 | namespace GeologicalLandforms.Patches; 12 | 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(FloatMenuMakerMap))] 15 | internal static class Patch_RimWorld_FloatMenuMakerMap 16 | { 17 | [HarmonyPostfix] 18 | [HarmonyPatch("AddHumanlikeOrders")] 19 | [HarmonyPriority(Priority.High)] 20 | private static void AddHumanlikeOrders(ref Vector3 clickPos, ref Pawn pawn, ref List opts) 21 | { 22 | if (!Prefs.DevMode) return; 23 | 24 | foreach (var target in GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn), true)) 25 | { 26 | var pawn1 = pawn; 27 | var dest = target; 28 | var pawn2 = (Pawn) dest.Thing; 29 | 30 | void ActionBest() 31 | { 32 | if (!RCellFinder.TryFindBestExitSpot(pawn2, out var dest1)) 33 | dest1 = pawn2.Position; 34 | var job1 = JobMaker.MakeJob(JobDefOf.Goto, dest1); 35 | job1.exitMapOnArrival = false; 36 | pawn1.jobs.TryTakeOrderedJob(job1); 37 | } 38 | 39 | void ActionRandom() 40 | { 41 | if (!RCellFinder.TryFindRandomExitSpot(pawn2, out var dest1)) 42 | dest1 = pawn2.Position; 43 | var job1 = JobMaker.MakeJob(JobDefOf.Goto, dest1); 44 | job1.exitMapOnArrival = false; 45 | pawn1.jobs.TryTakeOrderedJob(job1); 46 | } 47 | 48 | opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("[debug] Find best map exit", ActionBest, MenuOptionPriority.InitiateSocial, null, dest.Thing), pawn, pawn2)); 49 | opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("[debug] Find random map exit", ActionRandom, MenuOptionPriority.InitiateSocial, null, dest.Thing), pawn, pawn2)); 50 | } 51 | } 52 | } 53 | 54 | #endif 55 | #endif 56 | -------------------------------------------------------------------------------- /Sources/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1.6 4 | ..\..\..\.. 5 | 6 | 7 | 8 | full 9 | true 10 | false 11 | 12 | 13 | 14 | none 15 | false 16 | false 17 | 18 | 19 | 20 | $(DefineConstants);RW_1_6 21 | $(DefineConstants);RW_1_6_OR_GREATER 22 | $(DefineConstants);RW_1_5_OR_GREATER 23 | 24 | 25 | 26 | $(DefineConstants);RW_1_5 27 | $(DefineConstants);RW_1_5_OR_GREATER 28 | 29 | 30 | 31 | $(DefineConstants);RW_1_4 32 | 33 | 34 | 35 | ..\..\$(RimWorldVersion)\Lunar\Components\ 36 | false 37 | 38 | 39 | 40 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Grid/NodeGridTransformByMapSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Grid/Map Transform", 212)] 10 | public class NodeGridTransformByMapSize : NodeBase 11 | { 12 | public Landform Landform => (Landform) canvas; 13 | 14 | public const string ID = "gridTransformByMapSize"; 15 | public override string GetID => ID; 16 | 17 | public override string Title => "Map Transform"; 18 | 19 | [ValueConnectionKnob("Input", Direction.In, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob InputKnob; 21 | 22 | [ValueConnectionKnob("Output", Direction.Out, GridFunctionConnection.Id)] 23 | public ValueConnectionKnob OutputKnob; 24 | 25 | public override void NodeGUI() 26 | { 27 | InputKnob.SetPosition(FirstKnobPosition); 28 | OutputKnob.SetPosition(FirstKnobPosition); 29 | 30 | GUILayout.BeginVertical(BoxStyle); 31 | 32 | GUILayout.BeginHorizontal(BoxStyle); 33 | GUILayout.Label("Input", BoxLayout); 34 | GUILayout.EndHorizontal(); 35 | 36 | GUILayout.EndVertical(); 37 | } 38 | 39 | public override bool Calculate() 40 | { 41 | OutputKnob.SetValue>>(new Output( 42 | SupplierOrFallback(InputKnob, GridFunction.Zero), 43 | Landform.MapSpaceToNodeSpaceFactor 44 | )); 45 | return true; 46 | } 47 | 48 | private class Output : ISupplier> 49 | { 50 | private readonly ISupplier> _input; 51 | private readonly double _mapScale; 52 | 53 | public Output(ISupplier> input, double mapScale) 54 | { 55 | _input = input; 56 | _mapScale = mapScale; 57 | } 58 | 59 | public IGridFunction Get() 60 | { 61 | return new GridFunction.Transform(_input.Get(), _mapScale); 62 | } 63 | 64 | public void ResetState() 65 | { 66 | _input.ResetState(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /1.4/Languages/English/Keyed/GLFCore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | There are new versions available for some landforms that you previously modified. Would you like to use the new versions, or keep the old modified ones?\n\nAffected landforms: 5 | Replace with new data 6 | Keep old data 7 | 8 | Landform 9 | Bordering biomes 10 | Select landform 11 | 12 | Mountains 13 | Cave systems 14 | 15 | northern 16 | eastern 17 | southern 18 | western 19 | northeastern 20 | southeastern 21 | southwestern 22 | northwestern 23 | 24 | (corner) 25 | 26 | Geological Landforms 27 | 28 | Override rivers and coasts from Geological Landforms 29 | 30 | 31 | -------------------------------------------------------------------------------- /1.5/Languages/English/Keyed/GLFCore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | There are new versions available for some landforms that you previously modified. Would you like to use the new versions, or keep the old modified ones?\n\nAffected landforms: 5 | Replace with new data 6 | Keep old data 7 | 8 | Landform 9 | Bordering biomes 10 | Select landform 11 | 12 | Mountains 13 | Cave systems 14 | 15 | northern 16 | eastern 17 | southern 18 | western 19 | northeastern 20 | southeastern 21 | southwestern 22 | northwestern 23 | 24 | (corner) 25 | 26 | Geological Landforms 27 | 28 | Override rivers and coasts from Geological Landforms 29 | 30 | 31 | -------------------------------------------------------------------------------- /1.6/Languages/English/Keyed/GLFCore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | There are new versions available for some landforms that you previously modified. Would you like to use the new versions, or keep the old modified ones?\n\nAffected landforms: 5 | Replace with new data 6 | Keep old data 7 | 8 | Landform 9 | Bordering biomes 10 | Select landform 11 | 12 | Mountains 13 | Cave systems 14 | 15 | northern 16 | eastern 17 | southern 18 | western 19 | northeastern 20 | southeastern 21 | southwestern 22 | northwestern 23 | 24 | (corner) 25 | 26 | Geological Landforms 27 | 28 | Override rivers and coasts from Geological Landforms 29 | 30 | 31 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/World/WorldTileInfoPrimer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GeologicalLandforms.Defs; 3 | using GeologicalLandforms.GraphEditor; 4 | using LunarFramework.Utility; 5 | using RimWorld.Planet; 6 | using Verse; 7 | 8 | namespace GeologicalLandforms; 9 | 10 | public class WorldTileInfoPrimer : WorldTileInfo 11 | { 12 | public new IReadOnlyList Landforms 13 | { 14 | get => base.Landforms; 15 | set => base.Landforms = value; 16 | } 17 | 18 | public new IReadOnlyList BorderingBiomes 19 | { 20 | get => base.BorderingBiomes; 21 | set => base.BorderingBiomes = value; 22 | } 23 | 24 | public new IReadOnlyList BiomeVariants 25 | { 26 | get => base.BiomeVariants; 27 | set => base.BiomeVariants = value; 28 | } 29 | 30 | public new Topology Topology 31 | { 32 | get => base.Topology; 33 | set => base.Topology = value; 34 | } 35 | 36 | public new float TopologyValue 37 | { 38 | get => base.TopologyValue; 39 | set => base.TopologyValue = value; 40 | } 41 | 42 | public new Rot4 TopologyDirection 43 | { 44 | get => base.TopologyDirection; 45 | set => base.TopologyDirection = value; 46 | } 47 | 48 | public new StructRot4 Coast 49 | { 50 | get => base.Coast; 51 | set => base.Coast = value; 52 | } 53 | 54 | #if RW_1_6_OR_GREATER 55 | public WorldTileInfoPrimer(int tileId, SurfaceTile tile, World world) : base(tileId, tile, world) { } 56 | #else 57 | public WorldTileInfoPrimer(int tileId, Tile tile, World world) : base(tileId, tile, world) { } 58 | #endif 59 | 60 | public WorldTileInfoPrimer(WorldTileInfo other) : base(other.TileId, other.Tile, other.World) 61 | { 62 | Landforms = other.Landforms == null ? null : [..other.Landforms]; 63 | BorderingBiomes = other.BorderingBiomes == null ? null : [..other.BorderingBiomes]; 64 | BiomeVariants = other.BiomeVariants == null ? null : [..other.BiomeVariants]; 65 | 66 | Topology = other.Topology; 67 | TopologyValue = other.TopologyValue; 68 | TopologyDirection = other.TopologyDirection; 69 | 70 | Coast = other.Coast; 71 | RiverType = other.RiverType; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_GenStep_RocksFromGrid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection.Emit; 4 | using GeologicalLandforms.GraphEditor; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(GenStep_RocksFromGrid))] 14 | internal static class Patch_RimWorld_GenStep_RocksFromGrid 15 | { 16 | internal static readonly Type Self = typeof(Patch_RimWorld_GenStep_RocksFromGrid); 17 | 18 | [HarmonyTranspiler] 19 | [HarmonyPatch("Generate")] 20 | [HarmonyPriority(Priority.VeryLow)] 21 | [HarmonyAfter("rimworld.biomes.core", "BiomesTeam.BiomesCaverns")] 22 | private static IEnumerable Generate_Transpiler(IEnumerable instructions) 23 | { 24 | var setRoofs = TranspilerPattern.Build("SetRoofsFromLandform") 25 | .MatchNewobj(typeof(BoolGrid), [typeof(Map)]).Keep() 26 | .Match(OpCodes.Stfld).Keep() 27 | .Insert(OpCodes.Ldarg_1) 28 | .Insert(CodeInstruction.Call(Self, nameof(SetRoofsFromLandform))); 29 | 30 | var adjustMineables = TranspilerPattern.Build("AdjustMineables") 31 | .Insert(OpCodes.Ldarg_1) 32 | .Insert(CodeInstruction.Call(Self, nameof(AdjustMineables))) 33 | .MatchStore(typeof(GenStep_Scatterer), "countPer10kCellsRange").Keep(); 34 | 35 | return TranspilerPattern.Apply(instructions, setRoofs, adjustMineables); 36 | } 37 | 38 | private static void SetRoofsFromLandform(Map map) 39 | { 40 | if (!Landform.AnyGenerating) return; 41 | 42 | var roofGridModule = Landform.GetFeatureScaled(l => l.OutputRoofGrid?.Get()); 43 | if (roofGridModule == null) return; 44 | 45 | foreach (var cell in map.AllCells) 46 | { 47 | map.roofGrid.SetRoof(cell, roofGridModule.ValueAt(cell.x, cell.z)); 48 | } 49 | } 50 | 51 | private static FloatRange AdjustMineables(FloatRange original, Map map) 52 | { 53 | if (!Landform.AnyGenerating) return original; 54 | 55 | double? scatterAmount = Landform.GetFeature(l => l.OutputScatterers?.GetMineables()); 56 | return scatterAmount.HasValue ? new FloatRange((float) scatterAmount.Value, (float) scatterAmount.Value) : original; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_TileFinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld.Planet; 8 | using RimWorld.QuestGen; 9 | using Verse; 10 | 11 | namespace GeologicalLandforms.Patches; 12 | 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(TileFinder))] 15 | internal static class Patch_RimWorld_TileFinder 16 | { 17 | internal static readonly Type Self = typeof(Patch_RimWorld_TileFinder); 18 | 19 | [HarmonyTranspiler] 20 | [HarmonyPatch("IsValidTileForNewSettlement")] 21 | [HarmonyPriority(Priority.Low)] 22 | private static IEnumerable IsValidTileForNewSettlement_Transpiler(IEnumerable instructions) 23 | { 24 | var brtrueSkip = new CodeInstruction(OpCodes.Brtrue_S); 25 | 26 | var pattern = TranspilerPattern.Build("CanSettleOnTile") 27 | .MatchLdloc().Replace(OpCodes.Ldarg_0) 28 | .MatchLoad(typeof(Tile), "hilliness").Remove() 29 | .Match(OpCodes.Ldc_I4_5).Remove() 30 | .Match(OpCodes.Bne_Un_S).StoreOperandIn(brtrueSkip).Remove() 31 | .Insert(CodeInstruction.Call(Self, nameof(CanSettleOnTile))) 32 | .Insert(brtrueSkip); 33 | 34 | return TranspilerPattern.Apply(instructions, pattern); 35 | } 36 | 37 | #if RW_1_6_OR_GREATER 38 | private static bool CanSettleOnTile(PlanetTile tile) 39 | #else 40 | private static bool CanSettleOnTile(int tile) 41 | #endif 42 | { 43 | var world = Find.World; 44 | 45 | if (world.grid[tile].hilliness != Hilliness.Impassable) return true; 46 | 47 | if (QuestGen.Working) return false; // prevent quest sites from spawning on impassable tiles 48 | 49 | #if RW_1_6_OR_GREATER 50 | 51 | // FastTileFinder has async rebuilding which would cause WorldTileInfo.Get to be called off the main thread 52 | // But FastTileFinder is only used for quests anyway 53 | if (!CompatUtils.IsMainOrLongEventThread()) return false; 54 | 55 | #endif 56 | 57 | if (world.HasFinishedGenerating()) 58 | { 59 | var tileInfo = WorldTileInfo.Get(tile); 60 | if (tileInfo.Biome.Properties().allowSettlementsOnImpassableTerrain) return true; 61 | if (tileInfo.HasLandforms() && tileInfo.Landforms.Any(lf => !lf.IsLayer)) return true; 62 | } 63 | 64 | return false; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.github/workflows/prerelease.yml: -------------------------------------------------------------------------------- 1 | name: prerelease 2 | 3 | on: 4 | push: 5 | branches: 6 | - beta 7 | 8 | jobs: 9 | prerelease: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - name: Checkout latest commit 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: '0' 18 | 19 | - name: Read version file and build file names 20 | id: read_version 21 | run: | 22 | echo "version=$(cat About/Version.txt)" >> $GITHUB_OUTPUT 23 | echo "version_v=v$(cat About/Version.txt)" >> $GITHUB_OUTPUT 24 | echo "gl_zip=Geological_Landforms_v$(cat About/Version.txt).zip" >> $GITHUB_OUTPUT 25 | echo "bt_zip=Biome_Transitions_v$(cat About/Version.txt).zip" >> $GITHUB_OUTPUT 26 | 27 | - name: Create GL release zip 28 | uses: thedoctor0/zip-release@0.7.1 29 | with: 30 | type: 'zip' 31 | filename: ${{ steps.read_version.outputs.gl_zip }} 32 | exclusions: '/.git/* /Sources/* /AddOn/* /.github/* .git* *.pdb' 33 | 34 | - name: Create BT release zip 35 | uses: thedoctor0/zip-release@0.7.1 36 | with: 37 | type: 'zip' 38 | directory: 'AddOn/BiomeTransitions' 39 | filename: ${{ steps.read_version.outputs.bt_zip }} 40 | exclusions: '/.git/* /Sources/* .git*' 41 | 42 | - name: Read changelog 43 | id: read_changelog 44 | run: | 45 | awk -v RS= 'NR==2 {print > ("LatestChanges.txt")}' Changelog.md 46 | echo 'changes<> $GITHUB_OUTPUT 47 | echo "$(cat LatestChanges.txt)" >> $GITHUB_OUTPUT 48 | echo 'EOF' >> $GITHUB_OUTPUT 49 | echo 'changes_h<> $GITHUB_OUTPUT 50 | echo "Update $(cat About/Version.txt)" >> $GITHUB_OUTPUT 51 | echo "" >> $GITHUB_OUTPUT 52 | echo "$(cat LatestChanges.txt)" >> $GITHUB_OUTPUT 53 | echo 'EOF' >> $GITHUB_OUTPUT 54 | 55 | - name: Publish release 56 | uses: ncipollo/release-action@v1 57 | with: 58 | artifacts: ${{ format('{0},AddOn/BiomeTransitions/{1}', steps.read_version.outputs.gl_zip, steps.read_version.outputs.bt_zip) }} 59 | body: ${{ steps.read_changelog.outputs.changes }} 60 | name: ${{ format('Geological Landforms v{0}', steps.read_version.outputs.version) }} 61 | tag: ${{ steps.read_version.outputs.version_v }} 62 | commit: ${{ github.sha }} 63 | makeLatest: false 64 | prerelease: true 65 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/UI/NodeUILandformManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using LunarFramework.GUI; 5 | using NodeEditorFramework; 6 | using UnityEngine; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.GraphEditor; 10 | 11 | [Serializable] 12 | [Node(false, "Landform Manifest", 0)] 13 | public class NodeUILandformManifest : NodeUIBase 14 | { 15 | public const string ID = "landformManifest"; 16 | public override string GetID => ID; 17 | 18 | public override string Title => "Custom Landform"; 19 | public override Vector2 DefaultSize => new(400, 150); 20 | 21 | public string Id; 22 | public bool IsCustom = true; 23 | public bool IsExperimental; 24 | public bool IsInternal; 25 | 26 | public int RevisionVersion = 1; 27 | public long TimeCreated = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); 28 | public bool IsEdited; 29 | 30 | public string DisplayName; 31 | public bool DisplayNameHasDirection; 32 | 33 | protected override void DoWindowContents(LayoutRect layout) 34 | { 35 | layout.PushEnabled(Landform.IsCustom); 36 | 37 | var id = Id ?? ""; 38 | 39 | layout.BeginAbs(28f); 40 | LunarGUI.Label(layout.Rel(0.5f), "GeologicalLandforms.Settings.Landform.Id".Translate()); 41 | LunarGUI.TextField(layout, ref id); 42 | layout.End(); 43 | 44 | layout.Abs(10f); 45 | 46 | layout.BeginAbs(28f); 47 | LunarGUI.Label(layout.Rel(0.5f), "GeologicalLandforms.Settings.Landform.DisplayName".Translate()); 48 | LunarGUI.TextField(layout, ref DisplayName); 49 | layout.End(); 50 | 51 | layout.Abs(10f); 52 | 53 | LunarGUI.Checkbox(layout, ref DisplayNameHasDirection, "GeologicalLandforms.Settings.Landform.DisplayNameHasDirection".Translate()); 54 | 55 | if (id != Id) 56 | { 57 | char[] invalids = Path.GetInvalidFileNameChars(); 58 | id = invalids.Aggregate(id, (current, c) => current.Replace(c, '_')); 59 | LandformManager.Rename(Landform, id); 60 | } 61 | 62 | layout.PopEnabled(); 63 | } 64 | 65 | public override void DrawNode() 66 | { 67 | if (Landform.Id != null && IsCustom) base.DrawNode(); 68 | } 69 | 70 | public override void OnCreate(bool fromGUI) 71 | { 72 | var existing = Landform.Manifest; 73 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 74 | Landform.Manifest = this; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputTerrain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | [Serializable] 10 | [Node(false, "Output/Terrain", 402)] 11 | public class NodeOutputTerrain : NodeOutputBase 12 | { 13 | public const string ID = "outputTerrain"; 14 | public override string GetID => ID; 15 | 16 | public override string Title => "Terrain Output"; 17 | 18 | public override ValueConnectionKnob InputKnobRef => BaseKnob; 19 | 20 | [ValueConnectionKnob("Base", Direction.In, TerrainGridFunctionConnection.Id)] 21 | public ValueConnectionKnob BaseKnob; 22 | 23 | [ValueConnectionKnob("Stone", Direction.In, TerrainGridFunctionConnection.Id)] 24 | public ValueConnectionKnob StoneKnob; 25 | 26 | [ValueConnectionKnob("Cave", Direction.In, TerrainGridFunctionConnection.Id)] 27 | public ValueConnectionKnob CaveKnob; 28 | 29 | public override void NodeGUI() 30 | { 31 | GUILayout.BeginVertical(BoxStyle); 32 | 33 | GUILayout.BeginHorizontal(BoxStyle); 34 | GUILayout.Label(BaseKnob.name, BoxLayout); 35 | GUILayout.EndHorizontal(); 36 | BaseKnob.SetPosition(); 37 | 38 | GUILayout.BeginHorizontal(BoxStyle); 39 | GUILayout.Label(StoneKnob.name, BoxLayout); 40 | GUILayout.EndHorizontal(); 41 | StoneKnob.SetPosition(); 42 | 43 | GUILayout.BeginHorizontal(BoxStyle); 44 | GUILayout.Label(CaveKnob.name, BoxLayout); 45 | GUILayout.EndHorizontal(); 46 | CaveKnob.SetPosition(); 47 | 48 | GUILayout.EndVertical(); 49 | } 50 | 51 | public override void OnCreate(bool fromGUI) 52 | { 53 | var existing = Landform.OutputTerrain; 54 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 55 | Landform.OutputTerrain = this; 56 | } 57 | 58 | protected override void OnDelete() 59 | { 60 | if (Landform.OutputTerrain == this) Landform.OutputTerrain = null; 61 | } 62 | 63 | public IGridFunction GetBase() 64 | { 65 | return BaseKnob.GetValue>>()?.ResetAndGet(); 66 | } 67 | 68 | public IGridFunction GetStone() 69 | { 70 | return StoneKnob.GetValue>>()?.ResetAndGet(); 71 | } 72 | 73 | public IGridFunction GetCave() 74 | { 75 | return CaveKnob.GetValue>>()?.ResetAndGet(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/XML/BiomeWorkerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using LunarFramework.XML; 5 | using RimWorld; 6 | using RimWorld.Planet; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms; 10 | 11 | public class BiomeWorkerConfig : DefModExtension 12 | { 13 | public XmlDynamicValue score; 14 | 15 | public static void ApplyAll() 16 | { 17 | foreach (var def in DefDatabase.AllDefs) 18 | { 19 | if (def.workerClass == typeof(ConfigurableBiomeWorker)) 20 | { 21 | var biomeWorker = (ConfigurableBiomeWorker) def.Worker; 22 | var config = def.GetModExtension(); 23 | 24 | if (config != null) 25 | { 26 | #if RW_1_6_OR_GREATER 27 | biomeWorker.ScoreSuppliers[def] = config.score; 28 | #else 29 | biomeWorker.ScoreSupplier = config.score; 30 | #endif 31 | } 32 | else 33 | { 34 | GeologicalLandformsAPI.Logger.Warn($"Biome {def.defName} has no BiomeWorkerConfig"); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | public class ConfigurableBiomeWorker : BiomeWorker 42 | { 43 | #if RW_1_6_OR_GREATER 44 | internal readonly Dictionary> ScoreSuppliers = new(); 45 | #else 46 | internal XmlDynamicValue ScoreSupplier = new(); 47 | #endif 48 | 49 | private int _erroredWorldHash = -1; 50 | 51 | #if RW_1_6_OR_GREATER 52 | public override float GetScore(BiomeDef biome, Tile tile, PlanetTile planetTile) 53 | #else 54 | public override float GetScore(Tile tile, int tileID) 55 | #endif 56 | { 57 | try 58 | { 59 | #if RW_1_6_OR_GREATER 60 | return ScoreSuppliers[biome].Get(new CtxEarlyTile(planetTile.tileId, tile, Find.World)); 61 | #else 62 | return ScoreSupplier.Get(new CtxEarlyTile(tileID, tile, Find.World)); 63 | #endif 64 | } 65 | catch (ThreadAbortException) { throw; } 66 | catch (Exception e) 67 | { 68 | var worldHash = Find.World.GetHashCode(); 69 | 70 | if (_erroredWorldHash != worldHash) 71 | { 72 | _erroredWorldHash = worldHash; 73 | GeologicalLandformsAPI.Logger.Error("Error in configurable biome worker", e); 74 | } 75 | 76 | return -999f; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Utility/TerrainPriority.cs: -------------------------------------------------------------------------------- 1 | #if RW_1_6_OR_GREATER 2 | 3 | using Verse; 4 | 5 | namespace GeologicalLandforms; 6 | 7 | public static class TerrainPriority 8 | { 9 | public static readonly PriorityOptions DefaultOptions = new(); 10 | 11 | public static TerrainDef Apply(TerrainDef a, TerrainDef b, PriorityOptions options) 12 | { 13 | if (a == null) return b; 14 | if (b == null) return a; 15 | 16 | var aWater = a.IsWater; 17 | var bWater = b.IsWater; 18 | 19 | if (aWater && bWater) 20 | { 21 | var aDepth = WaterDepthFor(a); 22 | var bDepth = WaterDepthFor(b); 23 | 24 | if (aDepth > bDepth) return a; 25 | if (bDepth > aDepth) return b; 26 | 27 | var aMarshy = a.HasTag("WaterMarshy"); 28 | var bMarshy = b.HasTag("WaterMarshy"); 29 | 30 | if (aMarshy != bMarshy) 31 | return aMarshy ? b : a; 32 | 33 | var aRiver = a.IsRiver; 34 | var bRiver = b.IsRiver; 35 | 36 | if (aRiver != bRiver) 37 | return aRiver ^ options.PrioritizeMovingWater ? b : a; 38 | 39 | if (a.waterBodyType != b.waterBodyType) 40 | return a.waterBodyType > b.waterBodyType ? a : b; 41 | } 42 | else if (options.PrioritizeWater) 43 | { 44 | if (aWater) return a; 45 | if (bWater) return b; 46 | } 47 | 48 | if (options.PrioritizeIce) 49 | { 50 | var aIce = a.IsIce; 51 | var bIce = b.IsIce; 52 | 53 | if (aIce != bIce) 54 | return aIce ? a : b; 55 | } 56 | 57 | if (options.PrioritizeFertility && a.fertility != b.fertility) 58 | { 59 | return (a.fertility > b.fertility) ^ options.InvertFertility ? a : b; 60 | } 61 | 62 | return b; 63 | } 64 | 65 | public static WaterDepth WaterDepthFor(TerrainDef terrain) 66 | { 67 | if (terrain.defName.Contains("ChestDeep")) return WaterDepth.ChestDeep; 68 | if (terrain.defName.Contains("Deep")) return WaterDepth.Deep; 69 | return WaterDepth.Shallow; 70 | } 71 | 72 | public struct PriorityOptions 73 | { 74 | public bool PrioritizeWater = true; 75 | public bool PrioritizeMovingWater = false; 76 | public bool PrioritizeIce = false; 77 | public bool PrioritizeFertility = false; 78 | public bool InvertFertility = false; 79 | 80 | public PriorityOptions() {} 81 | } 82 | 83 | public enum WaterDepth 84 | { 85 | Shallow, ChestDeep, Deep 86 | } 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /Sources/GeologicalLandformsMod/Patches/Patch_Verse_Root_Play.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GeologicalLandforms.GraphEditor; 3 | using HarmonyLib; 4 | using LunarFramework.Patching; 5 | using RimWorld; 6 | using RimWorld.Planet; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.Patches; 10 | 11 | [PatchGroup("Main")] 12 | [HarmonyPatch(typeof(Root_Play))] 13 | internal static class Patch_Verse_Root_Play 14 | { 15 | [HarmonyPostfix] 16 | [HarmonyPatch("SetupForQuickTestPlay")] 17 | private static void SetupForQuickTestPlay() 18 | { 19 | if (GeologicalLandformsMod.Settings.DevQuickTestOverrideEnabled) 20 | { 21 | Find.GameInitData.mapSize = GeologicalLandformsMod.Settings.DevQuickTestOverrideMapSize.Value; 22 | 23 | var startingTile = Find.GameInitData.startingTile; 24 | 25 | var biomeId = GeologicalLandformsMod.Settings.DevQuickTestOverrideBiome.Value; 26 | var landformId = GeologicalLandformsMod.Settings.DevQuickTestOverrideLandform.Value; 27 | 28 | if (biomeId != "None") 29 | { 30 | var biome = DefDatabase.GetNamed(biomeId, false); 31 | if (biome != null) 32 | { 33 | #if RW_1_6_OR_GREATER 34 | var nbList = new List(); 35 | #else 36 | var nbList = new List(); 37 | #endif 38 | 39 | var worldGrid = Find.WorldGrid; 40 | 41 | worldGrid[startingTile].biome = biome; 42 | worldGrid.GetTileNeighbors(startingTile, nbList); 43 | 44 | foreach (var nb in nbList) 45 | { 46 | worldGrid[nb].biome = biome; 47 | } 48 | } 49 | } 50 | 51 | if (landformId != "None") 52 | { 53 | var landform = LandformManager.FindById(landformId); 54 | if (landform != null) 55 | { 56 | var tileInfo = WorldTileInfo.Get(startingTile, false); 57 | 58 | var tileData = new LandformData.TileData(tileInfo) 59 | { 60 | Landforms = [landform.Id] 61 | }; 62 | 63 | if (landform.WorldTileReq?.HillinessRequirement.max > 5) 64 | { 65 | Find.WorldGrid[startingTile].hilliness = Hilliness.Impassable; 66 | } 67 | 68 | Find.World.LandformData().Commit(startingTile, tileData); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/GeologicalLandformsMod/Patches/Patch_Verse_WaterInfo.cs: -------------------------------------------------------------------------------- 1 | #if DEBUG 2 | 3 | using GeologicalLandforms.GraphEditor; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld; 7 | using TerrainGraph.Flow; 8 | using UnityEngine; 9 | using Verse; 10 | 11 | namespace GeologicalLandforms.Patches; 12 | 13 | [PatchGroup("Main")] 14 | [HarmonyPatch(typeof(WaterInfo))] 15 | internal static class Patch_Verse_WaterInfo 16 | { 17 | [HarmonyPostfix] 18 | [HarmonyPatch("DebugDrawRiver")] 19 | private static void DebugDrawRiver() 20 | { 21 | if (PathTracer.DebugLines != null && !LandformGraphEditor.IsEditorOpen) 22 | { 23 | var group = Input.GetKey(KeyCode.Y) ? 1 : Input.GetKey(KeyCode.X) ? 2 : 0; 24 | 25 | foreach (var line in PathTracer.DebugLines) 26 | { 27 | if ((line.Group != 0 || line.MapPos1 != line.MapPos2) && line.Group != group) continue; 28 | 29 | var p1 = new Vector3((float) line.MapPos1.x, 0, (float) line.MapPos1.z); 30 | var p2 = new Vector3((float) line.MapPos2.x, 0, (float) line.MapPos2.z); 31 | 32 | if (p1 != p2) 33 | { 34 | GenDraw.DrawLineBetween(p1, p2, (SimpleColor) (line.Color % 8)); 35 | } 36 | else 37 | { 38 | GenDraw.DrawCircleOutline(p1, 0.2f, (SimpleColor) (line.Color % 8)); 39 | } 40 | } 41 | } 42 | } 43 | 44 | [HarmonyPostfix] 45 | [HarmonyPatch(typeof(MapInterface), "MapInterfaceOnGUI_BeforeMainTabs")] 46 | private static void MapInterfaceOnGUI_BeforeMainTabs() 47 | { 48 | if (DebugViewSettings.drawRiverDebug && PathTracer.DebugLines != null && !LandformGraphEditor.IsEditorOpen) 49 | { 50 | var group = Input.GetKey(KeyCode.Y) ? 1 : Input.GetKey(KeyCode.X) ? 2 : 0; 51 | 52 | foreach (var line in PathTracer.DebugLines) 53 | { 54 | if (line.Group != 0 && line.Group != group) continue; 55 | 56 | var p1 = new Vector3((float) line.MapPos1.x, 0, (float) line.MapPos1.z); 57 | var p2 = new Vector3((float) line.MapPos2.x, 0, (float) line.MapPos2.z); 58 | 59 | if (line.Label is { Length: > 0 }) 60 | { 61 | var p3 = Vector3.Lerp(p1, p2, 0.5f); 62 | 63 | Vector2 vec = Find.Camera.WorldToScreenPoint(p3) / Prefs.UIScale; 64 | vec.y = UI.screenHeight - vec.y - 1; 65 | 66 | GenMapUI.DrawThingLabel(vec, line.Label, Color.white); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputWaterFlow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | using Verse; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | [Serializable] 10 | [Node(false, "Output/Water Flow", 408)] 11 | public class NodeOutputWaterFlow : NodeOutputBase 12 | { 13 | public const string ID = "outputWaterFlow"; 14 | public override string GetID => ID; 15 | 16 | public override string Title => "Water Flow"; 17 | 18 | public override ValueConnectionKnob InputKnobRef => RiverTerrainKnob; 19 | 20 | [ValueConnectionKnob("River Terrain", Direction.In, TerrainGridFunctionConnection.Id)] 21 | public ValueConnectionKnob RiverTerrainKnob; 22 | 23 | [ValueConnectionKnob("Flow Alpha", Direction.In, GridFunctionConnection.Id)] 24 | public ValueConnectionKnob FlowAlphaKnob; 25 | 26 | [ValueConnectionKnob("Flow Beta", Direction.In, GridFunctionConnection.Id)] 27 | public ValueConnectionKnob FlowBetaKnob; 28 | 29 | public override void NodeGUI() 30 | { 31 | GUILayout.BeginVertical(BoxStyle); 32 | 33 | GUILayout.BeginHorizontal(BoxStyle); 34 | GUILayout.Label(RiverTerrainKnob.name, BoxLayout); 35 | GUILayout.EndHorizontal(); 36 | RiverTerrainKnob.SetPosition(); 37 | 38 | GUILayout.BeginHorizontal(BoxStyle); 39 | GUILayout.Label(FlowAlphaKnob.name, BoxLayout); 40 | GUILayout.EndHorizontal(); 41 | FlowAlphaKnob.SetPosition(); 42 | 43 | GUILayout.BeginHorizontal(BoxStyle); 44 | GUILayout.Label(FlowBetaKnob.name, BoxLayout); 45 | GUILayout.EndHorizontal(); 46 | FlowBetaKnob.SetPosition(); 47 | 48 | GUILayout.EndVertical(); 49 | } 50 | 51 | public override void OnCreate(bool fromGUI) 52 | { 53 | var existing = Landform.OutputWaterFlow; 54 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 55 | Landform.OutputWaterFlow = this; 56 | } 57 | 58 | protected override void OnDelete() 59 | { 60 | if (Landform.OutputWaterFlow == this) Landform.OutputWaterFlow = null; 61 | } 62 | 63 | public IGridFunction GetRiverTerrain() 64 | { 65 | return RiverTerrainKnob.GetValue>>()?.ResetAndGet(); 66 | } 67 | 68 | public IGridFunction GetFlowAlpha() 69 | { 70 | return FlowAlphaKnob.GetValue>>()?.ResetAndGet(); 71 | } 72 | 73 | public IGridFunction GetFlowBeta() 74 | { 75 | return FlowBetaKnob.GetValue>>()?.ResetAndGet(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_Verse_MapGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using GeologicalLandforms.GraphEditor; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using MapPreview; 7 | using Verse; 8 | 9 | #if DEBUG 10 | using RimWorld; 11 | #endif 12 | 13 | namespace GeologicalLandforms.Patches; 14 | 15 | [PatchGroup("Main")] 16 | [HarmonyPatch(typeof(MapGenerator))] 17 | internal static class Patch_Verse_MapGenerator 18 | { 19 | [HarmonyPrefix] 20 | [HarmonyPatch("GenerateContentsIntoMap")] 21 | [HarmonyPriority(Priority.First)] 22 | private static void GenerateContentsIntoMap_Prefix(Map map, ref IEnumerable genStepDefs) 23 | { 24 | LandformGraphEditor.ActiveEditor?.Close(); 25 | 26 | Landform.Prepare(map); 27 | 28 | if (!MapPreviewGenerator.IsGeneratingOnCurrentThread) 29 | { 30 | var data = Find.World?.LandformData(); 31 | var stored = data != null && map.Tile >= 0 && data.HasData(map.Tile); 32 | var indicator = data == null ? "X" : stored ? "L" : "F"; 33 | 34 | GeologicalLandformsAPI.Logger.Log($"Map generator context: {Landform.GeneratingTile} ({indicator})"); 35 | 36 | if (data != null && map.Tile >= 0) 37 | { 38 | data.CommitDirectly(map.Tile, new LandformData.TileData(Landform.GeneratingTile)); 39 | } 40 | } 41 | 42 | var biomeGrid = map.BiomeGrid(); 43 | if (biomeGrid != null) 44 | { 45 | biomeGrid.Primary.Set(map.Biome); 46 | biomeGrid.RefreshAllEntries(Landform.GeneratingTile); 47 | } 48 | 49 | var bvGenStepDef = new GenStepDef { order = 225, generated = true }; 50 | bvGenStepDef.genStep = new GenStep_BiomeVariants { def = bvGenStepDef }; 51 | 52 | genStepDefs = genStepDefs.Concat(new GenStepWithParams(bvGenStepDef, new GenStepParams())); 53 | 54 | if (Landform.AnyGenerating) 55 | { 56 | foreach (var node in Landform.GeneratingLandforms.SelectMany(lf => lf.CustomGenSteps)) 57 | { 58 | if (node.GenStepDef != null && (!MapPreviewAPI.IsGeneratingPreview || node.Order < 230)) 59 | { 60 | genStepDefs = genStepDefs.Concat(new GenStepWithParams(node.GenStepDef, new GenStepParams())); 61 | } 62 | } 63 | } 64 | } 65 | 66 | [HarmonyPostfix] 67 | [HarmonyPatch("GenerateContentsIntoMap")] 68 | [HarmonyPriority(Priority.Last)] 69 | private static void GenerateContentsIntoMap_Postfix(Map map) 70 | { 71 | Landform.CleanUp(); 72 | 73 | #if DEBUG 74 | if (Prefs.DevMode) map.weatherManager.curWeather = WeatherDefOf.Clear; 75 | #endif 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/World/IWorldTileInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GeologicalLandforms.Defs; 3 | using GeologicalLandforms.GraphEditor; 4 | using LunarFramework.Utility; 5 | using RimWorld; 6 | using RimWorld.Planet; 7 | using UnityEngine; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms; 11 | 12 | public interface IWorldTileInfo 13 | { 14 | public IReadOnlyList Landforms { get; } 15 | public IReadOnlyList BorderingBiomes { get; } 16 | public IReadOnlyList BiomeVariants { get; } 17 | 18 | public Topology Topology { get; } 19 | public float TopologyValue { get; } 20 | public Rot4 TopologyDirection { get; } 21 | public byte DepthInCaveSystem { get; } 22 | public StructRot4 Coast { get; } 23 | public RiverType RiverType { get; } 24 | 25 | public MapParent WorldObject { get; } 26 | public BiomeDef Biome { get; } 27 | 28 | public Hilliness Hilliness { get; } 29 | public float Elevation { get; } 30 | public float Temperature { get; } 31 | public float Rainfall { get; } 32 | public float Swampiness { get; } 33 | public float Pollution { get; } 34 | public bool HasCaves { get; } 35 | 36 | public RiverDef MainRiver { get; } 37 | public RoadDef MainRoad { get; } 38 | 39 | public IRiverData Rivers { get; } 40 | public IRoadData Roads { get; } 41 | 42 | #if RW_1_6_OR_GREATER 43 | public Landmark Landmark { get; } 44 | #endif 45 | 46 | public Vector3 PosInWorld { get; } 47 | 48 | public int StableSeed(int salt); 49 | } 50 | 51 | public interface IRiverData 52 | { 53 | public float RiverInflowAngle { get; } 54 | public float RiverInflowOffset { get; } 55 | public float RiverInflowWidth { get; } 56 | public float RiverTributaryAngle { get; } 57 | public float RiverTributaryOffset { get; } 58 | public float RiverTributaryWidth { get; } 59 | public float RiverTertiaryWidth { get; } 60 | public float RiverTertiaryAngle { get; } 61 | public float RiverTertiaryOffset { get; } 62 | public float RiverOutflowAngle { get; } 63 | public float RiverOutflowWidth { get; } 64 | } 65 | 66 | public interface IRoadData 67 | { 68 | public float RoadPrimaryAngle { get; } 69 | public float RoadSecondaryAngle { get; } 70 | } 71 | 72 | public readonly struct BorderingBiome 73 | { 74 | public readonly BiomeDef Biome; 75 | public readonly float Angle; 76 | 77 | public BorderingBiome(BiomeDef biome, float angle) 78 | { 79 | Biome = biome; 80 | Angle = angle; 81 | } 82 | } 83 | 84 | public enum CoastType : byte 85 | { 86 | None, 87 | Lake, 88 | Ocean 89 | } 90 | 91 | public enum RiverType : byte 92 | { 93 | None, 94 | Source, 95 | Normal, 96 | Confluence, 97 | Estuary 98 | } 99 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Legacy/Patch_RimWorld_GenStep_Plants.cs: -------------------------------------------------------------------------------- 1 | #if !RW_1_6_OR_GREATER 2 | 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using LunarFramework.Patching; 7 | using RimWorld; 8 | using Verse; 9 | 10 | namespace GeologicalLandforms.Patches; 11 | 12 | [PatchGroup("Main")] 13 | [HarmonyPatch(typeof(GenStep_Plants))] 14 | internal static class Patch_RimWorld_GenStep_Plants 15 | { 16 | [HarmonyPrefix] 17 | [HarmonyPatch("Generate")] 18 | [HarmonyPriority(Priority.VeryLow)] 19 | private static bool Generate_Prefix(GenStep_Plants __instance, Map map, GenStepParams parms) 20 | { 21 | var biomeGrid = map.BiomeGrid(); 22 | if (biomeGrid is not { Enabled: true }) return true; 23 | 24 | float condFactor = map.gameConditionManager.AggregatePlantDensityFactor(map); 25 | Generate_LocalBiomeAware(__instance, map, parms, biomeGrid, condFactor); 26 | return false; 27 | } 28 | 29 | [HarmonyPatch("Generate")] 30 | [HarmonyReversePatch(HarmonyReversePatchType.Snapshot)] 31 | [HarmonyPriority(Priority.VeryLow + 1)] 32 | private static void Generate_LocalBiomeAware(GenStep_Plants instance, Map map, GenStepParams parms, BiomeGrid biomeGrid, float condFactor) 33 | { 34 | IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) 35 | { 36 | var localBiomeEntry = generator.DeclareLocal(typeof(BiomeGrid.Entry)); 37 | 38 | var ldlocPos = new CodeInstruction(OpCodes.Ldloc); 39 | 40 | var pattern = TranspilerPattern.Build("GetPlantDensity") 41 | .MatchLdloc().StoreOperandIn(ldlocPos).Keep() 42 | .MatchLdloc().Replace(OpCodes.Ldarg_3) 43 | .Insert(ldlocPos) 44 | .Insert(CodeInstruction.Call(typeof(BiomeGrid), nameof(BiomeGrid.EntryAt), [typeof(IntVec3)])) 45 | .Insert(OpCodes.Stloc, localBiomeEntry) 46 | .Insert(OpCodes.Ldloc, localBiomeEntry) 47 | .Insert(CodeInstruction.Call(typeof(BiomeGrid.Entry), "get_Biome")) 48 | .Insert(CodeInstruction.LoadField(typeof(BiomeDef), "plantDensity")) 49 | .Insert(OpCodes.Ldarg, 4) 50 | .Insert(OpCodes.Mul) 51 | .MatchLdloc().Keep() 52 | .MatchAny().Keep() 53 | .MatchCall(typeof(WildPlantSpawner), "CheckSpawnWildPlantAt").Remove() 54 | .Insert(OpCodes.Ldloc, localBiomeEntry) 55 | .Insert(CodeInstruction.Call(typeof(Patch_RimWorld_WildPlantSpawner), "CheckSpawnWildPlantAt_LocalBiomeAware")); 56 | 57 | return TranspilerPattern.Apply(instructions, pattern); 58 | } 59 | 60 | _ = Transpiler(null, null); 61 | } 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/XML/BiomeVariantDef.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using LunarFramework.XML; 4 | using RimWorld.Planet; 5 | using UnityEngine; 6 | using Verse; 7 | using static GeologicalLandforms.BiomeProperties; 8 | 9 | namespace GeologicalLandforms.Defs; 10 | 11 | public class BiomeVariantDef : Def 12 | { 13 | public List layers; 14 | 15 | public XmlDynamicValue worldTileConditions; 16 | 17 | public XmlDynamicValue biomeLabel; 18 | public XmlDynamicValue biomeDescription; 19 | 20 | public WorldTileOverrides worldTileOverrides; 21 | public WorldTileGraphicAtlas worldTileGraphicAtlas; 22 | 23 | [NoTranslate] 24 | public string texture; 25 | 26 | public bool useOceanMaterial; 27 | 28 | [Unsaved] 29 | private Material cachedMat; 30 | 31 | public Material DrawMaterial 32 | { 33 | get 34 | { 35 | if (cachedMat != null) return cachedMat; 36 | if (texture.NullOrEmpty()) return null; 37 | cachedMat = useOceanMaterial ? new Material(WorldMaterials.WorldOcean) : new Material(WorldMaterials.WorldTerrain); 38 | cachedMat.mainTexture = ContentFinder.Get(texture); 39 | cachedMat.renderQueue = 3501; 40 | return cachedMat; 41 | } 42 | } 43 | 44 | public string ApplyToBiomeLabel(IWorldTileInfo tile, string str) 45 | => biomeLabel == null ? str : biomeLabel.Get(new CtxTile(tile), str); 46 | 47 | public string ApplyToBiomeDescription(IWorldTileInfo tile, string str) 48 | => biomeDescription == null ? str : biomeDescription.Get(new CtxTile(tile), str); 49 | 50 | public override void PostLoad() 51 | { 52 | foreach (var layer in layers) layer.IdPrefix = defName; 53 | } 54 | 55 | public override IEnumerable ConfigErrors() 56 | { 57 | foreach (var layer in layers) 58 | { 59 | if (string.IsNullOrEmpty(layer.id)) yield return "layer id can not be empty"; 60 | else if (!BiomeVariantLayer.AllowedIdRegex.IsMatch(layer.id)) yield return $"layer id {layer.id} in invalid"; 61 | else if (layers.Any(l => l.id == layer.id && l != layer)) yield return $"layer id duplicate: {layer}"; 62 | } 63 | } 64 | 65 | public static bool AnyHasTileGraphic { get; private set; } 66 | 67 | public static void InitialLoad() 68 | { 69 | AnyHasTileGraphic = DefDatabase.AllDefs.Any(def => def.DrawMaterial != null || def.worldTileGraphicAtlas != null); 70 | 71 | foreach (var grp in DefDatabase.AllDefsListForReading.GroupBy(def => def.modContentPack)) 72 | { 73 | GeologicalLandformsAPI.Logger.Log($"Found {grp.Count()} biome variants in mod {grp.Key.Name}."); 74 | } 75 | } 76 | 77 | public static BiomeVariantDef Named(string defName) => DefDatabase.GetNamed(defName); 78 | } 79 | -------------------------------------------------------------------------------- /1.5/Languages/Russian/Keyed/GLFCore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Для некоторых форм рельефа, которые вы ранее изменили, доступны новые версии. Вы хотите использовать новые версии или оставить старые модифицированные?\n\nЗатронутые формы рельефа: 5 | 6 | Заменить на новые 7 | 8 | Оставить старые 9 | 10 | 11 | Рельеф 12 | 13 | Граничащие биомы 14 | 15 | Выберите рельеф 16 | 17 | 18 | Горы 19 | 20 | Пещеры 21 | 22 | 23 | северный 24 | 25 | восточный 26 | 27 | южный 28 | 29 | западный 30 | 31 | северо-восточный 32 | 33 | юго-восточный 34 | 35 | юго-западный 36 | 37 | северо-западный 38 | 39 | 40 | (угловой) 41 | 42 | 43 | Geological Landforms 44 | 45 | 46 | 47 | Перезаписать реки и побережья из Geological Landforms 48 | 49 | 50 | -------------------------------------------------------------------------------- /1.6/Languages/Russian/Keyed/GLFCore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Для некоторых форм рельефа, которые вы ранее изменили, доступны новые версии. Вы хотите использовать новые версии или оставить старые модифицированные?\n\nЗатронутые формы рельефа: 5 | 6 | Заменить на новые 7 | 8 | Оставить старые 9 | 10 | 11 | Рельеф 12 | 13 | Граничащие биомы 14 | 15 | Выберите рельеф 16 | 17 | 18 | Горы 19 | 20 | Пещеры 21 | 22 | 23 | северный 24 | 25 | восточный 26 | 27 | южный 28 | 29 | западный 30 | 31 | северо-восточный 32 | 33 | юго-восточный 34 | 35 | юго-западный 36 | 37 | северо-западный 38 | 39 | 40 | (угловой) 41 | 42 | 43 | Geological Landforms 44 | 45 | 46 | 47 | Перезаписать реки и побережья из Geological Landforms 48 | 49 | 50 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Utility/WorldTileTraverser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RimWorld.Planet; 4 | 5 | namespace GeologicalLandforms; 6 | 7 | public class WorldTileTraverser 8 | { 9 | private bool _reentryFlag; 10 | 11 | private readonly Queue _queue = new(); 12 | private readonly List _visited = []; 13 | 14 | public delegate TraverseAction Processor(int tileId, int distance); 15 | 16 | public bool Traverse(WorldGrid worldGrid, int rootTile, int maxDistance, Processor processor) 17 | { 18 | return Traverse(worldGrid, rootTile, maxDistance, out _, out _, processor); 19 | } 20 | 21 | public bool Traverse( 22 | WorldGrid worldGrid, 23 | int rootTile, 24 | int maxDistance, 25 | out int resultTile, 26 | out int resultDistance, 27 | Processor processor) 28 | { 29 | if (_reentryFlag) throw new Exception("Nesting violation for WorldTileTraverser detected"); 30 | _reentryFlag = true; 31 | 32 | _visited.Clear(); 33 | _queue.Clear(); 34 | 35 | var nbValues = worldGrid.ExtNbValues(); 36 | var nbOffsets = worldGrid.ExtNbOffsets(); 37 | 38 | _visited.Add(rootTile); 39 | _queue.Enqueue(new QueuedTile(rootTile, 0)); 40 | 41 | while (_queue.Count > 0) 42 | { 43 | var tile = _queue.Dequeue(); 44 | var tileId = tile.TileId; 45 | var nbDist = tile.Distance + 1; 46 | 47 | int nBound = tileId + 1 < nbOffsets.Length() ? nbOffsets[tileId + 1] : nbValues.Length(); 48 | for (int nbIdx = nbOffsets[tileId]; nbIdx < nBound; nbIdx++) 49 | { 50 | int nb = nbValues[nbIdx]; 51 | if (!_visited.Contains(nb)) 52 | { 53 | _visited.Add(nb); 54 | 55 | var action = processor(nb, nbDist); 56 | 57 | if (action == TraverseAction.Stop) 58 | { 59 | resultTile = tileId; 60 | resultDistance = tile.Distance + 1; 61 | _reentryFlag = false; 62 | return true; 63 | } 64 | 65 | if (action == TraverseAction.Pass && nbDist < maxDistance) 66 | { 67 | _queue.Enqueue(new QueuedTile(nb, tile.Distance + 1)); 68 | } 69 | } 70 | } 71 | } 72 | 73 | resultDistance = maxDistance; 74 | resultTile = -1; 75 | 76 | _reentryFlag = false; 77 | return false; 78 | } 79 | 80 | private readonly struct QueuedTile 81 | { 82 | public readonly int TileId; 83 | public readonly int Distance; 84 | 85 | public QueuedTile(int tileId, int distance) 86 | { 87 | TileId = tileId; 88 | Distance = distance; 89 | } 90 | } 91 | 92 | public enum TraverseAction 93 | { 94 | Ignore, 95 | Pass, 96 | Stop 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Def/NodeDefConst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GeologicalLandforms.GraphEditor; 3 | using NodeEditorFramework; 4 | using RimWorld; 5 | using UnityEngine; 6 | using Verse; 7 | 8 | namespace TerrainGraph; 9 | 10 | public abstract class NodeDefConst : NodeBase where T : Def 11 | { 12 | public override Vector2 DefaultSize => new(100, 55); 13 | public override bool AutoLayout => false; 14 | 15 | public override string Title => "Const"; 16 | 17 | public abstract ValueConnectionKnob OutputKnobRef { get; } 18 | 19 | public abstract DefFunctionConnection ConnectionType { get; } 20 | 21 | public string Value; 22 | 23 | public override void NodeGUI() 24 | { 25 | OutputKnobRef.SetPosition(FirstKnobPosition); 26 | 27 | GUILayout.BeginVertical(BoxStyle); 28 | GUILayout.BeginHorizontal(BoxStyle); 29 | 30 | ConnectionType.SelectorUI(this, Value, true, selected => 31 | { 32 | Value = ConnectionType.ToString(selected); 33 | canvas.OnNodeChange(this); 34 | }, FullBoxLayout); 35 | 36 | GUILayout.EndHorizontal(); 37 | GUILayout.EndVertical(); 38 | 39 | if (GUI.changed) 40 | canvas.OnNodeChange(this); 41 | } 42 | 43 | public override bool Calculate() 44 | { 45 | OutputKnobRef.SetValue>(Supplier.Of(ConnectionType.FromString(Value))); 46 | return true; 47 | } 48 | } 49 | 50 | [Serializable] 51 | [Node(false, "Terrain/Const", 310)] 52 | public class NodeTerrainConst : NodeDefConst 53 | { 54 | public const string ID = "terrainConst"; 55 | public override string GetID => ID; 56 | 57 | [ValueConnectionKnob("Output", Direction.Out, TerrainFunctionConnection.Id)] 58 | public ValueConnectionKnob OutputKnob; 59 | 60 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 61 | 62 | public override DefFunctionConnection ConnectionType => TerrainFunctionConnection.Instance; 63 | } 64 | 65 | [Serializable] 66 | [Node(false, "Biome/Const", 340)] 67 | public class NodeBiomeConst : NodeDefConst 68 | { 69 | public const string ID = "biomeConst"; 70 | public override string GetID => ID; 71 | 72 | [ValueConnectionKnob("Output", Direction.Out, BiomeFunctionConnection.Id)] 73 | public ValueConnectionKnob OutputKnob; 74 | 75 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 76 | 77 | public override DefFunctionConnection ConnectionType => BiomeFunctionConnection.Instance; 78 | } 79 | 80 | [Serializable] 81 | [Node(false, "Roof/Const", 330)] 82 | public class NodeRoofConst : NodeDefConst 83 | { 84 | public const string ID = "roofConst"; 85 | public override string GetID => ID; 86 | 87 | [ValueConnectionKnob("Output", Direction.Out, RoofFunctionConnection.Id)] 88 | public ValueConnectionKnob OutputKnob; 89 | 90 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 91 | 92 | public override DefFunctionConnection ConnectionType => RoofFunctionConnection.Instance; 93 | } 94 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/UI/NodeUIWorldTileGraphic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LunarFramework.GUI; 3 | using NodeEditorFramework; 4 | using UnityEngine; 5 | using Verse; 6 | using static GeologicalLandforms.WorldTileGraphicAtlas; 7 | 8 | namespace GeologicalLandforms.GraphEditor; 9 | 10 | [Serializable] 11 | [Node(false, "World/Tile Graphic", 1001)] 12 | public class NodeUIWorldTileGraphic : NodeUIBase 13 | { 14 | public const string ID = "worldTileGraphic"; 15 | public override string GetID => ID; 16 | 17 | public override string Title => "World Tile Graphic"; 18 | public override Vector2 DefaultSize => new(400, 155); 19 | 20 | [NonSerialized] 21 | public readonly WorldTileGraphicAtlas Atlas = new(); 22 | 23 | public DrawMode DrawMode = DrawMode.HexRandom; 24 | 25 | public int AtlasSizeX = 2; 26 | public int AtlasSizeY = 2; 27 | 28 | public string TexPath = ""; 29 | 30 | private string _atlasSizeXEdit; 31 | private string _atlasSizeYEdit; 32 | 33 | protected override void DoWindowContents(LayoutRect layout) 34 | { 35 | layout.PushChanged(); 36 | 37 | layout.BeginAbs(28f); 38 | LunarGUI.Label(layout.Rel(0.3f), "GeologicalLandforms.Settings.Landform.WorldTileGraphic.DrawMode".Translate()); 39 | LunarGUI.Dropdown(layout, DrawMode, e => DrawMode = e, "GeologicalLandforms.Settings.Landform.WorldTileGraphic.DrawMode"); 40 | layout.End(); 41 | 42 | layout.Abs(10f); 43 | 44 | layout.BeginAbs(28f); 45 | LunarGUI.Label(layout.Rel(0.3f), "GeologicalLandforms.Settings.Landform.WorldTileGraphic.AtlasSize".Translate()); 46 | LunarGUI.IntField(layout.Rel(0.35f), ref AtlasSizeX, ref _atlasSizeXEdit, 1, 64); 47 | LunarGUI.IntField(layout.Abs(-1), ref AtlasSizeY, ref _atlasSizeYEdit, 1, 64); 48 | layout.End(); 49 | 50 | layout.Abs(10f); 51 | 52 | layout.BeginAbs(28f); 53 | LunarGUI.Label(layout.Rel(0.3f), "GeologicalLandforms.Settings.Landform.WorldTileGraphic.TexPath".Translate()); 54 | LunarGUI.TextField(layout.Abs(-1), ref TexPath); 55 | layout.End(); 56 | 57 | if (layout.PopChanged()) 58 | { 59 | UpdateAtlas(); 60 | } 61 | } 62 | 63 | private void UpdateAtlas() 64 | { 65 | Atlas.texture = !TexPath.NullOrEmpty() ? TexPath : "World/Landforms/" + Landform.Id; 66 | Atlas.atlasSize = new IntVec2(AtlasSizeX, AtlasSizeY); 67 | Atlas.drawMode = DrawMode; 68 | Atlas.renderQueue = 3517; 69 | Atlas.Refresh(); 70 | } 71 | 72 | public override void DrawNode() 73 | { 74 | if (Landform.Id != null) base.DrawNode(); 75 | } 76 | 77 | public override void OnCreate(bool fromGUI) 78 | { 79 | var existing = Landform.WorldTileGraphic; 80 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 81 | Landform.WorldTileGraphic = this; 82 | UpdateAtlas(); 83 | } 84 | 85 | protected override void OnDelete() 86 | { 87 | if (Landform.WorldTileGraphic == this) Landform.WorldTileGraphic = null; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - name: Checkout latest commit 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: '0' 18 | 19 | - name: Read version file and build file names 20 | id: read_version 21 | run: | 22 | echo "version=$(cat About/Version.txt)" >> $GITHUB_OUTPUT 23 | echo "version_v=v$(cat About/Version.txt)" >> $GITHUB_OUTPUT 24 | echo "gl_zip=Geological_Landforms_v$(cat About/Version.txt).zip" >> $GITHUB_OUTPUT 25 | echo "bt_zip=Biome_Transitions_v$(cat About/Version.txt).zip" >> $GITHUB_OUTPUT 26 | 27 | - name: Create GL release zip 28 | uses: thedoctor0/zip-release@0.7.1 29 | with: 30 | type: 'zip' 31 | filename: ${{ steps.read_version.outputs.gl_zip }} 32 | exclusions: '/.git/* /Sources/* /AddOn/* /.github/* .git* *.pdb' 33 | 34 | - name: Create BT release zip 35 | uses: thedoctor0/zip-release@0.7.1 36 | with: 37 | type: 'zip' 38 | directory: 'AddOn/BiomeTransitions' 39 | filename: ${{ steps.read_version.outputs.bt_zip }} 40 | exclusions: '/.git/* /Sources/* .git*' 41 | 42 | - name: Read changelog 43 | id: read_changelog 44 | run: | 45 | awk -v RS= 'NR==2 {print > ("LatestChanges.txt")}' Changelog.md 46 | echo 'changes<> $GITHUB_OUTPUT 47 | echo "$(cat LatestChanges.txt)" >> $GITHUB_OUTPUT 48 | echo 'EOF' >> $GITHUB_OUTPUT 49 | echo 'changes_h<> $GITHUB_OUTPUT 50 | echo "Update $(cat About/Version.txt)" >> $GITHUB_OUTPUT 51 | echo "" >> $GITHUB_OUTPUT 52 | echo "$(cat LatestChanges.txt)" >> $GITHUB_OUTPUT 53 | echo 'EOF' >> $GITHUB_OUTPUT 54 | 55 | - name: Publish release 56 | uses: ncipollo/release-action@v1 57 | with: 58 | artifacts: ${{ format('{0},AddOn/BiomeTransitions/{1}', steps.read_version.outputs.gl_zip, steps.read_version.outputs.bt_zip) }} 59 | body: ${{ steps.read_changelog.outputs.changes }} 60 | name: ${{ format('Geological Landforms v{0}', steps.read_version.outputs.version) }} 61 | tag: ${{ steps.read_version.outputs.version_v }} 62 | commit: ${{ github.sha }} 63 | makeLatest: true 64 | 65 | - name: Extract zip for workshop upload 66 | env: 67 | ZIP_FILE: ${{ steps.read_version.outputs.gl_zip }} 68 | run: | 69 | sudo apt-get install unzip 70 | mkdir ws-upload/ 71 | unzip $ZIP_FILE -d ws-upload 72 | 73 | - name: Upload to workshop 74 | uses: m00nl1ght-dev/steam-workshop-deploy@main 75 | with: 76 | username: ${{ secrets.STEAM_ACCOUNT }} 77 | configVdf: ${{ secrets.STEAM_CONFIG_VDF }} 78 | appId: 294100 79 | publishedFileId: 2773943594 80 | path: ws-upload 81 | changeNote: ${{ steps.read_changelog.outputs.changes_h }} 82 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Output/NodeOutputTerrainPatches.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using UnityEngine; 5 | 6 | namespace GeologicalLandforms.GraphEditor; 7 | 8 | [Serializable] 9 | [Node(false, "Output/Terrain Patches", 403)] 10 | public class NodeOutputTerrainPatches : NodeOutputBase 11 | { 12 | public const string ID = "outputTerrainPatches"; 13 | public override string GetID => ID; 14 | 15 | public override string Title => "Terrain Patches"; 16 | 17 | public override ValueConnectionKnob InputKnobRef => OffsetKnob; 18 | 19 | [ValueConnectionKnob("Offset", Direction.In, GridFunctionConnection.Id)] 20 | public ValueConnectionKnob OffsetKnob; 21 | 22 | [ValueConnectionKnob("Frequency", Direction.In, ValueFunctionConnection.Id)] 23 | public ValueConnectionKnob FrequencyKnob; 24 | 25 | [ValueConnectionKnob("Lacunarity", Direction.In, ValueFunctionConnection.Id)] 26 | public ValueConnectionKnob LacunarityKnob; 27 | 28 | [ValueConnectionKnob("Persistence", Direction.In, ValueFunctionConnection.Id)] 29 | public ValueConnectionKnob PersistenceKnob; 30 | 31 | public override void NodeGUI() 32 | { 33 | GUILayout.BeginVertical(BoxStyle); 34 | 35 | GUILayout.BeginHorizontal(BoxStyle); 36 | GUILayout.Label("Value offset", DoubleBoxLayout); 37 | GUILayout.EndHorizontal(); 38 | OffsetKnob.SetPosition(); 39 | 40 | GUILayout.BeginHorizontal(BoxStyle); 41 | GUILayout.Label("Frequency multiplier", DoubleBoxLayout); 42 | GUILayout.EndHorizontal(); 43 | FrequencyKnob.SetPosition(); 44 | 45 | GUILayout.BeginHorizontal(BoxStyle); 46 | GUILayout.Label("Lacunarity multiplier", DoubleBoxLayout); 47 | GUILayout.EndHorizontal(); 48 | LacunarityKnob.SetPosition(); 49 | 50 | GUILayout.BeginHorizontal(BoxStyle); 51 | GUILayout.Label("Persistence multiplier", DoubleBoxLayout); 52 | GUILayout.EndHorizontal(); 53 | PersistenceKnob.SetPosition(); 54 | 55 | GUILayout.EndVertical(); 56 | } 57 | 58 | public override void OnCreate(bool fromGUI) 59 | { 60 | var existing = Landform.OutputTerrainPatches; 61 | if (existing != null && existing != this && canvas.nodes.Contains(existing)) existing.Delete(); 62 | Landform.OutputTerrainPatches = this; 63 | } 64 | 65 | protected override void OnDelete() 66 | { 67 | if (Landform.OutputTerrainPatches == this) Landform.OutputTerrainPatches = null; 68 | } 69 | 70 | public IGridFunction GetOffset() 71 | { 72 | return OffsetKnob.GetValue>>()?.ResetAndGet(); 73 | } 74 | 75 | public double? GetFrequencyFactor() 76 | { 77 | return FrequencyKnob.GetValue>()?.ResetAndGet(); 78 | } 79 | 80 | public double? GetLacunarityFactor() 81 | { 82 | return LacunarityKnob.GetValue>()?.ResetAndGet(); 83 | } 84 | 85 | public double? GetPersistenceFactor() 86 | { 87 | return PersistenceKnob.GetValue>()?.ResetAndGet(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/Patches/Patch_RimWorld_WorldPathGrid.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection.Emit; 4 | using HarmonyLib; 5 | using LunarFramework.Patching; 6 | using RimWorld.Planet; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.Patches; 10 | 11 | [PatchGroup("Main")] 12 | [HarmonyPatch(typeof(WorldPathGrid))] 13 | internal static class Patch_RimWorld_WorldPathGrid 14 | { 15 | public const float ImpassableMovementDifficultyOffset = 9f; 16 | 17 | [HarmonyTranspiler] 18 | [HarmonyPatch("CalculatedMovementDifficultyAt")] 19 | [HarmonyPriority(Priority.Low)] 20 | private static IEnumerable CalculatedMovementDifficultyAt_Transpiler(IEnumerable instructions) 21 | { 22 | var brtrueSkip = new CodeInstruction(OpCodes.Brtrue_S); 23 | 24 | var pattern = TranspilerPattern.Build("CanSettleOnTile") 25 | .MatchLdloc().Replace(OpCodes.Ldarg_0) 26 | .MatchLoad(typeof(Tile), "hilliness").Remove() 27 | .Match(OpCodes.Ldc_I4_5).Remove() 28 | .Match(OpCodes.Bne_Un_S).StoreOperandIn(brtrueSkip).Remove() 29 | .Insert(CodeInstruction.Call(typeof(Patch_RimWorld_WorldPathGrid), nameof(ShouldTileBePassable))) 30 | .Insert(brtrueSkip); 31 | 32 | return TranspilerPattern.Apply(instructions, pattern); 33 | } 34 | 35 | [HarmonyPostfix] 36 | [HarmonyPatch("HillinessMovementDifficultyOffset")] 37 | [HarmonyPriority(Priority.Low)] 38 | private static void HillinessMovementDifficultyOffset(Hilliness hilliness, ref float __result) 39 | { 40 | if (hilliness == Hilliness.Impassable) __result = ImpassableMovementDifficultyOffset; 41 | } 42 | 43 | #if RW_1_6_OR_GREATER 44 | 45 | [HarmonyPrefix] 46 | [HarmonyPatch(nameof(WorldPathGrid.CalculatedMovementDifficultyAt))] 47 | [HarmonyPriority(Priority.First)] 48 | private static void CalculatedMovementDifficultyAt_Prefix() 49 | { 50 | TileMutatorsCustomization.SkipLandforms = true; 51 | } 52 | 53 | [HarmonyFinalizer] 54 | [HarmonyPatch(nameof(WorldPathGrid.CalculatedMovementDifficultyAt))] 55 | [HarmonyPriority(Priority.Last)] 56 | private static void CalculatedMovementDifficultyAt_Finalizer() 57 | { 58 | TileMutatorsCustomization.SkipLandforms = false; 59 | } 60 | 61 | #endif 62 | 63 | #if RW_1_6_OR_GREATER 64 | private static bool ShouldTileBePassable(PlanetTile tile) 65 | #else 66 | private static bool ShouldTileBePassable(int tile) 67 | #endif 68 | { 69 | var world = Find.World; 70 | 71 | #if RW_1_6_OR_GREATER 72 | if (!tile.Layer.IsRootSurface) return true; 73 | #endif 74 | 75 | if (world.grid[tile].hilliness != Hilliness.Impassable) return true; 76 | 77 | if (world.HasFinishedGenerating()) 78 | { 79 | var tileInfo = WorldTileInfo.Get(tile); 80 | if (tileInfo.Biome.Properties().allowSettlementsOnImpassableTerrain) return true; 81 | if (tileInfo.HasLandforms() && tileInfo.Landforms.Any(lf => !lf.IsLayer)) return true; 82 | if (tileInfo.WorldObject != null) return true; 83 | } 84 | 85 | return false; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/World/WorldGenStep_Landforms.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using LunarFramework.Utility; 3 | using RimWorld; 4 | using RimWorld.Planet; 5 | using Verse; 6 | using static GeologicalLandforms.BiomeProperties; 7 | 8 | namespace GeologicalLandforms; 9 | 10 | public class WorldGenStep_Landforms : WorldGenStep 11 | { 12 | public override int SeedPart => 494807164; 13 | 14 | #if RW_1_6_OR_GREATER 15 | public override void GenerateFresh(string seed, PlanetLayer layer) 16 | #else 17 | public override void GenerateFresh(string seed) 18 | #endif 19 | { 20 | if (!GeologicalLandformsAPI.LunarAPI.IsInitialized()) return; 21 | 22 | WorldTileInfo.CreateNewCache(); 23 | 24 | var world = Find.World; 25 | var grid = world.grid; 26 | 27 | if (world.worldObjects == null) return; 28 | 29 | var stopwatch = new Stopwatch(); 30 | stopwatch.Start(); 31 | 32 | for (int tileIdx = 0; tileIdx < grid.TilesCount; ++tileIdx) 33 | { 34 | var info = WorldTileInfo.Get(tileIdx); 35 | if (info.Biome == null) return; 36 | 37 | var tile = grid[tileIdx]; 38 | 39 | var fromBiome = info.Biome.Properties().worldTileOverrides; 40 | if (fromBiome != null) ApplyOverrides(tile, info, fromBiome); 41 | 42 | if (info.HasBiomeVariants()) 43 | { 44 | foreach (var biomeVariant in info.BiomeVariants) 45 | { 46 | var fromBiomeVariant = biomeVariant.worldTileOverrides; 47 | if (fromBiomeVariant != null) ApplyOverrides(tile, info, fromBiomeVariant); 48 | } 49 | } 50 | } 51 | 52 | stopwatch.Stop(); 53 | GeologicalLandformsAPI.Logger.Debug("Calculation of initial world tile data took " + stopwatch.ElapsedMilliseconds + " ms."); 54 | } 55 | 56 | #if RW_1_6_OR_GREATER 57 | public override void GenerateFromScribe(string seed, PlanetLayer layer) 58 | #else 59 | public override void GenerateFromScribe(string seed) 60 | #endif 61 | { 62 | if (!GeologicalLandformsAPI.LunarAPI.IsInitialized()) return; 63 | 64 | WorldTileInfo.CreateNewCache(); 65 | } 66 | 67 | private void ApplyOverrides(Tile tile, IWorldTileInfo info, WorldTileOverrides overrides) 68 | { 69 | var ctx = new CtxTile(info); 70 | 71 | overrides.elevation?.Apply(ctx, ref tile.elevation); 72 | overrides.temperature?.Apply(ctx, ref tile.temperature); 73 | overrides.rainfall?.Apply(ctx, ref tile.rainfall); 74 | 75 | if (ModLister.BiotechInstalled) 76 | { 77 | overrides.pollution?.Apply(ctx, ref tile.pollution); 78 | } 79 | } 80 | 81 | internal static void Register() 82 | { 83 | var def = new WorldGenStepDef 84 | { 85 | defName = "GL_InitLandformData", 86 | modContentPack = GeologicalLandformsAPI.LunarAPI.Component.LatestVersionProvidedBy.ModContentPack, 87 | worldGenStep = new WorldGenStep_Landforms(), 88 | order = 5000 89 | }; 90 | 91 | DefGenerator.AddImpliedDef(def); 92 | 93 | #if RW_1_6_OR_GREATER 94 | PlanetLayerDefOf.Surface.worldGenSteps.Add(def); 95 | PlanetLayerDefOf.Surface.cachedGenSteps = null; 96 | #endif 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Value/NodeValueRiversAndRoads.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NodeEditorFramework; 3 | using TerrainGraph; 4 | using TerrainGraph.Util; 5 | using UnityEngine; 6 | 7 | namespace GeologicalLandforms.GraphEditor; 8 | 9 | [Serializable] 10 | [Node(false, "World/Rivers & Roads", 1002)] 11 | public class NodeValueRiversAndRoads : NodeBase 12 | { 13 | public const string ID = "valueRiversAndRoads"; 14 | public override string GetID => ID; 15 | 16 | public override Vector2 MinSize => new(100, 10); 17 | 18 | public override string Title => "Rivers & Roads"; 19 | 20 | [ValueConnectionKnob("Angle", Direction.Out, ValueFunctionConnection.Id)] 21 | public ValueConnectionKnob AngleOutputKnob; 22 | 23 | [ValueConnectionKnob("Offset", Direction.Out, ValueFunctionConnection.Id)] 24 | public ValueConnectionKnob OffsetOutputKnob; 25 | 26 | [ValueConnectionKnob("River Width", Direction.Out, ValueFunctionConnection.Id)] 27 | public ValueConnectionKnob RiverWidthOutputKnob; 28 | 29 | [ValueConnectionKnob("Road Width", Direction.Out, ValueFunctionConnection.Id)] 30 | public ValueConnectionKnob RoadWidthOutputKnob; 31 | 32 | public override void NodeGUI() 33 | { 34 | GUILayout.BeginVertical(BoxStyle); 35 | 36 | GUILayout.BeginHorizontal(BoxStyle); 37 | GUILayout.Label("Angle", DoubleBoxLayout); 38 | GUILayout.EndHorizontal(); 39 | AngleOutputKnob.SetPosition(); 40 | 41 | GUILayout.BeginHorizontal(BoxStyle); 42 | GUILayout.Label("Offset", DoubleBoxLayout); 43 | GUILayout.EndHorizontal(); 44 | OffsetOutputKnob.SetPosition(); 45 | 46 | GUILayout.BeginHorizontal(BoxStyle); 47 | GUILayout.Label("River Size", DoubleBoxLayout); 48 | GUILayout.EndHorizontal(); 49 | RiverWidthOutputKnob.SetPosition(); 50 | 51 | GUILayout.BeginHorizontal(BoxStyle); 52 | GUILayout.Label("Road Size", DoubleBoxLayout); 53 | GUILayout.EndHorizontal(); 54 | RoadWidthOutputKnob.SetPosition(); 55 | 56 | GUILayout.EndVertical(); 57 | } 58 | 59 | public override bool Calculate() 60 | { 61 | var riverData = Landform.GeneratingTile.Rivers; 62 | var roadData = Landform.GeneratingTile.Roads; 63 | 64 | double angle = 0; 65 | double offset = 0; 66 | 67 | if (riverData.RiverOutflowWidth > 0) 68 | { 69 | angle = riverData.RiverOutflowAngle; 70 | offset = riverData.RiverInflowOffset; 71 | 72 | if (riverData.RiverInflowWidth > 0) 73 | { 74 | double diff = riverData.RiverInflowAngle - angle; 75 | angle += diff.NormalizeDeg() * 0.5; 76 | } 77 | } 78 | else if (riverData.RiverInflowWidth > 0) 79 | { 80 | angle = riverData.RiverInflowAngle; 81 | } 82 | else 83 | { 84 | angle = roadData.RoadPrimaryAngle; 85 | } 86 | 87 | AngleOutputKnob.SetValue>(Supplier.Of(angle)); 88 | OffsetOutputKnob.SetValue>(Supplier.Of(offset)); 89 | 90 | RiverWidthOutputKnob.SetValue>(Supplier.Of((double) Landform.GeneratingTile.MainRiver.WidthOnWorld())); 91 | RoadWidthOutputKnob.SetValue>(Supplier.Of((double) Landform.GeneratingTile.MainRoad.WidthOnWorld())); 92 | 93 | return true; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Def/NodeValueSelectDef.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using NodeEditorFramework; 5 | using RimWorld; 6 | using TerrainGraph; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.GraphEditor; 10 | 11 | public abstract class NodeValueSelectDef : NodeSelectBase where T : Def 12 | { 13 | [ValueConnectionKnob("Input", Direction.In, ValueFunctionConnection.Id)] 14 | public ValueConnectionKnob InputKnob; 15 | 16 | public override ValueConnectionKnob InputKnobRef => InputKnob; 17 | 18 | protected abstract DefFunctionConnection ConnectionType { get; } 19 | 20 | protected override string OptionConnectionTypeId => ConnectionType.Identifier; 21 | 22 | public override void RefreshPreview() => RefreshPreview(ConnectionType.ToString); 23 | 24 | protected override void DrawOptionKey(int i) => DrawDoubleOptionKey(Thresholds, i); 25 | 26 | protected override void DrawOptionValue(int i) 27 | { 28 | ConnectionType.SelectorUI(this, Values[i], !OptionKnobs[i].connected(), selected => 29 | { 30 | Values[i] = ConnectionType.ToString(selected); 31 | canvas.OnNodeChange(this); 32 | }); 33 | } 34 | 35 | public override bool Calculate() 36 | { 37 | var input = SupplierOrFallback(InputKnobRef, 0d); 38 | 39 | List> options = []; 40 | 41 | for (int i = 0; i < Math.Min(Values.Count, OptionKnobs.Count); i++) 42 | { 43 | options.Add(SupplierOrFallback(OptionKnobs[i], ConnectionType.FromString(Values[i]))); 44 | } 45 | 46 | OutputKnobRef.SetValue>(new Output(input, options, Thresholds.ToList(), null)); 47 | return true; 48 | } 49 | } 50 | 51 | [Serializable] 52 | [Node(false, "Value/Select/Terrain", 103)] 53 | public class NodeValueSelectTerrain : NodeValueSelectDef 54 | { 55 | public const string ID = "valueSelectTerrain"; 56 | public override string GetID => ID; 57 | 58 | [ValueConnectionKnob("Output", Direction.Out, TerrainFunctionConnection.Id)] 59 | public ValueConnectionKnob OutputKnob; 60 | 61 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 62 | 63 | protected override DefFunctionConnection ConnectionType => TerrainFunctionConnection.Instance; 64 | } 65 | 66 | [Serializable] 67 | [Node(false, "Value/Select/Biome", 104)] 68 | public class NodeValueSelectBiome : NodeValueSelectDef 69 | { 70 | public const string ID = "valueSelectBiome"; 71 | public override string GetID => ID; 72 | 73 | [ValueConnectionKnob("Output", Direction.Out, BiomeFunctionConnection.Id)] 74 | public ValueConnectionKnob OutputKnob; 75 | 76 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 77 | 78 | protected override DefFunctionConnection ConnectionType => BiomeFunctionConnection.Instance; 79 | } 80 | 81 | [Serializable] 82 | [Node(false, "Value/Select/Roof", 105)] 83 | public class NodeValueSelectRoof : NodeValueSelectDef 84 | { 85 | public const string ID = "valueSelectRoof"; 86 | public override string GetID => ID; 87 | 88 | [ValueConnectionKnob("Output", Direction.Out, RoofFunctionConnection.Id)] 89 | public ValueConnectionKnob OutputKnob; 90 | 91 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 92 | 93 | protected override DefFunctionConnection ConnectionType => RoofFunctionConnection.Instance; 94 | } 95 | -------------------------------------------------------------------------------- /Sources/GeologicalLandforms/GraphEditor/Nodes/Def/NodeGridSelectDef.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using NodeEditorFramework; 5 | using RimWorld; 6 | using TerrainGraph; 7 | using Verse; 8 | 9 | namespace GeologicalLandforms.GraphEditor; 10 | 11 | public abstract class NodeGridSelectDef : NodeSelectBase where T : Def 12 | { 13 | [ValueConnectionKnob("Input", Direction.In, GridFunctionConnection.Id)] 14 | public ValueConnectionKnob InputKnob; 15 | 16 | public override ValueConnectionKnob InputKnobRef => InputKnob; 17 | 18 | protected abstract DefFunctionConnection ConnectionType { get; } 19 | 20 | protected override string OptionConnectionTypeId => ConnectionType.Identifier; 21 | 22 | public override void RefreshPreview() => RefreshPreview(ConnectionType.ToString); 23 | 24 | protected override void DrawOptionKey(int i) => DrawDoubleOptionKey(Thresholds, i); 25 | 26 | protected override void DrawOptionValue(int i) 27 | { 28 | ConnectionType.SelectorUI(this, Values[i], !OptionKnobs[i].connected(), selected => 29 | { 30 | Values[i] = ConnectionType.ToString(selected); 31 | canvas.OnNodeChange(this); 32 | }); 33 | } 34 | 35 | public override bool Calculate() 36 | { 37 | var input = SupplierOrFallback(InputKnob, GridFunction.Zero); 38 | 39 | List>> options = []; 40 | 41 | for (int i = 0; i < Math.Min(Values.Count, OptionKnobs.Count); i++) 42 | { 43 | var value = ConnectionType.FromString(Values[i]); 44 | options.Add(new NodeGridFromValue.Output(SupplierOrFallback(OptionKnobs[i], value))); 45 | } 46 | 47 | OutputKnobRef.SetValue>>(new GridOutput(input, options, Thresholds.ToList(), null)); 48 | return true; 49 | } 50 | } 51 | 52 | [Serializable] 53 | [Node(false, "Grid/Select/Terrain", 201)] 54 | public class NodeGridSelectTerrain : NodeGridSelectDef 55 | { 56 | public const string ID = "gridSelectTerrain"; 57 | public override string GetID => ID; 58 | 59 | [ValueConnectionKnob("Output", Direction.Out, TerrainGridFunctionConnection.Id)] 60 | public ValueConnectionKnob OutputKnob; 61 | 62 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 63 | 64 | protected override DefFunctionConnection ConnectionType => TerrainFunctionConnection.Instance; 65 | } 66 | 67 | [Serializable] 68 | [Node(false, "Grid/Select/Biome", 202)] 69 | public class NodeGridSelectBiome : NodeGridSelectDef 70 | { 71 | public const string ID = "gridSelectBiome"; 72 | public override string GetID => ID; 73 | 74 | [ValueConnectionKnob("Output", Direction.Out, BiomeGridFunctionConnection.Id)] 75 | public ValueConnectionKnob OutputKnob; 76 | 77 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 78 | 79 | protected override DefFunctionConnection ConnectionType => BiomeFunctionConnection.Instance; 80 | } 81 | 82 | [Serializable] 83 | [Node(false, "Grid/Select/Roof", 203)] 84 | public class NodeGridSelectRoof : NodeGridSelectDef 85 | { 86 | public const string ID = "gridSelectRoof"; 87 | public override string GetID => ID; 88 | 89 | [ValueConnectionKnob("Output", Direction.Out, RoofGridFunctionConnection.Id)] 90 | public ValueConnectionKnob OutputKnob; 91 | 92 | public override ValueConnectionKnob OutputKnobRef => OutputKnob; 93 | 94 | protected override DefFunctionConnection ConnectionType => RoofFunctionConnection.Instance; 95 | } 96 | --------------------------------------------------------------------------------