push broken mod

This commit is contained in:
NotAKidoS 2023-04-26 11:18:40 -05:00
parent 742f816d3d
commit 344e3bb6d6
12 changed files with 500 additions and 0 deletions

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>..\_ManagedLibs\0Harmony.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\_ManagedLibs\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>..\_ManagedLibs\Assembly-CSharp-firstpass.dll</HintPath>
</Reference>
<Reference Include="ChatBox">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\ChatBox.dll</HintPath>
</Reference>
<Reference Include="MelonLoader">
<HintPath>..\_ManagedLibs\MelonLoader.dll</HintPath>
</Reference>
<Reference Include="ml_prm">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\_ManagedLibs\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputLegacyModule">
<HintPath>..\_ManagedLibs\UnityEngine.InputLegacyModule.dll</HintPath>
</Reference>
</ItemGroup>
<Target Name="Deploy" AfterTargets="Build">
<Copy SourceFiles="$(TargetPath)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" />
<Message Text="Copied $(TargetPath) to C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" Importance="high" />
</Target>
</Project>

View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32630.192
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatBoxExtensions", "ChatBoxExtensions.csproj", "{319281C7-C2CC-4350-ACE9-A52467C3E1EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{319281C7-C2CC-4350-ACE9-A52467C3E1EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{319281C7-C2CC-4350-ACE9-A52467C3E1EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{319281C7-C2CC-4350-ACE9-A52467C3E1EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{319281C7-C2CC-4350-ACE9-A52467C3E1EF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {67285FB2-B0B0-44AF-AC34-C47B3BF054ED}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,14 @@
using ABI_RC.Core.Savior;
using HarmonyLib;
namespace NAK.Melons.ChatBoxExtensions.HarmonyPatches;
public class CVRInputManagerPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(CVRInputManager), "Start")]
static void Postfix_CVRInputManager_Start(ref CVRInputManager __instance)
{
ChatBoxExtensions.InputModule = __instance.gameObject.AddComponent<InputModules.InputModuleChatBoxExtensions>();
}
}

View file

@ -0,0 +1,25 @@
using ABI_RC.Core.Savior;
using UnityEngine;
namespace NAK.Melons.ChatBoxExtensions.InputModules;
internal class InputModuleChatBoxExtensions : CVRInputModule
{
public bool jump = false;
public float emote = -1;
public Vector2 lookVector = Vector2.zero;
public Vector3 movementVector = Vector3.zero;
public override void UpdateInput()
{
CVRInputManager.Instance.jump |= jump;
CVRInputManager.Instance.movementVector += movementVector;
CVRInputManager.Instance.lookVector += lookVector;
if (emote > 0) CVRInputManager.Instance.emote = emote;
jump = false;
emote = -1;
lookVector = Vector3.zero;
movementVector = Vector3.zero;
}
}

View file

@ -0,0 +1,56 @@
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
namespace NAK.Melons.ChatBoxExtensions.Integrations;
public class CommandBase
{
internal static bool IsCommandForAll(string argument)
{
if (String.IsNullOrWhiteSpace(argument)) return false;
return argument == "*" || argument.StartsWith("@a") || argument.StartsWith("@e");
}
internal static bool IsCommandForLocalPlayer(string argument)
{
if (String.IsNullOrWhiteSpace(argument)) return false;
if (argument.Contains("*"))
{
string partialName = argument.Replace("*", "").Trim();
if (String.IsNullOrWhiteSpace(partialName)) return false;
return MetaPort.Instance.username.Contains(partialName);
}
return MetaPort.Instance.username == argument;
}
internal static void LocalCommandIgnoreOthers(string argument, Action<string[]> callback)
{
string[] args = argument.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray();
// will fail if arguments are specified which arent local player
if (args.Length == 0 || IsCommandForAll(args[0]) || IsCommandForLocalPlayer(args[0])) callback(args);
}
//remote must specify exact player, wont respawn to all
internal static void RemoteCommandListenForSelf(string argument, Action<string[]> callback)
{
string[] args = argument.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray();
if (args.Length == 0) return;
if (IsCommandForLocalPlayer(args[0])) callback(args);
}
// remote must specify player or all, ignore commands without arguments
internal static void RemoteCommandListenForAll(string argument, Action<string[]> callback)
{
string[] args = argument.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray();
if (args.Length == 0) return;
if (IsCommandForAll(args[0]) || IsCommandForLocalPlayer(args[0])) callback(args);
}
internal static string GetPlayerUsername(string guid)
{
return CVRPlayerManager.Instance.TryGetPlayerName(guid);
}
}

View file

@ -0,0 +1,43 @@
using Kafe.ChatBox;
namespace NAK.Melons.ChatBoxExtensions.Integrations;
internal class ChatBoxCommands : CommandBase
{
public static void RegisterCommands()
{
bool awaitingPing = false;
DateTime pingTime = DateTime.MinValue; // store the time when "ping" command was sent
Commands.RegisterCommand("ping",
onCommandSent: (message, sound) =>
{
pingTime = DateTime.Now;
awaitingPing = true;
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForSelf(message, args =>
{
ChatBox.SendMessage("/pong " + GetPlayerUsername(sender), false);
});
});
Commands.RegisterCommand("pong",
onCommandSent: null,
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForSelf(message, args =>
{
if (awaitingPing)
{
awaitingPing = false;
TimeSpan timeSincePing = DateTime.Now - pingTime; // calculate the time difference
ChatBox.SendMessage($"Time since ping: {timeSincePing.TotalMilliseconds}ms", false);
return;
}
ChatBox.SendMessage($"You have to ping first, {GetPlayerUsername(sender)}!", false);
});
});
}
}

View file

@ -0,0 +1,43 @@
using ABI_RC.Core;
using ABI_RC.Core.Base;
using Kafe.ChatBox;
namespace NAK.Melons.ChatBoxExtensions.Integrations;
internal class ChilloutVRBaseCommands : CommandBase
{
public static void RegisterCommands()
{
Commands.RegisterCommand("respawn",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, args =>
{
RootLogic.Instance.Respawn();
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, (args) =>
{
RootLogic.Instance.Respawn();
});
});
Commands.RegisterCommand("mute",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, args =>
{
Audio.SetMicrophoneActive(true);
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, args =>
{
Audio.SetMicrophoneActive(true);
});
});
}
}

View file

@ -0,0 +1,58 @@
using ABI_RC.Core;
using ABI_RC.Core.Base;
using ABI_RC.Core.Savior;
using Kafe.ChatBox;
namespace NAK.Melons.ChatBoxExtensions.Integrations;
internal class ChilloutVRInputCommands : CommandBase
{
public static void RegisterCommands()
{
Commands.RegisterCommand("emote",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, args =>
{
if (args.Length > 0 && int.TryParse(args[0], out int emote))
{
ChatBoxExtensions.InputModule.emote = (float)emote;
}
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, args =>
{
if (args.Length > 1 && int.TryParse(args[1], out int emote))
{
ChatBoxExtensions.InputModule.emote = (float)emote;
}
});
});
Commands.RegisterCommand("jump",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, args =>
{
if (args.Length > 0 && bool.TryParse(args[0], out bool jump))
{
ChatBoxExtensions.InputModule.jump = jump;
return;
}
ChatBoxExtensions.InputModule.jump = true;
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, args =>
{
if (bool.TryParse(args[0], out bool jump))
{
ChatBoxExtensions.InputModule.jump = jump;
}
});
});
}
}

View file

@ -0,0 +1,90 @@
using Kafe.ChatBox;
using ml_prm;
namespace NAK.Melons.ChatBoxExtensions.Integrations;
internal class PlayerRagdollModCommands : CommandBase
{
public static void RegisterCommands()
{
Commands.RegisterCommand("unragdoll",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, (args) =>
{
if (RagdollController.Instance.IsRagdolled())
{
RagdollController.Instance.SwitchRagdoll();
}
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, (args) =>
{
if (RagdollController.Instance.IsRagdolled())
{
RagdollController.Instance.SwitchRagdoll();
}
});
});
Commands.RegisterCommand("ragdoll",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, (args) =>
{
bool switchRagdoll = true;
if (args.Length > 0 && bool.TryParse(args[0], out bool state))
{
switchRagdoll = state != RagdollController.Instance.IsRagdolled();
}
if (switchRagdoll)
{
RagdollController.Instance.SwitchRagdoll();
}
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, (args) =>
{
bool switchRagdoll = true;
if (args.Length > 1 && bool.TryParse(args[1], out bool state))
{
switchRagdoll = state != RagdollController.Instance.IsRagdolled();
}
if (switchRagdoll)
{
RagdollController.Instance.SwitchRagdoll();
}
});
});
Commands.RegisterCommand("kill",
onCommandSent: (message, sound) =>
{
LocalCommandIgnoreOthers(message, (args) =>
{
if (!RagdollController.Instance.IsRagdolled())
{
RagdollController.Instance.SwitchRagdoll();
}
});
},
onCommandReceived: (sender, message, sound) =>
{
RemoteCommandListenForAll(message, (args) =>
{
if (!RagdollController.Instance.IsRagdolled())
{
RagdollController.Instance.SwitchRagdoll();
}
});
});
}
}

48
ChatBoxExtensions/Main.cs Normal file
View file

@ -0,0 +1,48 @@
using MelonLoader;
using NAK.Melons.ChatBoxExtensions.InputModules;
namespace NAK.Melons.ChatBoxExtensions;
public class ChatBoxExtensions : MelonMod
{
internal static MelonLogger.Instance Logger;
internal static InputModuleChatBoxExtensions InputModule;
public override void OnInitializeMelon()
{
Logger = LoggerInstance;
if (!MelonMod.RegisteredMelons.Any(it => it.Info.Name == "ChatBox"))
{
Logger.Error("ChatBox was not found!");
return;
}
ApplyIntegrations();
}
void ApplyIntegrations()
{
Integrations.ChatBoxCommands.RegisterCommands();
Integrations.ChilloutVRBaseCommands.RegisterCommands();
ApplyPatches(typeof(HarmonyPatches.CVRInputManagerPatches));
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "PlayerRagdollMod"))
{
Integrations.PlayerRagdollModCommands.RegisterCommands();
}
}
void ApplyPatches(Type type)
{
try
{
HarmonyInstance.PatchAll(type);
}
catch (Exception e)
{
Logger.Msg($"Failed while patching {type.Name}!");
Logger.Error(e);
}
}
}

View file

@ -0,0 +1,32 @@
using ChatBoxExtensions.Properties;
using MelonLoader;
using System.Reflection;
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyTitle(nameof(NAK.Melons.ChatBoxExtensions))]
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
[assembly: AssemblyProduct(nameof(NAK.Melons.ChatBoxExtensions))]
[assembly: MelonInfo(
typeof(NAK.Melons.ChatBoxExtensions.ChatBoxExtensions),
nameof(NAK.Melons.ChatBoxExtensions),
AssemblyInfoParams.Version,
AssemblyInfoParams.Author,
downloadLink: "https://github.com/NotAKidOnSteam/ChatBoxExtensions"
)]
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
[assembly: MelonOptionalDependencies("ChatBox", "PlayerRagdollMod")]
[assembly: HarmonyDontPatchAll]
namespace ChatBoxExtensions.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "1.0.0";
public const string Author = "NotAKidoS";
}

View file

@ -0,0 +1,23 @@
{
"_id": 129,
"name": "ChatBoxExtensions",
"modversion": "1.0.1",
"gameversion": "2022r170",
"loaderversion": "0.5.7",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "Prevents VRIK from using toe bones in VR & optionaly FBT.\n\nVRIK calculates weird center of mass when toes are mapped, so it is sometimes desired to unmap toes to prevent an avatars feet from resting far back.\n\nPlease see the README for relevant imagery detailing the problem.",
"searchtags": [
"toes",
"vrik",
"ik",
"feet"
],
"requirements": [
"None"
],
"downloadlink": "https://github.com/NotAKidOnSteam/ChatBoxExtensions/releases/download/v1.0.1/ChatBoxExtensions.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/ChatBoxExtensions/",
"changelog": "- Initial Release\n- No double patching. Bad. Stinky. Dont do it.",
"embedcolor": "#ffc700"
}