Initial Cult of the Shock plugin
This commit is contained in:
commit
8aa772cc8e
7 changed files with 320 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin
|
||||
obj
|
29
Cult_of_the_Shock.csproj
Normal file
29
Cult_of_the_Shock.csproj
Normal file
|
@ -0,0 +1,29 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyName>Cult_of_the_Shock</AssemblyName>
|
||||
<Product>Cult of the Shock</Product>
|
||||
<Version>1.0.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<RestoreAdditionalProjectSources>
|
||||
https://api.nuget.org/v3/index.json;
|
||||
https://nuget.bepinex.dev/v3/index.json;
|
||||
https://nuget.samboy.dev/v3/index.json
|
||||
</RestoreAdditionalProjectSources>
|
||||
<RootNamespace>Cult_of_the_Shock</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all" />
|
||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="2.*" />
|
||||
<PackageReference Include="CultOfTheLamb.GameLibs" Version="1.4.6.596-r.0" />
|
||||
<PackageReference Include="UnityEngine.Modules" Version="2021.3.16" IncludeAssets="compile" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
</Project>
|
24
Cult_of_the_Shock.sln
Normal file
24
Cult_of_the_Shock.sln
Normal file
|
@ -0,0 +1,24 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.2.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cult of the Shock", "Cult_of_the_Shock.csproj", "{CEAACF8E-CA24-1B25-FC4E-1D718312D8A1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CEAACF8E-CA24-1B25-FC4E-1D718312D8A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CEAACF8E-CA24-1B25-FC4E-1D718312D8A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CEAACF8E-CA24-1B25-FC4E-1D718312D8A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CEAACF8E-CA24-1B25-FC4E-1D718312D8A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2B7C2765-F52A-4A8D-BA5E-B4CBF9C9C57B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
38
Hooks.cs
Normal file
38
Hooks.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
using static Health;
|
||||
|
||||
namespace Cult_of_the_Shock
|
||||
{
|
||||
|
||||
[HarmonyPatch]
|
||||
public class Hooks
|
||||
{
|
||||
private static Shocker Shocker;
|
||||
|
||||
public static void OnDamage(GameObject attacker, Vector3 attackLocation, float damage, AttackTypes attackType, AttackFlags attackFlag)
|
||||
{
|
||||
Plugin.Logger.LogInfo($"PlayerController.Health.OnDamage: " + damage);
|
||||
Shocker.Shock(Plugin.Config.GetDamageJson());
|
||||
}
|
||||
|
||||
public static void OnDie(GameObject Attacker, Vector3 AttackLocation, Health Victim, AttackTypes AttackType, AttackFlags AttackFlags)
|
||||
{
|
||||
Plugin.Logger.LogInfo($"PlayerController.Health.OnDie");
|
||||
Shocker.Shock(Plugin.Config.GetDeathJson());
|
||||
}
|
||||
|
||||
public static void OnHit(GameObject Attacker, Vector3 AttackLocation, AttackTypes AttackType, bool FromBehind)
|
||||
{
|
||||
Plugin.Logger.LogInfo($"OnHit: " + Attacker);
|
||||
}
|
||||
|
||||
public static void OnEnable(PlayerController __instance)
|
||||
{
|
||||
__instance.health.OnDamaged += OnDamage;
|
||||
__instance.health.OnDie += OnDie;
|
||||
Shocker = new Shocker();
|
||||
Plugin.Config.Reload();
|
||||
}
|
||||
}
|
||||
}
|
53
Plugin.cs
Normal file
53
Plugin.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using HarmonyLib;
|
||||
using Unity.VideoHelper;
|
||||
|
||||
namespace Cult_of_the_Shock
|
||||
{
|
||||
|
||||
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
|
||||
public class Plugin : BaseUnityPlugin
|
||||
{
|
||||
internal static new ManualLogSource Logger;
|
||||
|
||||
internal static new ShockConfig Config;
|
||||
|
||||
internal readonly static Harmony Harmony = new Harmony(MyPluginInfo.PLUGIN_GUID);
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
Logger = base.Logger;
|
||||
Config = new ShockConfig(base.Config);
|
||||
|
||||
Logger.LogInfo($"Plugin {MyPluginInfo.PLUGIN_GUID} is loaded! Prepare for a shocking experiance...");
|
||||
|
||||
PatchMethods();
|
||||
}
|
||||
|
||||
private void PatchMethods()
|
||||
{
|
||||
MethodInfo method = null;
|
||||
|
||||
foreach (var m in typeof(PlayerController).GetRuntimeMethods())
|
||||
{
|
||||
if (m.Name == "OnEnable")
|
||||
{
|
||||
method = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogDebug("A possible method: " + method);
|
||||
Harmony.Patch(
|
||||
method,
|
||||
postfix: new HarmonyMethod(typeof(Hooks).GetMethod("OnEnable"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: https://github.com/InfernoDragon0/CotLMods/blob/4a157380362dccb1d8564368367ac3588eb5fa06/Patches/KnucklebonesPatch.cs#L54
|
137
ShockConfig.cs
Normal file
137
ShockConfig.cs
Normal file
|
@ -0,0 +1,137 @@
|
|||
using BepInEx.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Cult_of_the_Shock
|
||||
{
|
||||
public class ShockConfig
|
||||
{
|
||||
private static HashSet<string> ACTIONS = new HashSet<string> { "Shock", "Vibrate", "Sound" };
|
||||
|
||||
private readonly ConfigFile config;
|
||||
|
||||
private readonly ConfigEntry<string> url;
|
||||
private readonly ConfigEntry<string> token;
|
||||
private readonly ConfigEntry<string> shockerIds;
|
||||
|
||||
private readonly ConfigEntry<string> deathAction;
|
||||
private readonly ConfigEntry<string> deathIntensity;
|
||||
private readonly ConfigEntry<string> deathDuration;
|
||||
|
||||
private readonly ConfigEntry<string> damageAction;
|
||||
private readonly ConfigEntry<string> damageIntensity;
|
||||
private readonly ConfigEntry<string> damageDuration;
|
||||
|
||||
public ShockConfig(ConfigFile config)
|
||||
{
|
||||
this.config = config;
|
||||
|
||||
url = config.Bind("Shocker",
|
||||
"url",
|
||||
"https://api.openshock.app",
|
||||
"The base url of your api (without trailing slash)");
|
||||
token = config.Bind("Shocker",
|
||||
"token",
|
||||
"secrettoken",
|
||||
"Your API token");
|
||||
shockerIds = config.Bind("Shocker",
|
||||
"shockerIds",
|
||||
"uuid1,uuid2",
|
||||
"Ids of your shockers (separated by commas, to spaces)");
|
||||
|
||||
deathAction = config.Bind("Death",
|
||||
"action",
|
||||
"Nothing",
|
||||
"What to do on death (Nothing, Shock, Vibrate, Sound)");
|
||||
deathIntensity = config.Bind("Death",
|
||||
"intensity",
|
||||
"1",
|
||||
"Intensity on death (1 - 100)");
|
||||
deathDuration = config.Bind("Death",
|
||||
"duration",
|
||||
"300",
|
||||
"Duration on death in milliseconds (min 300)");
|
||||
|
||||
damageAction = config.Bind("Damage",
|
||||
"action",
|
||||
"Nothing",
|
||||
"What to do on damage (Nothing, Shock, Vibrate, Sound)");
|
||||
damageIntensity = config.Bind("Damage",
|
||||
"intensity",
|
||||
"1",
|
||||
"Intensity on death (1 - 100)");
|
||||
damageDuration = config.Bind("Damage",
|
||||
"duration",
|
||||
"300",
|
||||
"Duration on damage in milliseconds (min 300)");
|
||||
|
||||
config.ConfigReloaded += (_, _) => OnReload();
|
||||
}
|
||||
|
||||
private void OnReload()
|
||||
{
|
||||
Plugin.Logger.LogInfo($"Config reloaded");
|
||||
}
|
||||
|
||||
public string GetDeathJson()
|
||||
{
|
||||
if (!ACTIONS.Contains(deathAction.Value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var controls = GetIds().Select(id =>
|
||||
$@"{{
|
||||
""id"": ""{id}"",
|
||||
""type"": ""{deathAction.Value}"",
|
||||
""intensity"": {deathIntensity.Value},
|
||||
""duration"": {deathDuration.Value},
|
||||
""exclusive"": false
|
||||
}}"
|
||||
);
|
||||
|
||||
return "[" + string.Join(",\n", controls) + "]";
|
||||
}
|
||||
|
||||
public string GetDamageJson()
|
||||
{
|
||||
if (!ACTIONS.Contains(damageAction.Value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var controls = GetIds().Select(id =>
|
||||
$@"{{
|
||||
""id"": ""{id}"",
|
||||
""type"": ""{damageAction.Value}"",
|
||||
""intensity"": {damageIntensity.Value},
|
||||
""duration"": {damageDuration.Value},
|
||||
""exclusive"": false
|
||||
}}"
|
||||
);
|
||||
|
||||
return "[" + string.Join(",\n", controls) + "]";
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
config.Reload();
|
||||
}
|
||||
|
||||
private string[] GetIds()
|
||||
{
|
||||
return shockerIds.Value.Split(',');
|
||||
}
|
||||
|
||||
public string GetToken()
|
||||
{
|
||||
return token.Value;
|
||||
}
|
||||
|
||||
public string GetURL()
|
||||
{
|
||||
return url.Value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
Shocker.cs
Normal file
37
Shocker.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using BepInEx.Configuration;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Cult_of_the_Shock
|
||||
{
|
||||
public class Shocker
|
||||
{
|
||||
public void Shock(string json)
|
||||
{
|
||||
var uwr = new UnityWebRequest(Plugin.Config.GetURL() + "/1/shockers/control", "POST");
|
||||
uwr.SetTimeoutMsec(1000);
|
||||
|
||||
uwr.SetRequestHeader("OpenShockToken", Plugin.Config.GetToken());
|
||||
uwr.SetRequestHeader("Content-Type", "application/json");
|
||||
|
||||
byte[] requestData = new UTF8Encoding().GetBytes(json);
|
||||
uwr.uploadHandler = new UploadHandlerRaw(requestData);
|
||||
uwr.downloadHandler = new DownloadHandlerBuffer();
|
||||
|
||||
uwr.SendWebRequest();
|
||||
while (!uwr.isDone)
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
|
||||
if (uwr.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Plugin.Logger.LogError("Error while Sending Request: " + uwr.error);
|
||||
Plugin.Logger.LogError(uwr.downloadHandler.text);
|
||||
Plugin.Logger.LogError("Sent JSON: " + json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue