2.0.0 - any gameconfigurationasset can be changed! breaking public API

This commit is contained in:
2025-08-10 18:04:52 -04:00
parent 8f4ffff08a
commit 48ca74d2db
12 changed files with 464 additions and 117 deletions

View File

@@ -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;

View File

@@ -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<bool> StaticGameTeamConfig;
public static ConfigEntry<bool> StaticGameConfig;
public static ConfigEntry<bool> AnyGameFreeSpawn;
}
public static class GameManagerConfigDefaults
{
public static bool StaticGameTeamConfig;
public static bool StaticGameConfig;
public static bool AnyGameFreeSpawn;
}
public static class NameserverConfig

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
namespace undead_universal_patch_il2cpp.Core;

View File

@@ -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<TeamConfigurationDTO> 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<StatConfigurationDTO> 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; }
}

View File

@@ -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<Dictionary<string, GameConfigurationAssetDTO>> config = new(name, "{}", null);
}

View File

@@ -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<TeamConfiguration> TeamConfigurations { get; set; }
}
public static class TeamConfigurator
{
static readonly string name = "TeamConfigurator";
public static DediConfig<List<GameConfiguration>> config = new(name, "[]", null);
}

View File

@@ -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
{

View File

@@ -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<GameConfiguration> gameConfig = TeamConfigurator.config.Get();
static Dictionary<string, GameConfigurationAssetDTO> 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<TeamConfiguration>(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}'");
}
}

View File

@@ -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

View File

@@ -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<List<TeamConfigurationDTO>, Il2CppStructArray<TeamConfiguration>>()
.MapWith(src => new Il2CppStructArray<TeamConfiguration>(src.Select(x => x.Adapt<TeamConfiguration>()).ToArray()));
TypeAdapterConfig.GlobalSettings
.ForType<List<StatConfigurationDTO>, Il2CppReferenceArray<StatConfiguration>>()
.MapWith(src => new Il2CppReferenceArray<StatConfiguration>(src.Select(x => x.Adapt<StatConfiguration>()).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();
}
}

300
README.md
View File

@@ -1,85 +1,285 @@
# 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`
- `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
- 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
- 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": [
{
"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
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

View File

@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>undead_universal_patch_il2cpp</AssemblyName>
<Description>Non-EAC, IL2CPP build patcher for Rec Room (Late 2018*-*April-2020) </Description>
<Version>1.4.0</Version>
<Version>1.4.1</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<RestoreAdditionalProjectSources>
@@ -17,6 +17,7 @@
<ItemGroup>
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.*" IncludeAssets="compile" />
<PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup>
<ItemGroup>
@@ -38,8 +39,5 @@
<Reference Include="UnityEngine.CoreModule">
<HintPath>AssemblyReferences\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
<HintPath>AssemblyReferences\Google.Protobuf.dll</HintPath>
</Reference>
</ItemGroup>
</Project>