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 Taming v0.1.21
BepInEx/plugins/Zephyrfit-Taming/ZephyrfitTaming.dll
Decompiled an hour ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using LetMeTameYou; using LetMeTameYou.RPC; using Microsoft.CodeAnalysis; using MountUp; using Splatform; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; using UnityEngine.TextCore; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ZephyrfitTaming")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.21.0")] [assembly: AssemblyInformationalVersion("0.1.21")] [assembly: AssemblyProduct("ZephyrfitTaming")] [assembly: AssemblyTitle("ZephyrfitTaming")] [assembly: AssemblyVersion("0.1.21.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Zephyrfit.Taming { internal static class AnimalSexState { internal const string Key = "zf_sex_v1"; private static readonly Dictionary<string, ConfigEntry<SexMode>> modes = new Dictionary<string, ConfigEntry<SexMode>>(); private static float next; internal static void Configure(ConfigFile config) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown string[] array = new string[5] { "Bjorn", "Hare", "Lox", "Wolf", "Boar" }; foreach (string text in array) { modes[text] = config.Bind<SexMode>("Server Rules", text + " sex mode", SexMode.MaleFemale, new ConfigDescription("Server species rule: MaleFemale = opposite sexes and female pregnancy; Hermaphrodite = two distinct animals, one pregnancy per pairing; Disabled = native sex-free rules. Existing pregnancy survives every transition; persisted male/female assignment is retained when hidden.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } } internal static string Species(Component c) { if (!Object.op_Implicit((Object)(object)c)) { return ""; } Growup component = c.GetComponent<Growup>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.m_grownPrefab)) { return Utils.GetPrefabName(c.gameObject); } return Utils.GetPrefabName(component.m_grownPrefab); } internal static SexMode Mode(Component c) { if (!Object.op_Implicit((Object)(object)c) || !modes.TryGetValue(Species(c), out ConfigEntry<SexMode> value)) { return SexMode.Disabled; } Growup component = c.GetComponent<Growup>(); Procreation val = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_grownPrefab)) ? component.m_grownPrefab.GetComponent<Procreation>() : c.GetComponent<Procreation>()); if (!Object.op_Implicit((Object)(object)val) || !((Behaviour)val).enabled || !Object.op_Implicit((Object)(object)val.m_offspring)) { return SexMode.Disabled; } return value.Value; } internal static AnimalSex Read(Component c) { ZNetView val = (Object.op_Implicit((Object)(object)c) ? c.GetComponent<ZNetView>() : null); if (!Object.op_Implicit((Object)(object)val) || !val.IsValid()) { return AnimalSex.Unknown; } return (AnimalSex)val.GetZDO().GetInt("zf_sex_v1", 0); } internal unsafe static void Ensure(Component c) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (modes.ContainsKey(Species(c)) && CreatureState.Owner(c, out ZDO zdo)) { int num = zdo.GetInt("zf_sex_v1", 0); if (zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L && num != 2) { zdo.Set("zf_sex_v1", 2); ZDOID uid = zdo.m_uid; Plugin.Info("SEX migration existing pregnancy -> female, pregnancy/timers preserved ZDO=" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString()); } else if (num != 1 && num != 2 && Mode(c) != SexMode.Disabled) { zdo.Set("zf_sex_v1", (int)BreedingMath.Assignment((AnimalSex)num, pregnant: false, Mode(c), Random.value)); string[] obj = new string[6] { "SEX initial 50/50 assignment species=", Species(c), " ZDO=", null, null, null }; ZDOID uid = zdo.m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = " value="; obj[5] = zdo.GetInt("zf_sex_v1", 0).ToString(); Plugin.Info(string.Concat(obj)); } } } internal static void Tick() { MatingAuthority.Tick(); if (!Plugin.ConfigReady || Time.realtimeSinceStartup < next) { return; } next = Time.realtimeSinceStartup + 1f; foreach (Character allCharacter in Character.GetAllCharacters()) { Ensure((Component)(object)allCharacter); } } internal static bool Eligible(Procreation p) { if (Object.op_Implicit((Object)(object)p) && !Object.op_Implicit((Object)(object)((Component)p).GetComponent<Growup>()) && Object.op_Implicit((Object)(object)((Component)p).GetComponent<Tameable>()) && ((Component)p).GetComponent<Character>().IsTamed() && p.ReadyForProcreation()) { if (Object.op_Implicit((Object)(object)((Component)p).GetComponent<BaseAI>())) { return !((Component)p).GetComponent<BaseAI>().IsAlerted(); } return true; } return false; } internal static Procreation? Partner(Procreation p) { SexMode mode = Mode((Component)(object)p); if (!Eligible(p) || !BreedingMath.CanCarry(mode, Read((Component)(object)p))) { return null; } string species = Species((Component)(object)p); return (from c in Character.GetAllCharacters() where (Object)(object)((Component)c).gameObject != (Object)(object)((Component)p).gameObject && Species((Component)(object)c) == species && Vector3.Distance(((Component)c).transform.position, ((Component)p).transform.position) <= p.m_partnerCheckRange select ((Component)c).GetComponent<Procreation>() into b where Object.op_Implicit((Object)(object)b) && Eligible(b) where BreedingMath.Compatible(mode, Read((Component)(object)p), Read((Component)(object)b), distinct: true) orderby Vector3.Distance(((Component)b).transform.position, ((Component)p).transform.position) select b).FirstOrDefault(); } } [HarmonyPatch(typeof(Procreation), "Procreate")] internal static class SexPartnerSearch { [ThreadStatic] private static Procreation? scope; [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Procreation __instance, out Procreation? __state) { __state = scope; scope = __instance; AnimalSexState.Ensure((Component)(object)__instance); } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception, Procreation? __state) { scope = __state; return __exception; } internal static int Count(GameObject prefab, Vector3 centre, float range, bool events, bool ready) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) Procreation val = scope; if (ready && Object.op_Implicit((Object)(object)val) && AnimalSexState.Mode((Component)(object)val) != SexMode.Disabled && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<Growup>())) { if (!Object.op_Implicit((Object)(object)AnimalSexState.Partner(val))) { return 0; } return 2; } return SpawnSystem.GetNrOfInstances(prefab, centre, range, events, ready); } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { MethodInfo original = AccessTools.Method(typeof(SpawnSystem), "GetNrOfInstances", new Type[5] { typeof(GameObject), typeof(Vector3), typeof(float), typeof(bool), typeof(bool) }, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(SexPartnerSearch), "Count", (Type[])null, (Type[])null); int replaced = 0; foreach (CodeInstruction item in source) { if (CodeInstructionExtensions.Calls(item, original)) { item.operand = replacement; replaced++; } yield return item; } if (replaced != 4) { throw new InvalidOperationException("Native Procreate count contract changed: " + replaced); } } } [HarmonyPatch(typeof(Growup), "GrowUpdate")] internal static class PreserveAdultSex { [ThreadStatic] private static Growup? growing; [HarmonyPrefix] private static void Prefix(Growup __instance, out Growup? __state) { __state = growing; growing = __instance; AnimalSexState.Ensure((Component)(object)__instance); } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception, Growup? __state) { growing = __state; return __exception; } private static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot); if (Object.op_Implicit((Object)(object)growing) && CreatureState.Owner((Component)(object)val.transform, out ZDO zdo)) { AnimalSex animalSex = AnimalSexState.Read((Component)(object)growing); if (animalSex != AnimalSex.Unknown) { zdo.Set("zf_sex_v1", (int)animalSex); } } if (Object.op_Implicit((Object)(object)growing)) { BearGenetics.Grown((Component)(object)growing, val); } Character component = val.GetComponent<Character>(); if (Object.op_Implicit((Object)(object)component) && SexBody.Supported((Component)(object)component)) { SexBody.Bind(component).Refresh(); SexStats.Refresh(component); } return val; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { int replaced = 0; foreach (CodeInstruction item in source) { if (item.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments()[0] == typeof(GameObject) && methodInfo.GetParameters().Length == 3) { item.operand = AccessTools.Method(typeof(PreserveAdultSex), "Spawn", (Type[])null, (Type[])null); replaced++; } yield return item; } if (replaced != 1) { throw new InvalidOperationException("Growup spawn contract changed"); } } } internal sealed class BearAppearance : MonoBehaviour { private string applied = ""; private string failed = ""; private readonly List<(SkinnedMeshRenderer Renderer, Mesh Mesh, Material[] Materials)> originals = new List<(SkinnedMeshRenderer, Mesh, Material[])>(); private readonly List<Object> owned = new List<Object>(); private static readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); internal static BearAppearance Bind(Character c) { return ((Component)c).GetComponent<BearAppearance>() ?? ((Component)c).gameObject.AddComponent<BearAppearance>(); } internal void Refresh(BearGenes? genes) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_0254: Unknown result type (might be due to invalid IL or missing references) if (genes == null || genes.variant == applied || genes.variant == failed || (int)SystemInfo.graphicsDeviceType == 4) { return; } try { if (originals.Count == 0) { foreach (SkinnedMeshRenderer item in from val3 in ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true) where Object.op_Implicit((Object)(object)val3.sharedMesh) && ((Renderer)val3).sharedMaterials.Any((Material m) => Object.op_Implicit((Object)(object)m) && ((Object)m).name.StartsWith("Bjorn_mat", StringComparison.Ordinal)) select val3) { originals.Add((item, item.sharedMesh, ((Renderer)item).sharedMaterials)); } } if (originals.Count == 0) { return; } Restore(); foreach (var original in originals) { var (r, _, _) = original; if (!Object.op_Implicit((Object)(object)r)) { continue; } BearMesh bearMesh = BearMesh.Read(original.Mesh, r); Material[] array = ((IEnumerable<Material>)original.Materials).Select((Func<Material, Material>)((Material m) => new Material(m) { name = "ZF_Bjorn_" + genes.variant + "_" + ((Object)r).name })).ToArray(); Material[] array2 = array; foreach (Material val in array2) { string key = ((Object)original.Mesh).GetInstanceID() + ":" + ((Object)val.mainTexture).GetInstanceID() + ":" + genes.variant; if (!textures.TryGetValue(key, out Texture2D value)) { value = Paint(val.mainTexture, bearMesh, ((Object)r).name, genes.variant); textures[key] = value; } val.mainTexture = (Texture)(object)value; if (val.HasProperty("_EmissionMap")) { val.SetTexture("_EmissionMap", (Texture)null); } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", Color.black); } if (val.HasProperty("_NoiseGlowEnabled")) { val.SetFloat("_NoiseGlowEnabled", 0f); } val.DisableKeyword("_EMISSION"); owned.Add((Object)(object)val); } ((Renderer)r).sharedMaterials = array; Mesh val2 = bearMesh.Create(original.Mesh, genes.variant, r); r.sharedMesh = val2; owned.Add((Object)(object)val2); } applied = genes.variant; } catch (Exception ex) { Restore(); failed = genes.variant; Plugin.Error("BJORN appearance refused, native visual and gameplay retained: " + ex); } } private void Restore() { foreach (var original in originals) { if (Object.op_Implicit((Object)(object)original.Renderer)) { original.Renderer.sharedMesh = original.Mesh; ((Renderer)original.Renderer).sharedMaterials = original.Materials; } } foreach (Object item in owned) { if (Object.op_Implicit(item)) { Object.Destroy(item); } } owned.Clear(); } private void OnDestroy() { Restore(); } internal static Texture2D Paint(Texture source, BearMesh geometry, string renderer, string variant) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, true, false) { name = "ZF_Bjorn_" + variant + "_" + renderer, filterMode = (FilterMode)1, wrapMode = source.wrapMode }; try { Graphics.Blit(source, temporary); RenderTexture.active = temporary; val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0); val.Apply(); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } Color[] pixels = val.GetPixels(); bool[] array = geometry.Mask(source.width, source.height, upper: false); bool[] array2 = geometry.Mask(source.width, source.height, upper: true); bool flag = renderer == "Sphere"; bool flag2 = renderer == "Asora" || renderer == "Plane"; Color val2 = (Color)(variant switch { "black" => new Color(0.6f, 0.018f, 0.027f), "brown" => new Color(0.34f, 0.46f, 0.1f), "grizzly" => new Color(0.29f, 0.12f, 0.028f), _ => new Color(0.1f, 0.4f, 0.72f), }); Color val4 = default(Color); Color val5 = default(Color); Color val7 = default(Color); for (int i = 0; i < pixels.Length; i++) { if (!array[i]) { continue; } int num = i % source.width; int num2 = i / source.width; Color val3 = pixels[i]; float num3 = val3.r * 0.2126f + val3.g * 0.7152f + val3.b * 0.0722f; if (flag) { float num4 = Vector2.Distance(new Vector2(((float)num + 0.5f) / (float)source.width, ((float)num2 + 0.5f) / (float)source.height), new Vector2(0.281f, 0.943f)); if (num4 < 0.0115f) { ((Color)(ref val3))..ctor(0.012f, 0.009f, 0.007f, val3.a); } else if (num4 < 0.06f) { float num5 = 0.8f + 0.2f * Mathf.Clamp01(num3 * 3f); ((Color)(ref val3))..ctor(val2.r * num5, val2.g * num5, val2.b * num5, val3.a); } } else if (flag2 && num3 > 0.055f && num3 < 0.72f && (!(val3.r > val3.g * 1.7f) || !(val3.r > 0.35f))) { float num6 = Mathf.Clamp01(num3 * 2.8f); switch (variant) { case "black": ((Color)(ref val4))..ctor(0.018f, 0.022f, 0.028f); ((Color)(ref val5))..ctor(0.17f, 0.19f, 0.215f); break; case "gray": ((Color)(ref val4))..ctor(0.045f, 0.055f, 0.065f); ((Color)(ref val5))..ctor(0.34f, 0.35f, 0.33f); break; case "brown": ((Color)(ref val4))..ctor(0.08f, 0.035f, 0.014f); ((Color)(ref val5))..ctor(0.53f, 0.235f, 0.068f); break; default: ((Color)(ref val4))..ctor(0.1f, 0.055f, 0.024f); ((Color)(ref val5))..ctor(0.64f, 0.47f, 0.27f); break; } Color val6 = Color.Lerp(val4, val5, num6); if (variant == "gray") { ((Color)(ref val7))..ctor(0.17f, 0.185f, 0.19f); val6 = ((num6 < 0.55f) ? Color.Lerp(val4, val7, num6 / 0.55f) : Color.Lerp(val7, val5, (num6 - 0.55f) / 0.45f)); } if (variant == "grizzly" && array2[i]) { int num7 = (num * 73856093) ^ (num2 * 19349663); if ((float)((uint)(num7 ^ (num7 >>> 13)) % 100u) / 100f > 0.48f) { val6 = Color.Lerp(val6, new Color(0.72f, 0.72f, 0.66f), 0.25f + 0.45f * num6); } } ((Color)(ref val3))..ctor(val6.r, val6.g, val6.b, val3.a); } pixels[i] = val3; } val.SetPixels(pixels); val.Apply(true, true); return val; } } internal sealed class BearMesh { internal Vector3[] vertices = Array.Empty<Vector3>(); internal Vector3[] normals = Array.Empty<Vector3>(); internal Vector2[] uv = Array.Empty<Vector2>(); internal BoneWeight[] weights = Array.Empty<BoneWeight>(); internal int[] triangles = Array.Empty<int>(); private Mesh baked; private static readonly Dictionary<int, BearMesh> cache = new Dictionary<int, BearMesh>(); internal static BearMesh Read(Mesh native, SkinnedMeshRenderer renderer) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (cache.TryGetValue(((Object)native).GetInstanceID(), out BearMesh value)) { return value; } BearMesh bearMesh = new BearMesh(); bearMesh.baked = new Mesh(); renderer.BakeMesh(bearMesh.baked, false); bearMesh.uv = bearMesh.baked.uv; bearMesh.triangles = bearMesh.baked.triangles; bearMesh.vertices = Attribute((VertexAttribute)0); bearMesh.normals = Attribute((VertexAttribute)1); bearMesh.weights = (BoneWeight[])(object)new BoneWeight[native.vertexCount]; GraphicsBuffer boneWeightBuffer = native.GetBoneWeightBuffer((SkinWeights)4); try { boneWeightBuffer.GetData((Array)bearMesh.weights); } finally { ((IDisposable)boneWeightBuffer)?.Dispose(); } cache[((Object)native).GetInstanceID()] = bearMesh; return bearMesh; unsafe Vector3[] Attribute(VertexAttribute attribute) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((int)native.GetVertexAttributeFormat(attribute) != 0 || native.GetVertexAttributeDimension(attribute) != 3) { throw new InvalidOperationException("Bjorn native vertex contract changed: " + ((object)(*(VertexAttribute*)(&attribute))/*cast due to .constrained prefix*/).ToString()); } int vertexAttributeStream = native.GetVertexAttributeStream(attribute); int stride = native.GetVertexBufferStride(vertexAttributeStream); int offset = native.GetVertexAttributeOffset(attribute); byte[] bytes = new byte[native.vertexCount * stride]; GraphicsBuffer vertexBuffer = native.GetVertexBuffer(vertexAttributeStream); try { vertexBuffer.GetData((Array)bytes); } finally { ((IDisposable)vertexBuffer)?.Dispose(); } return Enumerable.Range(0, native.vertexCount).Select((Func<int, Vector3>)((int i) => new Vector3(BitConverter.ToSingle(bytes, i * stride + offset), BitConverter.ToSingle(bytes, i * stride + offset + 4), BitConverter.ToSingle(bytes, i * stride + offset + 8)))).ToArray(); } } internal Mesh Create(Mesh native, string variant, SkinnedMeshRenderer renderer) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh { name = "ZF_Bjorn_" + variant + "_" + ((Object)native).name }; Vector3[] array = (Vector3[])vertices.Clone(); string[] array2 = renderer.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name).ToArray(); float num = variant switch { "black" => -0.035f, "brown" => 0.035f, "grizzly" => 0.08f, _ => -0.02f, }; Transform val2 = ((IEnumerable<Transform>)renderer.bones).FirstOrDefault((Func<Transform, bool>)((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "Head")); Vector3 val3; if (!Object.op_Implicit((Object)(object)val2)) { Bounds bounds = native.bounds; val3 = ((Bounds)(ref bounds)).center; } else { val3 = ((Component)renderer).transform.InverseTransformPoint(val2.position); } Vector3 val4 = val3; for (int num2 = 0; num2 < array.Length; num2++) { BoneWeight val5 = weights[num2]; float num3 = 0f; float num4 = 0f; (int, float)[] array3 = new(int, float)[4] { (((BoneWeight)(ref val5)).boneIndex0, ((BoneWeight)(ref val5)).weight0), (((BoneWeight)(ref val5)).boneIndex1, ((BoneWeight)(ref val5)).weight1), (((BoneWeight)(ref val5)).boneIndex2, ((BoneWeight)(ref val5)).weight2), (((BoneWeight)(ref val5)).boneIndex3, ((BoneWeight)(ref val5)).weight3) }; for (int num5 = 0; num5 < array3.Length; num5++) { (int, float) tuple = array3[num5]; if (tuple.Item1 < array2.Length) { if (new string[3] { "Head", "Nose", "Jaw" }.Contains(array2[tuple.Item1])) { num3 += tuple.Item2; } if (array2[tuple.Item1] == "Neck") { num4 += tuple.Item2; } } } array[num2].x *= 1f + num * num3 + ((variant == "grizzly") ? (0.045f * num4) : 0f); if (variant == "black") { array[num2].y += (array[num2].y - val4.y) * 0.025f * num3; } if (variant == "brown") { array[num2].z += (array[num2].z - val4.z) * 0.015f * num3; } } val.vertices = array; val.normals = normals; val.boneWeights = weights; val.bindposes = native.bindposes; for (int num6 = 0; num6 < 8; num6++) { List<Vector4> list = new List<Vector4>(); baked.GetUVs(num6, list); if (list.Count == array.Length) { val.SetUVs(num6, list); } } if (baked.colors32.Length == array.Length) { val.colors32 = baked.colors32; } val.subMeshCount = baked.subMeshCount; for (int num7 = 0; num7 < baked.subMeshCount; num7++) { val.SetTriangles(baked.GetTriangles(num7), num7); } val.RecalculateNormals(); val.RecalculateTangents(); val.RecalculateBounds(); return val; } internal bool[] Mask(int width, int height, bool upper) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) bool[] array = new bool[width * height]; float num = vertices.Max((Vector3 v) => v.z); float num2 = vertices.Min((Vector3 v) => v.z); Vector2 val4 = default(Vector2); for (int num3 = 0; num3 < triangles.Length; num3 += 3) { int num4 = triangles[num3]; int num5 = triangles[num3 + 1]; int num6 = triangles[num3 + 2]; if (upper && (vertices[num4].z + vertices[num5].z + vertices[num6].z) / 3f < num2 + (num - num2) * 0.65f) { continue; } Vector2 val = uv[num4]; Vector2 val2 = uv[num5]; Vector2 val3 = uv[num6]; int num7 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(new float[3] { val.x, val2.x, val3.x }) * (float)width), 0, width - 1); int num8 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(new float[3] { val.x, val2.x, val3.x }) * (float)width), 0, width - 1); int num9 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(new float[3] { val.y, val2.y, val3.y }) * (float)height), 0, height - 1); int num10 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(new float[3] { val.y, val2.y, val3.y }) * (float)height), 0, height - 1); float num11 = Cross(val2 - val, val3 - val); if (Mathf.Abs(num11) < 1E-10f) { continue; } for (int num12 = num9; num12 <= num10; num12++) { for (int num13 = num7; num13 <= num8; num13++) { ((Vector2)(ref val4))..ctor(((float)num13 + 0.5f) / (float)width, ((float)num12 + 0.5f) / (float)height); float num14 = Cross(val2 - val4, val3 - val4) / num11; float num15 = Cross(val3 - val4, val - val4) / num11; float num16 = 1f - num14 - num15; if (num14 >= -0.02f && num15 >= -0.02f && num16 >= -0.02f) { array[num12 * width + num13] = true; } } } } return array; static float Cross(Vector2 p, Vector2 q) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return p.x * q.y - p.y * q.x; } } } internal sealed class BearDefense : MonoBehaviour { private delegate bool Patrol(BaseAI ai, out Vector3 point); private const string ThreatRpc = "ZF_BearThreat_v1"; private const string Threat = "zf_guard_threat_v1"; private const string Until = "zf_guard_until_v1"; private const string Home = "zf_guard_home_v1"; private static readonly FieldInfo Target = AccessTools.Field(typeof(MonsterAI), "m_targetCreature"); private static readonly FieldInfo Static = AccessTools.Field(typeof(MonsterAI), "m_targetStatic"); private static readonly FieldInfo WeaponTimer = AccessTools.Field(typeof(MonsterAI), "m_updateWeaponTimer"); private static readonly Action<MonsterAI, bool> Alert = AccessTools.MethodDelegate<Action<MonsterAI, bool>>(AccessTools.Method(typeof(MonsterAI), "SetAlerted", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<MonsterAI> Wake = AccessTools.MethodDelegate<Action<MonsterAI>>(AccessTools.Method(typeof(MonsterAI), "Wakeup", (Type[])null, (Type[])null), (object)null, true); private static readonly Patrol GetPatrol = AccessTools.MethodDelegate<Patrol>(AccessTools.Method(typeof(BaseAI), "GetPatrolPoint", (Type[])null, (Type[])null), (object)null, true); private Character animal; private MonsterAI ai; private ZNetView view; private string reason = "initialisation"; private string lastTrace = ""; private float nextScan; private float nextTrace; private bool Owned { get { ZDO zdo; if (Plugin.ConfigReady && Applies(animal) && !animal.IsDead() && Object.op_Implicit((Object)(object)ai)) { return CreatureState.Owner((Component)(object)animal, out zdo); } return false; } } private bool Ridden { get { if (Object.op_Implicit((Object)(object)((Component)animal).GetComponent<Tameable>()?.m_saddle)) { return ((Component)animal).GetComponent<Tameable>().m_saddle.HaveValidUser(); } return false; } } internal static bool Applies(Character c) { if (Object.op_Implicit((Object)(object)c) && c.IsTamed() && CreatureState.Is((Component)(object)c, "Bjorn")) { return !Object.op_Implicit((Object)(object)((Component)c).GetComponent<Growup>()); } return false; } internal static bool Enemy(Character bear, Character other) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)other) || (Object)(object)other == (Object)(object)bear) { return false; } return DefenseRules.Hostile(((object)other.GetFaction()/*cast due to .constrained prefix*/).ToString(), bear.GetGroup().Length > 0 && bear.GetGroup() == other.GetGroup(), other is Player, other.IsTamed(), other.IsDead(), other.m_aiSkipTarget, Object.op_Implicit((Object)(object)other.GetBaseAI()) && other.GetBaseAI().IsAggravated()); } internal static BearDefense Bind(Character c) { BearDefense bearDefense = ((Component)c).GetComponent<BearDefense>(); if (!Object.op_Implicit((Object)(object)bearDefense)) { bearDefense = ((Component)c).gameObject.AddComponent<BearDefense>(); } if (!Object.op_Implicit((Object)(object)bearDefense.view)) { bearDefense.animal = c; bearDefense.ai = ((Component)c).GetComponent<MonsterAI>(); bearDefense.view = ((Component)c).GetComponent<ZNetView>(); bearDefense.view.Register<ZDOID, ZDOID>("ZF_BearThreat_v1", (Action<long, ZDOID, ZDOID>)bearDefense.Receive); } return bearDefense; } private Vector3 Centre() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject followTarget = ai.GetFollowTarget(); if (Object.op_Implicit((Object)(object)followTarget)) { return followTarget.transform.position; } if (GetPatrol((BaseAI)(object)ai, out var point)) { return point; } ZDO zDO = view.GetZDO(); if (!zDO.GetBool("zf_guard_home_v1_set", false)) { zDO.Set("zf_guard_home_v1", ((Component)animal).transform.position); zDO.Set("zf_guard_home_v1_set", true); } return zDO.GetVec3("zf_guard_home_v1", ((Component)animal).transform.position); } private bool InGuard(Character c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) return DefenseRules.Within(Vector3.Distance(Centre(), ((Component)c).transform.position), Vector3.Distance(Centre(), ((Component)animal).transform.position), Plugin.GuardRadius.Value); } private bool Allowed(Character c, bool selfHit = false) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (!Enemy(animal, c)) { return false; } if (InGuard(c)) { return true; } long ms; bool num = selfHit || (ServerClock.TryNow(out ms) && view.GetZDO().GetLong("zf_guard_until_v1", 0L) > ms && view.GetZDO().GetZDOID("zf_guard_threat_v1") == c.GetZDOID()); Character obj = animal; Character obj2 = ((obj is Humanoid) ? obj : null); float nativeReach = ((obj2 == null) ? ((float?)null) : ((Humanoid)obj2).GetCurrentWeapon()?.m_shared.m_aiAttackRange) ?? animal.GetRadius(); if (num) { return DefenseRules.CloseRetaliation(Vector3.Distance(((Component)animal).transform.position, ((Component)c).transform.position), nativeReach, c.GetRadius()); } return false; } private bool Protects(Character victim) { //IL_001e: 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) if ((Object)(object)victim == (Object)(object)animal) { return true; } if (!(victim is Player) || Vector3.Distance(((Component)victim).transform.position, Centre()) > Plugin.GuardRadius.Value) { return false; } GameObject followTarget = ai.GetFollowTarget(); if (Object.op_Implicit((Object)(object)followTarget)) { return (Object)(object)followTarget == (Object)(object)((Component)victim).gameObject; } return true; } private void Receive(long sender, ZDOID victimId, ZDOID attackerId) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (Owned && !Ridden) { GameObject val = ZNetScene.instance.FindInstance(victimId); GameObject val2 = ZNetScene.instance.FindInstance(attackerId); Character val3 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null); Character val4 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<Character>() : null); ZNetView val5 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<ZNetView>() : null); if (!Object.op_Implicit((Object)(object)val5) || !val5.IsValid() || val5.GetZDO().GetOwner() != sender || !Protects(val3) || !Allowed(val4, (Object)(object)val3 == (Object)(object)animal)) { reason = "notification refusée : autorité, allié ou rayon / notification rejected: authority, ally or radius"; } else { Remember(val4, "agression reçue du pair autoritaire de la victime / hit reported by victim authority"); } } } internal static void Damage(Character victim, Character attacker) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)attacker) || !CreatureState.Owner((Component)(object)victim, out ZDO _) || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } foreach (Character allCharacter in Character.GetAllCharacters()) { if (!Applies(allCharacter) || Vector3.Distance(((Component)allCharacter).transform.position, ((Component)victim).transform.position) > 60f || !Enemy(allCharacter, attacker)) { continue; } BearDefense bearDefense = Bind(allCharacter); if (Object.op_Implicit((Object)(object)bearDefense.view) && bearDefense.view.IsValid()) { if (bearDefense.view.IsOwner()) { bearDefense.Receive(ZDOMan.GetSessionID(), victim.GetZDOID(), attacker.GetZDOID()); continue; } bearDefense.view.InvokeRPC(bearDefense.view.GetZDO().GetOwner(), "ZF_BearThreat_v1", new object[2] { victim.GetZDOID(), attacker.GetZDOID() }); } } } private void Remember(Character target, string why) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (ServerClock.TryNow(out var ms)) { ZDO zDO = view.GetZDO(); zDO.Set("zf_guard_threat_v1", target.GetZDOID()); zDO.Set("zf_guard_until_v1", ms + 12000); reason = why; Alert(ai, arg2: true); Wake(ai); Target.SetValue(ai, target); Static.SetValue(ai, null); WeaponTimer.SetValue(ai, 0f); } } internal void Prepare() { if (!Owned || Ridden || !(Time.time >= nextScan)) { return; } nextScan = Time.time + 0.5f; foreach (Character allCharacter in Character.GetAllCharacters()) { if (Enemy(animal, allCharacter) && InGuard(allCharacter)) { MonsterAI component = ((Component)allCharacter).GetComponent<MonsterAI>(); Character val = ((component != null) ? ((BaseAI)component).GetTargetCreature() : null); if (Object.op_Implicit((Object)(object)val) && Protects(val) && allCharacter.GetBaseAI().IsAlerted()) { Remember(allCharacter, "menace visant le joueur protégé ou l’ours / threat targets protected player or bear"); break; } } } } internal void AfterTarget(ref bool canHear, ref bool canSee) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) if (!Owned) { return; } if (Ridden) { Target.SetValue(ai, null); Static.SetValue(ai, null); reason = "cavalier : commandes conservées / rider controls"; return; } if (ServerClock.TryNow(out var ms) && view.GetZDO().GetLong("zf_guard_until_v1", 0L) > ms) { GameObject val = ZNetScene.instance.FindInstance(view.GetZDO().GetZDOID("zf_guard_threat_v1")); Character val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null); if (Object.op_Implicit((Object)(object)val2) && Allowed(val2)) { Target.SetValue(ai, val2); } } Character targetCreature = ((BaseAI)ai).GetTargetCreature(); if (Object.op_Implicit((Object)(object)targetCreature) && !Allowed(targetCreature)) { Target.SetValue(ai, null); Static.SetValue(ai, null); canHear = (canSee = false); Alert(ai, arg2: false); reason = "cible rejetée : allié, morte ou hors périmètre / ally, dead or outside guard radius"; } else if (Object.op_Implicit((Object)(object)targetCreature)) { canHear = ((BaseAI)ai).CanHearTarget(targetCreature); canSee = ((BaseAI)ai).CanSeeTarget(targetCreature); if (canHear | canSee) { Alert(ai, arg2: true); } if (view.GetZDO().GetZDOID("zf_guard_threat_v1") != targetCreature.GetZDOID()) { reason = "perception native d’une cible hostile / native hostile perception"; } } else { reason = "aucune menace perçue, retour Suivre/Rester / no sensed threat, follow/stay"; } Trace(); } private void Trace() { if (Plugin.AiTrace.Value && !(Time.time < nextTrace)) { nextTrace = Time.time + 2f; string text = Describe(animal); if (text != lastTrace) { lastTrace = text; Plugin.Info("DEFENSE " + text); } } } internal static string Describe(Character c) { //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) BearDefense component = ((Component)c).GetComponent<BearDefense>(); MonsterAI component2 = ((Component)c).GetComponent<MonsterAI>(); ZNetView component3 = ((Component)c).GetComponent<ZNetView>(); Character val = (Object.op_Implicit((Object)(object)component2) ? ((BaseAI)component2).GetTargetCreature() : null); Humanoid val2 = (Humanoid)(object)((c is Humanoid) ? c : null); ItemData val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetCurrentWeapon() : null); string text = ((!Object.op_Implicit((Object)(object)component3) || !component3.IsValid()) ? "ZDO invalide / invalid ZDO" : ((!component3.IsOwner()) ? "relevé non autoritaire / not authority" : ((!Applies(c)) ? "hors périmètre / excluded" : (c.HaveRider() ? "cavalier / rider" : ((!Object.op_Implicit((Object)(object)val)) ? "aucune cible / no target" : ((val3 == null) ? "arme native absente / no native weapon" : (c.InAttack() ? "attaque en cours / attacking" : (c.IsStaggering() ? "étourdi / staggered" : (c.IsKnockedBack() ? "projection / knocked back" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).CanSeeTarget(val)) ? "ligne de vue bloquée / no line of sight" : ((Vector3.Distance(((Component)c).transform.position, ((Component)val).transform.position) - val.GetRadius() > val3.m_shared.m_aiAttackRange) ? "approche, hors portée / approaching" : ((Time.time - val3.m_lastAttackTime <= val3.m_shared.m_aiAttackInterval) ? "recharge native / native cooldown" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).CanUseAttack(val3)) ? "conditions de l’arme native / native weapon conditions" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).IsLookingAt(((Component)val).transform.position, val3.m_shared.m_aiAttackMaxAngle, val3.m_shared.m_aiInvertAngleCheck)) ? "angle natif / native facing angle" : ((c.GetTimeSinceLastAttack() < (float)AccessTools.Field(typeof(MonsterAI), "m_minAttackInterval").GetValue(component2)) ? "délai global natif / native global cooldown" : "prêt, traitement natif / ready for native processing"))))))))))))))); object[] obj = new object[24] { c.GetHoverName(), c.GetZDOID(), c.IsTamed(), c.GetFaction(), c.GetGroup(), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; long? obj2; if (component3 == null) { obj2 = null; } else { ZDO zDO = component3.GetZDO(); obj2 = ((zDO != null) ? new long?(zDO.GetOwner()) : ((long?)null)); } obj[5] = obj2; obj[6] = Object.op_Implicit((Object)(object)component3) && component3.IsValid() && component3.IsOwner(); object obj3; if (component2 == null) { obj3 = null; } else { GameObject followTarget = component2.GetFollowTarget(); obj3 = ((followTarget != null) ? ((Object)followTarget).name : null); } obj[7] = obj3; obj[8] = ((val != null) ? new ZDOID?(val.GetZDOID()) : ((ZDOID?)null)); obj[9] = component?.reason ?? "pas encore exécuté / not run yet"; obj[10] = text; obj[11] = ((object)component2)?.GetType().Name; obj[12] = ((Character)(val2?)).m_aiCannotTargetOthers; obj[13] = c.m_aiSkipTarget; obj[14] = component2?.m_fleeIfNotAlerted; obj[15] = component2?.m_fleeIfLowHealth; obj[16] = component2?.m_fleeIfHurtWhenTargetCantBeReached; obj[17] = ((BaseAI)(component2?)).m_afraidOfFire; obj[18] = ((BaseAI)(component2?)).m_avoidFire; obj[19] = component2?.m_alertRange; obj[20] = Plugin.GuardRadius.Value; obj[21] = val3?.m_shared.m_name; obj[22] = val3?.m_shared.m_aiAttackRange; obj[23] = val3?.m_shared.m_aiAttackInterval; return string.Format("{0} ZDO={1} tame={2} faction={3} group={4} owner={5} localAuthority={6} follow={7} target={8} reason={9} attackGate={10} ai={11} cannotTarget={12} skip={13} fear={14}/{15}/{16} fire={17}/{18} nativeAlertRange={19} guard={20}m weapon={21} range={22} interval={23}", obj); } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class BearHostility { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character a, Character b, ref bool __result) { if (BearDefense.Applies(a)) { __result = BearDefense.Enemy(a, b); } else if (BearDefense.Applies(b)) { __result = BearDefense.Enemy(b, a); } } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] internal static class BearGuardAI { internal sealed class Snapshot { internal float Range; internal float Low; internal bool NotAlerted; internal bool Unreachable; } [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(MonsterAI __instance, out Snapshot? __state) { __state = null; Character component = ((Component)__instance).GetComponent<Character>(); if (Plugin.ConfigReady && BearDefense.Applies(component) && CreatureState.Owner((Component)(object)component, out ZDO _)) { BearDefense.Bind(component).Prepare(); if (!component.HaveRider()) { __state = new Snapshot { Range = __instance.m_alertRange, Low = __instance.m_fleeIfLowHealth, NotAlerted = __instance.m_fleeIfNotAlerted, Unreachable = __instance.m_fleeIfHurtWhenTargetCantBeReached }; __instance.m_alertRange = Plugin.GuardRadius.Value; __instance.m_fleeIfNotAlerted = false; __instance.m_fleeIfLowHealth = 0f; __instance.m_fleeIfHurtWhenTargetCantBeReached = false; } } } [HarmonyFinalizer] private static Exception? Finalizer(MonsterAI __instance, Snapshot? __state, Exception? __exception) { if (__state != null) { __instance.m_alertRange = __state.Range; __instance.m_fleeIfLowHealth = __state.Low; __instance.m_fleeIfNotAlerted = __state.NotAlerted; __instance.m_fleeIfHurtWhenTargetCantBeReached = __state.Unreachable; } return __exception; } } [HarmonyPatch(typeof(MonsterAI), "UpdateTarget")] internal static class BearGuardTarget { [HarmonyPostfix] private static void Postfix(MonsterAI __instance, ref bool canHearTarget, ref bool canSeeTarget) { Character component = ((Component)__instance).GetComponent<Character>(); if (BearDefense.Applies(component) && CreatureState.Owner((Component)(object)component, out ZDO _)) { BearDefense.Bind(component).AfterTarget(ref canHearTarget, ref canSeeTarget); } } } [HarmonyPatch(typeof(MonsterAI), "SetTarget")] internal static class BearRejectFriendlyHit { [HarmonyPrefix] private static bool Prefix(MonsterAI __instance, Character attacker) { Character component = ((Component)__instance).GetComponent<Character>(); if (BearDefense.Applies(component)) { return BearDefense.Enemy(component, attacker); } return true; } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class BearDamageNotification { [HarmonyPrefix] private static void Prefix(Character __instance, out float __state) { __state = __instance.GetHealth(); } [HarmonyPostfix] private static void Postfix(Character __instance, HitData hit, float __state) { if (__instance.GetHealth() < __state && CreatureState.Owner((Component)(object)__instance, out ZDO _)) { BearDefense.Damage(__instance, hit.GetAttacker()); } } } [HarmonyPatch(typeof(BaseAI), "Follow")] internal static class BearFollow { private sealed class State { internal GameObject? Target; internal bool Stopped; internal float Stop; } private static readonly ConditionalWeakTable<BaseAI, State> States = new ConditionalWeakTable<BaseAI, State>(); private static readonly Func<BaseAI, float, Vector3, float, bool, bool> Move = AccessTools.MethodDelegate<Func<BaseAI, float, Vector3, float, bool, bool>>(AccessTools.Method(typeof(BaseAI), "MoveTo", (Type[])null, (Type[])null), (object)null, true); internal static float Support(Character body, Vector3 direction) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) CapsuleCollider component = ((Component)body).GetComponent<CapsuleCollider>(); if (!Object.op_Implicit((Object)(object)component) || !((Collider)component).enabled) { return body.GetRadius(); } Bounds bounds = ((Collider)component).bounds; return Mathf.Max(0f, Vector3.Dot(((Bounds)(ref bounds)).center - ((Component)body).transform.position, direction) + Mathf.Abs(direction.x) * ((Bounds)(ref bounds)).extents.x + Mathf.Abs(direction.z) * ((Bounds)(ref bounds)).extents.z); } internal static float Clearance(Character bear, Character player, Vector3 dir) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) return Mathf.Max(3f, Support(bear, dir) + Support(player, -dir) + ((Utils.GetPrefabName(((Component)bear).gameObject) == "Lox") ? Plugin.LoxFollowGap.Value : Plugin.FollowGap.Value)); } [HarmonyPrefix] private static bool Prefix(BaseAI __instance, GameObject go, float dt) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) Character component = ((Component)__instance).GetComponent<Character>(); Player val = (Object.op_Implicit((Object)(object)go) ? go.GetComponent<Player>() : null); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)val) || !MountCapabilities.Supported(component) || !component.IsTamed() || !Plugin.ConfigReady || !CreatureState.Owner((Component)(object)__instance, out ZDO _)) { return true; } Sadle saddle = ((Component)component).GetComponent<Tameable>().m_saddle; if (Object.op_Implicit((Object)(object)saddle) && saddle.HaveValidUser()) { __instance.StopMoving(); return false; } Vector3 val2 = ((Component)val).transform.position - ((Component)component).transform.position; val2.y = 0f; Vector3 val3 = ((((Vector3)(ref val2)).sqrMagnitude > 0f) ? ((Vector3)(ref val2)).normalized : ((Component)component).transform.forward); float num = Clearance(component, (Character)(object)val, val3); State value = States.GetValue(__instance, (BaseAI _) => new State()); if ((Object)(object)value.Target != (Object)(object)go) { value.Target = go; value.Stopped = false; } float num2 = (value.Stopped ? 0f : (Mathf.Max(0f, Vector3.Dot(component.GetVelocity(), val3)) * 0.35f)); num += num2; if (value.Stopped) { num = Mathf.Max(num, value.Stop); } value.Stopped = MovementMath.ShouldStop(value.Stopped, ((Vector3)(ref val2)).magnitude, num, Plugin.FollowResume.Value); if (value.Stopped) { value.Stop = num; __instance.StopMoving(); component.SetRun(false); } else { value.Stop = num; bool arg = ((Vector3)(ref val2)).magnitude > Mathf.Max(10f, num + 4f); Move(__instance, dt, ((Component)val).transform.position, num, arg); } return false; } } [HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")] internal static class BearFood { [ThreadStatic] internal static MonsterAI? Consumer; internal static bool GroundFood(ItemDrop item) { Fish component = ((Component)item).GetComponent<Fish>(); if (Object.op_Implicit((Object)(object)component)) { if (item.m_itemData.m_pickedUp) { return component.IsOutOfWater(); } return false; } return true; } [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(MonsterAI __instance, out MonsterAI? __state) { __state = Consumer; Consumer = (CreatureState.Is((Component)(object)__instance, "Bjorn") ? __instance : null); if (Object.op_Implicit((Object)(object)Consumer)) { Tameable component = ((Component)__instance).GetComponent<Tameable>(); if (Object.op_Implicit((Object)(object)component)) { Policy.RefreshBear(component); } Traverse<ItemDrop> val = Traverse.Create((object)__instance).Field<ItemDrop>("m_consumeTarget"); if (Object.op_Implicit((Object)(object)val.Value) && !GroundFood(val.Value)) { val.Value = null; } } } [HarmonyFinalizer] private static void Finalizer(MonsterAI? __state) { Consumer = __state; } } [HarmonyPatch(typeof(MonsterAI), "FindClosestConsumableItem")] internal static class BearFishSelection { [ThreadStatic] internal static HashSet<ItemData>? Excluded; [HarmonyPrefix] private static void Prefix(MonsterAI __instance, float maxRange, out HashSet<ItemData>? __state) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) __state = Excluded; if (!CreatureState.Is((Component)(object)__instance, "Bjorn")) { return; } Excluded = new HashSet<ItemData>(); Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, maxRange, LayerMask.GetMask(new string[1] { "item" })); foreach (Collider val in array) { ItemDrop val2 = (Object.op_Implicit((Object)(object)val.attachedRigidbody) ? ((Component)val.attachedRigidbody).GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val2) && !BearFood.GroundFood(val2)) { Excluded.Add(val2.m_itemData); } } } [HarmonyFinalizer] private static void Finalizer(HashSet<ItemData>? __state) { Excluded = __state; } [HarmonyPostfix] private static void Postfix(MonsterAI __instance, ref ItemDrop __result) { if (CreatureState.Is((Component)(object)__instance, "Bjorn") && Object.op_Implicit((Object)(object)__result) && !BearFood.GroundFood(__result)) { __result = null; } } } [HarmonyPatch(typeof(MonsterAI), "CanConsume")] internal static class BearFishCandidate { [HarmonyPostfix] private static void Postfix(MonsterAI __instance, ItemData item, ref bool __result) { if (__result && CreatureState.Is((Component)(object)__instance, "Bjorn")) { HashSet<ItemData>? excluded = BearFishSelection.Excluded; if (excluded != null && excluded.Contains(item)) { __result = false; } } } } [HarmonyPatch(typeof(ItemDrop), "RemoveOne")] internal static class BearMealAudit { [HarmonyPrefix] private static bool Prefix(ItemDrop __instance, out int __state, ref bool __result) { __state = (Object.op_Implicit((Object)(object)BearFood.Consumer) ? __instance.m_itemData.m_stack : (-1)); if (__state < 0 || BearFood.GroundFood(__instance)) { return true; } __result = false; return false; } [HarmonyPostfix] private static void Postfix(ItemDrop __instance, int __state, bool __result) { if (__state >= 0 && __result) { int num = ((__state != 1) ? __instance.m_itemData.m_stack : 0); string message = $"BJORN FOOD UNIT prefab={Utils.GetPrefabName(((Component)__instance).gameObject)} quality={__instance.m_itemData.m_quality} before={__state} after={num} removed={__state - num} nativeRemoveOne=true"; if (__state - num != 1) { Plugin.Error(message); } else { Plugin.Info(message); } } } } [DataContract] internal sealed class Ancestor { [DataMember] public string id = ""; [DataMember] public string variant = ""; internal Ancestor Copy() { return new Ancestor { id = id, variant = variant }; } } [DataContract] internal sealed class BearGenes { [DataMember] public int schema = 1; [DataMember] public string id = ""; [DataMember] public string variant = ""; [DataMember] public string origin = ""; [DataMember] public Ancestor[] g1 = BearInheritance.Unknown(2); [DataMember] public Ancestor[] g2 = BearInheritance.Unknown(4); [DataMember] public Ancestor[] g3 = BearInheritance.Unknown(8); [DataMember] public double[] birth = Array.Empty<double>(); [DataMember] public double[] weights = Array.Empty<double>(); [DataMember] public string seed = ""; [DataMember] public long conceptionToken; } internal static class BearInheritance { internal static readonly string[] Variants = new string[4] { "grizzly", "brown", "black", "gray" }; internal static readonly double[] DefaultWeights = new double[3] { 0.5, 0.3, 0.2 }; internal static readonly double[] DefaultFoundation = new double[4] { 0.25, 0.25, 0.25, 0.25 }; internal static bool Known(string v) { return Array.IndexOf(Variants, v) >= 0; } internal static bool Finite(double d) { if (!double.IsNaN(d)) { return !double.IsInfinity(d); } return false; } internal static double[] Normalize(double[] values, int count) { if (values == null || values.Length != count || values.Any((double d) => !Finite(d) || d < 0.0)) { throw new ArgumentException("Negative/non-finite genetic weight"); } double max = values.Max(); if (max <= 0.0) { throw new ArgumentException("All genetic weights are zero"); } double sum = values.Sum((double d) => d / max); return values.Select((double d) => d / max / sum).ToArray(); } internal static Ancestor[] Unknown(int count) { return (from _ in Enumerable.Range(0, count) select new Ancestor()).ToArray(); } private static bool Level(Ancestor[] a, int max) { if (a != null && a.Length <= max) { return a.All((Ancestor p) => p != null && p.id != null && p.id.Length <= 128 && p.variant != null && ((p.id.Length == 0 && p.variant.Length == 0) || (p.id.Length > 0 && Known(p.variant)))); } return false; } internal static bool Valid(BearGenes? b) { if (b != null && b.schema == 1 && !string.IsNullOrEmpty(b.id) && b.id.Length <= 128 && Known(b.variant) && Level(b.g1, 2) && Level(b.g2, 4) && Level(b.g3, 8) && b.seed != null && b.seed.Length <= 128 && b.origin != null && b.birth != null && (b.birth.Length == 0 || (b.birth.Length == 4 && b.birth.All((double p) => Finite(p) && p >= 0.0 && p <= 1.0) && Math.Abs(b.birth.Sum() - 1.0) < 1E-08)) && b.weights != null) { if (b.weights.Length != 0) { if (b.weights.Length == 3 && b.weights.All((double p) => Finite(p) && p >= 0.0)) { return b.weights.Any((double p) => p > 0.0); } return false; } return true; } return false; } private static Ancestor Self(BearGenes? b) { if (!Valid(b)) { return new Ancestor(); } return new Ancestor { id = b.id, variant = b.variant }; } private static Ancestor[] Pad(Ancestor[]? a, int count) { return (from i in Enumerable.Range(0, count) select (a == null || i >= a.Length) ? new Ancestor() : a[i].Copy()).ToArray(); } internal static BearGenes Child(BearGenes? a, BearGenes? b, string id) { BearGenes bearGenes = new BearGenes(); bearGenes.id = id; bearGenes.origin = "inherited"; bearGenes.g1 = new Ancestor[2] { Self(a), Self(b) }; bearGenes.g2 = Pad(a?.g1, 2).Concat(Pad(b?.g1, 2)).ToArray(); bearGenes.g3 = Pad(a?.g2, 4).Concat(Pad(b?.g2, 4)).ToArray(); return bearGenes; } internal static double[] Probabilities(BearGenes child, double[] weights) { double[] array = Normalize(weights, 3); double[] array2 = new double[4]; Ancestor[][] array3 = new Ancestor[3][] { child.g1, child.g2, child.g3 }; int[] array4 = new int[3] { 2, 4, 8 }; for (int i = 0; i < 3; i++) { if (!Level(array3[i], array4[i])) { throw new ArgumentException("Unbounded or invalid genetic snapshots"); } Ancestor[] array5 = array3[i]; foreach (Ancestor ancestor in array5) { int num = Array.IndexOf(Variants, ancestor.variant); if (num >= 0) { array2[num] += array[i] / (double)array4[i]; } } } if (array2.All((double d) => d == 0.0)) { throw new ArgumentException("No weighted known ancestry; foundation required"); } return Normalize(array2, 4); } internal static double Roll(string seed) { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(seed)); ulong num = 0uL; for (int i = 0; i < 8; i++) { num = (num << 8) | array[i]; } return (double)(num >> 11) * 1.1102230246251565E-16; } internal static string Draw(double[] probabilities, string seed) { double[] array = Normalize(probabilities, 4); double num = Roll(seed); double num2 = 0.0; int num3 = 0; for (int i = 0; i < 4; i++) { if (array[i] > 0.0) { num3 = i; } num2 += array[i]; if (num < num2) { return Variants[i]; } } return Variants[num3]; } internal static BearGenes Complete(BearGenes child, double[] probabilities, double[] weights, string seed) { child.birth = Normalize(probabilities, 4); child.weights = (double[])weights.Clone(); child.seed = seed; child.variant = Draw(child.birth, seed); return child; } internal static double[] Percentages(double[] p) { double[] n = Normalize(p, 4); int[] units = n.Select((double x) => (int)Math.Floor(x * 1000.0)).ToArray(); int count = 1000 - units.Sum(); foreach (int item in (from i in Enumerable.Range(0, 4) orderby n[i] * 1000.0 - (double)units[i] descending, i select i).Take(count)) { units[item]++; } return units.Select((int x) => (double)x / 10.0).ToArray(); } } internal static class SexScaleMath { internal static double Factor(bool male, bool hermaphrodite, double maturity, double adultFactor) { if (!male || hermaphrodite) { return 1.0; } if (!BearInheritance.Finite(adultFactor) || adultFactor < 1.0 || adultFactor > 2.0) { adultFactor = 1.3; } return 1.0 + (adultFactor - 1.0) * Math.Max(0.0, Math.Min(1.0, BearInheritance.Finite(maturity) ? maturity : 0.0)); } internal static double Apply(double nativeBase, double factor) { return nativeBase * factor; } } internal static class BearGenetics { private sealed class Cache { internal string Raw = ""; internal BearGenes? Value; } internal const string Key = "zf_bjorn_genes_v1"; internal const string PendingKey = "zf_bjorn_child_v1"; internal static ConfigEntry<float> MaleFactor = null; internal static ConfigEntry<bool> Trace = null; private static ConfigEntry<float>[] weights = null; private static ConfigEntry<float>[] foundations = null; private static bool validating; private static float next; private static double[] validWeights = (double[])BearInheritance.DefaultWeights.Clone(); private static double[] validFoundation = (double[])BearInheritance.DefaultFoundation.Clone(); private static readonly Dictionary<string, Cache> cache = new Dictionary<string, Cache>(); private static ZNet? world; internal static double[] Weights => (double[])validWeights.Clone(); internal static double[] Foundation => (double[])validFoundation.Clone(); internal static bool IsBear(Component? c) { if (Object.op_Implicit((Object)(object)c)) { return AnimalSexState.Species(c) == "Bjorn"; } return false; } internal static void Configure(ConfigFile config) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown ConfigDescription description = new ConfigDescription("Server-synchronized Bjorn genetics; nonnegative finite weights, at least one positive. Invalid groups restore defaults. Variants have no statistics bonuses; Bjorn/Lox male health and female riding stamina each have a separate 10% sex bonus.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } }); MaleFactor = config.Bind<float>("Server Rules", "Male linear size factor", 1.3f, new ConfigDescription("Linear dimensions of recorded males only. Hermaphrodite/unknown keep native size. Uses existing growth clock. Valid range 1..2; invalid restores 1.30.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); weights = (from i in Enumerable.Range(0, 3) select config.Bind<float>("Server Rules", "Bjorn inheritance G" + (i + 1) + " weight", (float)BearInheritance.DefaultWeights[i], description)).ToArray(); foundations = (from i in Enumerable.Range(0, 4) select config.Bind<float>("Server Rules", "Bjorn foundation " + BearInheritance.Variants[i] + " weight", 0.25f, description)).ToArray(); Trace = config.Bind<bool>("Client", "Genetics and size diagnostics", false, "State-change diagnostics only. No per-frame tree calculation or log. zf_genetics_trace on/off."); Validate(); } internal static void Validate() { if (validating || weights == null) { return; } validating = true; try { Group(weights, BearInheritance.DefaultWeights, ref validWeights, "G1/G2/G3 weights"); Group(foundations, BearInheritance.DefaultFoundation, ref validFoundation, "foundation weights"); if (!BearInheritance.Finite(MaleFactor.Value) || MaleFactor.Value < 1f || MaleFactor.Value > 2f) { Plugin.Error("SIZE invalid male factor; restored 1.30."); MaleFactor.Value = 1.3f; } } finally { validating = false; } static void Group(ConfigEntry<float>[] entries, double[] defaults, ref double[] valid, string label) { try { valid = BearInheritance.Normalize(((IEnumerable<ConfigEntry<float>>)entries).Select((Func<ConfigEntry<float>, double>)((ConfigEntry<float> e) => e.Value)).ToArray(), entries.Length); } catch (ArgumentException ex) { valid = (double[])defaults.Clone(); Plugin.Error("GENETICS invalid " + label + ": " + ex.Message + "; restored defaults."); for (int num = 0; num < entries.Length; num++) { entries[num].Value = (float)defaults[num]; } } } } internal static BearGenes? Read(Component? c) { ZNetView val = (Object.op_Implicit((Object)(object)c) ? c.GetComponent<ZNetView>() : null); if (!IsBear(c) || !Object.op_Implicit((Object)(object)val) || !val.IsValid()) { return null; } return Read(val.GetZDO()); } internal static BearGenes? Read(ZDO z) { return Decode(z.GetString("zf_bjorn_genes_v1", "")); } internal static BearGenes? Decode(string raw) { if (string.IsNullOrEmpty(raw)) { return null; } if (cache.TryGetValue(raw, out Cache value)) { return value.Value; } BearGenes bearGenes = null; try { if (raw.Length > 12000) { throw new ArgumentException("Genetic record exceeds bound"); } bearGenes = PresetJson.FromJson<BearGenes>(raw); if (!BearInheritance.Valid(bearGenes)) { throw new ArgumentException("Invalid/unsupported bounded schema"); } } catch (Exception ex) { bearGenes = null; Plugin.Error("GENETICS existing data preserved, operation refused: " + ex.Message); } if (cache.Count >= 512) { cache.Clear(); } cache[raw] = new Cache { Raw = raw, Value = bearGenes }; return bearGenes; } internal static BearGenes FoundationRecord(string origin) { string id = Guid.NewGuid().ToString("N"); string seed = Guid.NewGuid().ToString("N"); return BearInheritance.Complete(new BearGenes { id = id, origin = origin }, Foundation, Array.Empty<double>(), seed); } internal static BearGenes? Ensure(Component c) { if (!IsBear(c)) { return null; } ZNetView component = c.GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return null; } ZDO zDO = component.GetZDO(); BearGenes bearGenes = Read(zDO); if (bearGenes != null || !Plugin.ConfigReady || !component.IsOwner() || !string.IsNullOrEmpty(zDO.GetString("zf_bjorn_genes_v1", ""))) { return bearGenes; } BearGenes bearGenes2 = FoundationRecord("foundation-or-migration"); Write(zDO, "zf_bjorn_genes_v1", bearGenes2, "foundation/migration"); return bearGenes2; } private static void Write(ZDO z, string key, BearGenes genes, string reason) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!BearInheritance.Valid(genes)) { throw new InvalidOperationException("Refused invalid genetic record"); } if (key == "zf_bjorn_child_v1") { genes.conceptionToken = z.GetLong(ZDOVars.s_pregnant, 0L); } z.Set(key, PresetJson.ToJson(genes)); if (Trace.Value) { Plugin.Info(string.Format("GENETICS {0} ZDO={1} owner={2} id={3} sex={4} variant={5} ancestry={6}/{7}/{8} weights={9} probabilities={10} seed={11}", reason, z.m_uid, z.GetOwner(), genes.id, z.GetInt("zf_sex_v1", 0), genes.variant, genes.g1.Count((Ancestor a) => a.id.Length > 0), genes.g2.Count((Ancestor a) => a.id.Length > 0), genes.g3.Count((Ancestor a) => a.id.Length > 0), string.Join(",", genes.weights), string.Join(",", genes.birth), genes.seed)); } } internal static void Conceived(Procreation mother) { if (IsBear((Component?)(object)mother) && CreatureState.Owner((Component)(object)mother, out ZDO zdo) && zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L && Decode(zdo.GetString("zf_bjorn_child_v1", ""))?.conceptionToken != zdo.GetLong(ZDOVars.s_pregnant, 0L)) { Procreation approvedPartner = MatingAuthority.ApprovedPartner; BearGenes bearGenes = Ensure((Component)(object)mother); BearGenes bearGenes2 = (Object.op_Implicit((Object)(object)approvedPartner) ? Read((Component?)(object)approvedPartner) : null); if (bearGenes == null || bearGenes2 == null) { LegacyPending(mother, zdo); return; } BearGenes bearGenes3 = BearInheritance.Child(bearGenes, bearGenes2, Guid.NewGuid().ToString("N")); double[] array = Weights; double[] probabilities = BearInheritance.Probabilities(bearGenes3, array); BearInheritance.Complete(bearGenes3, probabilities, array, Guid.NewGuid().ToString("N")); Write(zdo, "zf_bjorn_child_v1", bearGenes3, "conception parents=" + bearGenes.id + "/" + bearGenes2.id); } } internal static BearGenes? Pending(Procreation mother) { if (!Plugin.ConfigReady || !IsBear((Component?)(object)mother) || !CreatureState.Owner((Component)(object)mother, out ZDO zdo)) { return null; } string text = zdo.GetString("zf_bjorn_child_v1", ""); BearGenes bearGenes = Decode(text); if (text.Length > 0 && bearGenes == null) { return null; } if (bearGenes != null && bearGenes.conceptionToken == zdo.GetLong(ZDOVars.s_pregnant, 0L)) { return bearGenes; } if (text.Length > 0) { zdo.Set("zf_bjorn_child_v1", ""); } if (zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L) { LegacyPending(mother, zdo); return Decode(zdo.GetString("zf_bjorn_child_v1", "")); } return null; } private static void LegacyPending(Procreation mother, ZDO z) { if (string.IsNullOrEmpty(z.GetString("zf_bjorn_child_v1", ""))) { BearGenes genes = FoundationRecord("legacy-unrecorded-conception"); Write(z, "zf_bjorn_child_v1", genes, "legacy pregnancy, deadline untouched, parents unknown"); } } internal static void Born(GameObject baby, Procreation mother, BearGenes? child) { if (IsBear((Component?)(object)baby.transform) && child != null && CreatureState.Owner((Component)(object)baby.transform, out ZDO zdo)) { Write(zdo, "zf_bjorn_genes_v1", child, "native birth"); ApplyIndividual(baby, child); if (CreatureState.Owner((Component)(object)mother, out ZDO zdo2)) { zdo2.Set("zf_bjorn_child_v1", ""); } } } internal static void Grown(Component baby, GameObject adult) { if (IsBear(baby) && IsBear((Component?)(object)adult.transform) && CreatureState.Owner((Component)(object)adult.transform, out ZDO zdo)) { BearGenes bearGenes = Ensure(baby); if (bearGenes != null) { Write(zdo, "zf_bjorn_genes_v1", bearGenes, "native growth same identity/variant/lineage"); ApplyIndividual(adult, bearGenes); } } } private static void ApplyIndividual(GameObject go, BearGenes genes) { Character component = go.GetComponent<Character>(); if (Object.op_Implicit((Object)(object)component)) { AnimalSexState.Ensure((Component)(object)component); SexBody.Bind(component).Refresh(); SexStats.Refresh(component); BearAppearance.Bind(component).Refresh(genes); } } internal static void Tick() { if ((Object)(object)world != (Object)(object)ZNet.instance) { world = ZNet.instance; cache.Clear(); } if (!Plugin.ConfigReady || Time.realtimeSinceStartup < next) { return; } next = Time.realtimeSinceStartup + 1f; foreach (Character allCharacter in Character.GetAllCharacters()) { if (IsBear((Component?)(object)allCharacter)) { Ensure((Component)(object)allCharacter); Procreation component = ((Component)allCharacter).GetComponent<Procreation>(); if (Object.op_Implicit((Object)(object)component)) { Pending(component); } } if (SexBody.Supported((Component)(object)allCharacter)) { SexBody.Bind(allCharacter).Refresh(); SexStats.Refresh(allCharacter); } if (IsBear((Component?)(object)allCharacter)) { BearAppearance.Bind(allCharacter).Refresh(Read((Component?)(object)allCharacter)); } } } internal static bool CanConceive(Component mother, Component mate) { BearGenes bearGenes = Ensure(mother); BearGenes bearGenes2 = Read(mate); if (bearGenes == null || bearGenes2 == null) { return false; } try { BearInheritance.Probabilities(BearInheritance.Child(bearGenes, bearGenes2, "preview"), Weights); return true; } catch (ArgumentException) { return false; } } } [HarmonyPatch(typeof(Procreation), "Procreate")] internal static class BearBirth { private sealed class Scope { internal Procreation Mother; internal BearGenes? Child; } [ThreadStatic] private static Scope? scope; [HarmonyPrefix] private static bool Prefix(Procreation __instance, out Scope? __state) { __state = scope; scope = (BearGenetics.IsBear((Component?)(object)__instance) ? new Scope { Mother = __instance, Child = BearGenetics.Pending(__instance) } : null); if (scope != null && CreatureState.Owner((Component)(object)__instance, out ZDO zdo) && zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L) { return scope.Child != null; } return true; } [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception, Scope? __state) { scope = __state; return __exception; } private static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot); if (scope != null) { BearGenetics.Born(val, scope.Mother, scope.Child); } return val; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { int replaced = 0; foreach (CodeInstruction item in source) { if (item.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments()[0] == typeof(GameObject) && methodInfo.GetParameters().Length == 3) { item.operand = AccessTools.Method(typeof(BearBirth), "Spawn", (Type[])null, (Type[])null); replaced++; } yield return item; } if (replaced != 1) { throw new InvalidOperationException("Native birth contract changed: expected one native Instantiate, got " + replaced); } } } internal sealed class BearMount : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<Character, bool> <>9__10_0; public static Func<Character, float> <>9__10_1; public static Func<Character, BearMount> <>9__10_2; public static Func<BearMount, bool> <>9__10_3; public static ConsoleEvent <>9__11_0; internal bool <Select>b__10_0(Character c) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)c) && c.IsTamed() && Utils.GetPrefabName(((Component)c).gameObject) == "Bjorn") { return Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position) < 15f; } return false; } internal float <Select>b__10_1(Character c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position); } internal BearMount <Select>b__10_2(Character c) { return ((Component)c).GetComponent<BearMount>(); } internal bool <Select>b__10_3(BearMount c) { if (Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)c.mount) && Object.op_Implicit((Object)(object)c.bone)) { return Object.op_Implicit((Object)(object)c.mount.getSaddle()); } return false; } internal void <RegisterCommands>b__11_0(ConsoleEventArgs args) { if (args.Args.Length == 1 || args.Args[1] == "show") { Show(args.Context); } else { args.Context.AddString(Texts.T("Les anciennes commandes de modification sont remplacées par F9 et les presets.", "Legacy editing commands are replaced by F9 presets.")); } } } private Mountable mount; private Transform visual; private Transform bone; private static BearMount? preview; internal static void Bind(Mountable value) { if (!(Utils.GetPrefabName(((Component)value).gameObject) != "Bjorn") && !Object.op_Implicit((Object)(object)((Component)value).GetComponent<Growup>())) { BearMount bearMount = ((Component)value).GetComponent<BearMount>(); if (!Object.op_Implicit((Object)(object)bearMount)) { bearMount = ((Component)value).gameObject.AddComponent<BearMount>(); } bearMount.mount = value; bearMount.visual = ((Component)value).transform.Find("Visual"); bearMount.bone = (Object.op_Implicit((Object)(object)bearMount.visual) ? bearMount.visual.Find("Armature/Root/CoG/Hip/Spine_01/Spine_02") : null); MountRiding.Bind(((Component)value).GetComponent<Character>()); bearMount.Apply(); } } private void LateUpdate() { Apply(); } internal void Apply() { MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>()); if (Object.op_Implicit((Object)(object)mountPlacement) && mountPlacement.Ready()) { mountPlacement.Apply(); } } private static bool Valid(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (SaddleGeometry.Finite(v) && Math.Abs(v.x) <= 1000f && Math.Abs(v.y) <= 1000f) { return Math.Abs(v.z) <= 1000f; } return false; } private void Begin() { MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>()); if (!Object.op_Implicit((Object)(object)mountPlacement) || !mountPlacement.Ready()) { throw new InvalidOperationException("Saddle reference not loaded"); } mountPlacement.Capture().SaveConfig("Bjorn"); preview = this; Apply(); } private void Fit(Terminal context) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>()); if (!Object.op_Implicit((Object)(object)mountPlacement) || !mountPlacement.Ready()) { throw new InvalidOperationException("Saddle reference not loaded"); } if (mountPlacement.TryFit(PlacementPreset.Config("Bjorn", mountPlacement.ReferenceScale), out PlacementPreset candidate, out string explanation)) { candidate.SaveConfig("Bjorn"); Apply(); } context.AddString(explanation); } private static BearMount? Select() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return null; } IDoodadController doodadController = Player.m_localPlayer.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if (val != null) { Character character = val.GetCharacter(); if (Object.op_Implicit((Object)(object)character)) { return ((Component)character).GetComponent<BearMount>(); } } return (from c in Character.GetAllCharacters() where Object.op_Implicit((Object)(object)c) && c.IsTamed() && Utils.GetPrefabName(((Component)c).gameObject) == "Bjorn" && Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position) < 15f orderby Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position) select ((Component)c).GetComponent<BearMount>()).FirstOrDefault((BearMount c) => Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)c.mount) && Object.op_Implicit((Object)(object)c.bone) && Object.op_Implicit((Object)(object)c.mount.getSaddle())); } internal static void RegisterCommands() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown string text = Texts.T("Diagnostic Bjorn : show. Réglages dans F9 / presets.", "Bjorn diagnostic: show. Edit through F9 / presets."); object obj = <>c.<>9__11_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Args.Length == 1 || args.Args[1] == "show") { Show(args.Context); } else { args.Context.AddString(Texts.T("Les anciennes commandes de modification sont remplacées par F9 et les presets.", "Legacy editing commands are replaced by F9 presets.")); } }; <>c.<>9__11_0 = val; obj = (object)val; } new ConsoleCommand("zf_mount", text, (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static float Parse(string value) { return float.Parse(value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture); } private static Vector3 Wrapped(Vector3 value) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0030: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Mathf.DeltaAngle(0f, value.x), Mathf.DeltaAngle(0f, value.y), Mathf.DeltaAngle(0f, value.z)); } private static void Show(Terminal context) { //IL_0024: 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_003e: 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) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) object[] obj = new object[6] { Plugin.PlacementEnabled.Value, null, null, null, null, null }; Vector3 value = Plugin.ModelPosition.Value; obj[1] = ((Vector3)(ref value)).ToString("F4"); value = Plugin.ModelRotation.Value; obj[2] = ((Vector3)(ref value)).ToString("F3"); value = Plugin.ModelScale.Value; obj[3] = ((Vector3)(ref value)).ToString("F4"); value = Plugin.SeatPosition.Value; obj[4] = ((Vector3)(ref value)).ToString("F4"); value = Plugin.SeatRotation.Value; obj[5] = ((Vector3)(ref value)).ToString("F3"); string text = string.Format("BJORN PLACEMENT enabled={0} model={1} rot={2} scale={3} seat={4} seatRot={5}; origin=Spine_02, axes=Visual; calibration status requires human visual check.", obj); context.AddString(text + "\n" + Texts.T("Origine : Spine_02, axes du modèle Visual. Contrôle visuel humain nécessaire.", "Origin: Spine_02, Visual axes. Human visual check required.")); Plugin.Info(text); } } [HarmonyPatch(typeof(Mountable), "Awake")] internal static class BindBearMount { [HarmonyPostfix] private static void Postfix(Mountable __instance) { BearMount.Bind(__instance); } } [HarmonyPatch(typeof(Mountable), "ResetMountPoint")] internal static class PreserveIndependentSeat { [HarmonyPostfix] private static void Postfix(Mountable __instance) { ((Component)__instance).GetComponent<BearMount>()?.Apply(); } } internal static class BreedingDiagnostics { private sealed class Request { internal long Client; internal float Expires; internal Vector3 Position; internal bool French; internal bool Defense; } private sealed class Attempts { internal int Count; internal float Last; internal float Interval; internal float NextLog; internal string State = ""; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<KeyValuePair<string, Request>, bool> <>9__12_0; public static Func<KeyValuePair<string, Request>, string> <>9__12_1; public static ConsoleEvent <>9__13_0; public static ConsoleEvent <>9__13_1; internal bool <Tick>b__12_0(KeyValuePair<string, Request> p) { return Time.realtimeSinceStartup > p.Value.Expires; } internal string <Tick>b__12_1(KeyValuePair<string, Request> p) { return p.Key; } internal void <Register>b__13_0(ConsoleEventArgs args) { QuerySnapshot(new <>c__DisplayClass13_0 { args = args }.<Register>b__2, defense: true); } internal void <Register>b__13_1(ConsoleEventArgs args) { QuerySnapshot(new <>c__DisplayClass13_1 { args = args }.<Register>b__3, defense: false); } } [CompilerGenerated] private sealed class <>c__DisplayClass13_0 { public ConsoleEventArgs args; internal void <Register>b__2(string s) { args.Context.AddString(s); } } [CompilerGenerated] private sealed class <>c__DisplayClass13_1 { public ConsoleEventArgs args; internal void <Register>b__3(string s) { args.Context.AddString(s); } } private const string Query = "ZF_BreedingQuery_v2"; private const string OwnerQuery = "ZF_BreedingOwnerQuery_v2"; private const string Reply = "ZF_BreedingReply_v2"; private const string Result = "ZF_BreedingResult_v2"; private static readonly Dictionary<string, Request> requests = new Dictionary<string, Request>(); private static readonly Dictionary<ZDOID, Attempts> attempts = new Dictionary<ZDOID, Attempts>(); private static ZRoutedRpc? rpc; private static ZNet? world; private static Action<string>? output; private static string localRequest = ""; internal static void Tick() { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Plugin.ConfigReady || ZRoutedRpc.instance == null) { rpc = null; world = null; requests.Clear(); attempts.Clear(); output = null; return; } if ((Object)(object)world != (Object)(object)ZNet.instance) { world = ZNet.instance; requests.Clear(); attempts.Clear(); } if (rpc != ZRoutedRpc.instance) { rpc = ZRoutedRpc.instance; rpc.Register<ZPackage>("ZF_BreedingQuery_v2", (Action<long, ZPackage>)ReceiveQuery); rpc.Register<ZPackage>("ZF_BreedingOwnerQuery_v2", (Action<long, ZPackage>)ReceiveOwnerQuery); rpc.Register<ZPackage>("ZF_BreedingReply_v2", (Action<long, ZPackage>)ReceiveReply); rpc.Register<ZPackage>("ZF_BreedingResult_v2", (Action<long, ZPackage>)ReceiveResult); } string[] array = (from p in requests where Time.realtimeSinceStartup > p.Value.Expires select p.Key).ToArray(); foreach (string key in array) { requests.Remove(key); } } internal static void Register() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to inva