diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..eefd4d8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,75 @@ +name: Build + +on: + # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g., for dependabot pull requests) + push: + branches: [main] + # Trigger the workflow on any pull request + pull_request: + workflow_call: + inputs: + ref: + description: "A tag reference passed from Publish workflow" + default: ${{ github.sha }} + required: false + type: string + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Fetch Sources + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + fetch-depth: 0 + filter: tree:0 + + - name: Setup .NET environment + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8.0.100" + + - name: Install Evaisa's netcode-patcher + run: | + dotnet tool install -g Evaisa.NetcodePatcher.Cli + - name: Restore project + run: | + dotnet restore + dotnet tool restore + - name: Build and pack solution + run: | + dotnet pack -c Release + - name: Set MOD_NAME environment variable + run: echo "MOD_NAME=$(cat ./*/dist/name.txt )" >> $GITHUB_ENV + + - name: Set MOD_VERSION environment variable + run: echo "MOD_VERSION=$(cat ./*/dist/version.txt )" >> $GITHUB_ENV + + - name: Set ZIP_PATH environment variable + run: echo "ZIP_PATH=./${{ env.MOD_NAME }}/dist/curseforge.zip" >> $GITHUB_ENV + + - name: Upload CurseForge artifact + uses: actions/upload-artifact@v4 + with: + name: curseforge-build + path: ./*/dist/*.zip + + - name: Upload Thunderstore artifact + uses: actions/upload-artifact@v4 + with: + name: thunderstore-build + path: ./*/dist/*.zip + + - name: Upload nupkg artifact + uses: actions/upload-artifact@v4 + with: + name: nupkg-build + path: ./*/bin/Release/*.nupkg + + - name: Upload Versions artifact + uses: actions/upload-artifact@v4 + with: + name: versions + path: ./*/dist/*.txt \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..b41f2b5 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,46 @@ +name: Publish + +on: + release: + types: [prereleased, released] + +jobs: + build: + uses: ./.github/workflows/build.yml + with: + ref: ${{ github.event.release.tag_name }} + + upload-release-artifacts: + name: Add artifacts to Release + needs: build + runs-on: ubuntu-latest + steps: + - name: Fetch Sources + uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + + - name: Upload artifacts to Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB }} + run: gh release upload ${{ github.event.release.tag_name }} thunderstore-build/*/dist/*.zip nupkg-build/*/bin/Release/*.nupkg + + release-curseforge: + needs: build + uses: ./.github/workflows/release-curseforge.yml + secrets: + curseforge-token: ${{ secrets.CURSEFORGE_API_KEY }} + project-id: ${{ secrets.CURSEFORGE_PROJECTID }} + + release-thunderstore: + needs: build + uses: ./.github/workflows/release-thunderstore.yml + secrets: + thunderstore-token: ${{ secrets.THUNDERSTORE_API_KEY }} + + release-nuget: + needs: build + uses: ./.github/workflows/release-nuget.yml + secrets: + nuget-token: ${{ secrets.NUGET_API_KEY }} \ No newline at end of file diff --git a/.github/workflows/release-curseforge.yml b/.github/workflows/release-curseforge.yml new file mode 100644 index 0000000..fa7d759 --- /dev/null +++ b/.github/workflows/release-curseforge.yml @@ -0,0 +1,46 @@ +name: Release on Curseforge + +on: + workflow_call: + secrets: + curseforge-token: + required: true + project-id: + required: true + +jobs: + curseforge: + name: Upload + runs-on: ubuntu-latest + steps: + - name: Fetch Sources + uses: actions/checkout@v4 + + - name: Download Curseforge artifact + uses: actions/download-artifact@v4 + with: + name: curseforge-build + + - name: Download Versions artifact + uses: actions/download-artifact@v4 + with: + name: versions + + - name: Set MOD_NAME environment variable + run: echo "MOD_NAME=$(cat ./*/dist/name.txt )" >> $GITHUB_ENV + + - name: Set MOD_VERSION environment variable + run: echo "MOD_VERSION=$(cat ./*/dist/version.txt )" >> $GITHUB_ENV + + - name: Set ZIP_PATH environment variable + run: echo "ZIP_PATH=./${{ env.MOD_NAME }}/dist/curseforge.zip" >> $GITHUB_ENV + + - name: "Upload to CurseForge" + uses: itsmeow/curseforge-upload@v3 + with: + token: ${{ secrets.curseforge-token }} + project_id: ${{ secrets.project-id }} + game_endpoint: "lethal-company" + game_versions: "0.50.0" + file_path: ${{ env.ZIP_PATH }} + display_name: ${{ env.MOD_NAME }} v${{ env.MOD_VERSION }} \ No newline at end of file diff --git a/.github/workflows/release-nuget.yml b/.github/workflows/release-nuget.yml new file mode 100644 index 0000000..0b1a570 --- /dev/null +++ b/.github/workflows/release-nuget.yml @@ -0,0 +1,29 @@ +name: Release on Nuget + +on: + workflow_call: + secrets: + nuget-token: + required: true + +jobs: + nuget: + name: Upload + runs-on: ubuntu-latest + steps: + - name: Fetch Sources + uses: actions/checkout@v4 + + - name: Download nupkg artifact + uses: actions/download-artifact@v4 + with: + name: nupkg-build + + - name: Setup .NET environment + uses: actions/setup-dotnet@v3 + with: + dotnet-version: "8.0.100" + + - name: Publish to NuGet.org + run: | + dotnet nuget push ./*/bin/Release/*.nupkg --api-key ${{ secrets.nuget-token }} --source https://api.nuget.org/v3/index.json \ No newline at end of file diff --git a/.github/workflows/release-thunderstore.yml b/.github/workflows/release-thunderstore.yml new file mode 100644 index 0000000..224b602 --- /dev/null +++ b/.github/workflows/release-thunderstore.yml @@ -0,0 +1,37 @@ +name: Release on Thunderstore + +on: + workflow_call: + secrets: + thunderstore-token: + required: true + +jobs: + thunderstore: + name: Upload + runs-on: ubuntu-latest + steps: + - name: Fetch Sources + uses: actions/checkout@v4 + + - name: Download Thunderstore artifact + uses: actions/download-artifact@v4 + with: + name: thunderstore-build + + - name: Setup .NET environment + uses: actions/setup-dotnet@v3 + with: + dotnet-version: "8.0.100" + + - name: Install Evaisa's netcode-patcher + run: | + dotnet tool install -g Evaisa.NetcodePatcher.Cli + - name: Restore dotnet tools + run: | + dotnet tool restore + - name: Publish to Thunderstore + env: + TCLI_AUTH_TOKEN: ${{ secrets.thunderstore-token }} + run: | + dotnet build -target:PublishThunderstore \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e15aac..6711b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,120 @@ **Changelog** -- +**
Version 1.3.8** + +**
Features** + +* Added interior selection history to DayHistory + +
+ +
+ +**
Version 1.3.7** + +**
Fixes** + +* Added additional safety checks to ExtendedFootstepSurface patches + +
+ +
+ +**
Version 1.3.6** + +**
Features** + +* Added content restoration support for basegame water shader + +
+ +
+ +**
Version 1.3.5** + +**
Fixes** + +* Added safety checks to new FootstepSurface Material cache system. +* Added safety checks to new ExtendedLevel override fog size feature. +* Changed ContentRestoring of EnemyType's to use ScriptableObject name rather than enemyName +* Fixed issue where synced audio clip that plays when previewing enemy beastiary file was not playing for custom enemies +* Fixed issue where custom Enemy beastiary files did not have Info as a default keyword + +
+ +
+ +**
Version 1.3.4** + +**
Fixes** + +* Updated .csproj and thunderstore.toml +* Updated outdated README.md + +
+ +
+ +**
Version 1.3.3** + +**
Features** + +* Implemented ExtendedFootstepSurface + +
+ +
+ +**
Version 1.3.2** + +**
Fixes** + +* Updated onApparatusTaken ExtendedEvent + +
+ +
+ +**
Version 1.3.1** + +**
Fixes** + +* Fixed issue regarding deprecated Level list. + +
+ +
+ + +**
Version 1.3.0** + +**
Features** + +* Updated mod for Lethal Company version 56 +* Added initial ExtendedBuyableVehicle implementation +* Added LevelEvents.onShipLand ExtendedEvent +* Added LevelEvents.onShipLeave ExtendedEvent +* Added ExtendedLevel.OverrideDustStormVolumeSize Value +* Added ExtendedLevel.OverrideFoggyVolumeSize Value +* Added PatchedContent.TryGetExtendedContent() Function. +* Added public references to basegame manager instances to OriginalContent +* Updated ContentTag's for new Version 55/56 content + +
+ +**
Fixes** + +* Fixed issue with onApparatusTaken event running at unintended moments +* Added safeguard to prevent multiple Lethalbundles with identical names from causing a gamebreaking error +* Moved LethalLib from a Hard Dependency to a Soft Dependency +* Fixed ExtendedItem's not correctly playing the purchased SFX when purchased from Terminal +* Merged various pull requests to improve the workflow and deployment of further LethalLevelLoader development + +
+ +
+ **
Version 1.2.2** **
Fixes** diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedBuyableVehicle.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedBuyableVehicle.cs index aba73bc..ad5761c 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedBuyableVehicle.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedBuyableVehicle.cs @@ -8,14 +8,14 @@ namespace LethalLevelLoader [CreateAssetMenu(fileName = "ExtendedBuyableVehicle", menuName = "Lethal Level Loader/Extended Content/ExtendedBuyableVehicle", order = 21)] public class ExtendedBuyableVehicle : ExtendedContent { - [field: SerializeField] public BuyableVehicle BuyableVehicle { get; set; } + [field: SerializeField] public BuyableVehicle BuyableVehicle { get; set; } = null!; [field: SerializeField] public string TerminalKeywordName { get; set; } = string.Empty; public int VehicleID { get; set; } - public TerminalNode VehicleBuyNode { get; set; } - public TerminalNode VehicleBuyConfirmNode { get; set; } - public TerminalNode VehicleInfoNode { get; set; } + public TerminalNode VehicleBuyNode { get; set; } = null!; + public TerminalNode VehicleBuyConfirmNode { get; set; } = null!; + public TerminalNode VehicleInfoNode { get; set; } = null!; internal static ExtendedBuyableVehicle Create(BuyableVehicle newBuyableVehicle) { diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedContent.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedContent.cs index c1766a8..bf1094e 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedContent.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedContent.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using UnityEngine; @@ -8,7 +9,7 @@ namespace LethalLevelLoader { public class ExtendedContent : ScriptableObject { - public ExtendedMod ExtendedMod { get; internal set; } + public ExtendedMod ExtendedMod { get; internal set; } = null!; public ContentType ContentType { get; internal set; } = ContentType.Vanilla; /*Obsolete*/ public List ContentTagStrings { get; internal set; } = new List(); [field: SerializeField] public List ContentTags { get; internal set; } = new List(); @@ -30,7 +31,7 @@ public bool TryGetTag(string tag) return (false); } - public bool TryGetTag(string tag, out ContentTag returnTag) + public bool TryGetTag(string tag, [NotNullWhen(returnValue: true)] out ContentTag? returnTag) { returnTag = null; foreach (ContentTag contentTag in ContentTags) diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedDungeonFlow.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedDungeonFlow.cs index c587916..4fbab59 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedDungeonFlow.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedDungeonFlow.cs @@ -15,19 +15,19 @@ namespace LethalLevelLoader public class ExtendedDungeonFlow : ExtendedContent { [field: Header("General Settings")] - [field: SerializeField] public DungeonFlow DungeonFlow { get; set; } + [field: SerializeField] public DungeonFlow DungeonFlow { get; set; } = null!; [field: SerializeField] public string DungeonName { get; set; } = string.Empty; [field: SerializeField] public float MapTileSize { get; set; } = 1f; - [field: SerializeField] public AudioClip FirstTimeDungeonAudio { get; set; } + [field: SerializeField] public AudioClip FirstTimeDungeonAudio { get; set; } = null!; [field: Space(5)] [field: Header("Dynamic Injection Matching Settings")] - [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } + [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } = null!; [field: Space(5)] [field: Header("Extended Feature Settings")] - [field: SerializeField] public GameObject OverrideKeyPrefab { get; set; } + [field: SerializeField] public GameObject OverrideKeyPrefab { get; set; } = null!; [field: SerializeField] public List SpawnableMapObjects { get; set; } = new List(); [field: SerializeField] public List GlobalPropCountOverridesList { get; set; } = new List(); @@ -49,8 +49,8 @@ public class ExtendedDungeonFlow : ExtendedContent [Obsolete] public float dungeonSizeMin = 1; [Obsolete] public float dungeonSizeMax = 1; [Obsolete][Range(0, 1)] public float dungeonSizeLerpPercentage = 1; - [Obsolete] public AudioClip dungeonFirstTimeAudio; - [Obsolete] public DungeonFlow dungeonFlow; + [Obsolete] public AudioClip? dungeonFirstTimeAudio; + [Obsolete] public DungeonFlow? dungeonFlow; [Obsolete] public string dungeonDisplayName = string.Empty; [Obsolete] public string contentSourceName = string.Empty; [Obsolete] public List dynamicLevelTagsList = new List(); @@ -65,11 +65,11 @@ public class ExtendedDungeonFlow : ExtendedContent public bool IsCurrentDungeon => (DungeonManager.CurrentExtendedDungeonFlow == this); [HideInInspector] public DungeonEvents DungeonEvents { get; internal set; } = new DungeonEvents(); - internal static ExtendedDungeonFlow Create(DungeonFlow newDungeonFlow, AudioClip newFirstTimeDungeonAudio) + internal static ExtendedDungeonFlow Create(DungeonFlow newDungeonFlow, AudioClip? newFirstTimeDungeonAudio) { ExtendedDungeonFlow newExtendedDungeonFlow = ScriptableObject.CreateInstance(); newExtendedDungeonFlow.DungeonFlow = newDungeonFlow; - newExtendedDungeonFlow.FirstTimeDungeonAudio = newFirstTimeDungeonAudio; + newExtendedDungeonFlow.FirstTimeDungeonAudio = newFirstTimeDungeonAudio!; if (newExtendedDungeonFlow.LevelMatchingProperties == null) newExtendedDungeonFlow.LevelMatchingProperties = LevelMatchingProperties.Create(newExtendedDungeonFlow); diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedEnemyType.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedEnemyType.cs index c7f1e86..3c906de 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedEnemyType.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedEnemyType.cs @@ -12,27 +12,27 @@ public class ExtendedEnemyType : ExtendedContent { [field: Header("General Settings")] - [field: SerializeField] public EnemyType EnemyType { get; set; } - [field: SerializeField] public string EnemyDisplayName { get; set; } + [field: SerializeField] public EnemyType EnemyType { get; set; } = null!; + [field: SerializeField] public string EnemyDisplayName { get; set; } = null!; [field: Space(5)] [field: Header("Dynamic Injection Matching Settings")] - [field: SerializeField] public LevelMatchingProperties OutsideLevelMatchingProperties { get; set; } - [field: SerializeField] public LevelMatchingProperties DaytimeLevelMatchingProperties { get; set; } + [field: SerializeField] public LevelMatchingProperties OutsideLevelMatchingProperties { get; set; } = null!; + [field: SerializeField] public LevelMatchingProperties DaytimeLevelMatchingProperties { get; set; } = null!; - [field: SerializeField] public LevelMatchingProperties InsideLevelMatchingProperties { get; set; } - [field: SerializeField] public DungeonMatchingProperties InsideDungeonMatchingProperties { get; set; } + [field: SerializeField] public LevelMatchingProperties InsideLevelMatchingProperties { get; set; } = null!; + [field: SerializeField] public DungeonMatchingProperties InsideDungeonMatchingProperties { get; set; } = null!; [field: Space(5)] [field: Header("Terminal Bestiary Override Settings")] [field: SerializeField] [field: TextArea(2,20)] public string InfoNodeDescription { get; set; } = string.Empty; - [field: SerializeField] public VideoClip InfoNodeVideoClip { get; set; } + [field: SerializeField] public VideoClip? InfoNodeVideoClip { get; set; } - public ScanNodeProperties ScanNodeProperties { get; internal set; } + public ScanNodeProperties ScanNodeProperties { get; internal set; } = null!; public int EnemyID { get; internal set; } - public TerminalNode EnemyInfoNode { get; internal set; } + public TerminalNode? EnemyInfoNode { get; internal set; } public static ExtendedEnemyType Create(EnemyType enemyType, ExtendedMod extendedMod, ContentType contentType) { diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedFootstepSurface.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedFootstepSurface.cs index 385f9ad..d10682d 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedFootstepSurface.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedFootstepSurface.cs @@ -8,8 +8,7 @@ namespace LethalLevelLoader; [CreateAssetMenu(fileName = "ExtendedFootstepSurface", menuName = "Lethal Level Loader/Extended Content/ExtendedFootstepSurface", order = 27)] public class ExtendedFootstepSurface : ExtendedContent { - public FootstepSurface footstepSurface; - public List associatedMaterials; - public List associatedGameObjects; + public FootstepSurface footstepSurface = null!; + public List associatedMaterials = null!; internal int arrayIndex; } diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedItem.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedItem.cs index f7f8d2e..9bf70ca 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedItem.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedItem.cs @@ -10,15 +10,15 @@ public class ExtendedItem : ExtendedContent { [field: Header("General Settings")] - [field: SerializeField] public Item Item { get; set; } + [field: SerializeField] public Item Item { get; set; } = null!; [field: SerializeField] public string PluralisedItemName { get; set; } = string.Empty; [field: SerializeField] public bool IsBuyableItem { get; set; } [field: Space(5)] [field: Header("Dynamic Injection Matching Settings")] - [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } - [field: SerializeField] public DungeonMatchingProperties DungeonMatchingProperties { get; set; } + [field: SerializeField] public LevelMatchingProperties LevelMatchingProperties { get; set; } = null!; + [field: SerializeField] public DungeonMatchingProperties DungeonMatchingProperties { get; set; } = null!; [field: Space(5)] [field: Header("Terminal Store & Info Override Settings")] @@ -27,9 +27,9 @@ public class ExtendedItem : ExtendedContent [field: SerializeField] public string OverrideBuyNodeDescription { get; set; } = string.Empty; [field: SerializeField] public string OverrideBuyConfirmNodeDescription { get; set; } = string.Empty; - public TerminalNode BuyNode { get; internal set; } - public TerminalNode BuyConfirmNode { get; internal set; } - public TerminalNode BuyInfoNode { get; internal set; } + public TerminalNode? BuyNode { get; internal set; } + public TerminalNode? BuyConfirmNode { get; internal set; } + public TerminalNode? BuyInfoNode { get; internal set; } public int CreditsWorth { diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedLevel.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedLevel.cs index feec484..06f8cc2 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedLevel.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedLevel.cs @@ -14,7 +14,7 @@ namespace LethalLevelLoader public class ExtendedLevel : ExtendedContent { [field: Header("General Settings")] - [field: SerializeField] public SelectableLevel SelectableLevel { get; set; } + [field: SerializeField] public SelectableLevel SelectableLevel { get; set; } = null!; [Space(5)] [SerializeField] private int routePrice = 0; [field: Header("Extended Feature Settings")] @@ -22,7 +22,7 @@ public class ExtendedLevel : ExtendedContent [field: Space(5)] - [field: SerializeField] public GameObject OverrideQuicksandPrefab { get; set; } + [field: SerializeField] public GameObject OverrideQuicksandPrefab { get; set; } = null!; [field: Space(5)] @@ -32,13 +32,20 @@ public class ExtendedLevel : ExtendedContent [field: Space(5)] - [field: SerializeField] public AnimationClip ShipFlyToMoonClip { get; set; } - [field: SerializeField] public AnimationClip ShipFlyFromMoonClip { get; set; } + [field: SerializeField] public AnimationClip ShipFlyToMoonClip { get; set; } = null!; + [field: SerializeField] public AnimationClip ShipFlyFromMoonClip { get; set; } = null!; [field: Space(5)] [field: SerializeField] public List SceneSelections { get; set; } = new List(); + [field: Space(5)] + [field: Header("Weather Fog Distance Override Settings")] + + [field: SerializeField] public Vector3 OverrideDustStormVolumeSize { get; set; } = Vector3.zero; + [field: SerializeField] public Vector3 OverrideFoggyVolumeSize { get; set; } = Vector3.zero; + + [field: Space(5)] [field: Header("Terminal Route Override Settings")] @@ -53,7 +60,7 @@ public class ExtendedLevel : ExtendedContent [Space(25)] [Header("Obsolete (Legacy Fields, Will Be Removed In The Future)")] - [Obsolete] public SelectableLevel selectableLevel; + [Obsolete] public SelectableLevel? selectableLevel; [Obsolete][Space(5)] public string contentSourceName = string.Empty; //Levels from AssetBundles will have this as their Assembly Name. [Obsolete][Space(5)] public List levelTags = new List(); @@ -94,13 +101,13 @@ public int RoutePrice [HideInInspector] public LevelEvents LevelEvents { get; internal set; } = new LevelEvents(); - public TerminalNode RouteNode { get; internal set; } - public TerminalNode RouteConfirmNode { get; internal set; } - public TerminalNode InfoNode { get; internal set; } + public TerminalNode RouteNode { get; internal set; } = null!; + public TerminalNode RouteConfirmNode { get; internal set; } = null!; + public TerminalNode InfoNode { get; internal set; } = null!; //Dunno about these yet public List EnabledExtendedWeatherEffects { get; set; } = new List(); - public ExtendedWeatherEffect CurrentExtendedWeatherEffect { get; set; } + public ExtendedWeatherEffect? CurrentExtendedWeatherEffect { get; set; } internal static ExtendedLevel Create(SelectableLevel newSelectableLevel) { @@ -199,14 +206,14 @@ internal void SetLevelID() internal void SetExtendedDungeonFlowMatches() { foreach (IntWithRarity intWithRarity in SelectableLevel.dungeonFlowTypes) - if (DungeonManager.TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonFlowTypes[intWithRarity.id].dungeonFlow, out ExtendedDungeonFlow extendedDungeonFlow)) + if (DungeonManager.TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonFlowTypes[intWithRarity.id].dungeonFlow, out ExtendedDungeonFlow? extendedDungeonFlow)) extendedDungeonFlow.LevelMatchingProperties.planetNames.Add(new StringWithRarity(NumberlessPlanetName, intWithRarity.rarity)); if (SelectableLevel.sceneName == "Level4March") foreach (IndoorMapType indoorMapType in Patches.RoundManager.dungeonFlowTypes) if (indoorMapType.dungeonFlow.name == "Level1Flow3Exits") - if (DungeonManager.TryGetExtendedDungeonFlow(indoorMapType.dungeonFlow, out ExtendedDungeonFlow marchDungeonFlow)) + if (DungeonManager.TryGetExtendedDungeonFlow(indoorMapType.dungeonFlow, out ExtendedDungeonFlow? marchDungeonFlow)) marchDungeonFlow.LevelMatchingProperties.planetNames.Add(new StringWithRarity(NumberlessPlanetName, 300)); } diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedMod.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedMod.cs index d5c888e..16a1819 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedMod.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedMod.cs @@ -237,6 +237,8 @@ internal void UnregisterAllExtendedContent() ExtendedEnemyTypes.Clear(); ExtendedWeatherEffects.Clear(); ExtendedFootstepSurfaces.Clear(); + ExtendedStoryLogs.Clear(); + ExtendedBuyableVehicles.Clear(); } internal void SortRegisteredContent() @@ -247,6 +249,8 @@ internal void SortRegisteredContent() ExtendedEnemyTypes.Sort((s1, s2) => s1.name.CompareTo(s2.name)); ExtendedWeatherEffects.Sort((s1, s2) => s1.name.CompareTo(s2.name)); ExtendedFootstepSurfaces.Sort((s1, s2) => s1.name.CompareTo(s2.name)); + ExtendedStoryLogs.Sort((s1, s2) => s1.name.CompareTo(s2.name)); + ExtendedBuyableVehicles.Sort((s1, s2) => s1.name.CompareTo(s2.name)); } internal void Example() diff --git a/LethalLevelLoader/Components/ExtendedContent/ExtendedWeatherEffect.cs b/LethalLevelLoader/Components/ExtendedContent/ExtendedWeatherEffect.cs index c0bcec1..ca870a3 100644 --- a/LethalLevelLoader/Components/ExtendedContent/ExtendedWeatherEffect.cs +++ b/LethalLevelLoader/Components/ExtendedContent/ExtendedWeatherEffect.cs @@ -14,8 +14,8 @@ public class ExtendedWeatherEffect : ExtendedContent [field: SerializeField] public LevelWeatherType BaseWeatherType { get; set; } = LevelWeatherType.None; [field: SerializeField] public string WeatherDisplayName { get; set; } = string.Empty; - [field: SerializeField] public GameObject WorldObject { get; set; } - [field: SerializeField] public GameObject GlobalObject { get; set; } + [field: SerializeField] public GameObject? WorldObject { get; set; } + [field: SerializeField] public GameObject? GlobalObject { get; set; } public ContentType contentType; @@ -29,7 +29,7 @@ internal static ExtendedWeatherEffect Create(LevelWeatherType levelWeatherType, return (ExtendedWeatherEffect.Create(levelWeatherType, weatherEffect.effectObject, weatherEffect.effectPermanentObject, weatherDisplayName, newContentType)); } - internal static ExtendedWeatherEffect Create(LevelWeatherType levelWeatherType, GameObject worldObject, GameObject globalObject, string newWeatherDisplayName, ContentType newContentType) + internal static ExtendedWeatherEffect Create(LevelWeatherType levelWeatherType, GameObject? worldObject, GameObject? globalObject, string newWeatherDisplayName, ContentType newContentType) { ExtendedWeatherEffect newExtendedWeatherEffect = ScriptableObject.CreateInstance(); diff --git a/LethalLevelLoader/Components/MatchingProperties/ContentTag.cs b/LethalLevelLoader/Components/MatchingProperties/ContentTag.cs index 239419d..6974c00 100644 --- a/LethalLevelLoader/Components/MatchingProperties/ContentTag.cs +++ b/LethalLevelLoader/Components/MatchingProperties/ContentTag.cs @@ -8,7 +8,7 @@ namespace LethalLevelLoader [CreateAssetMenu(fileName = "ContentTag", menuName = "Lethal Level Loader/Utility/ContentTag", order = 11)] public class ContentTag : ScriptableObject { - public string contentTagName; + public string contentTagName = null!; public Color contentTagColor; diff --git a/LethalLevelLoader/Components/MatchingProperties/DungeonMatchingProperties.cs b/LethalLevelLoader/Components/MatchingProperties/DungeonMatchingProperties.cs index 3c4daeb..9408c22 100644 --- a/LethalLevelLoader/Components/MatchingProperties/DungeonMatchingProperties.cs +++ b/LethalLevelLoader/Components/MatchingProperties/DungeonMatchingProperties.cs @@ -30,7 +30,7 @@ public int GetDynamicRarity(ExtendedDungeonFlow extendedDungeonFlow) } - public void ApplyValues(List newModNames = null, List newAuthorNames = null, List newDungeonTags = null, List newDungeonNames = null) + public void ApplyValues(List? newModNames = null, List? newAuthorNames = null, List? newDungeonTags = null, List? newDungeonNames = null) { if (newModNames != null && newModNames.Count != 0) modNames = new List(newModNames); diff --git a/LethalLevelLoader/Components/MatchingProperties/LevelMatchingProperties.cs b/LethalLevelLoader/Components/MatchingProperties/LevelMatchingProperties.cs index 15abf5d..516699d 100644 --- a/LethalLevelLoader/Components/MatchingProperties/LevelMatchingProperties.cs +++ b/LethalLevelLoader/Components/MatchingProperties/LevelMatchingProperties.cs @@ -35,7 +35,7 @@ public int GetDynamicRarity(ExtendedLevel extendedLevel) return (returnRarity); } - public void ApplyValues(List newModNames = null, List newAuthorNames = null, List newLevelTags = null, List newRoutePrices = null, List newCurrentWeathers = null, List newPlanetNames = null) + public void ApplyValues(List? newModNames = null, List? newAuthorNames = null, List? newLevelTags = null, List? newRoutePrices = null, List? newCurrentWeathers = null, List? newPlanetNames = null) { if (newModNames != null && newModNames.Count != 0) modNames = new List(newModNames); diff --git a/LethalLevelLoader/Components/MatchingProperties/MatchingProperties.cs b/LethalLevelLoader/Components/MatchingProperties/MatchingProperties.cs index e3162fc..cf729dd 100644 --- a/LethalLevelLoader/Components/MatchingProperties/MatchingProperties.cs +++ b/LethalLevelLoader/Components/MatchingProperties/MatchingProperties.cs @@ -18,7 +18,7 @@ public static MatchingProperties Create(ExtendedContent extendedContent) return (matchingProperties); } - internal static bool UpdateRarity(ref int currentValue, int newValue, string debugActionObject = null, string debugActionReason = null) + internal static bool UpdateRarity(ref int currentValue, int newValue, string? debugActionObject = null, string? debugActionReason = null) { if (newValue > currentValue) { diff --git a/LethalLevelLoader/General/Content.cs b/LethalLevelLoader/General/Content.cs index e7a9b42..13a2972 100644 --- a/LethalLevelLoader/General/Content.cs +++ b/LethalLevelLoader/General/Content.cs @@ -11,12 +11,17 @@ namespace LethalLevelLoader { public static class PatchedContent { - public static ExtendedMod VanillaMod { get; internal set; } + public static ExtendedMod VanillaMod { get; internal set; } = null!; public static List AllLevelSceneNames { get; internal set; } = new List(); public static List ExtendedMods { get; internal set; } = new List(); + internal static Dictionary ExtendedLevelDictionary = new Dictionary(); + internal static Dictionary ExtendedDungeonFlowDictionary = new Dictionary(); + internal static Dictionary ExtendedItemDictionary = new Dictionary(); + internal static Dictionary ExtendedEnemyTypeDictionary = new Dictionary(); + internal static Dictionary ExtendedBuyableVehicleDictionary = new Dictionary(); public static List ExtendedLevels { get; internal set; } = new List(); @@ -45,6 +50,13 @@ public static List CustomExtendedLevels } } + [Obsolete("Use PatchedContent.SelectableLevels instead.")] // probably used by no mod, but this is public so we should be careful + public static List SeletectableLevels + { + get { return (SelectableLevels); } + } + + public static List SelectableLevels { @@ -245,10 +257,62 @@ internal static void SortExtendedMods() extendedMod.SortRegisteredContent(); } } + + internal static void PopulateContentDictionaries() + { + foreach (ExtendedLevel extendedLevel in ExtendedLevels) + TryAdd(ExtendedLevelDictionary, extendedLevel.SelectableLevel, extendedLevel); + foreach (ExtendedDungeonFlow extendedDungeonFlow in ExtendedDungeonFlows) + TryAdd(ExtendedDungeonFlowDictionary, extendedDungeonFlow.DungeonFlow, extendedDungeonFlow); + foreach (ExtendedItem extendedItem in ExtendedItems) + TryAdd(ExtendedItemDictionary, extendedItem.Item, extendedItem); + foreach (ExtendedEnemyType extendedEnemyType in ExtendedEnemyTypes) + TryAdd(ExtendedEnemyTypeDictionary, extendedEnemyType.EnemyType, extendedEnemyType); + foreach (ExtendedBuyableVehicle extendedBuyableVehicle in ExtendedBuyableVehicles) + TryAdd(ExtendedBuyableVehicleDictionary, extendedBuyableVehicle.BuyableVehicle, extendedBuyableVehicle); + } + + internal static void TryAdd(Dictionary dict, T1 key, T2 value) + { + if (!dict.ContainsKey(key)) + dict.Add(key, value); + else + DebugHelper.LogError("Could not add " + key.ToString() + " to dictionary.", DebugType.Developer); + } + + public static bool TryGetExtendedContent(SelectableLevel selectableLevel, out ExtendedLevel extendedLevel) + { + return (ExtendedLevelDictionary.TryGetValue(selectableLevel, out extendedLevel)); + } + + public static bool TryGetExtendedContent(DungeonFlow dungeonFlow, out ExtendedDungeonFlow extendedDungeonFlow) + { + return (ExtendedDungeonFlowDictionary.TryGetValue(dungeonFlow, out extendedDungeonFlow)); + } + + public static bool TryGetExtendedContent(Item item, out ExtendedItem extendedItem) + { + return (ExtendedItemDictionary.TryGetValue(item, out extendedItem)); + } + + public static bool TryGetExtendedContent(EnemyType enemyType, out ExtendedEnemyType extendedEnemyType) + { + return (ExtendedEnemyTypeDictionary.TryGetValue(enemyType, out extendedEnemyType)); + } + + public static bool TryGetExtendedContent(BuyableVehicle buyableVehicle, out ExtendedBuyableVehicle extendedBuyableVehicle) + { + return (ExtendedBuyableVehicleDictionary.TryGetValue(buyableVehicle, out extendedBuyableVehicle)); + } } public static class OriginalContent { + public static StartOfRound StartOfRound => Patches.StartOfRound; + public static RoundManager RoundManager => Patches.RoundManager; + public static Terminal Terminal => Patches.Terminal; + public static TimeOfDay TimeOfDay => Patches.TimeOfDay; + //Levels public static List SelectableLevels { get; internal set; } = new List(); diff --git a/LethalLevelLoader/General/EventPatches.cs b/LethalLevelLoader/General/EventPatches.cs index f2c7f84..16e5e99 100644 --- a/LethalLevelLoader/General/EventPatches.cs +++ b/LethalLevelLoader/General/EventPatches.cs @@ -133,7 +133,7 @@ internal static void RoundManagerSpawnSyncedProps_Postfix() } } - private static EnemyVent cachedSelectedVent; + private static EnemyVent? cachedSelectedVent; [HarmonyPriority(Patches.harmonyPriority)] [HarmonyPatch(typeof(RoundManager), "SpawnEnemyFromVent")] [HarmonyPrefix] @@ -161,7 +161,7 @@ internal static void RoundManagerSpawnEventFromVent_Postfix() [HarmonyPostfix] internal static void RoundManagerSpawnMapObjects_Postfix() { - if (DungeonManager.CurrentExtendedDungeonFlow != null) + if (DungeonManager.CurrentExtendedDungeonFlow != null && LevelManager.CurrentExtendedLevel != null) { List mapObjects = new List(); foreach (GameObject rootObject in SceneManager.GetSceneByName(LevelManager.CurrentExtendedLevel.SelectableLevel.sceneName).GetRootGameObjects()) @@ -249,9 +249,9 @@ internal static void EntranceTeleportTeleportPlayerServerRpc_Prefix(EntranceTele [HarmonyPriority(Patches.harmonyPriority)] [HarmonyPatch(typeof(LungProp), "EquipItem")] [HarmonyPrefix] - internal static void LungPropEquipItem_Postfix(LungProp __instance) + internal static void LungPropEquipItem_Prefix(LungProp __instance) { - if (__instance.IsServer == true && __instance.isLungDockedInElevator) + if (__instance.IsServer == true && __instance.isLungDocked) { if (DungeonManager.CurrentExtendedDungeonFlow != null) { @@ -285,18 +285,27 @@ internal static void TimeOfDayGetDayPhase_Postfix(DayMode __result) public class ExtendedEvent { public delegate void ParameterEvent(T param); - private event ParameterEvent onParameterEvent; + + private event ParameterEvent? onParameterEvent; + private event Action? onEvent; + public bool HasListeners => (Listeners != 0); public int Listeners { get; internal set; } - public void Invoke(T param) { onParameterEvent?.Invoke(param); } + + public void Invoke(T param) { onParameterEvent?.Invoke(param); onEvent?.Invoke(); } + public void Invoke() { onEvent?.Invoke(); } + public void AddListener(ParameterEvent listener) { onParameterEvent += listener; Listeners++; } + public void AddListener(Action listener) { onEvent += listener; Listeners++; } + public void RemoveListener(ParameterEvent listener) { onParameterEvent -= listener; Listeners--; } + public void RemoveListener(Action listener) { onEvent -= listener; Listeners--; } } public class ExtendedEvent { public delegate void Event(); - private event Event onEvent; + private event Event? onEvent; public bool HasListeners => (Listeners != 0); public int Listeners { get; internal set; } public void Invoke() { onEvent?.Invoke(); } diff --git a/LethalLevelLoader/General/Extensions.cs b/LethalLevelLoader/General/Extensions.cs index c862b9d..7bc5d10 100644 --- a/LethalLevelLoader/General/Extensions.cs +++ b/LethalLevelLoader/General/Extensions.cs @@ -33,7 +33,7 @@ public static List GetTiles(this DungeonFlow dungeonFlow) foreach (Tile tile in new List(tilesList)) if (tile == null) - tilesList.Remove(tile); + tilesList.Remove(tile!); return (tilesList); } diff --git a/LethalLevelLoader/General/OptionalPatches/LethalLibPatches.cs b/LethalLevelLoader/General/OptionalPatches/LethalLibPatches.cs new file mode 100644 index 0000000..99fd793 --- /dev/null +++ b/LethalLevelLoader/General/OptionalPatches/LethalLibPatches.cs @@ -0,0 +1,30 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Text; + +namespace LethalLevelLoader +{ + internal class LethalLibPatches + { + [HarmonyPriority(Patches.harmonyPriority)] + [HarmonyPatch(typeof(LethalLib.Modules.Dungeon), "RoundManager_Start")] + [HarmonyPrefix] + internal static bool Dungeon_Start_Prefix(Action orig, RoundManager self) + { + DebugHelper.LogWarning("Disabling LethalLib Dungeon.RoundManager_Start() Function To Prevent Conflicts", DebugType.User); + orig(self); + return (false); + } + + [HarmonyPriority(Patches.harmonyPriority)] + [HarmonyPatch(typeof(LethalLib.Modules.Dungeon), "RoundManager_GenerateNewFloor")] + [HarmonyPrefix] + internal static bool Dungeon_GenerateNewFloor_Prefix(Action orig, RoundManager self) + { + DebugHelper.LogWarning("Disabling LethalLib Dungeon.RoundManager_GenerateNewFloor() Function To Prevent Conflicts", DebugType.User); + orig(self); + return (false); + } + } +} diff --git a/LethalLevelLoader/General/Patches.cs b/LethalLevelLoader/General/Patches.cs index 6d3efbe..96c92e6 100644 --- a/LethalLevelLoader/General/Patches.cs +++ b/LethalLevelLoader/General/Patches.cs @@ -18,6 +18,8 @@ using UnityEngine; using UnityEngine.Audio; using UnityEngine.Device; +using UnityEngine.InputSystem.Utilities; +using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using static LethalLevelLoader.AssetBundleLoader; using NetworkManager = Unity.Netcode.NetworkManager; @@ -33,10 +35,10 @@ internal static class Patches internal static List allSceneNamesCalledToLoad = new List(); //Singletons and such for these are set in each classes Awake function, But they all are accessible on the first awake function of the earliest one of these four managers awake function, so i grab them directly via findobjectoftype to safely access them as early as possible. - public static StartOfRound StartOfRound { get; internal set; } - public static RoundManager RoundManager { get; internal set; } - public static Terminal Terminal { get; internal set; } - public static TimeOfDay TimeOfDay { get; internal set; } + public static StartOfRound StartOfRound { get; internal set; } = null!; + public static RoundManager RoundManager { get; internal set; } = null!; + public static Terminal Terminal { get; internal set; } = null!; + public static TimeOfDay TimeOfDay { get; internal set; } = null!; [HarmonyPriority(harmonyPriority)] [HarmonyPatch(typeof(PreInitSceneScript), "Awake")] @@ -210,9 +212,38 @@ internal static void StartOfRoundAwake_Prefix(StartOfRound __instance) //Initialize ExtendedContent Objects For Custom Content. AssetBundleLoader.InitializeBundles(); + PatchedContent.PopulateContentDictionaries(); + foreach (ExtendedLevel extendedLevel in PatchedContent.CustomExtendedLevels) extendedLevel.SetLevelID(); + foreach (WeatherEffect weatherEffect in TimeOfDay.effects) + { + if (weatherEffect.effectObject != null && weatherEffect.effectObject.name == "DustStorm") + if (weatherEffect.effectObject.TryGetComponent(out LocalVolumetricFog dustFog)) + { + LevelLoader.dustCloudFog = dustFog; + LevelLoader.defaultDustCloudFogVolumeSize = dustFog.parameters.size; + break; + } + } + + LevelLoader.foggyFog = TimeOfDay.foggyWeather; + LevelLoader.defaultFoggyFogVolumeSize = TimeOfDay.foggyWeather.parameters.size; + + foreach (ExtendedLevel vanillaLevel in PatchedContent.VanillaExtendedLevels) + { + vanillaLevel.OverrideDustStormVolumeSize = LevelLoader.defaultDustCloudFogVolumeSize; + vanillaLevel.OverrideFoggyVolumeSize = LevelLoader.defaultFoggyFogVolumeSize; + } + foreach (ExtendedLevel customLevel in PatchedContent.CustomExtendedLevels) + { + if (customLevel.OverrideDustStormVolumeSize == Vector3.zero) + customLevel.OverrideDustStormVolumeSize = LevelLoader.defaultDustCloudFogVolumeSize; + if (customLevel.OverrideFoggyVolumeSize == Vector3.zero) + customLevel.OverrideFoggyVolumeSize = LevelLoader.defaultFoggyFogVolumeSize; + } + //Some Debugging. string debugString = "LethalLevelLoader Loaded The Following ExtendedLevels:" + "\n"; foreach (ExtendedLevel extendedLevel in PatchedContent.ExtendedLevels) @@ -314,6 +345,7 @@ internal static void StartOfRoundAwake_Prefix(StartOfRound __instance) TerminalManager.AddTerminalNodeEventListener(TerminalManager.moonsKeyword.specialKeywordResult, TerminalManager.RefreshMoonsCataloguePage, TerminalManager.LoadNodeActionType.After); } + LevelLoader.defaultFootstepSurfaces = new List(StartOfRound.footstepSurfaces).ToArray(); //We Might Not Need This Now /*if (LevelManager.invalidSaveLevelID != -1 && StartOfRound.levels.Length > LevelManager.invalidSaveLevelID) { @@ -427,7 +459,7 @@ internal static void TerminalParseWord_Postfix(Terminal __instance, ref Terminal { if (__result != null) { - TerminalKeyword newKeyword = TerminalManager.TryFindAlternativeNoun(__instance, __result, playerWord); + TerminalKeyword? newKeyword = TerminalManager.TryFindAlternativeNoun(__instance, __result, playerWord); if (newKeyword != null) __result = newKeyword; } @@ -494,7 +526,7 @@ internal static void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) if (LevelManager.CurrentExtendedLevel != null && LevelManager.CurrentExtendedLevel.IsLevelLoaded) foreach (GameObject rootObject in SceneManager.GetSceneByName(LevelManager.CurrentExtendedLevel.SelectableLevel.sceneName).GetRootGameObjects()) { - LevelLoader.UpdateStoryLogs(LevelManager.CurrentExtendedLevel, rootObject); + LevelLoader.RefreshFogSize(LevelManager.CurrentExtendedLevel); ContentRestorer.RestoreAudioAssetReferencesInParent(rootObject); } @@ -508,7 +540,7 @@ internal static void StartOfRoundStartGame_Prefix() if (LethalLevelLoaderNetworkManager.networkManager.IsServer == false) return; - ExtendedLevel extendedLevel = LevelManager.CurrentExtendedLevel; + ExtendedLevel? extendedLevel = LevelManager.CurrentExtendedLevel; if (extendedLevel == null) return; @@ -517,7 +549,7 @@ internal static void StartOfRoundStartGame_Prefix() RoundManager.InitializeRandomNumberGenerators(); int counter = 1; - foreach (StringWithRarity sceneSelection in LevelManager.CurrentExtendedLevel.SceneSelections) + foreach (StringWithRarity sceneSelection in LevelManager.CurrentExtendedLevel!.SceneSelections) { DebugHelper.Log("Scene Selection #" + counter + " \"" + sceneSelection.Name + "\" (" + sceneSelection.Rarity + ")", DebugType.Developer); counter++; @@ -619,6 +651,20 @@ internal static void RoundManagerSpawnOutsideHazards_Prefix() RoundManager.quicksandPrefab = LevelManager.CurrentExtendedLevel.OverrideQuicksandPrefab; } + [HarmonyPriority(harmonyPriority)] + [HarmonyPatch(typeof(RoundManager), nameof(RoundManager.FinishGeneratingNewLevelClientRpc))] + [HarmonyPostfix] + internal static void RoundManagerFinishGeneratingNewLevelClientRpc_Prefix() + { + if (TimeOfDay.sunAnimator != null) + { + LevelLoader.RefreshFootstepSurfaces(); + LevelLoader.BakeSceneColliderMaterialData(TimeOfDay.sunAnimator.gameObject.scene); + if (LevelLoader.vanillaWaterShader != null) + LevelLoader.TryRestoreWaterShaders(TimeOfDay.sunAnimator.gameObject.scene); + } + } + /* [HarmonyPriority(harmonyPriority)] [HarmonyPatch(typeof(MoldSpreadManager), nameof(MoldSpreadManager.Start))] @@ -683,43 +729,15 @@ internal static void RoundManagerSpawnMapObjects_Postfix() temporarySpawnableMapObjectList.Clear(); } - internal static GameObject previousHit; - internal static FootstepSurface previouslyAssignedFootstepSurface; - - [HarmonyPriority(harmonyPriority)] - [HarmonyPatch(typeof(PlayerControllerB), "GetCurrentMaterialStandingOn")] - [HarmonyPrefix] - internal static bool PlayerControllerBGetCurrentMaterialStandingOn_Prefix(PlayerControllerB __instance) - { - /*if (LevelManager.CurrentExtendedLevel.extendedFootstepSurfaces.Count != 0) - if (Physics.Raycast(new Ray(__instance.thisPlayerBody.position + Vector3.up, -Vector3.up), out RaycastHit hit, 6f, Patches.StartOfRound.walkableSurfacesMask, QueryTriggerInteraction.Ignore)) - if (hit.collider.gameObject == previousHit) - return (false);*/ - return (true); - } + static FootstepSurface? previousFootstepSurface; [HarmonyPriority(harmonyPriority)] [HarmonyPatch(typeof(PlayerControllerB), "GetCurrentMaterialStandingOn")] [HarmonyPostfix] internal static void PlayerControllerBGetCurrentMaterialStandingOn_Postfix(PlayerControllerB __instance) { - /*if (LevelManager.CurrentExtendedLevel.extendedFootstepSurfaces.Count != 0) - if (Physics.Raycast(new Ray(__instance.thisPlayerBody.position + Vector3.up, -Vector3.up), out RaycastHit hit, 6f, Patches.StartOfRound.walkableSurfacesMask, QueryTriggerInteraction.Ignore)) - if (hit.collider.gameObject != previousHit || previousHit == null) - { - previousHit = hit.collider.gameObject; - if (hit.collider.CompareTag("Untagged") || !LevelManager.cachedFootstepSurfaceTagsList.Contains(hit.collider.tag)) - if (hit.collider.gameObject.TryGetComponent(out MeshRenderer meshRenderer)) - foreach (Material material in meshRenderer.sharedMaterials) - foreach (ExtendedFootstepSurface extendedFootstepSurface in LevelManager.CurrentExtendedLevel.extendedFootstepSurfaces) - foreach (Material associatedMaterial in extendedFootstepSurface.associatedMaterials) - if (material.name == associatedMaterial.name) - { - __instance.currentFootstepSurfaceIndex = extendedFootstepSurface.arrayIndex; - return; - } - } - */ + if (LevelLoader.TryGetFootstepSurface(__instance.hit.collider, out FootstepSurface footstepSurface)) + __instance.currentFootstepSurfaceIndex = StartOfRound.footstepSurfaces.IndexOf(footstepSurface); } //DunGen Optimization Patches (Credit To LadyRaphtalia, Author Of Scarlet Devil Mansion) diff --git a/LethalLevelLoader/General/SafetyPatches.cs b/LethalLevelLoader/General/SafetyPatches.cs index a9facf7..232c5ff 100644 --- a/LethalLevelLoader/General/SafetyPatches.cs +++ b/LethalLevelLoader/General/SafetyPatches.cs @@ -132,25 +132,5 @@ internal static void TimeOfDaySetWeatherBasedOnVariables_Prefix(TimeOfDay __inst } } } - - [HarmonyPriority(harmonyPriority)] - [HarmonyPatch(typeof(LethalLib.Modules.Dungeon), "RoundManager_Start")] - [HarmonyPrefix] - internal static bool Dungeon_Start_Prefix(Action orig, RoundManager self) - { - DebugHelper.LogWarning("Disabling LethalLib Dungeon.RoundManager_Start() Function To Prevent Conflicts", DebugType.User); - orig(self); - return (false); - } - - [HarmonyPriority(harmonyPriority)] - [HarmonyPatch(typeof(LethalLib.Modules.Dungeon), "RoundManager_GenerateNewFloor")] - [HarmonyPrefix] - internal static bool Dungeon_GenerateNewFloor_Prefix(Action orig, RoundManager self) - { - DebugHelper.LogWarning("Disabling LethalLib Dungeon.RoundManager_GenerateNewFloor() Function To Prevent Conflicts", DebugType.User); - orig(self); - return (false); - } } } diff --git a/LethalLevelLoader/LethalLevelLoader.csproj b/LethalLevelLoader/LethalLevelLoader.csproj index 0293a6f..6b99fe6 100644 --- a/LethalLevelLoader/LethalLevelLoader.csproj +++ b/LethalLevelLoader/LethalLevelLoader.csproj @@ -25,6 +25,7 @@ embedded $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))=./ + enable @@ -91,12 +92,24 @@ - + - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/LethalLevelLoader/Loaders/DungeonLoader.cs b/LethalLevelLoader/Loaders/DungeonLoader.cs index e367d39..e7b8a76 100644 --- a/LethalLevelLoader/Loaders/DungeonLoader.cs +++ b/LethalLevelLoader/Loaders/DungeonLoader.cs @@ -27,7 +27,7 @@ public class ExtendedDungeonFlowWithRarity public static class DungeonLoader { - internal static GameObject defaultKeyPrefab; + internal static GameObject defaultKeyPrefab = null!; internal static void SelectDungeon() { @@ -39,8 +39,8 @@ internal static void SelectDungeon() internal static void PrepareDungeon() { DungeonGenerator dungeonGenerator = Patches.RoundManager.dungeonGenerator.Generator; - ExtendedLevel currentExtendedLevel = LevelManager.CurrentExtendedLevel; - ExtendedDungeonFlow currentExtendedDungeonFlow = DungeonManager.CurrentExtendedDungeonFlow; + ExtendedLevel currentExtendedLevel = LevelManager.CurrentExtendedLevel!; // checked for null in calling method + ExtendedDungeonFlow currentExtendedDungeonFlow = DungeonManager.CurrentExtendedDungeonFlow!; //PatchDungeonSize(dungeonGenerator, currentExtendedLevel, currentExtendedDungeonFlow); PatchFireEscapes(dungeonGenerator, currentExtendedLevel, SceneManager.GetSceneByName(currentExtendedLevel.SelectableLevel.sceneName)); @@ -49,8 +49,8 @@ internal static void PrepareDungeon() public static float GetClampedDungeonSize() { - ExtendedDungeonFlow extendedDungeonFlow = DungeonManager.CurrentExtendedDungeonFlow; - ExtendedLevel extendedLevel = LevelManager.CurrentExtendedLevel; + ExtendedDungeonFlow? extendedDungeonFlow = DungeonManager.CurrentExtendedDungeonFlow; + ExtendedLevel? extendedLevel = LevelManager.CurrentExtendedLevel; float calculatedMultiplier = CalculateDungeonMultiplier(LevelManager.CurrentExtendedLevel, DungeonManager.CurrentExtendedDungeonFlow); if (DungeonManager.CurrentExtendedDungeonFlow != null && DungeonManager.CurrentExtendedDungeonFlow.IsDynamicDungeonSizeRestrictionEnabled == true) { @@ -99,7 +99,7 @@ internal static void PatchFireEscapes(DungeonGenerator dungeonGenerator, Extende { string debugString = "Fire Exit Patch Report, Details Below;" + "\n" + "\n"; - if (DungeonManager.TryGetExtendedDungeonFlow(dungeonGenerator.DungeonFlow, out ExtendedDungeonFlow extendedDungeonFlow)) + if (DungeonManager.TryGetExtendedDungeonFlow(dungeonGenerator.DungeonFlow, out ExtendedDungeonFlow? extendedDungeonFlow)) { List entranceTeleports = GetEntranceTeleports(scene).OrderBy(o => o.entranceId).ToList(); diff --git a/LethalLevelLoader/Loaders/LevelLoader.cs b/LethalLevelLoader/Loaders/LevelLoader.cs index 63a9888..275c651 100644 --- a/LethalLevelLoader/Loaders/LevelLoader.cs +++ b/LethalLevelLoader/Loaders/LevelLoader.cs @@ -9,18 +9,36 @@ using Unity.AI.Navigation; using UnityEngine.AI; using LethalLevelLoader.Tools; +using UnityEngine.Rendering.HighDefinition; +using UnityEngine.Rendering; namespace LethalLevelLoader { - public class LevelLoader + public static class LevelLoader { internal static List customLevelMeshCollidersList = new List(); - internal static AnimatorOverrideController shipAnimatorOverrideController; - internal static AnimationClip defaultShipFlyToMoonClip; - internal static AnimationClip defaultShipFlyFromMoonClip; + internal static AnimatorOverrideController shipAnimatorOverrideController = null!; + internal static AnimationClip defaultShipFlyToMoonClip = null!; + internal static AnimationClip defaultShipFlyFromMoonClip = null!; - internal static GameObject defaultQuicksandPrefab; + internal static Vector3 defaultDustCloudFogVolumeSize; + internal static Vector3 defaultFoggyFogVolumeSize; + + internal static LocalVolumetricFog? dustCloudFog; + internal static LocalVolumetricFog? foggyFog; + + + internal static GameObject defaultQuicksandPrefab = null!; + + internal static FootstepSurface[] defaultFootstepSurfaces = null!; + + internal static Dictionary> cachedLevelColliderMaterialDictionary = new Dictionary>(); + internal static Dictionary> cachedLevelMaterialColliderDictionary = new Dictionary>(); + internal static Dictionary activeExtendedFootstepSurfaceDictionary = new Dictionary(); + internal static LayerMask triggerMask; + + internal static Shader vanillaWaterShader; internal static async void EnableMeshColliders() { @@ -51,15 +69,137 @@ internal static async Task EnableMeshCollider(MeshCollider meshCollider) await Task.Yield(); } - internal static void UpdateStoryLogs(ExtendedLevel extendedLevel, GameObject sceneRootObject) - { - } - internal static void RefreshShipAnimatorClips(ExtendedLevel extendedLevel) { DebugHelper.Log("Refreshing Ship Animator Clips!", DebugType.Developer); shipAnimatorOverrideController["HangarShipLandB"] = extendedLevel.ShipFlyToMoonClip; shipAnimatorOverrideController["ShipLeave"] = extendedLevel.ShipFlyFromMoonClip; } + + internal static void RefreshFogSize(ExtendedLevel extendedLevel) + { + if (dustCloudFog != null) + dustCloudFog.parameters.size = extendedLevel.OverrideDustStormVolumeSize; + if (foggyFog != null) + foggyFog.parameters.size = extendedLevel.OverrideFoggyVolumeSize; + } + + internal static void RefreshFootstepSurfaces() + { + List activeFootstepSurfaces = new List(defaultFootstepSurfaces); + foreach (ExtendedFootstepSurface extendedSurface in LevelManager.CurrentExtendedLevel.ExtendedMod.ExtendedFootstepSurfaces) + { + extendedSurface.footstepSurface.surfaceTag = "Untagged"; + activeFootstepSurfaces.Add(extendedSurface.footstepSurface); + } + + Patches.StartOfRound.footstepSurfaces = activeFootstepSurfaces.ToArray(); + } + + internal static void TryRestoreWaterShaders(Scene scene) + { + List uniqueMaterials = new List(); + foreach (MeshRenderer meshRenderer in Object.FindObjectsByType(FindObjectsSortMode.None)) + if (meshRenderer.gameObject.scene == scene) + foreach (Material sharedMaterial in meshRenderer.sharedMaterials) + { + if (sharedMaterial != null && !string.IsNullOrEmpty(sharedMaterial.name)) + if (!uniqueMaterials.Contains(sharedMaterial)) + uniqueMaterials.Add(sharedMaterial); + } + + foreach (Material sharedMaterial in uniqueMaterials) + ContentRestorer.TryRestoreWaterShader(sharedMaterial); + } + + internal static void BakeSceneColliderMaterialData(Scene scene) + { + cachedLevelColliderMaterialDictionary.Clear(); + cachedLevelMaterialColliderDictionary.Clear(); + activeExtendedFootstepSurfaceDictionary = GetActiveExtendedFoostepSurfaceDictionary(); + + triggerMask = LayerMask.NameToLayer("Triggers"); + + List allValidSceneColliders = new List(); + + foreach (GameObject rootObject in scene.GetRootGameObjects()) + { + foreach (Collider collider in rootObject.GetComponents()) + { + if (ValidateCollider(collider) && !allValidSceneColliders.Contains(collider)) + allValidSceneColliders.Add(collider); + } + foreach (Collider collider in rootObject.GetComponentsInChildren()) + { + if (ValidateCollider(collider) && !allValidSceneColliders.Contains(collider)) + allValidSceneColliders.Add(collider); + } + } + + foreach (Collider sceneCollider in allValidSceneColliders) + { + if (sceneCollider.TryGetComponent(out MeshRenderer meshRenderer)) + { + List validMaterials = new List(); + foreach (Material material in meshRenderer.sharedMaterials) + if (material != null && !string.IsNullOrEmpty(material.name)) + validMaterials.Add(material); + + if (!cachedLevelColliderMaterialDictionary.ContainsKey(sceneCollider)) + cachedLevelColliderMaterialDictionary.Add(sceneCollider, new List(validMaterials)); + + foreach (Material material in validMaterials) + { + if (!cachedLevelMaterialColliderDictionary.ContainsKey(material.name)) + cachedLevelMaterialColliderDictionary.Add(material.name, new List { sceneCollider }); + else if (!cachedLevelMaterialColliderDictionary[material.name].Contains(sceneCollider)) + cachedLevelMaterialColliderDictionary[material.name].Add(sceneCollider); + } + } + } + + //DebugHelper.DebugCachedLevelColliderData(); + } + + internal static bool ValidateCollider(Collider collider) + { + if (collider == null) return (false); + if (collider.gameObject.activeSelf == false) return (false); + if (collider.isTrigger == true) return (false); + if (collider.gameObject.layer == triggerMask) return (false); + if (collider.gameObject.CompareTag("Untagged") == false) return (false); + + return (true); + } + + internal static Dictionary GetActiveExtendedFoostepSurfaceDictionary() + { + Dictionary returnDict = new Dictionary(); + + foreach (ExtendedFootstepSurface extendedFootstepSurface in LevelManager.CurrentExtendedLevel.ExtendedMod.ExtendedFootstepSurfaces) + foreach (Material material in extendedFootstepSurface.associatedMaterials) + if (material != null && !string.IsNullOrEmpty(material.name)) + if (!returnDict.ContainsKey(material.name)) + returnDict.Add(material.name, extendedFootstepSurface.footstepSurface); + + + return (returnDict); + } + + public static bool TryGetFootstepSurface(Collider collider, out FootstepSurface? footstepSurface) + { + footstepSurface = null; + + if (collider == null) + return (false); + + if (cachedLevelColliderMaterialDictionary.TryGetValue(collider, out List materials)) + if (materials != null) + foreach (Material material in materials) + if (material != null && !string.IsNullOrEmpty(material.name)) + activeExtendedFootstepSurfaceDictionary.TryGetValue(material.name, out footstepSurface); + + return (footstepSurface != null); + } } } \ No newline at end of file diff --git a/LethalLevelLoader/Patches/DungeonManager.cs b/LethalLevelLoader/Patches/DungeonManager.cs index f4ddf6c..373ad99 100644 --- a/LethalLevelLoader/Patches/DungeonManager.cs +++ b/LethalLevelLoader/Patches/DungeonManager.cs @@ -3,6 +3,7 @@ using HarmonyLib; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; using UnityEngine.Events; @@ -11,13 +12,13 @@ namespace LethalLevelLoader { public class DungeonManager { - public static ExtendedDungeonFlow CurrentExtendedDungeonFlow + public static ExtendedDungeonFlow? CurrentExtendedDungeonFlow { get { - ExtendedDungeonFlow returnFlow = null; + ExtendedDungeonFlow? returnFlow = null; if (Patches.RoundManager != null && Patches.RoundManager.dungeonGenerator != null) - if (TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonGenerator.Generator.DungeonFlow, out ExtendedDungeonFlow flow)) + if (TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonGenerator.Generator.DungeonFlow, out ExtendedDungeonFlow? flow)) returnFlow = flow; return (returnFlow); } @@ -119,10 +120,10 @@ internal static void RefreshDungeonFlowIDs() Patches.RoundManager.dungeonFlowTypes = indoorMapTypes.ToArray(); } - internal static bool TryGetExtendedDungeonFlow(DungeonFlow dungeonFlow, out ExtendedDungeonFlow returnExtendedDungeonFlow, ContentType contentType = ContentType.Any) + internal static bool TryGetExtendedDungeonFlow(DungeonFlow dungeonFlow, [NotNullWhen(returnValue: true)] out ExtendedDungeonFlow? returnExtendedDungeonFlow, ContentType contentType = ContentType.Any) { returnExtendedDungeonFlow = null; - List extendedDungeonFlowsList = null; + List extendedDungeonFlowsList = null!; if (dungeonFlow == null) return (false); @@ -140,7 +141,7 @@ internal static bool TryGetExtendedDungeonFlow(DungeonFlow dungeonFlow, out Exte return (returnExtendedDungeonFlow != null); } - internal static bool TryGetExtendedDungeonFlow(IndoorMapType indoorMapType, out ExtendedDungeonFlow returnExtendedDungeonFlow, ContentType contentType = ContentType.Any) + internal static bool TryGetExtendedDungeonFlow(IndoorMapType indoorMapType, out ExtendedDungeonFlow? returnExtendedDungeonFlow, ContentType contentType = ContentType.Any) { return (TryGetExtendedDungeonFlow(indoorMapType.dungeonFlow, out returnExtendedDungeonFlow, contentType)); } diff --git a/LethalLevelLoader/Patches/EnemyManager.cs b/LethalLevelLoader/Patches/EnemyManager.cs index 5346f50..69ae689 100644 --- a/LethalLevelLoader/Patches/EnemyManager.cs +++ b/LethalLevelLoader/Patches/EnemyManager.cs @@ -20,9 +20,9 @@ public static void InjectCustomEnemyTypesIntoLevelViaDynamicRarity(ExtendedLevel foreach (ExtendedEnemyType extendedEnemyType in PatchedContent.CustomExtendedEnemyTypes) { string debugString = string.Empty; - SpawnableEnemyWithRarity alreadyInjectedInsideEnemy = null; - SpawnableEnemyWithRarity alreadyInjectedOutsideEnemy = null; - SpawnableEnemyWithRarity alreadyInjectedDaytimeEnemy = null; + SpawnableEnemyWithRarity? alreadyInjectedInsideEnemy; + SpawnableEnemyWithRarity? alreadyInjectedOutsideEnemy; + SpawnableEnemyWithRarity? alreadyInjectedDaytimeEnemy; foreach (SpawnableEnemyWithRarity spawnableEnemyWithRarity in extendedLevel.SelectableLevel.Enemies) if (spawnableEnemyWithRarity.enemyType == extendedEnemyType) @@ -56,7 +56,7 @@ public static void InjectCustomEnemyTypesIntoLevelViaDynamicRarity(ExtendedLevel internal static bool TryInjectEnemyIntoPool(List enemyPool, ExtendedEnemyType extendedEnemy, int newRarity, out SpawnableEnemyWithRarity spawnableEnemyWithRarity) { - spawnableEnemyWithRarity = null; + spawnableEnemyWithRarity = null!; foreach (SpawnableEnemyWithRarity currentSpawnableEnemyWithRarity in enemyPool) if (currentSpawnableEnemyWithRarity.enemyType == extendedEnemy.EnemyType) spawnableEnemyWithRarity = currentSpawnableEnemyWithRarity; diff --git a/LethalLevelLoader/Patches/ItemManager.cs b/LethalLevelLoader/Patches/ItemManager.cs index c53457b..028b31c 100644 --- a/LethalLevelLoader/Patches/ItemManager.cs +++ b/LethalLevelLoader/Patches/ItemManager.cs @@ -21,7 +21,7 @@ public static void InjectCustomItemsIntoLevelViaDynamicRarity(ExtendedLevel exte if (extendedItem.Item.isScrap) { string debugString = string.Empty; - SpawnableItemWithRarity alreadyInjectedItem = null; + SpawnableItemWithRarity? alreadyInjectedItem = null; foreach (SpawnableItemWithRarity spawnableItem in extendedLevel.SelectableLevel.spawnableScrap) if (spawnableItem.spawnableItem == extendedItem) alreadyInjectedItem = spawnableItem; diff --git a/LethalLevelLoader/Patches/LethalLevelLoaderNetworkManager.cs b/LethalLevelLoader/Patches/LethalLevelLoaderNetworkManager.cs index a23fabe..4aec83b 100644 --- a/LethalLevelLoader/Patches/LethalLevelLoaderNetworkManager.cs +++ b/LethalLevelLoader/Patches/LethalLevelLoaderNetworkManager.cs @@ -14,8 +14,8 @@ namespace LethalLevelLoader { public class LethalLevelLoaderNetworkManager : NetworkBehaviour { - public static GameObject networkingManagerPrefab; - private static LethalLevelLoaderNetworkManager _instance; + public static GameObject networkingManagerPrefab = null!; + private static LethalLevelLoaderNetworkManager? _instance; public static LethalLevelLoaderNetworkManager Instance { get @@ -24,11 +24,11 @@ public static LethalLevelLoaderNetworkManager Instance _instance = UnityEngine.Object.FindObjectOfType(); if (_instance == null) DebugHelper.LogError("LethalLevelLoaderNetworkManager Could Not Be Found! Returning Null!", DebugType.User); - return _instance; + return _instance!; } set { _instance = value; } } - public static NetworkManager networkManager; + public static NetworkManager networkManager = null!; private static List queuedNetworkPrefabs = new List(); public static bool networkHasStarted; @@ -192,7 +192,7 @@ internal static void RegisterPrefabs(NetworkManager networkManager) public class StringContainer : INetworkSerializable { - public string SomeText; + public string SomeText = null!; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { if (serializer.IsWriter) diff --git a/LethalLevelLoader/Patches/LevelManager.cs b/LethalLevelLoader/Patches/LevelManager.cs index 8965884..dd8a704 100644 --- a/LethalLevelLoader/Patches/LevelManager.cs +++ b/LethalLevelLoader/Patches/LevelManager.cs @@ -2,6 +2,7 @@ using HarmonyLib; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using Unity.AI.Navigation; @@ -14,13 +15,13 @@ namespace LethalLevelLoader { public class LevelManager { - public static ExtendedLevel CurrentExtendedLevel + public static ExtendedLevel? CurrentExtendedLevel { get { - ExtendedLevel returnLevel = null; + ExtendedLevel? returnLevel = null; if (Patches.StartOfRound != null) - if (TryGetExtendedLevel(Patches.StartOfRound.currentLevel, out ExtendedLevel level)) + if (TryGetExtendedLevel(Patches.StartOfRound.currentLevel, out ExtendedLevel? level)) returnLevel = level; return returnLevel; } @@ -33,11 +34,6 @@ public static ExtendedLevel CurrentExtendedLevel public static int invalidSaveLevelID = -1; - public static List cachedFootstepSurfaceTagsList = new List(); - public static List cachedExtendedFootstepSurfaceMaterialsList = new List(); - public static List cachedExtendedFootstepSurfaceGameObjectsList = new List(); - public static Dictionary cachedFootstepSurfacesDictionary = new Dictionary(); - public static Dictionary dynamicRiskLevelDictionary = new Dictionary() { {"D-", 0}, @@ -88,10 +84,10 @@ internal static void InitializeShipAnimatorOverrideController() //shipAnimator.enabled = false; } - public static bool TryGetExtendedLevel(SelectableLevel selectableLevel, out ExtendedLevel returnExtendedLevel, ContentType levelType = ContentType.Any) + public static bool TryGetExtendedLevel(SelectableLevel selectableLevel, [NotNullWhen(returnValue: true)] out ExtendedLevel? returnExtendedLevel, ContentType levelType = ContentType.Any) { returnExtendedLevel = null; - List extendedLevelsList = null; + List extendedLevelsList = null!; if (selectableLevel == null) return false; @@ -111,7 +107,7 @@ public static bool TryGetExtendedLevel(SelectableLevel selectableLevel, out Exte public static ExtendedLevel GetExtendedLevel(SelectableLevel selectableLevel) { - ExtendedLevel returnExtendedLevel = null; + ExtendedLevel returnExtendedLevel = null!; foreach (ExtendedLevel extendedLevel in PatchedContent.ExtendedLevels) if (extendedLevel.SelectableLevel == selectableLevel) @@ -308,6 +304,7 @@ public static void LogDayHistory() DayHistory newDayHistory = new DayHistory(); daysTotal++; + newDayHistory.allViableOptions = DungeonManager.GetValidExtendedDungeonFlows(CurrentExtendedLevel, false).Select(e => e.extendedDungeonFlow).ToList(); newDayHistory.extendedLevel = LevelManager.CurrentExtendedLevel; newDayHistory.extendedDungeonFlow = DungeonManager.CurrentExtendedDungeonFlow; newDayHistory.day = daysTotal; @@ -392,8 +389,9 @@ public class DayHistory { public int quota; public int day; - public ExtendedLevel extendedLevel; - public ExtendedDungeonFlow extendedDungeonFlow; + public ExtendedLevel? extendedLevel; + public List? allViableOptions; // this whole class should have a constructor that set all these variables + public ExtendedDungeonFlow? extendedDungeonFlow; public LevelWeatherType weatherEffect; } } \ No newline at end of file diff --git a/LethalLevelLoader/Patches/SaveManager.cs b/LethalLevelLoader/Patches/SaveManager.cs index 384ee93..e73e40f 100644 --- a/LethalLevelLoader/Patches/SaveManager.cs +++ b/LethalLevelLoader/Patches/SaveManager.cs @@ -10,7 +10,7 @@ namespace LethalLevelLoader { internal static class SaveManager { - public static LLLSaveFile currentSaveFile; + public static LLLSaveFile currentSaveFile = null!; public static bool parityCheck; internal static void InitializeSave() @@ -392,10 +392,10 @@ internal static List GetConstructedSavedShipItemData(Dictiona string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName; - List shipGrabbableItemIDs = null; - List shipGrabbableItemPos = null; - List shipScrapValues = null; - List shipItemSaveData = null; + List shipGrabbableItemIDs; + List shipGrabbableItemPos; + List shipScrapValues; + List shipItemSaveData; if (ES3.KeyExists("shipGrabbableItemIDs", currentSaveFileName)) shipGrabbableItemIDs = ES3.Load("shipGrabbableItemIDs", currentSaveFileName).ToList(); diff --git a/LethalLevelLoader/Patches/TerminalManager.cs b/LethalLevelLoader/Patches/TerminalManager.cs index 731e3fb..10c709c 100644 --- a/LethalLevelLoader/Patches/TerminalManager.cs +++ b/LethalLevelLoader/Patches/TerminalManager.cs @@ -12,7 +12,7 @@ namespace LethalLevelLoader { public class TerminalManager { - private static Terminal _terminal; + private static Terminal? _terminal; internal static Terminal Terminal { get @@ -24,30 +24,30 @@ internal static Terminal Terminal } } - internal static TerminalNode lockedNode; + internal static TerminalNode lockedNode = null!; - public static MoonsCataloguePage defaultMoonsCataloguePage { get; internal set; } - public static MoonsCataloguePage currentMoonsCataloguePage { get; internal set; } + public static MoonsCataloguePage defaultMoonsCataloguePage { get; internal set; } = null!; + public static MoonsCataloguePage currentMoonsCataloguePage { get; internal set; } = null!; //Cached References To Important Base-Game TerminalKeywords; - internal static TerminalKeyword routeKeyword; - internal static TerminalKeyword routeInfoKeyword; - internal static TerminalKeyword routeConfirmKeyword; - internal static TerminalKeyword routeDenyKeyword; - internal static TerminalKeyword moonsKeyword; - internal static TerminalKeyword viewKeyword; - internal static TerminalKeyword buyKeyword; - internal static TerminalNode cancelRouteNode; - internal static TerminalNode cancelPurchaseNode; - - internal static string currentTagFilter; + internal static TerminalKeyword routeKeyword = null!; + internal static TerminalKeyword routeInfoKeyword = null!; + internal static TerminalKeyword routeConfirmKeyword = null!; + internal static TerminalKeyword routeDenyKeyword = null!; + internal static TerminalKeyword moonsKeyword = null!; + internal static TerminalKeyword viewKeyword = null!; + internal static TerminalKeyword buyKeyword = null!; + internal static TerminalNode cancelRouteNode = null!; + internal static TerminalNode cancelPurchaseNode = null!; + + internal static string currentTagFilter = null!; internal static float defaultTerminalFontSize; - internal static TerminalKeyword lastParsedVerbKeyword; + internal static TerminalKeyword? lastParsedVerbKeyword; public delegate string PreviewInfoText(ExtendedLevel extendedLevel, PreviewInfoType infoType); - public static event PreviewInfoText onBeforePreviewInfoTextAdded; + public static event PreviewInfoText? onBeforePreviewInfoTextAdded; //internal static Dictionary> terminalNodeRegisteredEventDictionary = new Dictionary>(); @@ -371,7 +371,7 @@ public static string GetExtendedLevelPreviewInfo(ExtendedLevel extendedLevel) if (extendedLevel.IsRouteLocked == true) levelPreviewInfo += " (Locked)"; - string overridePreviewInfo = onBeforePreviewInfoTextAdded?.Invoke(extendedLevel, Settings.levelPreviewInfoType); + string? overridePreviewInfo = onBeforePreviewInfoTextAdded?.Invoke(extendedLevel, Settings.levelPreviewInfoType); if (overridePreviewInfo != null && overridePreviewInfo != string.Empty) levelPreviewInfo = overridePreviewInfo; @@ -391,7 +391,7 @@ public static string GetWeatherConditions(ExtendedLevel extendedLevel) public static string GetHistoryConditions(ExtendedLevel extendedLevel) { - DayHistory dayHistory = null; + DayHistory? dayHistory = null; foreach (DayHistory loggedDayHistory in LevelManager.dayHistoryList) if (loggedDayHistory.extendedLevel == extendedLevel) @@ -465,9 +465,9 @@ public static string GetOffsetExtendedLevelName(ExtendedLevel extendedLevel) return returnString; } - internal static TerminalKeyword TryFindAlternativeNoun(Terminal terminal, TerminalKeyword foundKeyword, string playerInput) + internal static TerminalKeyword? TryFindAlternativeNoun(Terminal terminal, TerminalKeyword? foundKeyword, string playerInput) { - if (foundKeyword != null & terminal.hasGottenVerb == false && foundKeyword.isVerb == true) + if (foundKeyword != null && terminal.hasGottenVerb == false && foundKeyword.isVerb == true) lastParsedVerbKeyword = foundKeyword; if (foundKeyword != null && foundKeyword.isVerb == false && terminal.hasGottenVerb == true && lastParsedVerbKeyword != null) @@ -775,10 +775,11 @@ internal static void CreateItemTerminalData(ExtendedItem extendedItem) terminalNodeBuyConfirm.maxCharactersToType = 35; terminalNodeBuyConfirm.buyItemIndex = buyableItemIndex; terminalNodeBuyConfirm.isConfirmationNode = false; + terminalNodeBuyConfirm.playSyncedClip = 0; } //Terminal Info Node - TerminalNode terminalNodeInfo = null; + TerminalNode? terminalNodeInfo = null; if (!string.IsNullOrEmpty(extendedItem.OverrideInfoNodeDescription)) { if (extendedItem.BuyInfoNode != null) @@ -814,12 +815,14 @@ internal static void CreateEnemyTypeTerminalData(ExtendedEnemyType extendedEnemy TerminalKeyword newEnemyInfoKeyword = CreateNewTerminalKeyword(); newEnemyInfoKeyword.name = extendedEnemyType.name + "BestiaryKeyword"; newEnemyInfoKeyword.word = extendedEnemyType.EnemyDisplayName.ToLower(); + newEnemyInfoKeyword.defaultVerb = routeInfoKeyword; TerminalNode newEnemyInfoNode = CreateNewTerminalNode(); newEnemyInfoNode.name = extendedEnemyType.name + "BestiaryNode"; newEnemyInfoNode.displayText = extendedEnemyType.InfoNodeDescription; newEnemyInfoNode.creatureFileID = extendedEnemyType.EnemyID; newEnemyInfoNode.creatureName = extendedEnemyType.EnemyDisplayName; + newEnemyInfoNode.playSyncedClip = 2; if (extendedEnemyType.InfoNodeVideoClip != null) { @@ -862,6 +865,7 @@ internal static void CreateBuyableVehicleTerminalData(ExtendedBuyableVehicle ext newVehicleBuyConfirmNode.buyVehicleIndex = extendedBuyableVehicle.VehicleID; newVehicleBuyConfirmNode.clearPreviousText = true; newVehicleBuyConfirmNode.maxCharactersToType = 35; + newVehicleBuyConfirmNode.playSyncedClip = 0; newVehicleBuyConfirmNode.displayText = "Ordered the " + extendedBuyableVehicle.BuyableVehicle.vehicleDisplayName + ". Your new balance is [playerCredits]." + "\n\n" + "We are so confident in the quality of this product, it comes with a life-time warranty! If your " + extendedBuyableVehicle.BuyableVehicle.vehicleDisplayName + " is lost or destroyed, you can get one free replacement. Items cannot be purchased while the vehicle is en route." + "\n\n"; @@ -931,16 +935,20 @@ internal static List CreateTerminalEventNodes(string newVerbKeywor return (CreateTerminalEventNodes(newVerbKeywordWord, convertedList)); } - internal static List CreateTerminalEventNodes(string newVerbKeywordWord, List nounWords, List terminalEventStrings = null, bool createNewVerbKeyword = true) + internal static List CreateTerminalEventNodes(string newVerbKeywordWord, List nounWords, List? terminalEventStrings = null, bool createNewVerbKeyword = true) { List newTerminalNodes = new List(); - TerminalKeyword verbKeyword = null; + TerminalKeyword? verbKeyword = null; if (createNewVerbKeyword == true) verbKeyword = CreateNewTerminalKeyword(); else foreach (TerminalKeyword terminalKeyword in Terminal.terminalNodes.allKeywords) if (terminalKeyword.isVerb == true && terminalKeyword.word == newVerbKeywordWord.ToLower()) - verbKeyword = terminalKeyword; + verbKeyword = terminalKeyword; + + if (verbKeyword == null) // Should this throw? I left the possible NRE where it was, but with a clear message. + throw new NullReferenceException($"A new 'VerbKeyword' was not created, and an existing verb called '{newVerbKeywordWord}' wasn't found!"); + verbKeyword.word = newVerbKeywordWord.ToLower(); verbKeyword.name = newVerbKeywordWord.ToLower() + "Keyword"; verbKeyword.isVerb = true; diff --git a/LethalLevelLoader/Patches/WeatherManager.cs b/LethalLevelLoader/Patches/WeatherManager.cs index c361ac0..664b91f 100644 --- a/LethalLevelLoader/Patches/WeatherManager.cs +++ b/LethalLevelLoader/Patches/WeatherManager.cs @@ -9,7 +9,7 @@ namespace LethalLevelLoader { internal class WeatherManager { - public static ExtendedWeatherEffect CurrentExtendedWeatherEffect; + public static ExtendedWeatherEffect? CurrentExtendedWeatherEffect; // temporarily marked as nullable since no usage public static Dictionary vanillaExtendedWeatherEffectsDictionary = new Dictionary(); @@ -111,7 +111,7 @@ public static ExtendedWeatherEffect GetVanillaExtendedWeatherEffect(LevelWeather if (extendedWeatherEffect.BaseWeatherType == levelWeatherType) return (extendedWeatherEffect); - return (null); + return (null!); } } } diff --git a/LethalLevelLoader/Plugin.cs b/LethalLevelLoader/Plugin.cs index 9bd88e4..1f1d6d3 100644 --- a/LethalLevelLoader/Plugin.cs +++ b/LethalLevelLoader/Plugin.cs @@ -1,4 +1,5 @@ using BepInEx; +using BepInEx.Bootstrap; using BepInEx.Configuration; using DunGen; using HarmonyLib; @@ -10,32 +11,33 @@ using Unity.Netcode; using UnityEngine; using UnityEngine.Device; +using UnityEngine.Rendering; using UnityEngine.SceneManagement; using Application = UnityEngine.Application; namespace LethalLevelLoader { [BepInPlugin(ModGUID, ModName, ModVersion)] - [BepInDependency(LethalLib.Plugin.ModGUID)] + [BepInDependency(LethalLib.Plugin.ModGUID, BepInDependency.DependencyFlags.SoftDependency)] [BepInDependency(LethalModDataLib.PluginInfo.PLUGIN_GUID)] public class Plugin : BaseUnityPlugin { public const string ModGUID = "imabatby.lethallevelloader"; public const string ModName = "LethalLevelLoader"; - public const string ModVersion = "1.3.0"; + public const string ModVersion = "1.3.8"; - internal static Plugin Instance; + internal static Plugin Instance = null!; - internal static AssetBundle MainAssets; + internal static AssetBundle? MainAssets; internal static readonly Harmony Harmony = new Harmony(ModGUID); - internal static BepInEx.Logging.ManualLogSource logger; + internal static BepInEx.Logging.ManualLogSource logger = null!; - public static event Action onBeforeSetup; - public static event Action onSetupComplete; + public static event Action? onBeforeSetup; + public static event Action? onSetupComplete; public static bool IsSetupComplete { get; private set; } = false; - internal static GameObject networkManagerPrefab; + internal static GameObject? networkManagerPrefab; private void Awake() { @@ -46,32 +48,34 @@ private void Awake() Logger.LogInfo($"LethalLevelLoader loaded!!"); + //We do this here to try and assure this doesn't accidently catch anything from any AssetBundles + LevelLoader.vanillaWaterShader = Shader.Find("Shader Graphs/WaterShaderHDRP"); + if (LevelLoader.vanillaWaterShader == null) + DebugHelper.LogError("Could Not Find Water Shader", DebugType.User); + Harmony.PatchAll(typeof(LethalLevelLoaderNetworkManager)); Harmony.PatchAll(typeof(DungeonLoader)); Harmony.PatchAll(typeof(Patches)); Harmony.PatchAll(typeof(EventPatches)); Harmony.PatchAll(typeof(SafetyPatches)); + + TrySoftPatch(LethalLib.Plugin.ModGUID, typeof(LethalLibPatches)); NetworkScenePatcher.Patch(); Patches.InitMonoModHooks(); NetcodePatch(); - //AssetBundleLoader.LoadBundles(); - //AssetBundleLoader.Instance.pluginInstace = this; - - GameObject test = new GameObject("LethalLevelLoader AssetBundleLoader"); - test.AddComponent().LoadBundles(); + GameObject assetBundleLoaderObject = new GameObject("LethalLevelLoader AssetBundleLoader"); + assetBundleLoaderObject.AddComponent().LoadBundles(); if (Application.isEditor) - DontDestroyOnLoad(test); + DontDestroyOnLoad(assetBundleLoaderObject); else - test.hideFlags = HideFlags.HideAndDontSave; + assetBundleLoaderObject.hideFlags = HideFlags.HideAndDontSave; AssetBundleLoader.onBundlesFinishedLoading += AssetBundleLoader.LoadContentInBundles; ConfigLoader.BindGeneralConfigs(); - - //UnityEngine.Object.FindFirstObjectByType() } internal static void OnBeforeSetupInvoke() @@ -106,8 +110,18 @@ private void NetcodePatch() } catch { - DebugHelper.Log("NetcodePatcher did a big fucksie wuckise!", DebugType.Developer); + DebugHelper.LogError("NetcodePatcher Failed! This Is Very Bad.", DebugType.Developer); + } + } + + internal static void TrySoftPatch(string pluginName, Type type) + { + if (Chainloader.PluginInfos.ContainsKey(pluginName)) + { + Harmony.CreateClassProcessor(type, true).Patch(); + DebugHelper.Log(pluginName + "found, enabling compatability patches.", DebugType.User); } + } } } \ No newline at end of file diff --git a/LethalLevelLoader/Tools/AssetBundleLoader.cs b/LethalLevelLoader/Tools/AssetBundleLoader.cs index db04ef3..be275de 100644 --- a/LethalLevelLoader/Tools/AssetBundleLoader.cs +++ b/LethalLevelLoader/Tools/AssetBundleLoader.cs @@ -23,22 +23,22 @@ namespace LethalLevelLoader { public class AssetBundleLoader : MonoBehaviour { - public static AssetBundleLoader Instance; + public static AssetBundleLoader Instance = null!; - internal Plugin pluginInstace; + internal Plugin? pluginInstace; public const string specifiedFileExtension = "*.lethalbundle"; internal static DirectoryInfo lethalLibFile = new DirectoryInfo(Assembly.GetExecutingAssembly().Location); - internal static DirectoryInfo lethalLibFolder; - internal static DirectoryInfo pluginsFolder; + internal static DirectoryInfo lethalLibFolder = null!; + internal static DirectoryInfo pluginsFolder = null!; internal static Dictionary obtainedExtendedModsDictionary = new Dictionary(); public enum LoadingStatus { Inactive, Loading, Complete }; public static LoadingStatus CurrentLoadingStatus { get; internal set; } = LoadingStatus.Inactive; - internal static Dictionary assetBundles = new Dictionary(); + internal static Dictionary assetBundles = new Dictionary(); internal static Dictionary assetBundleLoadTimes = new Dictionary(); internal static Dictionary>> onLethalBundleLoadedRequestDictionary = new Dictionary>>(); @@ -49,7 +49,7 @@ internal static bool HaveBundlesFinishedLoading get { bool bundlesFinishedLoading = true; - foreach (KeyValuePair assetBundle in assetBundles) + foreach (KeyValuePair assetBundle in assetBundles) if (assetBundle.Value == null) bundlesFinishedLoading = false; return (bundlesFinishedLoading); @@ -61,7 +61,7 @@ internal static int BundlesFinishedLoadingCount get { int bundlesFinishedLoading = 0; - foreach (KeyValuePair assetBundle in assetBundles) + foreach (KeyValuePair assetBundle in assetBundles) if (assetBundle.Value != null) bundlesFinishedLoading++; return (bundlesFinishedLoading); @@ -69,12 +69,12 @@ internal static int BundlesFinishedLoadingCount } public delegate void BundlesFinishedLoading(); - public static event BundlesFinishedLoading onBundlesFinishedLoading; + public static event BundlesFinishedLoading? onBundlesFinishedLoading; public delegate void BundleFinishedLoading(AssetBundle assetBundle); - public static event BundleFinishedLoading onBundleFinishedLoading; + public static event BundleFinishedLoading? onBundleFinishedLoading; - internal static TextMeshProUGUI loadingBundlesHeaderText; + internal static TextMeshProUGUI? loadingBundlesHeaderText; internal static bool noBundlesFound = false; @@ -123,13 +123,16 @@ internal void LoadBundles() int counter = 0; foreach (string file in Directory.GetFiles(pluginsFolder.FullName, specifiedFileExtension, SearchOption.AllDirectories)) { - counter++; FileInfo fileInfo = new FileInfo(file); - assetBundles.Add(fileInfo.Name, null); - UpdateLoadingBundlesHeaderText(null); - - //preInitSceneScript.StartCoroutine(Instance.LoadBundle(file, fileInfo.Name)); - this.StartCoroutine(Instance.LoadBundle(file, fileInfo.Name)); + if (!assetBundles.ContainsKey(fileInfo.Name)) + { + counter++; + assetBundles.Add(fileInfo.Name, null); + UpdateLoadingBundlesHeaderText(null); + StartCoroutine(Instance.LoadBundle(file, fileInfo.Name)); + } + else + DebugHelper.LogError("Failed To Load Lethalbundle: " + fileInfo.Name + ". A Lethalbundle with an indentical name has already been found.", DebugType.User); } if (counter == 0) { @@ -209,7 +212,7 @@ internal static void RegisterExtendedMod(ExtendedMod extendedMod) { DebugHelper.Log("Found ExtendedMod: " + extendedMod.name, DebugType.User); extendedMod.ModNameAliases.Add(extendedMod.ModName); - ExtendedMod matchingExtendedMod = null; + ExtendedMod? matchingExtendedMod = null; foreach (ExtendedMod registeredExtendedMod in obtainedExtendedModsDictionary.Values) { if (extendedMod.ModMergeSetting == ModMergeSetting.MatchingModName && registeredExtendedMod.ModMergeSetting == ModMergeSetting.MatchingModName) @@ -281,7 +284,7 @@ public static void AddOnLethalBundleLoadedListener(Action invokedFu } } - public static void AddOnExtendedModLoadedListener(Action invokedFunction, string extendedModAuthorName = null, string extendedModModName = null) + public static void AddOnExtendedModLoadedListener(Action invokedFunction, string? extendedModAuthorName = null, string? extendedModModName = null) { if (invokedFunction != null && !string.IsNullOrEmpty(extendedModAuthorName)) { @@ -319,7 +322,7 @@ internal static void OnBundlesFinishedLoading() foreach (KeyValuePair>> kvp in onLethalBundleLoadedRequestDictionary) if (assetBundles.ContainsKey(kvp.Key)) foreach (Action action in kvp.Value) - action(assetBundles[kvp.Key]); + action(assetBundles[kvp.Key]!); foreach (KeyValuePair>> kvp in onExtendedModLoadedRequestDictionary) foreach (ExtendedMod extendedMod in PatchedContent.ExtendedMods) @@ -337,7 +340,7 @@ internal static void RegisterNewExtendedContent(ExtendedContent extendedContent, return; } - ExtendedMod extendedMod = null; + ExtendedMod? extendedMod = null; if (extendedContent is ExtendedLevel extendedLevel) { if (string.IsNullOrEmpty(extendedLevel.contentSourceName)) @@ -419,7 +422,7 @@ internal static void LoadContentInBundles() { foundExtendedLevelScene = false; string debugString = "Could Not Find Scene File For ExtendedLevel: " + extendedLevel.SelectableLevel.name + ", Unregistering Early. \nSelectable Scene Name Is: " + extendedLevel.SelectableLevel.sceneName + ". Scenes Found In Bundles Are: " + "\n"; - foreach (KeyValuePair assetBundle in assetBundles) + foreach (KeyValuePair assetBundle in assetBundles) if (assetBundle.Value != null && assetBundle.Value.isStreamedSceneAssetBundle) foreach (string scenePath in assetBundle.Value.GetAllScenePaths()) { @@ -604,7 +607,7 @@ internal static void CreateVanillaExtendedWeatherEffects(StartOfRound startOfRou internal static void CreateVanillaExtendedDungeonFlow(DungeonFlow dungeonFlow) { - AudioClip firstTimeDungeonAudio = null; + AudioClip? firstTimeDungeonAudio = null; string dungeonDisplayName = string.Empty; if (dungeonFlow.name.Contains("Level1")) @@ -702,13 +705,13 @@ internal static void NetworkRegisterDungeonContent(ExtendedDungeonFlow extendedD internal static void SetVanillaLevelTags(ExtendedLevel vanillaLevel) { foreach (IntWithRarity intWithRarity in vanillaLevel.SelectableLevel.dungeonFlowTypes) - if (DungeonManager.TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonFlowTypes[intWithRarity.id].dungeonFlow, out ExtendedDungeonFlow extendedDungeonFlow)) + if (DungeonManager.TryGetExtendedDungeonFlow(Patches.RoundManager.dungeonFlowTypes[intWithRarity.id].dungeonFlow, out ExtendedDungeonFlow? extendedDungeonFlow)) extendedDungeonFlow.LevelMatchingProperties.planetNames.Add(new StringWithRarity(vanillaLevel.NumberlessPlanetName, intWithRarity.rarity)); if (vanillaLevel.SelectableLevel.sceneName == "Level4March") foreach (IndoorMapType indoorMapType in Patches.RoundManager.dungeonFlowTypes) if (indoorMapType.dungeonFlow.name == "Level1Flow3Exits") - if (DungeonManager.TryGetExtendedDungeonFlow(indoorMapType.dungeonFlow, out ExtendedDungeonFlow marchDungeonFlow)) + if (DungeonManager.TryGetExtendedDungeonFlow(indoorMapType.dungeonFlow, out ExtendedDungeonFlow? marchDungeonFlow)) marchDungeonFlow.LevelMatchingProperties.planetNames.Add(new StringWithRarity(vanillaLevel.NumberlessPlanetName, 300)); foreach (CompatibleNoun infoNoun in TerminalManager.routeInfoKeyword.compatibleNouns) @@ -753,7 +756,7 @@ internal static void CreateLoadingBundlesHeaderText(PreInitSceneScript preInitSc } - internal static void UpdateLoadingBundlesHeaderText(AssetBundle _) + internal static void UpdateLoadingBundlesHeaderText(AssetBundle? _) { if (loadingBundlesHeaderText != null) { diff --git a/LethalLevelLoader/Tools/ConfigLoader.cs b/LethalLevelLoader/Tools/ConfigLoader.cs index 95289cf..9a42515 100644 --- a/LethalLevelLoader/Tools/ConfigLoader.cs +++ b/LethalLevelLoader/Tools/ConfigLoader.cs @@ -14,7 +14,7 @@ internal static class ConfigLoader { public static string debugLevelsString = string.Empty; public static string debugDungeonsString = string.Empty; - public static ConfigFile configFile; + public static ConfigFile configFile = null!; internal static void BindConfigs() { @@ -74,14 +74,14 @@ internal static string GetConfigCategory(string categoryName, string contentName public class GeneralSettingsConfig : ConfigTemplate { - private ConfigEntry previewInfoTypeToggle; - private ConfigEntry sortInfoTypeToggle; - private ConfigEntry filterInfoTypeToggle; - private ConfigEntry simulateInfoTypeToggle; - private ConfigEntry debugTypeToggle; + private ConfigEntry previewInfoTypeToggle = null!; + private ConfigEntry sortInfoTypeToggle = null!; + private ConfigEntry filterInfoTypeToggle = null!; + private ConfigEntry simulateInfoTypeToggle = null!; + private ConfigEntry debugTypeToggle = null!; - private ConfigEntry moonsCatalogueSplitCount; - private ConfigEntry requireMatchesOnAllDungeonFlows; + private ConfigEntry moonsCatalogueSplitCount = null!; + private ConfigEntry requireMatchesOnAllDungeonFlows = null!; public GeneralSettingsConfig(ConfigFile newConfigFile, string newCategory, int newSortingPriority) : base(newConfigFile, newCategory, newSortingPriority) { } @@ -113,20 +113,20 @@ public void BindConfigs() public class ExtendedDungeonConfig : ConfigTemplate { - public ConfigEntry enableContentConfiguration; + public ConfigEntry enableContentConfiguration = null!; - public ConfigEntry manualLevelNames; - public ConfigEntry manualModNames; + public ConfigEntry? manualLevelNames; + public ConfigEntry? manualModNames; - public ConfigEntry enableDynamicDungeonSizeRestriction; - public ConfigEntry minimumDungeonSizeMultiplier; - public ConfigEntry maximumDungeonSizeMultiplier; - public ConfigEntry restrictDungeonSizeScaler; + public ConfigEntry? enableDynamicDungeonSizeRestriction; + public ConfigEntry? minimumDungeonSizeMultiplier; + public ConfigEntry? maximumDungeonSizeMultiplier; + public ConfigEntry? restrictDungeonSizeScaler; - public ConfigEntry dynamicLevelTags; - public ConfigEntry dynamicRoutePrices; + public ConfigEntry? dynamicLevelTags; + public ConfigEntry? dynamicRoutePrices; - public ConfigEntry disabledWarning; + public ConfigEntry? disabledWarning; public ExtendedDungeonConfig(ConfigFile newConfigFile, string newCategory, int sortingPriority) : base(newConfigFile, newCategory, sortingPriority) { } @@ -194,33 +194,33 @@ public void BindConfigs(ExtendedDungeonFlow extendedDungeonFlow) public class ExtendedLevelConfig : ConfigTemplate { //General - public ConfigEntry enableContentConfiguration; + public ConfigEntry enableContentConfiguration = null!; - public ConfigEntry routePrice; - public ConfigEntry daySpeedMultiplier; - public ConfigEntry doesPlanetHaveTime; - public ConfigEntry isLevelHidden; - public ConfigEntry isLevelRegistered; + public ConfigEntry? routePrice; + public ConfigEntry? daySpeedMultiplier; + public ConfigEntry? doesPlanetHaveTime; + public ConfigEntry? isLevelHidden; + public ConfigEntry? isLevelRegistered; //Scrap - public ConfigEntry minScrapItemSpawns; - public ConfigEntry maxScrapItemSpawns; + public ConfigEntry? minScrapItemSpawns; + public ConfigEntry? maxScrapItemSpawns; - public ConfigEntry minTotalScrapValue; - public ConfigEntry maxTotalScrapValue; + public ConfigEntry? minTotalScrapValue; + public ConfigEntry? maxTotalScrapValue; - public ConfigEntry scrapOverrides; + public ConfigEntry? scrapOverrides; //Enemies - public ConfigEntry maxInsideEnemyPowerCount; - public ConfigEntry maxOutsideDaytimeEnemyPowerCount; - public ConfigEntry maxOutsideNighttimeEnemyPowerCount; + public ConfigEntry? maxInsideEnemyPowerCount; + public ConfigEntry? maxOutsideDaytimeEnemyPowerCount; + public ConfigEntry? maxOutsideNighttimeEnemyPowerCount; - public ConfigEntry insideEnemiesOverrides; - public ConfigEntry outsideDaytimeEnemiesOverrides; - public ConfigEntry outsideNighttimeEnemiesOverrides; + public ConfigEntry? insideEnemiesOverrides; + public ConfigEntry? outsideDaytimeEnemiesOverrides; + public ConfigEntry? outsideNighttimeEnemiesOverrides; - public ConfigEntry disabledWarning; + public ConfigEntry? disabledWarning; public ExtendedLevelConfig(ConfigFile newConfigFile, string newCategory, int sortingPriority) : base(newConfigFile, newCategory, sortingPriority) { } diff --git a/LethalLevelLoader/Tools/ContentExtractor.cs b/LethalLevelLoader/Tools/ContentExtractor.cs index 5640940..568e4e2 100644 --- a/LethalLevelLoader/Tools/ContentExtractor.cs +++ b/LethalLevelLoader/Tools/ContentExtractor.cs @@ -39,17 +39,16 @@ internal static void TryScrapeVanillaContent(StartOfRound startOfRound, RoundMan { if (Plugin.IsSetupComplete == false) { - if (startOfRound != null) - { - foreach (IndoorMapType indoorFlowType in roundManager.dungeonFlowTypes) - TryAddReference(OriginalContent.DungeonFlows, indoorFlowType.dungeonFlow); + + foreach (IndoorMapType indoorFlowType in roundManager.dungeonFlowTypes) + TryAddReference(OriginalContent.DungeonFlows, indoorFlowType.dungeonFlow); - foreach (SelectableLevel selectableLevel in startOfRound.levels) - ExtractSelectableLevelReferences(selectableLevel); + foreach (SelectableLevel selectableLevel in startOfRound.levels) + ExtractSelectableLevelReferences(selectableLevel); - foreach (IndoorMapType indoorFlowType in roundManager.dungeonFlowTypes) - ExtractDungeonFlowReferences(indoorFlowType.dungeonFlow); - } + foreach (IndoorMapType indoorFlowType in roundManager.dungeonFlowTypes) + ExtractDungeonFlowReferences(indoorFlowType.dungeonFlow); + if (TerminalManager.Terminal.currentNode != null) TryAddReference(OriginalContent.TerminalNodes, TerminalManager.Terminal.currentNode); diff --git a/LethalLevelLoader/Tools/ContentRestorer.cs b/LethalLevelLoader/Tools/ContentRestorer.cs index c7a14c3..f1cf2ab 100644 --- a/LethalLevelLoader/Tools/ContentRestorer.cs +++ b/LethalLevelLoader/Tools/ContentRestorer.cs @@ -5,6 +5,7 @@ using System.Text; using UnityEngine; using UnityEngine.Audio; +using UnityEngine.Rendering; using Object = UnityEngine.Object; namespace LethalLevelLoader.Tools @@ -60,7 +61,7 @@ internal static void RestoreVanillaLevelAssetReferences(ExtendedLevel extendedLe foreach (EnemyType vanillaEnemyType in OriginalContent.Enemies) foreach (SpawnableEnemyWithRarity enemyRarityPair in extendedLevel.SelectableLevel.Enemies.Concat(extendedLevel.SelectableLevel.DaytimeEnemies).Concat(extendedLevel.SelectableLevel.OutsideEnemies)) - if (enemyRarityPair.enemyType != null && enemyRarityPair.enemyType.enemyName == vanillaEnemyType.enemyName) + if (enemyRarityPair.enemyType != null && !string.IsNullOrEmpty(enemyRarityPair.enemyType.name) && enemyRarityPair.enemyType.name == vanillaEnemyType.name) enemyRarityPair.enemyType = RestoreAsset(enemyRarityPair.enemyType, vanillaEnemyType); foreach (SpawnableMapObject spawnableMapObject in extendedLevel.SelectableLevel.spawnableMapObjects) @@ -125,8 +126,8 @@ internal static void TryRestoreAudioSource(AudioSource audioSource) AudioMixerGroup targetMixerGroup = audioSource.outputAudioMixerGroup; AudioMixer targetMixer = audioSource.outputAudioMixerGroup.audioMixer; - AudioMixerGroup restoredMixerGroup = null; - AudioMixer restoredMixer = null; + AudioMixerGroup? restoredMixerGroup = null; + AudioMixer? restoredMixer = null; foreach (AudioMixer vanillaMixer in OriginalContent.AudioMixers) if (targetMixer.name == vanillaMixer.name) @@ -157,6 +158,24 @@ internal static void DestroyRestoredAssets(bool debugAction = false) objectsToDestroy.Clear(); } + internal static void TryRestoreWaterShader(Material customMaterial) + { + if (customMaterial == null || customMaterial.shader == null || string.IsNullOrEmpty(customMaterial.shader.name)) + return; + + if (customMaterial.shader == LevelLoader.vanillaWaterShader) + return; + + if (customMaterial.shader.name == LevelLoader.vanillaWaterShader.name) + { + customMaterial.shader = LevelLoader.vanillaWaterShader; + customMaterial.DisableKeyword("_BLENDMODE_ALPHA"); + customMaterial.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); + customMaterial.EnableKeyword("_ENABLE_FOG_ON_TRANSPARENT"); + customMaterial.EnableKeyword("_DISABLE_SSR_TRANSPARENT"); + } + } + internal static T RestoreAsset(UnityEngine.Object currentAsset, T newAsset, bool debugAction = false, bool destroyOnReplace = true) { diff --git a/LethalLevelLoader/Tools/DebugHelper.cs b/LethalLevelLoader/Tools/DebugHelper.cs index da6bf3d..8c21fa5 100644 --- a/LethalLevelLoader/Tools/DebugHelper.cs +++ b/LethalLevelLoader/Tools/DebugHelper.cs @@ -653,6 +653,32 @@ public static void DebugAllContentTags() } } + public static void DebugCachedLevelColliderData() + { + string debugString = "Cached Level Collider-Material Data" + "\n\n"; + + foreach (KeyValuePair> kvp in LevelLoader.cachedLevelColliderMaterialDictionary) + { + debugString += "\n" + "Collider: " + kvp.Key.gameObject.name + " - Materials: "; + foreach (Material material in kvp.Value) + { + debugString += material.name; + if (material != kvp.Value.Last()) + debugString += ", "; + } + } + + DebugHelper.Log(debugString, DebugType.User); + + debugString = "Cached Level Material-Collider Data" + "\n\n"; + + foreach (KeyValuePair> kvp in LevelLoader.cachedLevelMaterialColliderDictionary) + debugString += "\n" + kvp.Key+ " (" + kvp.Value.Count + ")"; + + DebugHelper.Log(debugString, DebugType.User); + + } + public static void LogDebugInstructionsFrom(CodeMatcher matcher) { var methodName = new StackTrace().GetFrame(1).GetMethod().Name; diff --git a/LethalLevelLoader/Tools/HookHelper.cs b/LethalLevelLoader/Tools/HookHelper.cs index 6498333..dca3191 100644 --- a/LethalLevelLoader/Tools/HookHelper.cs +++ b/LethalLevelLoader/Tools/HookHelper.cs @@ -10,13 +10,13 @@ internal static class HookHelper { public static MethodInfo methodof(Delegate method) => method.Method; - public static MethodInfo EzGetMethod(Type type, string name, Type[] parameters = null) + public static MethodInfo EzGetMethod(Type type, string name, Type[]? parameters = null) { BindingFlags query = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; if (parameters == null) return type.GetMethod(name, query); return type.GetMethod(name, query, null, parameters, null); } - public static MethodInfo EzGetMethod(string name, Type[] parameters = null) => EzGetMethod(typeof(T), name, parameters); + public static MethodInfo EzGetMethod(string name, Type[]? parameters = null) => EzGetMethod(typeof(T), name, parameters); public class DisposableHookCollection { @@ -36,11 +36,11 @@ public void Clear() } ilHooks.Clear(); } - public void ILHook(string methodName, ILContext.Manipulator to, Type[] parameters = null) + public void ILHook(string methodName, ILContext.Manipulator to, Type[]? parameters = null) { ilHooks.Add(new(EzGetMethod(methodName, parameters), to)); } - public void Hook(string methodName, Delegate to, Type[] parameters = null) + public void Hook(string methodName, Delegate to, Type[]? parameters = null) { hooks.Add(new(EzGetMethod(methodName, parameters), to)); } diff --git a/LethalLevelLoader/Tools/Validators.cs b/LethalLevelLoader/Tools/Validators.cs index 8881a96..8025573 100644 --- a/LethalLevelLoader/Tools/Validators.cs +++ b/LethalLevelLoader/Tools/Validators.cs @@ -98,6 +98,17 @@ public static (bool result, string log) ValidateExtendedContent(ExtendedWeatherE public static (bool result, string log) ValidateExtendedContent(ExtendedFootstepSurface extendedFootstepSurface) { + if (extendedFootstepSurface.footstepSurface == null) + return (false, "FootstepSurface Was Null"); + if (extendedFootstepSurface.associatedMaterials == null) + return (false, "Associated Materials List Was Null"); + if (extendedFootstepSurface.associatedMaterials.Count == 0) + return (false, "Associated Materials List Was Empty"); + if (extendedFootstepSurface.footstepSurface.clips == null) + return (false, "FootstepSurface Clips Array Was Null"); + if (extendedFootstepSurface.footstepSurface.clips.Length == 0) + return (false, "FootstepSurface Clips Array Was Empty"); + return (true, string.Empty); } diff --git a/LethalLevelLoader/VanillaContentTags/Enemies.csv b/LethalLevelLoader/VanillaContentTags/Enemies.csv index 20813bc..fa9b1e8 100644 --- a/LethalLevelLoader/VanillaContentTags/Enemies.csv +++ b/LethalLevelLoader/VanillaContentTags/Enemies.csv @@ -1,5 +1,5 @@ ,Is Automatically Applied:,No,No,No,No,No,No,No,No,No,No -Item Name,Total Tags,18,13,3,6,13,13,4,5,15,3 +Item Name,Total Tags,19,14,3,6,15,14,5,5,17,3 ,,Organic,Killable,Passive,Neutral,Hostile,Biped,Quadruped,Small,Medium,Large Baboon Hawk,5,Organic,Killable,,Neutral,,Biped,,,Medium, Bunker Spider,5,Organic,Killable,,Neutral,,,Quadruped,,Medium, @@ -23,4 +23,6 @@ Puffer,4,Organic,,,Neutral,,,Quadruped,,Medium, Crawler,5,Organic,Killable,,,Hostile,,Quadruped,,Medium, Butler,5,Organic,Killable,,,Hostile,Biped,,,Medium, Rad Mech,4,,Killable,,,Hostile,Biped,,,,Large -Tulip Snake,4,Organic,Killable,Passive,,,,,Small,, \ No newline at end of file +Tulip Snake,4,Organic,Killable,Passive,,,,,Small,, +Bush Wolf,5,Organic,Killable,,,Hostile,,Quadruped,,Medium, +Clay Surgeon,3,,,,,Hostile,Biped,,,Medium, \ No newline at end of file diff --git a/LethalLevelLoader/VanillaContentTags/Items.csv b/LethalLevelLoader/VanillaContentTags/Items.csv index cc522ab..8e60d18 100644 --- a/LethalLevelLoader/VanillaContentTags/Items.csv +++ b/LethalLevelLoader/VanillaContentTags/Items.csv @@ -1,5 +1,5 @@ ,Is Automatically Applied:,Yes,Yes,Yes,Yes,Yes,Yes,Yes,Yes,Yes,Yes,Yes,,Yes,Yes,,Yes,No,No,No,No,No,No,No,No,No,No,No,No -Item Name,Total Tags,13,51,41,26,27,5,20,56,9,10,39,25,3,26,24,3,29,21,13,10,7,5,5,4,3,0,3,3 +Item Name,Total Tags,14,51,41,27,27,5,21,57,9,10,40,25,3,26,24,3,29,21,13,10,8,5,5,4,3,0,3,3 ,,Buyable,Scrap,Non-Interactable,Interactable,Conductive,Chargable,Tool,One-Handed,Two-Handed,Noisy,Light-Weight,Medium-Weight,Heavy-Weight,Low-Value,Medium-Value,High-Value,Household,Metal,Harmful,Weapon,Consumable,Machine Part,Luminescent,Transportation,Communicative,Information,Natural,Beast Byproduct Airhorn,8,,Scrap,,Interactable,,,,One-Handed,,Noisy,Light-Weight,,,,Medium-Value,,Household,Metal,,,,,,,,,, Apparatus,9,,Scrap,Non-Interactable,,Conductive,,,,Two-Handed,,Light-Weight,,,,,High-Value,,Metal,,,,Machine Part,Luminescent,,,,, @@ -67,4 +67,5 @@ V-Type Engine,8,,Scrap,Non-Interactable,,Conductive,,,,Two-Handed,,,Medium-Weigh Walkie-Talkie,7,Buyable,,,Interactable,,Chargable,Tool,One-Handed,,,Light-Weight,,,,,,,,,,,,,,Communicative,,, Whoopie Cushion,8,,Scrap,Non-Interactable,,Conductive,,,One-Handed,,Noisy,Light-Weight,,,Low-Value,,,Household,,,,,,,,,,, Yield Sign,10,,Scrap,,Interactable,Conductive,,Tool,One-Handed,,,,Medium-Weight,,Low-Value,,,,Metal,Harmful,Weapon,,,,,,,, -Zap Gun,9,Buyable,,,Interactable,Conductive,Chargable,Tool,One-Handed,,,Light-Weight,,,,,,,,Harmful,Weapon,,,,,,,, \ No newline at end of file +Zap Gun,9,Buyable,,,Interactable,Conductive,Chargable,Tool,One-Handed,,,Light-Weight,,,,,,,,Harmful,Weapon,,,,,,,, +Weed Killer,6,Buyable,,,Interactable,,,Tool,One-Handed,,,Light-Weight,,,,,,,,,,Consumable,,,,,,, \ No newline at end of file diff --git a/README.md b/README.md index 625e6bd..69beeed 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ **Description** -- -### **1.2.0 for Lethal Company v50 Has Released!** +### **1.3.0 for Lethal Company v55 Has Released!** **LethalLevelLoader** is a custom API to support the manual and dynamic integration of custom levels and dungeons in Lethal Company. Mod Developers can provide LethalLevelLoader with their custom content via code or via automatic AssetBundle detection, and from there LethalLevelLoader will seamlessly load the content into the game. @@ -70,5 +70,6 @@ You should be now set up, and ready compile your fork of LethalLevelLoader on yo * **Maxwasunavailable** *(For creating LethalModDataLib and assisting me with it’s usage.)* * **Mrov** *(For collaborating with me on initial Custom weather support related code, assisting in fixes related to the Config file and a bunch of miscellaneous assistance.)* * **LadyRaphtalia**, **Xu Xiaolan**, **Badhamknibbs**, **Mrov**, **sfDesat**, **AboveFire**, **Autumnis The Everchanging**, **RosiePies**, **Drako** & **Audio Knight** *(For testing development on experimental 1.2.0 builds.)* -* **狐萝卜呀**, **tumbleweed**, **Corey**, **Ritskee**, **Altan**, **qxZap**, **Salamander**, **Chiseled Cactus**, **Phantom139**, **ImmaBawss**, **takeothewolf**, **zuzaratrust**, **Hackattack242**, **Mail Me Dabs**, **Kyros**, **SourceShard** & **Chupacabra** *(For playtesting and reporting bugs on experimental 1.2.0 builds.* -* **Lunxara** *For the heavy, rapid testing throughout all the experimental 1.2.0 builds.*) +* **狐萝卜呀**, **tumbleweed**, **Corey**, **Ritskee**, **Altan**, **qxZap**, **Salamander**, **Chiseled Cactus**, **Phantom139**, **ImmaBawss**, **takeothewolf**, **zuzaratrust**, **Hackattack242**, **Mail Me Dabs**, **Kyros**, **SourceShard** & **Chupacabra** *(For playtesting and reporting bugs on experimental 1.2.0 builds.)* +* **Lunxara** *(For the heavy, rapid testing throughout all the experimental 1.2.0 builds.)* +* **Adi**, **Hamunii**, **Xu Xiaolan & **Wherget** *F(or various new contributions in the forms of direct suggestions and pull requests.)* diff --git a/Thunderstore/CHANGELOG.md b/Thunderstore/CHANGELOG.md deleted file mode 100644 index 82ba4b7..0000000 --- a/Thunderstore/CHANGELOG.md +++ /dev/null @@ -1,494 +0,0 @@ -**Changelog** --- - -**
Version 1.3.0** - -**
Features** - -* Added initial version of ExtendedBuyableVehicle. - -
- -**
Fixes** - -* Updated mod for Lethal Company version 55 Beta 1. -* Changed ExtendedLevel's to now be sorted alphabetically to improve issues with desync. -* Fixed LevelEvents.onApparatusTaken and DungeonEvents.onApparatusTaken unintentionally running every time the Apparatus was equipped rather than only initially. - -
- -
- -**
Version 1.2.3** - -**
Fixes** - -* Fixed issue regarding routing to Company -* Changed ExtendedDungeonFlow.dungeonEvents to ExtendedDungeonFlow.DungeonEvents (Sorry to PoolRooms which likely needs an update) -* Changed TerminalNode parameters used in TerminalManager functions to be ref values (Possibly breaks mrov related mods) -* Added Custom EnemyTypes to debug spawn menus -* Potentially fixed issue where Custom EnemyType Beastiary TerminalNode's had default values -* Potentially fixed issues running the mod in editor by changing GameObject flags to a DontDestroyOnLoad call (Thanks nomnom) -* Fixed issue with mods with matching author and mod names not receiving requested calls (May break custom enemy and item mods with custom code) -* Potentially resolved issue with additional scenes listed in ExtendedLevel's not loading correctly -* Potentially resolved issue with Route locking and hiding -* Implemented @Sylvi's Better Item Saving pull request (Thanks for the help and sorry for the delay) -* Added onShipLand and onShipLeave to ExtendedLevel and ExtendedDungeonFlow events - -
- -
- -**
Version 1.2.2** - -**
Fixes** - -* Fixed issue where vanilla items were being incorrectly destroyed when playing multiple lobbies during the same game session -* Restored functionality of the ExtendedLevel.IsRouteLocked feature -* Added safety check to help prevent saves made in pre 1.2.0 LethalLevelLoader modpacks from corrupting when being used -* Fixed issues with ExtendedDungeonFlow.DynamicDungeonSize related settings incorrectly applying after version 50 changes -* Removed ExtendedMod.ContentTagAsStrings() function -* Added ExtendedMod.TryGetTag(string tag) function -* Added ExtendedMod.TryGetTag(string tag, out ContentTag contentTag) function -* Added ExtendedMod.TryAddTag(string tag) function - -
- -
- -**
Version 1.2.1** - -**
Fixes** - -* Updated LICENSE -* Changed accessor for ExtendedDungeonFlow.GenerateAutomaticConfigurationOptions from internal to public -* Fixed issue where ExtendedDungeonFlow.GenerationAutomaticConfigurationOptions was defaulting to false -* Changed accessor for EnemyManager.RefreshDynamicEnemyTypeRarityOnAllExtendedLevels from internal to public -* Changed accessor for EnemyManager.InjectCustomEnemyTypesIntoLevelViaDynamicRarity from internal to public -* Changed accessor for ItemManager.RefreshDynamicItemRarityOnAllExtendedLevels from internal to public -* Changed accessor for ItemManager.InjectCustomItemsIntoLevelViaDynamicRarity from internal to public -* Changed ConfigLoader default dungeon binding to list current level matching values as default values -* Added "Killable" ContentTag to Forest Giant -* Added "Chargable" ContentTag to Jetpack -* Added "Weapon" ContentTag to Knife -* Added additional developer debug logging for the scene validation and selection process - -
- -
- - -**
Version 1.2.0** - -**
Features** - -* Updated mod for Lethal Company version 50 - -
General - -* Added ExtendedMod -* Added ExtendedEnemyType -* Added ExtendedItem -* Added ExtendedStoryLog -* Added ExtendedFootstepSurface (WIP) -* Added ExtendedWeatherEffect (WIP) -* Added LevelMatchingProperties -* Added DungeonMatchingProperties -* Added ContentTags - -* Added Global LevelEvents Instance (Thanks mrov) -* Added Global DungeonEvents Instance (Thanks mrov) -* Added IsSetupComplete bool for modders to reference. -* Added onBeforeSetup event for modders to reference -* Added onSetupComplete event for modders to reference -* Revamped DebugLogs and provided a configurable debuglog setting in the config to allow Users to only receive relevant logs by default. -* Moved AssetBundleLoading earlier to help speed up load time -* Revamped debug logs when trying to load a level or simulate the loading of a level -* Revamped Moons Catalogue display to split custom moons into groups similar to the basegame moon listings. -* Revamped Moons Catalogue display to order custom moon groups by average risk level -* Revamped Moons Catalogue display to order custom moons inside groups by risk level -* Revamped Moons Catalogue display to prefer to group custom moons created by the same author -* Revamped Moons Catalogue display to dynamically adjust font size depending on the amount of Moons being displayed -* Probably a lot more! - -
- -
ExtendedLevel - -* Added string value to allow Authors to use custom route node display text to their levels -* Added string value to allow Authors to use custom route confirmation node display text to their levels -By default SelectableLevel.riskLevel is now automatically assigned using calculations and comparisons of SelectableLevel values between both Custom and Vanilla levels. This can be manually overridden. -* Added an OverrideQuicksandPrefab value to allow authors to modify the Quicksand used on their level -* Added ShipFlyToMoonClip & ShipFlyFromMoonClip AnimationClip values to allow authors to modify the AnimationClips used when the Ship lands to and from their level (Currently disabled until bug is resolved with Unity Assetrip Fixer) -* Overhauled the way Scene’s are correlated with Levels by implementing a new weight based system built into ExtendedLevel to allow authors to randomly switch between multiple variant scenes for a single level. - -
- -
ExtendedDungeonFlow - -* Added an OverrideKeyPrefab value to allow authors to modify the Key prefab used in their Dungeon -* Added a MapTileSize value to allow authors to set a correlated MapTileSize value that is used in new basegame functions implemented in Version 50. -* Added a new SpawnableMapObjects list value to allow authors to inject custom RandomMapObjects in their Dungeon - -
- -
ExtendedItem - -* Custom Item support has now been added. -* Added a PluralisedItemName string value to allow developers to change how their item name is parsed when being referenced as a plural (eg. when buying multiple of them from the store) - -
- -
ExtendedEnemyType - -* Custom Enemy support has now been added. - -
- -
ExtendedStoryLog - -* Custom StoryLog support has now been added. - -
- -
ExtendedFootstepSurfaces - -* Custom FootstepSurface support has now been added. (Currently disabled) - -
- -
ExtendedWeatherEffect - -* Custom WeatherEffect support has now been added. (Currently disabled) - -
- -
ContentTags & MatchingProperties - -* Created integrated ContentTag system that allows developers to put relevant string tags on all types of custom content (with an optional correlating colour). Developers can access groups of content based on a specific content tag as well as match their content with other pieces of content dynamically using the built in LevelMatchingProperties and DungeonMatchingProperties. -* All Vanilla content has been manually assigned Content Tags to allow developers to reference vanilla content via tags the same way they would custom content, You can find those tags here: https://docs.google.com/spreadsheets/d/1WO77KGJplIEC64qmBClOgfEEoFxrhMurCEqe9FKod8I/edit?usp=sharing - - -
- -
- -**
Fixes** - -* Fixed switch Terminal command incorrectly working -* Fixed Weather selection desyncing -* Fixed Dungeon selection desyncing -* Fixed Config duplicating entities (Credit to mrov) -* Added safety checks to correctly save and restore previously selected route and prevent previous routes to disabled levels from breaking -* Added safety checks to prevent invalid Foggy weather level values from breaking the game -* Added safety checks to prevent Levels & Dungeons having incorrect SpawnableMapObject setups from breaking the game -* Added safety check to prevent level missing MapPropsContainer tagged object from breaking the game -* Added safety check to prevent level with .SpawnScrapAndEnemies enabled and no spawnable scrap listed from breaking the game -* Fixed LevelEvents & DungeonEvents EntranceTeleport events behaving incorrectly (credit to mrov) -* Added custom code to optimize specific internal code used in DunGen generation (Credit to LadyRaphtalia) -* Made LogDayHistory function safer to allow DunGen generation in editor while using LethalLevelLoader to correctly work -* Fixed issue where specific special items (Shotgun, Shells, Hive, Knife) were not being collected -* Fixed issue where LethalLevelLoader was destroying assets in mods with multiple levels before it could correctly restore all those references first -* Probably a lot more! - -
- -
- - -**
Version 1.1.0** - -**
Features** - -
Terminal >preview Keyword -* *LethalLevelLoader now has a new feature added to the Terminal which allows users to change what information is previewed adjacent to each Moon listed in the `MoonsCatalogue`. This can be toggled via the `preview` verb keyword followed by one of the following options. (LethalLevelLoader also includes a configuration option to set which information type is used by default.)* - -* * `preview weather` -* * `preview difficulty` -* * `preview history` -* * `preview all` -* * `preview none` -* * `preview vanilla` -
- - -
Terminal >sort Keyword -* *LethalLevelLoader now has a new feature added to the Terminal which allows users to decide how Moons are sorted when listed in the `MoonsCatalogue`. This can be toggled via the `sort` verb keyword followed by one of the following options. (LethalLevelLoader also includes a configuration option to set which sorting type is used by default.)* - -* * `sort price` -* * `sort difficulty` -* * `sort tag` -* * `sort quota` -* * `sort run` -* * `sort none` -
- -
Terminal >filter Keyword -* *LethalLevelLoader now has a new feature added to the Terminal which allows users to decide which Moons are listed in the `MoonsCatalogue`. This can be toggled via the `filter` verb keyword followed by one of the following options. (LethalLevelLoader also includes a configuration option to set which filtering type is used by default.)* - -* * `filter price` -* * `filter weather` -* * `filter tag` -* * `filter last travelled` -* * `filter none` -
- -
Terminal >simulate Keyword -* *LethalLevelLoader now has a new feature added to the Terminal which allows users to "Simulate" landing on a Moon. This provides a presentable, lore friendly way to view the possible `DungeonFlow` choices with accurate rarity via the Terminal. To use this feature, use `simulate` and a Moon's name, the same way you would use `route`. LethalLevelLoader now includes a configuration option to switch between viewing the `DungeonFlow`'s rarity via raw value or calculated percentage.* -
- -
LevelHistory -* *LethalLevelLoader now has an experimental `LevelHistory` feature that stores notable information regarding each day in the current save. This includes information such as the Level, DungeonFlow, Weather and more. This feature allows modders and future updates to LethalLevelLoader to create mechanics and systems dependant on the history of the current play session.* -
- -
ExtendedDungeonFlow: Host Decides DungeonFlow & DungeonSize -* *LethalLevelLoader now modifies the way Lethal Company selects the random `DungeonFlow` and it's dungeon size so only the Host client selects these values which is then sent to the remaining non host clients. This is to help prevent game-breaking dungeon desync when players have mismatching dungeon configuration settings.* -
- -
ExtendedDungeonFlow: Dynamic Weather Rarity Injection -* *ExtendedDungeonFlow's now contain a `StringWithRarity` list which allows dungeon developers to dynamically inject their dungeon into the current `SelectableLevel`'s possible `DungeonFlow` options.* -
- -
ExtendedDungeonFlow: GlobalProp Dynamic Scaling -* *ExtendedDungeonFlow's now contain a `GlobalPropCountOverride` list which allows dungeon developers to dynamically increase or increase a `GlobalProp`'s minimum and maximum values based on the currently used dungeon size.* -
- -
ExtendedLevel: MoonCataloguePages & ExtendedLevelGroups -* *LethalLevelLoader now completely overhauls how the `MoonsCatalogue` TerminalNode functions internally. `ExtendedLevel`'s are now stored in groups via a class named `ExtendedLevelGroup`, These `ExtendedLevelGroup`'s are then stored in groups via a class named `MoonsCataloguePage`. This overhaul allows other mods and future updates to LethalLevelLoader to control and store `ExtendedLevel`s in many ways that were previously limited.* -
- -
ExtendedLevel: Lock Route -* *ExtendedLevel's now contain a `isLocked` bool and `lockedNodeText` string that controls whether the Level can currently be routed to via the Terminal. When locked the Terminal will display the `lockedNodeText` string as failed routing response on the Terminal (Or a generic response if the string is left empty)* -
- -
ExtendedLevel: Hide Level -* *ExtendedLevel's now contain a `isHidden` bool that controls whether the Level is displayed in the >Moons Terminal page* -
- -
ExtendedLevel: New Story Log Support -* *ExtendedLevel's can now add their own custom Story Log's, Without the need of custom code. ExtendedLevel's now contain a `List` that takes in a level-dependent `storyLogID` int, a `terminalWord`string, a `storyLogTitle` string and a `storyLogDescription` string.* -
- -
ExtendedLevel: Provide Level Info Description -* *By default ExtendedLevel's have their >info display text generated using their `SelectableLevel.LevelDescription` string, ExtendedLevel's now have an optional `infoNodeDescription` string if they wish to write their text manually.* -
- -
ExtendedLevel Events -* *ExtendedLevel's now contain gameplay specific `ExtendedEvent`'s that will Invoke when these events happen while playing the relevant ExtendedLevel.* - -* * `onLevelLoaded` -* * `onDaytimeEnemySpawn(EnemyAI)` -* * `onNighttimeEnemySpawn(EnemyAI)` -* * `onStoryLogCollected(StoryLog)` -* * `onApparatusTaken(LungProp)` -* * `onPlayerEnterDungeon(EntranceTeleport, PlayerControllerB)` -* * `onPlayerExitDungeon(EntranceTeleport, PlayerControllerB)` -* * `onPowerSwitchToggle(bool)` -
- -
ExtendedDungeonFlow Events -* *ExtendedLevel's now contain gameplay specific `ExtendedEvent`'s that will Invoke when these events happen while playing the relevant ExtendedLevel.* - - -* * `onBeforeDungeonGenerate(RoundManager)` -* * `onSpawnedSyncedObjects(List)` -* * `onSpawnedMapObjects(List)` -* * `onSpawnedScrapObjects(List)` -* * `onEnemySpawnedFromVent(EnemyVent, EnemyAI)` -* * `onApparatusTaken(LungProp)` -* * `onPlayerEnterDungeon(EntranceTeleport, PlayerControllerB)` -* * `onPlayerExitDungeon(EntranceTeleport, PlayerControllerB)` -* * `onPowerSwitchToggle(bool)` -
- -
Default Configuration Options -* *LethalLevelLoader now provides five new global configuration options.* - - -* `Default PreviewInfo Toggle` -* * *Controls which Preview Info setting is used when previewing moons via the Terminal `MoonCatalogue`.* -* `Default SortInfo Toggle` -* * *Controls which Sort Info setting is used when previewing moons via the Terminal `MoonCatalogue`.* -* `Default FilterInfo Toggle` -* * *Controls which Filter Info setting is used when previewing moons via the Terminal `MoonCatalogue`.* -* `Default SimulateInfo Toggle` -* * *Controls whether rarity is displayed as it's raw value or a calculated percentage while using the >simulate Terminal keyword.* -* `All DungeonFlows Require Matching` -* * *Experimental setting that forces `DungeonFlow`'s requested by a `SelectableLevel` to have a valid dynamic match. false by default.* -
- -
ExtendedLevel Automatic Configuration Options -* *LethalLevelLoader now provides automatically generated configuration options for all `ExtendedLevel`'s. This can be disabled by the author of the `ExtendedLevel` if they wish to provide these options themselves.* - -* * `enableContentConfiguration` -* * `routePrice` -* * `daySpeedMultiplier` -* * `enablePlanetTime` -* * `isLevelHidden` -* * `isLevelRegistered` -* * `minimumScrapItemSpawnsCount` -* * `maxiumumScrapItemSpawnsCount` -* * `scrapSpawnsList` -* * `maximumInsideEnemyPowerCount` -* * `maxiumumOutsideDaytimeEnemyPowerCount` -* * `maximumOutsideNighttimeEnemyPowerCount` -* * `insideEnemiesList` -* * `outsideDaytimeEnemiesList` -* * `outsideNighttimeEnemiesList` -
- -
ExtendedDungeonFlow Automatic Configuration Options -* *LethalLevelLoader now provides automatically generated configuration options for all `ExtendedDungeonFlow`'s. This can be disabled by the author of the `ExtendedDungeonFlow` if they wish to provide these options themselves.* -* -* * `EnableContentConfiguration` -* * `manualContentSourceNameReferenceList` -* * `manualPlanetNameReferenceList` -* * `dynamicLevelTagsReferenceList` -* * `dynamicRoutePriceReferenceList` -* * `enableDynamicDungeonSizeRestriction` -* * `minimumDungeonSizeMultiplier` -* * `maximumDungeonSizeMultiplier` -* * `restrictDungeonSizeScaler` -
- -
Content Config Helper Functions -* *LethalLevelLoader now provides a variety of helper functions for parsing configuration strings into usuable data. These are used in the `ExtendedLevel` and `ExtendedDungeonFlow` automatic configuration options to ensure standardization.* - -* * `List ConvertToStringWithRarityList(string inputString, Vector2 clampRarity)` -* * `List ConvertToVector2WithRarityList(string inputString, Vector2 clampRarity)` -* * `List ConvertToSpawnableEnemyWithRarityList(string inputString, Vector2 clampRarity)` -* * `List ConvertToSpawnableItemWithRarityList(string inputString, Vector2 clampRarity)` -* * `(string, string) SplitStringByIndexSeperator(string inputString)` -* * `(string, string) SplitStringByKeyPairSeperator(string inputString)` -* * `(string, string) SplitStringByVectorSeperator(string inputString)` -
- -
Extensions -* *LethalLevelLoader now provides a variety of helper extensions to assist in creating content in Lethal Company.* - -* * `DungeonFlow` `ListGetTiles()` -* * `DungeonFlow` `ListGetRandomMapObjects()` -* * `DungeonFlow` `ListGetSpawnSyncedObjects()` - -* * `CompatibleNoun` `AddReferences(TerminalKeyword, TerminalNode)` -* * `TerminalKeyword` `AddCompatibleNoun(TerminalKeyword, TerminalNode)` -* * `TerminalNode` `AddCompatibleNoun(TerminalKeyword, TerminalNoun)` -
- - -
Async AssetBundle Loading -* *LethalLevelLoader now loads `.lethalbundle`s asynchronously to improve load times while starting Lethal Company. The progress of the AssetBundle loading can be viewed on the initial game launch options screen.* -
- -
- -**
Fixes** - -* *The entire codebase has been refactored to streamline functionality, improve stability and reduce errors.* -* *As a safety fallback, LethalLevelLoader will now select the Facility DungeonFlow if there are no DungeonFlow's for the game to select from.* -* *Fixed a Lethal Company bug where game breaks for all clients if a client doesn't finish generating Dungen in one frame* -* *LethalLevelLoader now correctly restores references to base game ItemGroup's found in Custom DungeonFlow's* -* *LethalLevelLoader now correctly restores references to base game ReverbPresets's found in Custom SelectableLevel's and DungeonFlow's* -* *LethalLevelLoader now correctly restores references to base game AudioMixers's found in Custom SelectableLevel's and DungeonFlow's* -* *LethalLevelLoader now correctly restores references to base game AudioMixerController's found in Custom SelectableLevel's and DungeonFlow's* -* *LethalLevelLoader now correctly restores references to base game AudioMixerSnapshots's found in Custom SelectableLevel's and DungeonFlow's* -* *LethalLevelLoader now injects it's random DungeonFlow selection into Lethal Company's random DungeonFlow selection function to improve natural compatibility with other mods. (Thank you BananaPatcher714)* -* *LethalLevelLoader now injects custom DungeonFlow's into Lethal Company's DungeonFlowTypes array to improve natural compatibility with other mods. (Thank you BananaPatcher714)* -* *LethalLevelLoader now injects custom firstTimeDungeonAudio's into Lethal Company's DungeonAudios array to improve natural compatibility with other mods. (Thank you BananaPatcher714)* -* *LethalLevelLoader's dynamic dungeon rarity matching system was overhauled to ensure the highest matching rarity is used, rather than the first matching rarity.* -* *ExtendedLevel's `routePrice` value is now automatically synced with it's associated TerminalNode to ensure dynamic updates to route price are correctly set and reflected on the Terminal.* -* *After references to base game content are restored by LethalLevelLoader, they are now destroyed to avoid issues with other mods obtaining assets via `Resources.FindObjectsOfType()`* -* *Fixed an issue where Custom ExtendedLevel's failed to integrate into the game due to lacking `"FAUNA"` and `"CONDITIONS"` in their `SelectableLevel.LevelDescription`* -* *Modified how LethalLevelLoader accesses the Terminal in order to improve safety and stability in larger modpacks.* -* *Modified how LethalLevelLoader accesses TerminalNode's to avoid errors when playing Lethal Company in different languages. (Thanks Paradox75831004)* -* *Fixed a Lethal Company bug where AudioSource's unintentionally log harmless AudioSpatializer related warnings in the console. -* *Fixed an issue where LethalLevelLoader's dynamic dungeon size clamping was unintentionally being applied.* -* *Fixed an oversight where LethalLevelLoader was logging via Unity rather than Bepinex.* -* *Fixed an issue where `GetTiles()` could potentially trigger null reference exception errors.* -* *Fixed major oversight where Game-Icons.net was not correctly attributed for LethalLevelLoader's logo* - -
- -
- - - -**
Version 1.0.7** - -* *Overhauled Custom Level system to use dynamically injected scenes rather than dynamically injected prefabs (Thanks onionymous!)* - -
- -**
Version 1.0.6** - -* *Moved all logs from Unity.Debug() to BepInEx.ManualLogSauce.LogInfo()* -* *Modified Custom ExtendedLevel loading to initially disable all MeshColliders then reenable them asynchronously to vastly improve load times* -* *Slightly improved manualPlanetNameReferenceList comparison to improve suggested edgecases* -* *Fixed oversight were Terminal moonsListCatalogue was being displayed inaccurately compared to base game implementation* -* *Fixed issue were the NavMesh was incorrectly attempting to bake the Player Ship* - -
- -**
Version 1.0.5** - -* *Fixed issue related to SelectableLevel: March not being correctly loaded with it's intended DungeonFlow on additional visits* -* *Revamped manualPlanetNameReferenceList comparison to increase the likelyhood of user inputs working as intended* - -
- -**
Version 1.0.4** - -* *Updated LethalLib dependancy from 0.10.1 to 0.11.0* -* *Fixed issues related to SelectableLevel: March not being correctly loaded with it's intended DungeonFlow* -* *Fixed oversight were Custom DungeonFlow's were not having all SpawnSyncedObject's correctly restored* -* *Modified DungeonFlow_Patch levelTags check to increase odds of correctly matching user input* -* *Removed deprecated debug logs* - -
- -**
Version 1.0.3** - -* *Fixed issues caused by the v47 and v48 updates, specific changes will be listed below* -* *Fixed an oversight were ExtendedDungeonFlow dungeonID's were not being assigned correctly* -* *Changed ExtendedDungeonFlow.dungeonRarity variable name to ExtendedDungeonFlow.dungeonDefaultRarity for improved clarity* -* *Moved Prefix Patch Targets From RoundManager to StartOfRound to account for the order of execution changes made in v47* -* *Improved the EntranceTeleport patch to re-organise entranceID settings to avoid user error* -* *Fixed an oversight were PatchDungeonSize() incorrectly checked if the compared values were identical* -* *Moved a majority of public access modifiers to internal to prevent unintential use of internal classes* -* *Fixed an issue were DungeonFlow SpawnSyncObject's were failing to restore their Vanilla reference* -* *Changed ExtendedDungeonFlow.dungeonSizeMin and ExtendedDungeonFlow.dungeonSizeMaz to floats to improve usability* -* *Changed the way the basegame's internal variables are patched to resolve an issue where leaving the game would corrupt saves* -* *Improved debug logs for clarity* - -
- -**
Version 1.0.2** - -* *All Registering of Custom Content has been moved from the GameNetworkManager.Awake() Prefix to the GameNetworkManager.Start() Prefix to give developers safe access to Awake() if needed.* -* *AssetBundleLoader.specifiedFileExtension has now been changed to a public const to allow for improved referencing.* -* *ExtendedDungeonFlow's are now automatically registered with the Network when added using AssetBundleLoader.RegisterExtendedDungeonFlow()* -* *sourceName in ExtendedLevel and ExtendedDungeonFlow have been changed to contentSourceName, to improve clarity.* -* *Fixed an oversight where dungeonSizeMin was not being considered.* -* *Removed deprecated variables from ExtendedDungeonPreferences.* -* *Vector2WithRarity now correctly uses a Vector2, Allowing for improved usability in the Unity inspector.* -* *Variables in ExtendedDungeonPreferences have now been protected with properties, to allow for future validation options.* -* *Removed ExtendedDungeonPreferences, This has now been combined into ExtendedDungeonFlow for better usability and more streamlined referencing.* -* *Refactored ExtendedDungeonFlow to improve on visual organisation when viewed in the Unity inspector.* -* *Refactored ExtendedLevel to improve on visual organisation when viewed in the Unity inspector.* -* *Introduced ConfigHelper.ConvertToStringWithRarity() To assist with developers configeration creation.* -* *Cached Terminal.allTerminalKeywords for improved reference safetey.* -* *Adjusted Harmony Patch Priority Orders from 0 to 350.* - -
- -**
Version 1.0.1** - -* *Updated README* - -
- -**
Version 1.0.0** - -* *Initial Release* - -
\ No newline at end of file diff --git a/Thunderstore/README.md b/Thunderstore/README.md deleted file mode 100644 index 0416f0a..0000000 --- a/Thunderstore/README.md +++ /dev/null @@ -1,63 +0,0 @@ -**LethalLevelLoader** --- - -**A Custom API to support the manual and dynamic integration of all forms of custom content in Lethal Company.** - -**Thunderstore Link:** *https://thunderstore.io/c/lethal-company/p/IAmBatby/LethalLevelLoader/* - -**Discord Thread:** *https://discord.com/channels/1168655651455639582/1193461151636398080* - -**Description** --- - -### **1.2.0 for Lethal Company v50 Has Released!** - -**LethalLevelLoader** is a custom API to support the manual and dynamic integration of custom levels and dungeons in Lethal Company. -Mod Developers can provide LethalLevelLoader with their custom content via code or via automatic assetbundle detection, From there LethalLevelLoader will seamlessly load it into the game. - -This Mod is Likely To Be Incompataible with **LethalExpansion**, Due To The inherit conflicts involved in changing the same systems. - -**How To Use (Users / Players)** --- - - - Simply install LethalLevelLoader and it's dependencies. - - - If a mod using **LethalLevelLoader** supplies a **.lethalbundle** file, **LethalLevelLoader** will automatically find and load it’s content as long as it’s in the /plugins/ folder (Subfolders will be detected) - -**How To Use (Modders / Developers)** --- - - - Please refer to the LethalLevelLoader Wiki for documentation on utalising this API for your custom content - https://github.com/IAmBatby/LethalLevelLoader/wiki - -**Features Currently Supported** --- -* Custom Moons -* Custom Interiors -* Custom Items (Scrap / Items) -* Custom Enemies (Enemies) -* Custom StoryLog's -* Custom Weather Effects (WIP) -* Custom Footstep Surfaces (WIP) - -**Credits** --- - -* **Evaisa** *(This Mod is directly based from LethalLib's codebase and could have been made without it's pre-existing foundations.)* -* **SkullCrusher** *(This Mod is directly based from SkullCrusher's LethalLib' Fork and could have been made without it's pre-existing foundations.)* -* **HolographicWings** *(This Mod was inspired by LethalExpansion and could not have been made without HolographicWing's support and research.)* -* **KayNetsua** *(This Mod was internally tested using KayNetsua's "E Gypt" Custom Level and KayNetsua assisted in testing LethalLevelLoader's usage)* -* **Badhamknibb** *(This Mod was internally tested using Badhamknibb's "SCP Foundation" Custom Dungeon and Badhamknibb's assisted in testing LethalLevelLoader's usage)* -* **Scoopy** *(This Mod was internally tested using Scoopy's "LethalExtension Castle" Custom Dungeon and Scoopy assisted in testing LethalLevelLoader's usage)* -* **Xilo** *(Xilo provided multiple instances of Bepinex & Unity.Netcode related support during the development of this Mod.)* -* **Lordfirespeed** *(Lordfirespeed provided multiple instances of Bepinex & Unity.Netcode related support during the development of this Mod.)* -* **onionymous** *(Onionymous provided a preview build of their Networked Scene Patcher API, allowing for dynamic, networked scene injection)* -* **Game-Icons.net** *(For the artwork used for the mod's logo)* -**Maxwasunavailable** *(For creating LethalModDataLib and assisting me with it’s usage.)* -**Mrov** *(For collaborating with me on initial Custom weather support related code, assisting in fixes related to the Config file and a bunch of miscellaneous assistance.)* -**LadyRaphtalia**, **Xu Xiaolan**, **Badhamknibbs**, **Mrov**, **sfDesat**, **AboveFire**, **Autumnis The Everchanging**, **RosiePies**, **Drako** & **Audio Knight** *(For testing development on experimental 1.2.0 builds.)* -**狐萝卜呀**, **tumbleweed**, **Corey**, **Ritskee**, **Altan**, **qxZap**, **Salamander**, **Chiseled Cactus**, **Phantom139**, **ImmaBawss**, **takeothewolf**, **zuzaratrust**, **Hackattack242**, **Mail Me Dabs**, **Kyros**, **SourceShard** & **Chupacabra** *(For playtesting and reporting bugs on experimental 1.2.0 builds.* -**Lunxara** *For the heavy, rapid testing throughout all the experimental 1.2.0 builds.*) \ No newline at end of file diff --git a/Thunderstore/icon.png b/Thunderstore/icon.png deleted file mode 100644 index 753f0e9..0000000 Binary files a/Thunderstore/icon.png and /dev/null differ diff --git a/Thunderstore/plugins/LethalLevelLoader.dll b/Thunderstore/plugins/LethalLevelLoader.dll deleted file mode 100644 index 12bd89e..0000000 Binary files a/Thunderstore/plugins/LethalLevelLoader.dll and /dev/null differ diff --git a/assets/thunderstore.toml b/assets/thunderstore.toml index 3c44e86..436c468 100644 --- a/assets/thunderstore.toml +++ b/assets/thunderstore.toml @@ -1,6 +1,6 @@ # all directories are relative to the location of this toml file (/assets/thunderstore.toml) [config] -schemaVersion = "1.3.0" +schemaVersion = "0.0.1" [general] repository = "https://thunderstore.io" diff --git a/Thunderstore/manifest.json b/manifest.json similarity index 82% rename from Thunderstore/manifest.json rename to manifest.json index fe89258..5a68b14 100644 --- a/Thunderstore/manifest.json +++ b/manifest.json @@ -1,10 +1,9 @@ { "name": "LethalLevelLoader", - "version_number": "1.3.0", + "version_number": "1.3.1", "website_url": "https://github.com/IAmBatby/LethalLevelLoader", - "description": "A Custom API to support the manual and dynamic integration of all forms of custom content in Lethal Company. (v50 Compatible)", + "description": "A Custom API to support the manual and dynamic integration of all forms of custom content in Lethal Company. (v56 Compatible)", "dependencies": [ - "Evaisa-LethalLib-0.16.0", "Evaisa-FixPluginTypesSerialization-1.1.1", "MaxWasUnavailable-LethalModDataLib-1.2.2", "BepInEx-BepInExPack-5.4.2100"