using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using MelonLoader;
using Microsoft.CodeAnalysis;
using PetTheInkling;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Class1), "PetTheInkling", "1.0", "AlexHouk, TheMrEvil", null)]
[assembly: MelonGame("Alvios", "Vellum")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PetTheInkling")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5b43ae245f43b42654b0494322f618d7f39fc7ec")]
[assembly: AssemblyProduct("PetTheInkling")]
[assembly: AssemblyTitle("PetTheInkling")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace PetTheInkling
{
[HarmonyPatch(typeof(AIDiageticInteraction), "Select")]
public static class DiageticInteractionPatch
{
public static void Postfix(AIDiageticInteraction __instance)
{
((DiageticOption)__instance).OnInteract?.Invoke();
__instance.InternalCooldown = __instance.Cooldown;
}
}
public class Class1 : MelonMod
{
private bool modInitialized = false;
private FieldInfo petOwnerIDField = null;
private MethodInfo hasTagMethod = null;
private PropertyInfo viewIDProperty = null;
private float lastPetCheckTime = 0f;
private const float PET_CHECK_INTERVAL = 3f;
public override void OnApplicationStart()
{
try
{
petOwnerIDField = typeof(AIControl).GetField("PetOwnerID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (petOwnerIDField != null)
{
MelonLogger.Msg("Successfully found PetOwnerID field");
}
else
{
MelonLogger.Warning("PetOwnerID field not found");
}
hasTagMethod = typeof(AIControl).GetMethod("HasTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (hasTagMethod != null)
{
MelonLogger.Msg("Successfully found HasTag method");
}
else
{
MelonLogger.Warning("HasTag method not found");
}
viewIDProperty = typeof(PlayerControl).GetProperty("ViewID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (viewIDProperty == null)
{
viewIDProperty = typeof(PlayerControl).GetProperty("viewID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (viewIDProperty != null)
{
MelonLogger.Msg("Successfully found ViewID property");
}
else
{
MelonLogger.Warning("ViewID property not found");
}
}
catch (Exception ex)
{
MelonLogger.Error("Error finding required members: " + ex.Message);
}
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
MelonLogger.Msg($"Scene loaded: {sceneName} (Build Index: {buildIndex})");
lastPetCheckTime = 0f;
}
public override void OnUpdate()
{
if (Time.time - lastPetCheckTime >= 3f)
{
lastPetCheckTime = Time.time;
CheckAndSetupPets();
}
}
private void CheckAndSetupPets()
{
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
try
{
PlayerControl myInstance = PlayerControl.myInstance;
if ((Object)(object)myInstance == (Object)null)
{
return;
}
AIControl[] array = Object.FindObjectsOfType<AIControl>();
int num = 0;
int playerViewID = GetPlayerViewID(myInstance);
AIControl[] array2 = array;
foreach (AIControl val in array2)
{
try
{
AIDiageticInteraction componentInChildren = ((Component)val).GetComponentInChildren<AIDiageticInteraction>();
if ((Object)(object)componentInChildren != (Object)null && componentInChildren.Label == "Pet")
{
continue;
}
bool flag = false;
int num2 = -1;
if (petOwnerIDField != null)
{
try
{
num2 = (int)petOwnerIDField.GetValue(val);
flag = num2 != -1;
}
catch (Exception ex)
{
MelonLogger.Error("Error accessing PetOwnerID for " + ((Object)val).name + ": " + ex.Message);
}
}
if (!flag)
{
bool flag2 = ((Object)val).name.ToLower().Contains("inkling") || val.AIName.ToLower().Contains("inkling");
bool flag3 = HasTagSafe(val, "Inkling");
bool flag4 = HasTagSafe(val, "Pet");
flag = flag2 || flag3 || flag4;
}
if (flag)
{
MelonLogger.Msg($"Found pet/Inkling: {((Object)val).name} (Owner: {num2})");
AIDiageticInteraction val2 = ((Component)((Component)val).transform.GetChild(0)).gameObject.AddComponent<AIDiageticInteraction>();
val2.Label = "Pet";
((DiageticOption)val2).InteractDistance = 2.5f;
val2.Interactivity = (RepeatType)1;
val2.Cooldown = 3f;
val2.OwnerOnly = false;
val2.Act = (InteractType)0;
SetupPettingAction(val2, val);
num++;
MelonLogger.Msg($"Added pet interaction to Inkling owned by player {num2}");
}
}
catch (Exception ex2)
{
MelonLogger.Error("Error processing AI " + ((Object)val).name + ": " + ex2.Message);
}
}
}
catch (Exception ex3)
{
MelonLogger.Error("Error in CheckAndSetupPets: " + ex3.Message);
}
}
private bool HasTagSafe(AIControl aiControl, string tag)
{
try
{
if (hasTagMethod != null)
{
return (bool)hasTagMethod.Invoke(aiControl, new object[1] { tag });
}
return ((Object)aiControl).name.ToLower().Contains(tag.ToLower()) || aiControl.AIName.ToLower().Contains(tag.ToLower());
}
catch (Exception ex)
{
MelonLogger.Error("Error checking tag " + tag + ": " + ex.Message);
return false;
}
}
private int GetPlayerViewID(PlayerControl player)
{
try
{
if (viewIDProperty != null)
{
return (int)viewIDProperty.GetValue(player);
}
string[] array = new string[5] { "ViewID", "viewID", "ID", "ActorNr", "NetworkId" };
string[] array2 = array;
foreach (string name in array2)
{
PropertyInfo property = typeof(PlayerControl).GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null && property.PropertyType == typeof(int))
{
return (int)property.GetValue(player);
}
}
return -1;
}
catch (Exception ex)
{
MelonLogger.Error("Error getting player ViewID: " + ex.Message);
return -1;
}
}
private void SetupPettingAction(AIDiageticInteraction interaction, AIControl aiControl)
{
AIDiageticInteraction interaction2 = interaction;
AIControl aiControl2 = aiControl;
try
{
AIDiageticInteraction obj = interaction2;
((DiageticOption)obj).OnInteract = (Action)Delegate.Combine(((DiageticOption)obj).OnInteract, (Action)delegate
{
PlayerControl.myInstance.Display.Emote("emote_pet");
ParticleSystem component = ((Component)((Component)interaction2).transform.Find("RigHead/Bubbles")).GetComponent<ParticleSystem>();
component.Emit(320);
((Component)((Component)component).transform.Find("Bubbles")).GetComponent<ParticleSystem>().Emit(320);
((Component)((Component)component).transform.Find("bubble")).GetComponent<ParticleSystem>().Emit(320);
MelonLogger.Msg(((Object)aiControl2).name + " has been pet!");
});
MelonLogger.Msg("Pet interaction configured for Inkling: " + ((Object)aiControl2).name);
}
catch (Exception ex)
{
MelonLogger.Error("Error setting up petting action: " + ex.Message);
}
}
private void CheckForNearbyPetInteractions()
{
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
try
{
PlayerControl player = PlayerControl.myInstance;
if ((Object)(object)player == (Object)null)
{
return;
}
AIDiageticInteraction[] source = Object.FindObjectsOfType<AIDiageticInteraction>();
List<AIDiageticInteraction> list = source.Where((AIDiageticInteraction i) => i.Label == "Pet" && Vector3.Distance(((Component)i).transform.position, ((Component)player).transform.position) < 10f).ToList();
if (list.Count <= 0)
{
return;
}
MelonLogger.Msg($"Found {list.Count} nearby pet interactions:");
foreach (AIDiageticInteraction item in list)
{
float num = Vector3.Distance(((Component)item).transform.position, ((Component)player).transform.position);
MelonLogger.Msg($" - {((Object)item).name} at distance {num:F2}");
}
}
catch (Exception ex)
{
MelonLogger.Error("Error checking nearby interactions: " + ex.Message);
}
}
private bool IsOwnedByPlayer(AIControl ai, PlayerControl player)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
try
{
if (petOwnerIDField != null)
{
int num = (int)petOwnerIDField.GetValue(ai);
int playerViewID = GetPlayerViewID(player);
return num == playerViewID;
}
return Vector3.Distance(((Component)ai).transform.position, ((Component)player).transform.position) < 15f && (((Object)ai).name.ToLower().Contains("inkling") || ai.AIName.ToLower().Contains("inkling"));
}
catch (Exception ex)
{
MelonLogger.Error("Error checking pet ownership: " + ex.Message);
return false;
}
}
}
}