Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepoEventsBhaptics v2.1.0
RepoEventsBhaptics.dll
Decompiled 10 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Photon.Pun; using UnityEngine; using tact_csharp2; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RepoEventsBhaptics")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RepoEventsBhaptics")] [assembly: AssemblyTitle("RepoEventsBhaptics")] [assembly: AssemblyVersion("1.0.0.0")] namespace RepoEventsHaptics { [BepInPlugin("com.dylan.repoevents", "REPO bHaptics", "1.0.0")] public class RepoEventsHaptics : BaseUnityPlugin { private static bool isHolding = false; internal static bool FloaterSmashJustHappened = false; internal static bool PlayerJustDied = false; private static string appId = "692b843fe3348ff1af12474b"; private static string sdkKey = "iqYVDIQZUv1ZUA6eq3RS"; private const float ConnectionCheckIntervalSeconds = 15f; private bool reconnectInProgress; private bool startedBhapticsPlayer; private bool shuttingDown; private bool sdkInitialized; private int startupInitAttempt; private const int StartupInitAttempts = 10; private const float StartupInitRetrySeconds = 1.5f; private Coroutine initCoroutine; private bool isQuitting; private bool startupInitStartedLogged; private bool startupInitFailedLogged; private void Awake() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"RepoEventsHaptics plugin loaded (grab + collision + gun logging + item upgrades)."); EnsureBhapticsPlayerRunning(); startupInitAttempt = 0; TryInitializeBhapticsOnce(); if (!sdkInitialized) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] Scheduling startup retries."); ((MonoBehaviour)this).InvokeRepeating("TryInitializeBhapticsOnce", 1.5f, 1.5f); } try { bool flag = SemiFunc.IsMasterClientOrSingleplayer(); ((BaseUnityPlugin)this).Logger.LogInfo((object)(flag ? "[HAPTIC DEBUG] Game started in SINGLEPLAYER mode." : "[HAPTIC DEBUG] Game started in MULTIPLAYER mode.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] Could not determine game mode at startup: " + ex.Message)); } try { Harmony val = new Harmony("com.dylan.repoevents"); val.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] Harmony PatchAll completed."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[HAPTIC DEBUG] Harmony PatchAll failed: {arg}"); } ((MonoBehaviour)this).InvokeRepeating("CheckBhapticsConnection", 15f, 15f); PlayerCollision val2 = Object.FindObjectOfType<PlayerCollision>(); if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject.GetComponent<PlayerCollisionRelay>() == (Object)null) { ((Component)val2).gameObject.AddComponent<PlayerCollisionRelay>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"PlayerCollisionRelay attached to player."); } } private void TryInitializeBhapticsOnce() { if (shuttingDown) { ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); return; } if (sdkInitialized) { ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); return; } if (!startupInitStartedLogged) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] Startup initialization started."); startupInitStartedLogged = true; } startupInitAttempt++; try { bool flag = false; try { flag = BhapticsSDK2Wrapper.wsIsConnected(); } catch { } if (flag) { sdkInitialized = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] bHaptics already connected at startup."); ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); return; } if (!BhapticsSDK2Wrapper.isPlayerRunning()) { bool flag2 = BhapticsSDK2Wrapper.launchPlayer(tryLaunch: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] Startup launch attempt={flag2}"); } bool flag3 = false; try { flag3 = BhapticsSDK2Wrapper.reInitMessage(sdkKey, appId, ""); } catch { } if (!flag3) { try { flag3 = BhapticsSDK2Wrapper.registryAndInit(sdkKey, appId, ""); } catch { } } bool flag4 = false; try { flag4 = BhapticsSDK2Wrapper.wsIsConnected(); } catch { } if (flag3 && flag4) { sdkInitialized = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] bHaptics startup initialization succeeded."); ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); return; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] Startup init exception: " + ex.Message)); } if (startupInitAttempt >= 10) { if (!startupInitFailedLogged) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[HAPTIC DEBUG] bHaptics startup initialization failed after max attempts."); startupInitFailedLogged = true; } ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); } } private void OnApplicationQuit() { isQuitting = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] OnApplicationQuit fired."); ShutdownBhaptics(allowClosePlayerProcess: true); } private void OnDestroy() { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] OnDestroy fired. isQuitting={isQuitting}"); if (isQuitting) { ShutdownBhaptics(allowClosePlayerProcess: false); } } private void ShutdownBhaptics(bool allowClosePlayerProcess) { if (!shuttingDown) { shuttingDown = true; try { ((MonoBehaviour)this).CancelInvoke("CheckBhapticsConnection"); ((MonoBehaviour)this).CancelInvoke("TryInitializeBhapticsOnce"); } catch { } try { BhapticsSDK2Wrapper.stopAll(); } catch { } try { BhapticsSDK2Wrapper.wsClose(); } catch { } if (allowClosePlayerProcess && startedBhapticsPlayer) { TryCloseBhapticsPlayerProcess(); } } } private void TryCloseBhapticsPlayerProcess() { try { Process[] processesByName = Process.GetProcessesByName("bHapticsPlayer"); foreach (Process process in processesByName) { try { if (!process.HasExited) { process.CloseMainWindow(); if (!process.WaitForExit(2000)) { process.Kill(); } } } catch { } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] Failed to close bHaptics Player process: " + ex.Message)); } } private void CheckBhapticsConnection() { bool flag; try { flag = BhapticsSDK2Wrapper.wsIsConnected(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] wsIsConnected check failed: " + ex.Message)); return; } if (flag || reconnectInProgress) { return; } reconnectInProgress = true; try { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[HAPTIC DEBUG] bHaptics socket disconnected. Attempting reconnection..."); try { if (!BhapticsSDK2Wrapper.isPlayerRunning()) { bool flag2 = BhapticsSDK2Wrapper.launchPlayer(tryLaunch: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] bHaptics Player launch attempted: {flag2}"); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] Could not verify/launch bHaptics Player: " + ex2.Message)); } try { BhapticsSDK2Wrapper.wsClose(); } catch { } bool flag3 = false; try { flag3 = BhapticsSDK2Wrapper.reInitMessage(sdkKey, appId, ""); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] reInitMessage result={flag3}"); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(ex3.Message ?? "")); } if (!flag3) { try { flag3 = BhapticsSDK2Wrapper.registryAndInit(sdkKey, appId, ""); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] registryAndInit retry result={flag3}"); } catch (Exception ex4) { ((BaseUnityPlugin)this).Logger.LogError((object)("[HAPTIC DEBUG] registryAndInit retry failed: " + ex4.Message)); } } bool flag4 = false; try { flag4 = BhapticsSDK2Wrapper.wsIsConnected(); } catch { } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] Reconnect finished. connected={flag4}"); } finally { reconnectInProgress = false; } } private void EnsureBhapticsPlayerRunning() { try { if (!BhapticsSDK2Wrapper.isPlayerInstalled()) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[HAPTIC DEBUG] bHaptics Player is not installed."); return; } if (BhapticsSDK2Wrapper.isPlayerRunning()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HAPTIC DEBUG] bHaptics Player already running."); return; } bool flag = (startedBhapticsPlayer = BhapticsSDK2Wrapper.launchPlayer(tryLaunch: true)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[HAPTIC DEBUG] bHaptics Player launch requested. success={flag}"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HAPTIC DEBUG] Failed to start bHaptics Player: " + ex.Message)); } } internal static int Play(string eventId) { try { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[bHaptics] Play called for event: " + eventId)); Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[HAPTIC DEBUG] About to play haptic event: " + eventId)); return BhapticsSDK2Wrapper.play(eventId); } catch (Exception ex) { Logger.CreateLogSource("RepoEventsHaptics").LogError((object)("Play failed for " + eventId + ": " + ex.Message)); return -1; } } internal static void Stop(string eventId) { try { BhapticsSDK2Wrapper.stopByEventId(eventId); } catch (Exception ex) { Logger.CreateLogSource("RepoEventsHaptics").LogError((object)("Stop failed for " + eventId + ": " + ex.Message)); } } internal static void OnGrabStarted() { if (!isHolding) { Play("grabfeedback"); isHolding = true; } } internal static void OnGrabEnded() { if (isHolding) { Stop("grabfeedback"); isHolding = false; } } internal static void OnCollisionStarted(Collision collision, PlayerCollision player) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Play("collisionfeedback"); ContactPoint[] contacts = collision.contacts; for (int i = 0; i < contacts.Length; i++) { ContactPoint val = contacts[i]; Vector3 val2 = ((Component)player).transform.InverseTransformPoint(((ContactPoint)(ref val)).point); Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"Collision START at local {val2} with {((Object)collision.gameObject).name}"); } } internal static void OnCollisionEnded(Collision collision, PlayerCollision player) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Stop("collisionfeedback"); ContactPoint[] contacts = collision.contacts; for (int i = 0; i < contacts.Length; i++) { ContactPoint val = contacts[i]; Vector3 val2 = ((Component)player).transform.InverseTransformPoint(((ContactPoint)(ref val)).point); Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"Collision END at local {val2} with {((Object)collision.gameObject).name}"); } } internal static void OnGunFired(ItemGun gun) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[HAPTIC DEBUG] OnGunFired called. Gun type: " + ((object)gun).GetType().FullName + ", Gun name: " + ((Object)gun).name)); object obj = AccessTools.Field(((object)gun).GetType(), "physGrabObject")?.GetValue(gun); if (obj == null) { Logger.CreateLogSource("RepoEventsHaptics").LogWarning((object)"[HAPTIC DEBUG] physGrabObject is null. Cannot resolve player."); return; } object obj2 = AccessTools.Field(obj.GetType(), "lastPlayerGrabbing")?.GetValue(obj); if (obj2 == null) { Logger.CreateLogSource("RepoEventsHaptics").LogWarning((object)"[HAPTIC DEBUG] lastPlayerGrabbing is null. Cannot resolve player."); return; } Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"[HAPTIC DEBUG] lastPlayerGrabbing type: {obj2.GetType().FullName}, value: {obj2}"); PlayerAvatar val = (PlayerAvatar)((obj2 is PlayerAvatar) ? obj2 : null); if ((Object)(object)val == (Object)null) { Type type = obj2.GetType(); PropertyInfo propertyInfo = type.GetProperty("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("avatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null) { object? value = propertyInfo.GetValue(obj2, null); val = (PlayerAvatar)((value is PlayerAvatar) ? value : null); } } if ((Object)(object)val == (Object)null) { Type type2 = obj2.GetType(); FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"[HAPTIC DEBUG] lastPlayerGrabbing field: {fieldInfo.Name}, type: {fieldInfo.FieldType}"); } PropertyInfo[] properties = type2.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo2 in properties) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"[HAPTIC DEBUG] lastPlayerGrabbing property: {propertyInfo2.Name}, type: {propertyInfo2.PropertyType}"); } Logger.CreateLogSource("RepoEventsHaptics").LogWarning((object)"[HAPTIC DEBUG] playerAvatar is null. Cannot resolve player."); return; } PhotonView component = ((Component)val).GetComponent<PhotonView>(); if ((Object)(object)component == (Object)null) { Logger.CreateLogSource("RepoEventsHaptics").LogWarning((object)"[HAPTIC DEBUG] PhotonView is null on playerAvatar."); return; } bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (!flag && !component.IsMine) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] PhotonView is not mine. Not playing haptic."); return; } if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check."); } string name = ((Object)gun).name; string text; if (name.Contains("Shotgun")) { text = "playershootsshotgun"; } else if (name.Contains("Shockwave")) { text = "playershootsshockwave"; } else if (name.Contains("Handgun")) { text = "playershootspistol"; } else if (name.Contains("Stun")) { text = "playershootsstun"; } else if (name.Contains("Laser")) { text = "playershootslaser"; } else { text = "playershootsgeneric"; Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[HAPTIC DEBUG] Uncaptured weapon: '" + name + "'. Playing generic haptic event.")); } Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[HAPTIC DEBUG] Playing haptic event '" + text + "' for gun '" + name + "'.")); Play(text); } internal static void OnStaffCast(MonoBehaviour staff) { PhotonView component = ((Component)staff).GetComponent<PhotonView>(); bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (!flag && ((Object)(object)component == (Object)null || !component.IsMine)) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] StaffCast: PhotonView is not mine or null. Not playing haptic."); return; } if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] StaffCast: Singleplayer mode detected, skipping PhotonView check."); } string text = ((Object)staff).name ?? ((object)staff).GetType().Name; string text2 = ((text.IndexOf("Item Staff Void", StringComparison.OrdinalIgnoreCase) >= 0) ? "staff_cast_void" : ((text.IndexOf("Item Staff Torque", StringComparison.OrdinalIgnoreCase) >= 0) ? "staff_cast_torque" : ((text.IndexOf("Item Staff Zero Gravity", StringComparison.OrdinalIgnoreCase) < 0) ? "staff_cast_generic" : "staff_cast_zerog"))); Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)("[HAPTIC DEBUG] Staff cast detected: '" + text + "', playing haptic '" + text2 + "'.")); Play(text2); } } [HarmonyPatch(typeof(ItemGun), "Shoot")] internal class ItemGunShootPatch { private static void Postfix(ItemGun __instance) { RepoEventsHaptics.OnGunFired(__instance); } } [HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")] internal class GrabStartedPatch { private static void Postfix(PhysGrabObject __instance) { FieldInfo fieldInfo = AccessTools.Field(typeof(PhysGrabObject), "heldByLocalPlayer"); if (fieldInfo != null && (bool)fieldInfo.GetValue(__instance)) { RepoEventsHaptics.OnGrabStarted(); } } } [HarmonyPatch(typeof(PhysGrabObject), "GrabEnded")] internal class GrabEndedPatch { private static void Postfix(PhysGrabObject __instance) { FieldInfo fieldInfo = AccessTools.Field(typeof(PhysGrabObject), "heldByLocalPlayer"); if (fieldInfo != null && (bool)fieldInfo.GetValue(__instance)) { RepoEventsHaptics.OnGrabEnded(); } } } [HarmonyPatch(typeof(ItemStaffVoid), "CastSpell", new Type[] { typeof(bool) })] internal class ItemStaffVoidCastSpellPatch { private static void Postfix(ItemStaffVoid __instance) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] ItemStaffVoidCastSpellPatch.Postfix called."); RepoEventsHaptics.OnStaffCast((MonoBehaviour)(object)__instance); } } [HarmonyPatch(typeof(ItemStaffTorque), "CastSpell", new Type[] { typeof(bool) })] internal class ItemStaffTorqueCastSpellPatch { private static void Postfix(ItemStaffTorque __instance) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] ItemStaffTorqueCastSpellPatch.Postfix called."); RepoEventsHaptics.OnStaffCast((MonoBehaviour)(object)__instance); } } [HarmonyPatch(typeof(ItemStaffZeroGravity), "CastSpell", new Type[] { typeof(bool) })] internal class ItemStaffZeroGravityCastSpellPatch { private static void Postfix(ItemStaffZeroGravity __instance) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] ItemStaffZeroGravityCastSpellPatch.Postfix called."); RepoEventsHaptics.OnStaffCast((MonoBehaviour)(object)__instance); } } public class PlayerCollisionRelay : MonoBehaviour { private PlayerCollision player; private void Awake() { player = ((Component)this).GetComponent<PlayerCollision>(); } private void OnCollisionEnter(Collision other) { if ((Object)(object)player != (Object)null) { RepoEventsHaptics.OnCollisionStarted(other, player); } } private void OnCollisionExit(Collision other) { if ((Object)(object)player != (Object)null) { RepoEventsHaptics.OnCollisionEnded(other, player); } } } [HarmonyPatch(typeof(ItemUpgrade), "PlayerUpgrade")] internal class ItemUpgradePatch { private static FieldInfo playerIdField; private static void Postfix(ItemUpgrade __instance) { try { ItemToggle component = ((Component)__instance).GetComponent<ItemToggle>(); if ((Object)(object)component == (Object)null) { return; } if (playerIdField == null) { playerIdField = typeof(ItemToggle).GetField("playerTogglePhotonID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(ItemToggle).GetField("field_Private_Int32_0", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(ItemToggle).GetField("field_Public_Int32_0", BindingFlags.Instance | BindingFlags.Public) ?? typeof(ItemToggle).GetField("<playerTogglePhotonID>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); } if (playerIdField == null) { return; } int num = (int)playerIdField.GetValue(component); PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(num); if ((Object)(object)val == (Object)null) { return; } PhotonView component2 = ((Component)val).GetComponent<PhotonView>(); bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (flag || (!((Object)(object)component2 == (Object)null) && component2.IsMine)) { if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check (ItemUpgradePatch)."); } string name = ((Object)__instance).name; string eventId = "playerupgrade_generic"; if (name.Contains("Tumble Climb")) { eventId = "playerupgrade_tumbleclimb"; } else if (name.Contains("Map Player Count")) { eventId = "playerupgrade_mapcount"; } else if (name.Contains("Sprint Speed")) { eventId = "playerupgrade_sprintspeed"; } else if (name.Contains("Grab Range")) { eventId = "playerupgrade_grabrange"; } else if (name.Contains("Energy")) { eventId = "playerupgrade_energy"; } else if (name.Contains("Grab Strength")) { eventId = "playerupgrade_grabstrength"; } else if (name.Contains("Extra Jump")) { eventId = "playerupgrade_extrajump"; } else if (name.Contains("Health")) { eventId = "playerupgrade_health"; } else if (name.Contains("Tumble Wing")) { eventId = "playerupgrade_tumblewings"; } else if (name.Contains("Tumble Launch")) { eventId = "playerupgrade_tumblelaunch"; } else if (name.Contains("Death Head Battery")) { eventId = "playerupgrade_deadhead"; } else if (name.Contains("Crouch Rest")) { eventId = "playerupgrade_crouchrest"; } RepoEventsHaptics.Play(eventId); } } catch (Exception ex) { Logger.CreateLogSource("RepoEventsHaptics").LogError((object)("ItemUpgradePatch failed: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerDeathEffects), "Trigger")] internal class PlayerDeathEffectsTriggerPatch { private static void Postfix(PlayerDeathEffects __instance) { try { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] PlayerDeathEffects.Trigger postfix called."); PlayerAvatar componentInParent = ((Component)__instance).GetComponentInParent<PlayerAvatar>(); if ((Object)(object)componentInParent == (Object)null) { Logger.CreateLogSource("RepoEventsHaptics").LogWarning((object)"[HAPTIC DEBUG] Death patch: PlayerAvatar not found."); return; } bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (!flag) { PhotonView component = ((Component)componentInParent).GetComponent<PhotonView>(); if ((Object)(object)component == (Object)null || !component.IsMine) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Death patch: Not local player in multiplayer."); return; } } RepoEventsHaptics.PlayerJustDied = true; int num = RepoEventsHaptics.Play("playerdeath"); Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"[HAPTIC DEBUG] playerdeath played. reqId={num}"); } catch (Exception ex) { Logger.CreateLogSource("RepoEventsHaptics").LogError((object)("PlayerDeathEffectsTriggerPatch failed: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerTumble), "ImpactHurtSet")] internal class FloaterImpactHurtPatch { private static void Postfix(PlayerTumble __instance, object[] __args) { try { PhotonView componentInParent = ((Component)__instance).GetComponentInParent<PhotonView>(); if ((Object)(object)componentInParent == (Object)null) { return; } bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (flag || componentInParent.IsMine) { if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check."); } RepoEventsHaptics.FloaterSmashJustHappened = true; RepoEventsHaptics.Play("hurt_floater_smash"); } } catch { } } } [HarmonyPatch(typeof(EnemyHeartHugger), "StateLure")] internal class HeartHuggerDistanceScaledPullPatch { private static void Postfix(EnemyHeartHugger __instance) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) object? obj = typeof(EnemyHeartHugger).GetField("currentTarget", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); PlayerAvatar val = (PlayerAvatar)((obj is PlayerAvatar) ? obj : null); if ((Object)(object)val == (Object)null) { return; } PhotonView component = ((Component)val).GetComponent<PhotonView>(); bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (((Object)(object)component != (Object)null && component.IsMine) || ((Object)(object)PlayerAvatar.instance != (Object)null && (Object)(object)val == (Object)(object)PlayerAvatar.instance) || flag) { if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check (HeartHuggerDistanceScaledPullPatch)."); } float num = Vector3.Distance(((Component)val).transform.position, ((Component)__instance).transform.position); RepoEventsHaptics.Play("heart_hugger_pull"); } } } [HarmonyPatch(typeof(PlayerHealth))] public static class GenericHurtHapticPatch { [HarmonyPostfix] [HarmonyPatch("Hurt", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(bool) })] public static void Postfix_GenericHurt(PlayerHealth __instance, int damage, bool savingGrace, int enemyIndex, bool hurtByHeal) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)$"[HAPTIC DEBUG] PlayerHealth.Hurt postfix called: damage={damage}, savingGrace={savingGrace}, enemyIndex={enemyIndex}, hurtByHeal={hurtByHeal}"); try { if (damage <= 0) { return; } bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (!flag) { PhotonView componentInParent = ((Component)__instance).GetComponentInParent<PhotonView>(); if ((Object)(object)componentInParent == (Object)null) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Skipping: PhotonView is null (multiplayer)"); return; } if (!componentInParent.IsMine) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Skipping: PhotonView is not mine (multiplayer)"); return; } } else { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check."); } if (RepoEventsHaptics.FloaterSmashJustHappened) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Skipping haptic: FloaterSmashJustHappened was true"); RepoEventsHaptics.FloaterSmashJustHappened = false; } else if (RepoEventsHaptics.PlayerJustDied) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Skipping haptic: PlayerJustDied was true"); RepoEventsHaptics.PlayerJustDied = false; } else if (damage < 33) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Playing haptic: player_hurt_low"); RepoEventsHaptics.Play("player_hurt_low"); } else if (damage < 67) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Playing haptic: player_hurt_medium"); RepoEventsHaptics.Play("player_hurt_medium"); } else { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Playing haptic: player_hurt_high"); RepoEventsHaptics.Play("player_hurt_high"); } } catch (Exception arg) { Logger.CreateLogSource("RepoEventsHaptics").LogError((object)$"[GenericHurt] Error in Hurt postfix: {arg}"); } } } [HarmonyPatch(typeof(FloaterAttackLogic), "StateLevitateFixed")] internal class FloaterLevitateLoopPatch { private static void Postfix(FloaterAttackLogic __instance) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 FieldInfo field = typeof(FloaterAttackLogic).GetField("state", BindingFlags.Instance | BindingFlags.NonPublic); FloaterAttackState val = (FloaterAttackState)field.GetValue(__instance); if ((int)val != 1) { return; } FieldInfo field2 = typeof(FloaterAttackLogic).GetField("capturedPlayerAvatars", BindingFlags.Instance | BindingFlags.NonPublic); if (!(field2.GetValue(__instance) is List<PlayerAvatar> list)) { return; } foreach (PlayerAvatar item in list) { if ((Object)(object)item == (Object)null) { continue; } PhotonView component = ((Component)item).GetComponent<PhotonView>(); bool flag = false; try { flag = SemiFunc.IsMasterClientOrSingleplayer(); } catch { } if (!(((Object)(object)component != (Object)null && component.IsMine) || ((Object)(object)PlayerAvatar.instance != (Object)null && (Object)(object)item == (Object)(object)PlayerAvatar.instance) || flag)) { continue; } if (flag) { Logger.CreateLogSource("RepoEventsHaptics").LogInfo((object)"[HAPTIC DEBUG] Singleplayer mode detected, skipping PhotonView check (FloaterLevitateLoopPatch)."); } RepoEventsHaptics.Play("floater_levitate_loop"); break; } } } } namespace tact_csharp2 { public class BhapticsSDK2Wrapper { private const string ModuleName = "bhaptics_library"; [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool registryAndInit(string sdkAPIKey, string workspaceId, string initData); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool registryAndInitHost(string sdkAPIKey, string workspaceId, string initData, string url); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool wsIsConnected(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern void wsClose(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool reInitMessage(string sdkAPIKey, string workspaceId, string initData); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int play(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int playParam(string eventId, int requestId, float intensity, float duration, float angleX, float offsetY); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern void playWithStartTime(string eventId, int requestId, int startMillis, float intensity, float duration, float angleX, float offsetY); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int playLoop(string eventId, int requestId, float intensity, float duration, float angleX, float offsetY, int interval, int maxCount); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int pause(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool resume(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool stop(int requestId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool stopByEventId(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool stopAll(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isPlaying(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isPlayingByRequestId(int requestId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isPlayingByEventId(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int playDot(int requestId, int position, int durationMillis, int[] motors, int size); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int playWaveform(int requestId, int position, int[] motorValues, int[] playTimeValues, int[] shapeValues, int motorLen); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int playPath(int requestId, int position, float[] xValues, float[] yValues, int[] intensityValues, int Len); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isbHapticsConnected(int position); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool ping(string address); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool pingAll(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool swapPosition(string address); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool setDeviceVsm(string address, int vsm); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr getDeviceInfoJson(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isPlayerInstalled(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool isPlayerRunning(); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool launchPlayer(bool tryLaunch); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern int getEventTime(string eventId); [DllImport("bhaptics_library", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr getHapticMappingsJson(); } }