diff --git a/Core/AssetChanges/AGRoomChanges.cs b/Core/AssetChanges/AGRoomChanges.cs index 8dbafbf..8d37156 100644 --- a/Core/AssetChanges/AGRoomChanges.cs +++ b/Core/AssetChanges/AGRoomChanges.cs @@ -1,6 +1,4 @@ using System.Collections.Generic; -using System.IO; -using System.Text.Json; using System.Text.Json.Serialization; namespace undead_universal_patch_il2cpp.Core.AssetChanges; diff --git a/Core/Config.cs b/Core/Config.cs index a724b8b..64b46e7 100644 --- a/Core/Config.cs +++ b/Core/Config.cs @@ -1,5 +1,4 @@ -using System; -using BepInEx.Configuration; +using BepInEx.Configuration; namespace undead_universal_patch_il2cpp.Core { @@ -33,12 +32,12 @@ namespace undead_universal_patch_il2cpp.Core } public static class GameManagerConfig { - public static ConfigEntry StaticGameTeamConfig; + public static ConfigEntry StaticGameConfig; public static ConfigEntry AnyGameFreeSpawn; } public static class GameManagerConfigDefaults { - public static bool StaticGameTeamConfig; + public static bool StaticGameConfig; public static bool AnyGameFreeSpawn; } public static class NameserverConfig diff --git a/Core/DediConfig.cs b/Core/DediConfig.cs index 4ed9095..74c785b 100644 --- a/Core/DediConfig.cs +++ b/Core/DediConfig.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Text.Json; -using System.Threading.Tasks; namespace undead_universal_patch_il2cpp.Core; diff --git a/Core/GameManager/GameAssetConfigs.cs b/Core/GameManager/GameAssetConfigs.cs new file mode 100644 index 0000000..29f1699 --- /dev/null +++ b/Core/GameManager/GameAssetConfigs.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using RecRoom.Tools; + +namespace undead_universal_patch_il2cpp.Core.UndeadGameManager; + +public class AutoHealSettingsDTO +{ + public float Delay { get; set; } + public float Duration{ get; set; } +} +public class GameStartRequirementDTO +{ + public int MinPlayerCount { get; set; } + public int MinTeamCount { get; set; } + public int MinTeamSize { get; set; } +} +public class DownButNotOutSettingsDTO +{ + public float MaxDepletionDuration { get; set; } + public float InvincibilityDuration { get; set; } +} +public struct EnemyCombatUISettingsDTO +{ + public bool OpponentUISupported { get; set; } + public bool TeammateUISupported { get; set; } +} +public struct FriendlyFireSettingsDTO +{ + public bool PlayerOnPlayerFriendlyFireSupported { get; set; } + public bool PlayerOnEnemyFriendlyFireSupported { get; set; } + public bool EnemyOnPlayerFriendlyFireSupported { get; set; } + public bool EnemyOnEnemyFriendlyFireSupported { get; set; } + public bool GrenadesCanDamageTeammates { get; set; } +} +public struct PlayerCombatUISettingsDTO +{ + public bool LocalPlayerUISupported { get; set; } + public bool OpponentUISupported { get; set; } + public bool TeammateUISupported { get; set; } + public bool TeammateUIAlwaysVisible { get; set; } + public bool OpponentUIAlwaysVisible { get; set; } +} +public class TeamConfigurationDTO +{ + public int MaxTeamSize { get; set; } +} +public class PlayerVisualSettingsDTO +{ + public bool UseTeamNameInsteadOfPlayerNameInNotifications { get; set; } + public bool UseTeamColorInFeedback { get; set; } + public TeamPlayerColorMode TeamColorMode { get; set; } + public bool TeamOutfitsSupported { get; set; } + public PlayerBeaconMode TeammateBeaconMode { get; set; } + public PlayerBeaconMode OpponentBeaconMode { get; set; } +} +public class TeamRadioSettingsDTO +{ + public float RadioVolume { get; set; } + public float EnterRadioDistance { get; set; } + public float ExitRadioDistance { get; set; } +} +public struct StatConfigurationDTO +{ + public string Name { get; set; } + public bool HideInUI { get; set; } + public bool HideInHUD { get; set; } + public GameUIDataModelStatFormat Format { get; set; } +} +public struct RespawnSettingsDTO +{ + public float AutoRespawnDelay { get; set; } + public bool RestoreHealthOnRespawn { get; set; } + public float RespawnInvincibilityDuration { get; set; } +} +public struct ReviveSettingsDTO +{ + public float RequiredDelay { get; set; } + public float MaxReviveHealthNormalized { get; set; } + public float MinReviveHealthNormalized { get; set; } + public float MultiplierPerReviveHealthNormalized { get; set; } + public bool PickupToolsOnRevive { get; set; } + public float ReviverInvincibilityDuration { get; set; } + public float ReviveeInvincibilityDuration { get; set; } + public float HandshakeHoldDuration { get; set; } +} + +public class GameConfigurationAssetDTO +{ + public string Name { get; set; } + public int LoadPriority { get; set; } + public GameStartRequirementDTO ManualGameStartRequirement { get; set; } + public bool AutomaticGameStartSupported { get; set; } + public GameStartRequirementDTO AutomaticGameStartRequirement { get; set; } + public bool PreGameVoiceOverSupported { get; set; } + public bool ResultsVoiceOverSupported { get; set; } + public bool CountdownVoiceOverSupported { get; set; } + public bool GameModeNotificationsSupported { get; set; } + public bool InGamePlayerNotificationsSupported { get; set; } + public float GameStartDelay { get; set; } + public float EndGameResultsDuration { get; set; } + public bool RespawnOnGameStartSupported { get; set; } + public bool RespawnOnGameEndSupported { get; set; } + public bool JoinInProgressSupported { get; set; } + public List TeamConfigurations { get; set; } + public TeamSelectionMethod TeamSelectionMethod { get; set; } + public bool EndGameIfStartRequirementsNotMet { get; set; } + public bool ExplicitTeamSelectionSupported { get; set; } + public bool GameRunningTeamChangeSupported { get; set; } + public bool RespawnOnGameRunningTeamChangeSupported { get; set; } + public bool SpectatingSupported { get; set; } + public bool ShowOpenSlotsOnScoreboard { get; set; } + public bool ClearTeamsAfterGame { get; set; } + public PlayerVisualSettingsDTO TeamPlayerVisualSettings { get; set; } + public bool TeamRadioSupported { get; set; } + public TeamRadioSettingsDTO TeamRadioSettings { get; set; } + public List StatConfigurations { get; set; } + public bool PersistStatsOnGameStart { get; set; } + public int MaxHealth { get; set; } + public int MaxShield { get; set; } + public bool SuppressWeaponDamage { get; set; } + public bool AutoHealSupported { get; set; } + public AutoHealSettingsDTO AutoHealSettings { get; set; } + public bool DownButNotOutSupported { get; set; } + public DownButNotOutSettingsDTO DownButNotOutSettings { get; set; } + public bool AutoRespawnSupported { get; set; } + public RespawnSettingsDTO RespawnSettings { get; set; } + public GameCombatManager.PlayerReviveMode ReviveMode { get; set; } + public ReviveSettingsDTO ReviveSettings { get; set; } + public bool HUDSupported { get; set; } + public FriendlyFireSettingsDTO FriendlyFireSettings { get; set; } + public PlayerCombatUISettingsDTO PlayerCombatUISettings { get; set; } + public EnemyCombatUISettingsDTO EnemyCombatUISettings { get; set; } + public bool DeadMonochromeEffectSupported { get; set; } + public bool DownButNotOutMonochromeEffectSupported { get; set; } + public bool DamageRedFlashEffectSupported { get; set; } + public bool DefaultHitFeedbackSupported { get; set; } + public bool DefaultReviveFeedbackSupported { get; set; } + public bool DefaultDownedOpponentFeedbackSupported { get; set; } + public bool DefaultDownedLocalPlayerFeedbackSupported { get; set; } + public bool DefaultDownedTeammateFeedbackSupported { get; set; } + public bool DeadPersistentNotificationSupported { get; set; } + public GameSpawnPointSelectionMethod SpawnPointSelectionMethod { get; set; } + public SpawnableToolType MainHandTool { get; set; } + public SpawnableToolType OffHandTool { get; set; } + public bool ResetToolsOnGameStartSupported { get; set; } + public ToolEntity.BrokenBehavior BrokenToolBehavior { get; set; } + public bool EquipmentBeaconsSupported { get; set; } + public bool WeaponInfiniteAmmoSupported { get; set; } + public bool TeleportBufferDistanceRetricted { get; set; } + public bool OutOfBoundsSupported { get; set; } + public bool OutOfBoundsSpectatorsSupported { get; set; } + public bool DownOutOfBoundsPlayers { get; set; } + public float OutOfBoundsGracePeriod { get; set; } + public float OutOfBoundsMaxDuration { get; set; } +} \ No newline at end of file diff --git a/Core/GameManager/GameConfigurator.cs b/Core/GameManager/GameConfigurator.cs new file mode 100644 index 0000000..de982e2 --- /dev/null +++ b/Core/GameManager/GameConfigurator.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace undead_universal_patch_il2cpp.Core.UndeadGameManager; + +public static class GameConfigurator +{ + static readonly string name = "GameConfigurations"; + public static DediConfig> config = new(name, "{}", null); +} \ No newline at end of file diff --git a/Core/GameManager/TeamConfigurator.cs b/Core/GameManager/TeamConfigurator.cs deleted file mode 100644 index e836300..0000000 --- a/Core/GameManager/TeamConfigurator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; - -namespace undead_universal_patch_il2cpp.Core.UndeadGameManager; - -public class TeamConfiguration -{ - public int Size { get; set; } -} -public class GameConfiguration -{ - public string GameName { get; set; } - public List TeamConfigurations { get; set; } -} - -public static class TeamConfigurator -{ - static readonly string name = "TeamConfigurator"; - public static DediConfig> config = new(name, "[]", null); -} \ No newline at end of file diff --git a/Core/Util.cs b/Core/Util.cs index 9419a05..ebebb43 100644 --- a/Core/Util.cs +++ b/Core/Util.cs @@ -1,8 +1,4 @@ -using System; -using System.Reflection; -using HarmonyLib; - -namespace undead_universal_patch_il2cpp.Core +namespace undead_universal_patch_il2cpp.Core { public class Util { diff --git a/Patches/GameManager/TeamConfigurator.cs b/Patches/GameManager/GameConfigurator.cs similarity index 61% rename from Patches/GameManager/TeamConfigurator.cs rename to Patches/GameManager/GameConfigurator.cs index 9cb560d..a47cb3f 100644 --- a/Patches/GameManager/TeamConfigurator.cs +++ b/Patches/GameManager/GameConfigurator.cs @@ -1,30 +1,30 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using HarmonyLib; -using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Mapster; using RecRoom.Core.GameManagement; +using RecRoom.Protobuf; using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core.UndeadGameManager; namespace undead_universal_patch_il2cpp.Patches.UndeadGameManager; [HarmonyPatch] -public class TeamConfiguratorPatch +public class GameConfiguratorPatch { - static List gameConfig = TeamConfigurator.config.Get(); + static Dictionary gameConfig = GameConfigurator.config.Get(); static string TargetTypeName = "GameConfigurationTool"; static string TargetMethodName = "SetGameConfiguration"; - static string Description = "TeamConfigurator event patch"; + static string Description = "GameConfigurator event patch"; static Type targetType = AccessTools.TypeByName(TargetTypeName); static MethodInfo targetMethod = AccessTools.Method(targetType, TargetMethodName); public static bool Prepare() { - if (!GameManagerConfig.StaticGameTeamConfig.Value) return false; + if (!GameManagerConfig.StaticGameConfig.Value) return false; if (targetMethod == null) { Plugin.Log.LogWarning($"'{Description}' disabled. The method for this patch was not found."); @@ -37,22 +37,24 @@ public class TeamConfiguratorPatch public static MethodBase TargetMethod() => targetMethod; + public static GameConfigurationData res; + public static void Prefix(ref GameConfigurationAsset config, ref bool showNotification) { var conf = config; showNotification = GenericConfig.PatchDebug.Value; - var teamConf = gameConfig.Find(match => match.GameName == conf.Name); - if (teamConf == null) + var gameConf = gameConfig.GetValueOrDefault(conf.Name, null); + if (gameConf == null) { - if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"'{config.Name}' does not have explicit team configurations"); + if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"Game '{conf.Name}' does not have external configuration"); return; } - var arr = new Il2CppStructArray(teamConf.TeamConfigurations.Count); - for (int i = 0; i < arr.Length; i++) arr[i] = new TeamConfiguration { MaxTeamSize = teamConf.TeamConfigurations[i].Size }; - config.TeamConfigurations = arr; + gameConf.Adapt(conf); - if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"New team configuration length for '{config.Name}': {arr.Length}"); + config = conf; + if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"Applied external game configuration for '{config.Name}'"); } + } \ No newline at end of file diff --git a/Patches/PhotonPatch.cs b/Patches/PhotonPatch.cs index 34c3ed2..78dd9fd 100644 --- a/Patches/PhotonPatch.cs +++ b/Patches/PhotonPatch.cs @@ -188,7 +188,7 @@ namespace undead_universal_patch_il2cpp.Patches return; } - string id = Util.LocalInstanceGuid; + string id = Core.Util.LocalInstanceGuid; if (GenericConfig.PatchDebug.Value) Plugin.Log.LogDebug($"Instance GUID is {id}"); PhotonNetwork.AuthValues = new AuthenticationValues diff --git a/Plugin.cs b/Plugin.cs index ebec7b3..eaa1d49 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,16 +1,19 @@ using System; -using System.Text.Json; +using System.Collections.Generic; +using System.Linq; using BepInEx; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Mapster; using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core.AssetChanges; using undead_universal_patch_il2cpp.Core.UndeadGameManager; namespace undead_universal_patch_il2cpp; -[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "1.4.0")] +[BepInPlugin("dev.proxnet.recroom.universalpatch.noneac.il2cpp", "Undead Universal Patch", "1.4.1")] public class Plugin : BasePlugin { public static new readonly ManualLogSource Log = Logger.CreateLogSource("UUPatch"); @@ -51,8 +54,8 @@ public class Plugin : BasePlugin $"Use patches from '{AGRoomChanges.config.path}' to change the properties of internal AGRooms. See README.md"); GameManagerConfig.AnyGameFreeSpawn = Config.Bind("GameManagerConfig", "AnyGameFreeSpawn", GameManagerConfigDefaults.AnyGameFreeSpawn, $"Use patches from '{GameFreeSpawns.config.path}' to spawn in any valid player spawnpoint in specified games. See README.md"); - GameManagerConfig.StaticGameTeamConfig = Config.Bind("GameManagerConfig", "StaticGameTeamConfig", GameManagerConfigDefaults.StaticGameTeamConfig, - $"Use patches from '{TeamConfigurator.config.path}' to set the static configuration of teams in specified games. See README.md"); + GameManagerConfig.StaticGameConfig = Config.Bind("GameManagerConfig", "StaticGameConfig", GameManagerConfigDefaults.StaticGameConfig, + $"Use patches from '{GameConfigurator.config.path}' to set new configurations for built-in games. See README.md"); PhotonConfig.PatchPhotonIds = Config.Bind("Photon", "PatchPhotonIds", PhotonConfigDefaults.PatchPhotonIds, "Patch Photon configuration."); @@ -117,12 +120,19 @@ public class Plugin : BasePlugin { Log.LogError($"Could not load change patches: {ex}"); } + + TypeAdapterConfig.GlobalSettings + .ForType, Il2CppStructArray>() + .MapWith(src => new Il2CppStructArray(src.Select(x => x.Adapt()).ToArray())); + TypeAdapterConfig.GlobalSettings + .ForType, Il2CppReferenceArray>() + .MapWith(src => new Il2CppReferenceArray(src.Select(x => x.Adapt()).ToArray())); } private static void CacheChangePatchConfigs() { if (AssetChangesConfig.AGRoomChanges.Value) AGRoomChanges.config.Get(); if (GameManagerConfig.AnyGameFreeSpawn.Value) GameFreeSpawns.config.Get(); - if (GameManagerConfig.StaticGameTeamConfig.Value) TeamConfigurator.config.Get(); + if (GameManagerConfig.StaticGameConfig.Value) GameConfigurator.config.Get(); } } \ No newline at end of file diff --git a/README.md b/README.md index 7414433..cfd365b 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,289 @@ # Undead Universal Patch + Non-EAC, IL2CPP build patcher for Rec Room (Dec 2018\*-*Apr 3 2020) **Currently only supports unobfuscated builds** -Part two of two universal patches. The Mono patch is available at https://git.proxnet.dev/zombieb/undead-universal-patch-mono. +Part two of two universal patches. The Mono patch is available at +https://git.proxnet.dev/zombieb/undead-universal-patch-mono. -Compatible with [BepInEx builds](https://builds.bepinex.dev/projects/bepinex_be) that can automatically load interop assemblies before plugins (builds 710 and later) +Compatible with [BepInEx builds](https://builds.bepinex.dev/projects/bepinex_be) +that can automatically load interop assemblies before plugins (builds 710 and +later) -**When submitting issues**, please submit your BepInEx log file with all log levels enabled. You can do this by setting `Logging.Disk.LogLevels` in `BepInEx.cfg` to `All`. +**When submitting issues**, please submit your BepInEx log file with all log +levels enabled. You can do this by setting `Logging.Disk.LogLevels` in +`BepInEx.cfg` to `All`. ### Compiling + Unlike the Mono patch, some assemblies must be referenced. -Run BepInEx interop on your build and add the following assemblies to new folder `.\AssemblyReferences\` in this project directory: -* `BepInEx/interop/Assembly-CSharp.dll` -* `BepInEx/interop/Il2Cppmscorlib.dll` -* `BepInEx/interop/Il2CppSystem.dll` -* `BepInEx/interop/Photon3Unity3D.dll` -* `BepInEx/interop/RecRoom.Datastructures.Runtime` -* `BepInEx/interop/UnityEngine.CoreModule.dll` +Run BepInEx interop on your build and add the following assemblies to new folder +`.\AssemblyReferences\` in this project directory: + +- `BepInEx/interop/Assembly-CSharp.dll` +- `BepInEx/interop/Il2Cppmscorlib.dll` +- `BepInEx/interop/Il2CppSystem.dll` +- `BepInEx/interop/Photon3Unity3D.dll` +- `BepInEx/interop/RecRoom.Datastructures.Runtime` +- `BepInEx/interop/UnityEngine.CoreModule.dll` + +## Dependencies + +- Mapster + - Requires `Mapster.dll` and `Mapster.Core.dll` (place in /BepInEx/plugins) + - [Mapster on GitHub](https://github.com/MapsterMapper/Mapster) ### Linux users -Wine currently has problems generating the keypair used in Galvanic authentication. + +Wine currently has problems generating the keypair used in Galvanic +authentication. You can use a real Windows system to generate the keys for the first startup. If you're unsure how to start your build on linux: -* Install Steam -* Add Rec Room as a non-steam game -* Set the compatibility mode to the latest stable version of proton -* Use protontricks to add the doorstop DLL -* Start Rec Room through Steam + +- Install Steam +- Add Rec Room as a non-steam game +- Set the compatibility mode to the latest stable version of proton +- Use protontricks to add the doorstop DLL +- Start Rec Room through Steam ### (AssetChanges) and (GameManager Patches) -Properties of the object in the patch file will be used to set the properties of the respective object in the game's assembly. + +Properties of the object in the patch file will be used to set the properties of +the respective object in the game's assembly. Each object type can be configured as follows: -* `AGRoomRuntimeConfig.Room` or `AGRoomRuntimeConfig.RoomScene` or `AGRoomRuntimeConfig.Location` - - Set the key to the replicationId of the object you want to change - * Any object with a replicationId can be changed - - Objects in the list have properties "Key" and "Value" - * The key represents the name of the property to modify - * The value will replace the current value in the assembly - - Example: - ```json - {"76d98498-60a1-430c-ab76-b54a29b7a163": [ + +- `AGRoomRuntimeConfig.Room` or `AGRoomRuntimeConfig.RoomScene` or + `AGRoomRuntimeConfig.Location` + - Set the key to the replicationId of the object you want to change + - Any object with a replicationId can be changed + - Objects in the list have properties "Key" and "Value" + - The key represents the name of the property to modify + - The value will replace the current value in the assembly + - Example: + ```json + { + "76d98498-60a1-430c-ab76-b54a29b7a163": [ { "Key": "ReleaseStatus", "Value": 0 } - ]} - ``` - will prevent you from loading into the dorm, because you can't go to editor-only rooms. - You can set rooms with ReleaseStatus:0 to 2 if you'd like to go to those rooms. - This isn't very useful for most people. You *should* set this when using `TeamConfiguration` below. -* `GameConfigurationAsset` - - List of changes to the game configurations - - See the example for syntax - * Ex. "Crescendo Of The Blood Moon" (CrescendoOfTheBloodMoon_Config, 20200306) - - Example: - ```json - [ - { - "GameName": "Crescendo Of The Blood Moon", - "TeamConfigurations": [ - {"Size":6}, - {"Size":6} - ] - }, - { - "GameName": "Paintball Capture The Flag", - "TeamConfigurations": [ - {"Size":1}, - {"Size":1}, - {"Size":1}, - ] - } ] - ``` - * Some games have issues with spawning players from other teams into regular spawnpoints. Use `GameFreeSpawns` to remedy this. -* GameFreeSpawns - - Sets every current playing spawnpoint to be available to any team - - Allows more than 4 players to spawn in correctly in quests like Crescendo - - List the game names (strings) to enable the patch for - - Example: - ```json - ["Crescendo Of The Blood Moon", "Paintball Capture The Flag"] - ``` \ No newline at end of file + } + ``` + will prevent you from loading into the dorm, because you can't go to + editor-only rooms. You can set rooms with ReleaseStatus:0 to 2 if you'd like + to go to those rooms. This isn't very useful for most people. You _should_ + set this when using `TeamConfiguration` below. +- `GameConfigurationAsset` + - Dictionary of changes to the game configurations + - Must use the entire game configuration when including one + - See the example for syntax + - Example: + ```json + { + "Soccer": { + "Name": "COOLER Soccer", + "LoadPriority": -1, + "ManualGameStartRequirement": { + "MinPlayerCount": 2, + "MinTeamCount": 2, + "MinTeamSize": 1 + }, + "AutomaticGameStartSupported": false, + "AutomaticGameStartRequirement": { + "MinPlayerCount": -1, + "MinTeamCount": -1, + "MinTeamSize": -1 + }, + "PreGameVoiceOverSupported": true, + "ResultsVoiceOverSupported": true, + "CountdownVoiceOverSupported": true, + "GameModeNotificationsSupported": true, + "InGamePlayerNotificationsSupported": true, + "GameStartDelay": 10.0, + "EndGameResultsDuration": 15.0, + "RespawnOnGameStartSupported": true, + "RespawnOnGameEndSupported": true, + "JoinInProgressSupported": true, + "TeamConfigurations": [ + { + "MaxTeamSize": 12 + }, + { + "MaxTeamSize": 12 + } + ], + "TeamSelectionMethod": 2, + "EndGameIfStartRequirementsNotMet": true, + "ExplicitTeamSelectionSupported": false, + "GameRunningTeamChangeSupported": false, + "RespawnOnGameRunningTeamChangeSupported": true, + "SpectatingSupported": true, + "ShowOpenSlotsOnScoreboard": true, + "ClearTeamsAfterGame": true, + "TeamPlayerVisualSettings": { + "UseTeamNameInsteadOfPlayerNameInNotifications": true, + "UseTeamColorInFeedback": true, + "TeamColorMode": 0, + "TeamOutfitsSupported": true, + "TeammateBeaconMode": 0, + "OpponentBeaconMode": 0 + }, + "TeamRadioSupported": true, + "TeamRadioSettings": { + "RadioVolume": 0.12, + "EnterRadioDistance": 1.5, + "ExitRadioDistance": 1.0 + }, + "StatConfigurations": [ + { + "Name": "Stat 1", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 2", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 3", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 4", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 5", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 6", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 7", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 8", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 9", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + }, + { + "Name": "Stat 10", + "HideInUI": true, + "HideInHUD": true, + "Format": 0 + } + ], + "PersistStatsOnGameStart": false, + "MaxHealth": 100, + "MaxShield": 0, + "SuppressWeaponDamage": false, + "AutoHealSupported": false, + "AutoHealSettings": { + "Delay": 0.0, + "Duration": 0.0 + }, + "DownButNotOutSupported": false, + "DownButNotOutSettings": { + "MaxDepletionDuration": 0.0, + "InvincibilityDuration": 0.0 + }, + "AutoRespawnSupported": true, + "RespawnSettings": { + "AutoRespawnDelay": 5.0, + "RestoreHealthOnRespawn": true, + "RespawnInvincibilityDuration": 3.0 + }, + "ReviveMode": 0, + "ReviveSettings": { + "RequiredDelay": 0.0, + "MaxReviveHealthNormalized": 1.0, + "MinReviveHealthNormalized": 1.0, + "MultiplierPerReviveHealthNormalized": 1.0, + "PickupToolsOnRevive": false, + "ReviverInvincibilityDuration": 0.0, + "ReviveeInvincibilityDuration": 0.0, + "HandshakeHoldDuration": 0.0 + }, + "HUDSupported": false, + "FriendlyFireSettings": { + "PlayerOnPlayerFriendlyFireSupported": false, + "PlayerOnEnemyFriendlyFireSupported": false, + "EnemyOnPlayerFriendlyFireSupported": false, + "EnemyOnEnemyFriendlyFireSupported": false, + "GrenadesCanDamageTeammates": true + }, + "PlayerCombatUISettings": { + "LocalPlayerUISupported": false, + "OpponentUISupported": true, + "TeammateUISupported": true, + "TeammateUIAlwaysVisible": false, + "OpponentUIAlwaysVisible": false + }, + "EnemyCombatUISettings": { + "OpponentUISupported": true, + "TeammateUISupported": false + }, + "DeadMonochromeEffectSupported": true, + "DownButNotOutMonochromeEffectSupported": true, + "DamageRedFlashEffectSupported": true, + "DefaultHitFeedbackSupported": true, + "DefaultReviveFeedbackSupported": true, + "DefaultDownedOpponentFeedbackSupported": true, + "DefaultDownedLocalPlayerFeedbackSupported": true, + "DefaultDownedTeammateFeedbackSupported": false, + "DeadPersistentNotificationSupported": true, + "SpawnPointSelectionMethod": 2, + "MainHandTool": -1, + "OffHandTool": -1, + "ResetToolsOnGameStartSupported": true, + "BrokenToolBehavior": 0, + "EquipmentBeaconsSupported": true, + "WeaponInfiniteAmmoSupported": false, + "TeleportBufferDistanceRetricted": false, + "OutOfBoundsSupported": false, + "OutOfBoundsSpectatorsSupported": false, + "DownOutOfBoundsPlayers": false, + "OutOfBoundsGracePeriod": 3.0, + "OutOfBoundsMaxDuration": 4.0 + } + } + ``` + - Some games have issues with spawning players from other teams into regular + spawnpoints. Use `GameFreeSpawns` to remedy this. +- GameFreeSpawns + - Sets every current playing spawnpoint to be available to any team + - Allows more than 4 players to spawn in correctly in quests like Crescendo + - List the game names (strings) to enable the patch for + - Example: + ```json + ["Crescendo Of The Blood Moon", "Paintball Capture The Flag"] + ``` diff --git a/undead-universal-patch-il2cpp.csproj b/undead-universal-patch-il2cpp.csproj index 7ff94b3..3d9c729 100644 --- a/undead-universal-patch-il2cpp.csproj +++ b/undead-universal-patch-il2cpp.csproj @@ -4,7 +4,7 @@ net6.0 undead_universal_patch_il2cpp Non-EAC, IL2CPP build patcher for Rec Room (Late 2018*-*April-2020) - 1.4.0 + 1.4.1 true latest @@ -17,6 +17,7 @@ + @@ -38,8 +39,5 @@ AssemblyReferences\UnityEngine.CoreModule.dll - - AssemblyReferences\Google.Protobuf.dll -