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 Hoardgoblin v0.1.0
Hoardgoblin.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Hoardgoblin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+de7a0841a076597f80d0fedde23b4601a133ce6a")] [assembly: AssemblyProduct("Hoardgoblin")] [assembly: AssemblyTitle("Hoardgoblin")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 MyMods { public static class HallClient { private struct Pending { public string Id; public string Title; public int Order; public Action<Rect> Draw; } private static readonly List<Pending> s_pending = new List<Pending>(); private static Type s_type; private static bool s_miss; private static MethodInfo s_register; private static MethodInfo s_open; private static MethodInfo s_close; private static MethodInfo s_hosting; private static MethodInfo s_yield; private static MethodInfo s_hold; private static PropertyInfo s_ready; private static PropertyInfo s_openProp; private static Type HallType { get { if (s_type != null || s_miss) { return s_type; } s_type = Type.GetType("DFGHub.HallBoard, DFGHub"); s_miss = s_type == null; return s_type; } } public static bool Ready { get { if (s_ready == null && HallType != null) { s_ready = HallType.GetProperty("Ready", BindingFlags.Static | BindingFlags.Public); } if (s_ready == null) { return false; } object value = s_ready.GetValue(null, null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } public static bool IsOpen { get { if (s_openProp == null && HallType != null) { s_openProp = HallType.GetProperty("IsOpen", BindingFlags.Static | BindingFlags.Public); } if (s_openProp == null) { return false; } object value = s_openProp.GetValue(null, null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } public static void Bind(string id, string title, int order, Action<Rect> draw) { if (string.IsNullOrEmpty(id) || draw == null) { return; } for (int num = s_pending.Count - 1; num >= 0; num--) { if (string.Equals(s_pending[num].Id, id, StringComparison.OrdinalIgnoreCase)) { s_pending.RemoveAt(num); } } s_pending.Add(new Pending { Id = id, Title = title, Order = order, Draw = draw }); Flush(); } public static void Flush() { if (s_pending.Count != 0 && Ready) { for (int i = 0; i < s_pending.Count; i++) { Pending pending = s_pending[i]; TryRegister(pending.Id, pending.Title, pending.Order, pending.Draw); } s_pending.Clear(); } } public static bool TryOpen(string tabId) { if (!Ready) { return false; } if (s_open == null) { s_open = HallType.GetMethod("Open", BindingFlags.Static | BindingFlags.Public); } if (s_open == null) { return false; } try { object obj = s_open.Invoke(null, new object[1] { tabId }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception) { return false; } } public static void Close() { if (HallType == null) { return; } if (s_close == null) { s_close = HallType.GetMethod("Close", BindingFlags.Static | BindingFlags.Public); } try { s_close?.Invoke(null, null); } catch (Exception) { } } public static bool IsHosting(string id) { if (HallType == null || string.IsNullOrEmpty(id)) { return false; } if (s_hosting == null) { s_hosting = HallType.GetMethod("IsHosting", BindingFlags.Static | BindingFlags.Public); } if (s_hosting == null) { return false; } try { object obj = s_hosting.Invoke(null, new object[1] { id }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception) { return false; } } public static void SetYield(bool yieldScreen) { if (HallType == null) { return; } if (s_yield == null) { s_yield = HallType.GetMethod("SetYield", BindingFlags.Static | BindingFlags.Public); } try { s_yield?.Invoke(null, new object[1] { yieldScreen }); } catch (Exception) { } } public static void HoldEscape() { if (HallType == null) { return; } if (s_hold == null) { s_hold = HallType.GetMethod("HoldEscape", BindingFlags.Static | BindingFlags.Public); } try { s_hold?.Invoke(null, null); } catch (Exception) { } } private static void TryRegister(string id, string title, int order, Action<Rect> draw) { if (s_register == null) { s_register = HallType.GetMethod("Register", BindingFlags.Static | BindingFlags.Public); } s_register?.Invoke(null, new object[4] { id, title, order, draw }); } } } namespace Hoardgoblin { public class HoardgoblinAnimator : MonoBehaviour { private const float DefaultFadeSeconds = 0.18f; private readonly Dictionary<string, Transform> m_bones = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase); private Pose m_current; private Pose m_previous; private float m_time; private float m_previousTime; private float m_fade = 1f; private float m_fadeDuration = 0.18f; private bool m_loop = true; private float m_speed = 1f; public string CurrentClip { get { if (m_current == null) { return null; } return m_current.Name; } } public bool IsBusy { get { if (m_current != null && !m_loop) { return m_time < m_current.Length; } return false; } } public float NormalizedTime { get { if (m_current == null || !(m_current.Length > 0.001f)) { return 0f; } return Mathf.Clamp01(m_time / m_current.Length); } } public void Bind(Transform armature) { m_bones.Clear(); if ((Object)(object)armature == (Object)null) { return; } foreach (Pose value in HoardgoblinGlb.Poses.Values) { for (int i = 0; i < value.Tracks.Length; i++) { string path = value.Tracks[i].Path; if (!m_bones.ContainsKey(path)) { Transform val = armature.Find(path); if ((Object)(object)val != (Object)null) { m_bones[path] = val; } } } } MapBonesRecursive(armature, ""); } private void MapBonesRecursive(Transform current, string parentPath) { string text = (string.IsNullOrEmpty(parentPath) ? ((Object)current).name : (parentPath + "/" + ((Object)current).name)); if (!m_bones.ContainsKey(((Object)current).name)) { m_bones[((Object)current).name] = current; } if (!m_bones.ContainsKey(text)) { m_bones[text] = current; } for (int i = 0; i < current.childCount; i++) { MapBonesRecursive(current.GetChild(i), text); } } public bool Play(string clip, bool loop, float speed = 1f, bool restart = false, float fadeSeconds = 0.18f) { Pose pose = HoardgoblinGlb.Get(clip); if (pose == null) { return false; } if (pose == m_current && !restart) { m_loop = loop; m_speed = speed; return true; } m_previous = m_current; m_previousTime = m_time; m_current = pose; m_time = 0f; m_fadeDuration = Mathf.Max(0.01f, fadeSeconds); m_fade = ((m_previous == null) ? 1f : 0f); m_loop = loop; m_speed = speed; return true; } private void LateUpdate() { if (m_current != null) { float deltaTime = Time.deltaTime; m_time = Advance(m_time, deltaTime * m_speed, m_current.Length, m_loop); if (m_fade < 1f) { m_fade = Mathf.Min(1f, m_fade + deltaTime / m_fadeDuration); } if (m_previous != null && m_fade < 1f) { m_previousTime = Advance(m_previousTime, deltaTime, m_previous.Length, loop: true); Track(m_previous, m_previousTime, 1f); Track(m_current, m_time, m_fade); } else { Track(m_current, m_time, 1f); } } } private void Track(Pose pose, float time, float weight) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) Pose.Track[] tracks = pose.Tracks; foreach (Pose.Track track in tracks) { if (!m_bones.TryGetValue(track.Path, out var value) || (Object)(object)value == (Object)null) { int num = track.Path.LastIndexOf('/'); string key = ((num >= 0) ? track.Path.Substring(num + 1) : track.Path); if (!m_bones.TryGetValue(key, out value) || (Object)(object)value == (Object)null) { continue; } } if (track.SampleRotation(time, out var value2)) { value.localRotation = ((weight >= 1f) ? value2 : Quaternion.Slerp(value.localRotation, value2, weight)); } if (track.SamplePosition(time, out var value3)) { value.localPosition = ((weight >= 1f) ? value3 : Vector3.Lerp(value.localPosition, value3, weight)); } if (track.SampleScale(time, out var value4)) { value.localScale = ((weight >= 1f) ? value4 : Vector3.Lerp(value.localScale, value4, weight)); } } } private static float Advance(float time, float dt, float length, bool loop) { if (length <= 0.0001f) { return 0f; } time += dt; if (time < length) { return time; } if (!loop) { return length; } return time % length; } } public class HoardgoblinController : MonoBehaviour { public const string PrefabName = "DFG_Hoardgoblin"; private static int s_obstacleMask; private Character m_character; private ZNetView m_nview; private AnimalAI m_animalAI; private BaseAI m_baseAI; private Transform m_model; private HoardgoblinAnimator m_anim; private float m_trailTimer; private float m_chaseTimer; private bool m_isChannelingEscape; private float m_escapeChannelTimer; private GameObject m_portalEffectInstance; private bool m_isDead; private float m_deathTimer; private float m_panicTimer; private float m_lastHealth; private Vector3 m_lastStuckPos; private float m_stuckCheckTimer; private float m_jumpCooldown; private void Awake() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (s_obstacleMask == 0) { s_obstacleMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" }); if (s_obstacleMask == 0) { s_obstacleMask = -1; } } m_character = ((Component)this).GetComponent<Character>(); m_nview = ((Component)this).GetComponent<ZNetView>(); m_animalAI = ((Component)this).GetComponent<AnimalAI>(); m_baseAI = ((Component)this).GetComponent<BaseAI>(); if ((Object)(object)m_character != (Object)null) { m_character.m_speed = HoardgoblinSettings.WalkSpeed.Value; m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value; m_character.m_turnSpeed = 450f; m_character.m_jumpForce = HoardgoblinSettings.JumpForce.Value; m_lastHealth = m_character.GetHealth(); } m_lastStuckPos = ((Component)this).transform.position; AttachCustomModel(); HideVanillaRenderers(); } private void Start() { if ((Object)(object)m_character != (Object)null) { m_lastHealth = m_character.GetHealth(); m_character.m_speed = HoardgoblinSettings.WalkSpeed.Value; m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value; } } private void AttachCustomModel() { //IL_003f: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)HoardgoblinGlb.Template == (Object)null) { HoardgoblinPlugin.Log.LogError((object)"Hoardgoblin: template model is null!"); return; } GameObject val = Object.Instantiate<GameObject>(HoardgoblinGlb.Template, ((Component)this).transform); ((Object)val).name = "Hoardgoblin_Visual"; val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one * HoardgoblinSettings.ModelScale.Value; val.SetActive(true); m_model = val.transform; m_anim = val.AddComponent<HoardgoblinAnimator>(); Transform val2 = val.transform.Find("Armature"); if ((Object)(object)val2 != (Object)null) { m_anim.Bind(val2); } else { m_anim.Bind(val.transform); } m_anim.Play("walk", loop: true); } private void HideVanillaRenderers() { Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)m_model != (Object)null) || !((Component)val).transform.IsChildOf(m_model)) { val.enabled = false; } } LODGroup[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<LODGroup>(true); foreach (LODGroup val2 in componentsInChildren2) { if (!((Object)(object)m_model != (Object)null) || !((Component)val2).transform.IsChildOf(m_model)) { val2.enabled = false; } } Animator[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Animator>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { componentsInChildren3[i].cullingMode = (AnimatorCullingMode)0; } } private void Update() { if ((Object)(object)m_character == (Object)null || (Object)(object)m_anim == (Object)null) { return; } if (m_isDead || m_character.IsDead() || m_character.GetHealth() <= 0f) { HandleDeath(); return; } m_character.m_speed = HoardgoblinSettings.RunSpeed.Value; m_character.m_walkSpeed = HoardgoblinSettings.WalkSpeed.Value; m_character.m_runSpeed = HoardgoblinSettings.RunSpeed.Value; m_character.m_acceleration = 35f; m_character.m_turnSpeed = 600f; m_character.m_runTurnSpeed = 600f; float health = m_character.GetHealth(); if (health < m_lastHealth - 0.1f) { OnDamaged(); } m_lastHealth = health; if (m_panicTimer > 0f) { m_panicTimer -= Time.deltaTime; } if (m_jumpCooldown > 0f) { m_jumpCooldown -= Time.deltaTime; } if ((Object)(object)m_nview == (Object)null || m_nview.IsOwner()) { TickAI(); } SyncAnimations(); } private void OnDamaged() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) m_panicTimer = 1.5f; if (m_isChannelingEscape) { CancelEscapeChannel("Interrupted by damage!"); } PlayPanicSqueal(); HoardgoblinLoot.DropTrailPouch(((Component)this).transform.position); if ((Object)(object)m_baseAI != (Object)null) { m_baseAI.Alert(); } } private void TickAI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, HoardgoblinSettings.FleeDistance.Value * 1.5f); bool flag = (Object)(object)closestPlayer != (Object)null; float num = (flag ? Vector3.Distance(((Component)this).transform.position, ((Component)closestPlayer).transform.position) : 999f); if (m_isChannelingEscape) { if ((Object)(object)m_baseAI != (Object)null) { m_baseAI.StopMoving(); } m_escapeChannelTimer += Time.deltaTime; if (m_escapeChannelTimer >= HoardgoblinSettings.EscapeChannelDuration.Value) { CompleteEscape(); } } else if (((flag && num <= HoardgoblinSettings.AlertRange.Value) || m_panicTimer > 0f) && (Object)(object)closestPlayer != (Object)null) { m_chaseTimer += Time.deltaTime; if ((Object)(object)m_baseAI != (Object)null) { m_baseAI.Alert(); } Vector3 val; if ((Object)(object)m_character != (Object)null) { m_character.SetWalk(false); m_character.SetRun(true); Vector3 moveDir = m_character.GetMoveDir(); if (((Vector3)(ref moveDir)).sqrMagnitude < 0.1f) { val = ((Component)this).transform.position - ((Component)closestPlayer).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; normalized.y = 0f; m_character.SetMoveDir(normalized); } } val = ((Component)this).transform.position - ((Component)closestPlayer).transform.position; Vector3 normalized2 = ((Vector3)(ref val)).normalized; normalized2.y = 0f; HandleObstacleJumping(normalized2); m_trailTimer += Time.deltaTime; if (m_trailTimer >= HoardgoblinSettings.CoinTrailInterval.Value) { m_trailTimer = 0f; HoardgoblinLoot.DropTrailPouch(((Component)this).transform.position); } if (m_chaseTimer >= HoardgoblinSettings.ChaseTimeBeforeEscape.Value && num >= 14f) { StartEscapeChannel(); } } else { m_trailTimer = 0f; if (m_chaseTimer > 0f) { m_chaseTimer = Mathf.Max(0f, m_chaseTimer - Time.deltaTime * 0.5f); } } } private void HandleObstacleJumping(Vector3 fleeDir) { //IL_005b: 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) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00d6: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (!HoardgoblinSettings.JumpObstacles.Value || (Object)(object)m_character == (Object)null || !m_character.IsOnGround()) { return; } m_stuckCheckTimer += Time.deltaTime; if (m_stuckCheckTimer >= 1f) { m_stuckCheckTimer = 0f; if (Vector3.Distance(((Component)this).transform.position, m_lastStuckPos) < 0.4f && m_jumpCooldown <= 0f) { m_character.Jump(false); m_jumpCooldown = 3.5f; Vector3 val = Vector3.Cross(fleeDir, Vector3.up) * ((Random.value < 0.5f) ? 1f : (-1f)); Vector3 val2 = fleeDir + val * 1.2f; Vector3 normalized = ((Vector3)(ref val2)).normalized; m_character.SetMoveDir(normalized); m_character.SetLookDir(normalized, 0f); } m_lastStuckPos = ((Component)this).transform.position; } } private void SyncAnimations() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) if (m_isDead) { m_anim.Play("defeat_03", loop: false); return; } if (m_isChannelingEscape) { m_anim.Play("cast_a_spell", loop: true, 1.2f); return; } if (m_character.IsSwimming()) { m_anim.Play("swim", loop: true, 1.2f); return; } if (!m_character.IsOnGround()) { m_anim.Play("dive", loop: true, 1.4f); return; } if (m_panicTimer > 0f) { m_anim.Play("frightened", loop: true, 1.4f); return; } bool num = (Object)(object)Player.GetClosestPlayer(((Component)this).transform.position, HoardgoblinSettings.AlertRange.Value) != (Object)null || m_panicTimer > 0f; Vector3 velocity = m_character.GetVelocity(); Vector2 val = new Vector2(velocity.x, velocity.z); float magnitude = ((Vector2)(ref val)).magnitude; if (num || magnitude > 2.5f) { m_anim.Play("run", loop: true, 1.65f); } else if (magnitude > 0.2f) { m_anim.Play("walk", loop: true, 1.2f); } else { m_anim.Play("walk", loop: true, 0.4f); } } private void StartEscapeChannel() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) m_isChannelingEscape = true; m_escapeChannelTimer = 0f; HoardgoblinPlugin.Log.LogInfo((object)"Hoardgoblin: started escape portal channel!"); if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject val = ZNetScene.instance.GetPrefab("vfx_bifrost") ?? ZNetScene.instance.GetPrefab("vfx_portal_connected") ?? ZNetScene.instance.GetPrefab("vfx_spawn"); if ((Object)(object)val != (Object)null) { m_portalEffectInstance = Object.Instantiate<GameObject>(val, ((Component)this).transform.position, Quaternion.identity); m_portalEffectInstance.transform.localScale = Vector3.one * 0.6f; } } } private void CancelEscapeChannel(string reason) { if (m_isChannelingEscape) { m_isChannelingEscape = false; m_escapeChannelTimer = 0f; m_chaseTimer = 0f; if ((Object)(object)m_portalEffectInstance != (Object)null) { Object.Destroy((Object)(object)m_portalEffectInstance); m_portalEffectInstance = null; } HoardgoblinPlugin.Log.LogInfo((object)("Hoardgoblin: escape canceled (" + reason + ")")); } } private void CompleteEscape() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) m_isChannelingEscape = false; if ((Object)(object)m_portalEffectInstance != (Object)null) { Object.Destroy((Object)(object)m_portalEffectInstance, 2.5f); } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject val = ZNetScene.instance.GetPrefab("vfx_creature_soared") ?? ZNetScene.instance.GetPrefab("vfx_troll_death"); if ((Object)(object)val != (Object)null) { Object.Instantiate<GameObject>(val, ((Component)this).transform.position, Quaternion.identity); } } HoardgoblinPlugin.Log.LogInfo((object)"Hoardgoblin escaped through the rift!"); if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { ZNetScene.instance.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void HandleDeath() { //IL_0020: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!m_isDead) { m_isDead = true; m_deathTimer = 0f; Biome biome = Heightmap.FindBiome(((Component)this).transform.position); HoardgoblinLoot.DropJackpot(((Component)this).transform.position, biome); m_anim.Play("defeat_03", loop: false, 1f, restart: true); if ((Object)(object)m_portalEffectInstance != (Object)null) { Object.Destroy((Object)(object)m_portalEffectInstance); } } m_deathTimer += Time.deltaTime; if (m_deathTimer >= 3f) { if ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) { ZNetScene.instance.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } } private void PlayPanicSqueal() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_character != (Object)null && m_character.m_hitEffects.m_effectPrefabs != null) { m_character.m_hitEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } } private void OnDestroy() { if ((Object)(object)m_portalEffectInstance != (Object)null) { Object.Destroy((Object)(object)m_portalEffectInstance); } } } public static class HoardgoblinGlb { private sealed class Node { public string Name; public int[] Children; public Vector3 Translation = Vector3.zero; public Quaternion Rotation = Quaternion.identity; public Vector3 Scale = Vector3.one; public int Mesh = -1; } private sealed class Doc { private struct Accessor { public int Count; public int Components; public int ComponentSize; public int Offset; public int Stride; } public readonly JObject Root; public readonly List<Node> Nodes = new List<Node>(); public readonly int SceneRoot; public readonly int[] SkinJoints; public readonly int BaseColorImage; private readonly Bin m_bin; private readonly JArray m_accessors; private readonly JArray m_views; private readonly JArray m_images; public Doc(JObject root, Bin bin) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown Root = root; m_bin = bin; m_accessors = (JArray)root["accessors"]; m_views = (JArray)root["bufferViews"]; m_images = (JArray)root["images"]; JArray val = (JArray)root["nodes"]; for (int i = 0; i < ((JContainer)val).Count; i++) { Nodes.Add(ReadNode((JObject)val[i])); } SceneRoot = (int)root["scenes"][(object)0][(object)"nodes"][(object)0]; JArray val2 = (JArray)root["skins"]; if (val2 != null && ((JContainer)val2).Count > 0) { JArray val3 = (JArray)val2[0][(object)"joints"]; SkinJoints = new int[((JContainer)val3).Count]; for (int j = 0; j < ((JContainer)val3).Count; j++) { SkinJoints[j] = (int)val3[j]; } } JToken val4 = ((JToken)root).SelectToken("materials[0].pbrMetallicRoughness.baseColorTexture.index"); JArray val5 = (JArray)root["textures"]; if (val4 != null && val5 != null && (int)val4 < ((JContainer)val5).Count && val5[(int)val4][(object)"source"] != null) { BaseColorImage = (int)val5[(int)val4][(object)"source"]; } } public Mesh ReadMesh(int boneCount) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00df: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown JObject val = (JObject)Root["meshes"][(object)0][(object)"primitives"][(object)0]; JObject val2 = (JObject)val["attributes"]; Vector3[] array = ReadVec3((int)val2["POSITION"]); Vector3[] normals = ReadVec3((int)val2["NORMAL"]); Vector2[] uv = ReadVec2((int)val2["TEXCOORD_0"]); int[] array2 = ReadIndices((int)val["indices"]); BoneWeight[] boneWeights = ReadWeights((int)val2["JOINTS_0"], (int)val2["WEIGHTS_0"], boneCount); Matrix4x4[] array3 = (Matrix4x4[])(object)new Matrix4x4[boneCount]; for (int i = 0; i < array3.Length; i++) { array3[i] = Matrix4x4.identity; } Color32[] array4 = (Color32[])(object)new Color32[array.Length]; for (int j = 0; j < array4.Length; j++) { array4[j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); } Mesh val3 = new Mesh { name = "Hoardgoblin_Mesh" }; if (array.Length > 65535) { val3.indexFormat = (IndexFormat)1; } val3.vertices = array; val3.normals = normals; val3.uv = uv; val3.colors32 = array4; val3.boneWeights = boneWeights; val3.bindposes = array3; int[] array5 = new int[array2.Length * 2]; Array.Copy(array2, array5, array2.Length); for (int k = 0; k < array2.Length; k += 3) { array5[array2.Length + k] = array2[k]; array5[array2.Length + k + 1] = array2[k + 2]; array5[array2.Length + k + 2] = array2[k + 1]; } val3.triangles = array5; val3.RecalculateTangents(); val3.RecalculateBounds(); return val3; } public float[] ReadFloats(int accessor) { Accessor accessor2 = GetAccessor(accessor); int num = accessor2.Count * accessor2.Components; float[] array = new float[num]; for (int i = 0; i < num; i++) { int num2 = i / accessor2.Components; int num3 = i % accessor2.Components; array[i] = m_bin.Float(accessor2.Offset + num2 * accessor2.Stride + num3 * 4); } return array; } public Texture2D ReadImage(int imageIndex, bool linear) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown if (m_images == null || imageIndex < 0 || imageIndex >= ((JContainer)m_images).Count) { return null; } JObject val = (JObject)m_images[imageIndex]; if (val["bufferView"] == null) { return null; } JObject val2 = (JObject)m_views[(int)val["bufferView"]]; int offset = ((val2["byteOffset"] != null) ? ((int)val2["byteOffset"]) : 0); byte[] array = m_bin.Slice(offset, (int)val2["byteLength"]); Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, true, linear); if (!ImageConversion.LoadImage(val3, array)) { HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: failed to decode image " + (object)val["name"])); Object.Destroy((Object)(object)val3); return null; } ((Object)val3).name = ((string)val["name"]) ?? "hoardgoblin_tex"; ((Texture)val3).wrapMode = (TextureWrapMode)1; ((Texture)val3).anisoLevel = 4; return val3; } private Vector3[] ReadVec3(int accessor) { //IL_0053: 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) Accessor accessor2 = GetAccessor(accessor); Vector3[] array = (Vector3[])(object)new Vector3[accessor2.Count]; for (int i = 0; i < accessor2.Count; i++) { int num = accessor2.Offset + i * accessor2.Stride; array[i] = new Vector3(m_bin.Float(num), m_bin.Float(num + 4), 0f - m_bin.Float(num + 8)); } return array; } private Vector2[] ReadVec2(int accessor) { //IL_004a: 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) Accessor accessor2 = GetAccessor(accessor); Vector2[] array = (Vector2[])(object)new Vector2[accessor2.Count]; for (int i = 0; i < accessor2.Count; i++) { int num = accessor2.Offset + i * accessor2.Stride; array[i] = new Vector2(m_bin.Float(num), 1f - m_bin.Float(num + 4)); } return array; } private int[] ReadIndices(int accessor) { Accessor accessor2 = GetAccessor(accessor); int[] array = new int[accessor2.Count]; int componentSize = accessor2.ComponentSize; for (int i = 0; i < accessor2.Count; i++) { int offset = accessor2.Offset + i * componentSize; array[i] = componentSize switch { 2 => m_bin.UInt16(offset), 4 => (int)m_bin.UInt32(offset), _ => m_bin.Byte(offset), }; } return array; } private BoneWeight[] ReadWeights(int jointsAccessor, int weightsAccessor, int boneCount) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) Accessor accessor = GetAccessor(jointsAccessor); Accessor accessor2 = GetAccessor(weightsAccessor); BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[accessor.Count]; for (int i = 0; i < accessor.Count; i++) { int elementOffset = accessor.Offset + i * accessor.Stride; int num = accessor2.Offset + i * accessor2.Stride; float num2 = m_bin.Float(num); float num3 = m_bin.Float(num + 4); float num4 = m_bin.Float(num + 8); float num5 = m_bin.Float(num + 12); float num6 = num2 + num3 + num4 + num5; if (num6 > 0.0001f) { num2 /= num6; num3 /= num6; num4 /= num6; num5 /= num6; } else { num2 = 1f; } int num7 = i; BoneWeight val = default(BoneWeight); ((BoneWeight)(ref val)).boneIndex0 = Joint(accessor, elementOffset, 0, boneCount); ((BoneWeight)(ref val)).weight0 = num2; ((BoneWeight)(ref val)).boneIndex1 = Joint(accessor, elementOffset, 1, boneCount); ((BoneWeight)(ref val)).weight1 = num3; ((BoneWeight)(ref val)).boneIndex2 = Joint(accessor, elementOffset, 2, boneCount); ((BoneWeight)(ref val)).weight2 = num4; ((BoneWeight)(ref val)).boneIndex3 = Joint(accessor, elementOffset, 3, boneCount); ((BoneWeight)(ref val)).weight3 = num5; array[num7] = val; } return array; } private int Joint(Accessor acc, int elementOffset, int component, int boneCount) { int offset = elementOffset + component * acc.ComponentSize; int num = ((acc.ComponentSize == 1) ? m_bin.Byte(offset) : ((acc.ComponentSize == 2) ? m_bin.UInt16(offset) : ((int)m_bin.UInt32(offset)))); if (num >= 0 && num < boneCount) { return num; } return 0; } private Accessor GetAccessor(int index) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown JObject val = (JObject)m_accessors[index]; JObject val2 = (JObject)m_views[(int)val["bufferView"]]; int num = (int)val["componentType"]; int num2 = (string)val["type"] switch { "VEC2" => 2, "VEC3" => 3, "VEC4" => 4, "MAT4" => 16, _ => 1, }; int num3; switch (num) { default: num3 = 1; break; case 5122: case 5123: num3 = 2; break; case 5125: case 5126: num3 = 4; break; } int num4 = num3; int num5 = ((val2["byteOffset"] != null) ? ((int)val2["byteOffset"]) : 0); int num6 = ((val["byteOffset"] != null) ? ((int)val["byteOffset"]) : 0); int stride = ((val2["byteStride"] != null) ? ((int)val2["byteStride"]) : (num4 * num2)); return new Accessor { Count = (int)val["count"], Components = num2, ComponentSize = num4, Offset = num5 + num6, Stride = stride }; } private static Node ReadNode(JObject n) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown Node node = new Node { Name = (string)n["name"] }; if (n["mesh"] != null) { node.Mesh = (int)n["mesh"]; } if (n["translation"] != null) { JArray val = (JArray)n["translation"]; node.Translation = new Vector3((float)val[0], (float)val[1], 0f - (float)val[2]); } if (n["rotation"] != null) { JArray val2 = (JArray)n["rotation"]; node.Rotation = new Quaternion((float)val2[0], (float)val2[1], 0f - (float)val2[2], 0f - (float)val2[3]); } if (n["scale"] != null) { JArray val3 = (JArray)n["scale"]; node.Scale = new Vector3((float)val3[0], (float)val3[1], (float)val3[2]); } if (n["children"] != null) { JArray val4 = (JArray)n["children"]; node.Children = new int[((JContainer)val4).Count]; for (int i = 0; i < ((JContainer)val4).Count; i++) { node.Children[i] = (int)val4[i]; } } return node; } } private sealed class Bin { private readonly byte[] m_file; private readonly int m_start; public Bin(byte[] file, int start, int length) { m_file = file; m_start = start; } public float Float(int offset) { return BitConverter.ToSingle(m_file, m_start + offset); } public int Byte(int offset) { return m_file[m_start + offset]; } public int UInt16(int offset) { return BitConverter.ToUInt16(m_file, m_start + offset); } public uint UInt32(int offset) { return BitConverter.ToUInt32(m_file, m_start + offset); } public byte[] Slice(int offset, int length) { byte[] array = new byte[length]; Buffer.BlockCopy(m_file, m_start + offset, array, 0, length); return array; } } private const uint GlbMagic = 1179937895u; private const int FloatType = 5126; private static readonly string[] RootMotionBones = new string[4] { "mixamorig:Hips", "Hips", "pelvis", "root" }; public static readonly Dictionary<string, Pose> Poses = new Dictionary<string, Pose>(StringComparer.OrdinalIgnoreCase); public static GameObject Template { get; private set; } public static float RawHeight { get; private set; } public static bool Load(string path, Material sourceMaterial, Transform holder) { if ((Object)(object)Template != (Object)null) { return true; } try { Template = Build(path, sourceMaterial); Template.SetActive(false); ((Object)Template).hideFlags = (HideFlags)61; if ((Object)(object)holder != (Object)null) { Template.transform.SetParent(holder, false); } return true; } catch (Exception ex) { HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: failed to build the model from " + Path.GetFileName(path) + ": " + ex)); Template = null; return false; } } public static Pose Get(string name) { if (name == null || !Poses.TryGetValue(name, out var value)) { return null; } return value; } private static GameObject Build(string path, Material sourceMaterial) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00b5: 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_00e5: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown byte[] array = File.ReadAllBytes(path); if (array.Length < 20 || BitConverter.ToUInt32(array, 0) != 1179937895) { throw new InvalidDataException("Not a GLB file: " + path); } int num = BitConverter.ToInt32(array, 12); string text = Encoding.UTF8.GetString(array, 20, num); int num2 = 20 + num; int length = BitConverter.ToInt32(array, num2); int start = num2 + 8; JObject obj = JObject.Parse(text); Doc doc = new Doc(obj, new Bin(array, start, length)); GameObject val = new GameObject("Hoardgoblin_Model"); Dictionary<int, Transform> transforms; Dictionary<int, string> paths; GameObject obj2 = BuildHierarchy(doc, out transforms, out paths); ((Object)obj2).name = "Armature"; obj2.transform.SetParent(val.transform, false); obj2.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); AttachMesh(material: CreateMaterial(doc, sourceMaterial), doc: doc, transforms: transforms); JArray val2 = (JArray)obj["animations"]; Poses.Clear(); if (val2 != null) { for (int i = 0; i < ((JContainer)val2).Count; i++) { Pose pose = BuildPose(doc, paths, (JObject)val2[i]); if (pose != null) { Poses[pose.Name] = pose; } } } SkinnedMeshRenderer componentInChildren = val.GetComponentInChildren<SkinnedMeshRenderer>(); float rawHeight; if (!((Object)(object)componentInChildren != (Object)null) || !((Object)(object)componentInChildren.sharedMesh != (Object)null)) { rawHeight = 1f; } else { Bounds bounds = componentInChildren.sharedMesh.bounds; rawHeight = ((Bounds)(ref bounds)).size.y; } RawHeight = rawHeight; HoardgoblinPlugin.Log.LogInfo((object)string.Format("Hoardgoblin: built model from {0} ({1:0.00} m in the file), {2} clips: {3}.", Path.GetFileName(path), RawHeight, Poses.Count, string.Join(", ", Poses.Keys))); return val; } private static GameObject BuildHierarchy(Doc doc, out Dictionary<int, Transform> transforms, out Dictionary<int, string> paths) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) int count = doc.Nodes.Count; GameObject[] array = (GameObject[])(object)new GameObject[count]; transforms = new Dictionary<int, Transform>(count); for (int i = 0; i < count; i++) { Node node = doc.Nodes[i]; GameObject val = new GameObject(string.IsNullOrEmpty(node.Name) ? ("node" + i) : node.Name); val.transform.localPosition = node.Translation; val.transform.localRotation = node.Rotation; val.transform.localScale = node.Scale; array[i] = val; transforms[i] = val.transform; } for (int j = 0; j < count; j++) { int[] children = doc.Nodes[j].Children; if (children != null) { for (int k = 0; k < children.Length; k++) { array[children[k]].transform.SetParent(array[j].transform, false); } } } paths = new Dictionary<int, string>(); WritePaths(doc, doc.SceneRoot, "", paths); return array[doc.SceneRoot]; } private static void WritePaths(Doc doc, int index, string path, Dictionary<int, string> paths) { paths[index] = path; int[] children = doc.Nodes[index].Children; if (children == null) { return; } for (int i = 0; i < children.Length; i++) { int index2 = children[i]; string text = doc.Nodes[index2].Name; if (string.IsNullOrEmpty(text)) { text = "node" + index2; } WritePaths(doc, index2, string.IsNullOrEmpty(path) ? text : (path + "/" + text), paths); } } private static void AttachMesh(Doc doc, Dictionary<int, Transform> transforms, Material material) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_0137: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) int num = -1; for (int i = 0; i < doc.Nodes.Count; i++) { if (doc.Nodes[i].Mesh >= 0) { num = i; break; } } if (num < 0 || doc.SkinJoints == null) { throw new InvalidDataException("GLB has no skinned mesh."); } int[] skinJoints = doc.SkinJoints; Transform[] array = (Transform[])(object)new Transform[skinJoints.Length]; for (int j = 0; j < skinJoints.Length; j++) { array[j] = transforms[skinJoints[j]]; } Mesh val = doc.ReadMesh(array.Length); SkinnedMeshRenderer val2 = ((Component)transforms[num]).gameObject.AddComponent<SkinnedMeshRenderer>(); val2.sharedMesh = val; val2.bones = array; val2.rootBone = ((array.Length != 0) ? array[0] : null); ((Renderer)val2).sharedMaterial = material; val2.updateWhenOffscreen = false; val2.quality = (SkinQuality)4; Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[array.Length]; Matrix4x4 localToWorldMatrix = ((Component)val2).transform.localToWorldMatrix; for (int k = 0; k < array.Length; k++) { array2[k] = (((Object)(object)array[k] == (Object)null) ? Matrix4x4.identity : (array[k].worldToLocalMatrix * localToWorldMatrix)); } val.bindposes = array2; Bounds bounds = val.bounds; ((Bounds)(ref bounds)).Expand(new Vector3(1.5f, 0.6f, 1.5f)); ((Renderer)val2).localBounds = bounds; } private static Material CreateMaterial(Doc doc, Material sourceMaterial) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = doc.ReadImage(doc.BaseColorImage, linear: false); Material val2 = (((Object)(object)sourceMaterial != (Object)null) ? new Material(sourceMaterial) : new Material(Shader.Find("Custom/Creature") ?? Shader.Find("Standard"))); ((Object)val2).name = "Hoardgoblin_Mat"; if ((Object)(object)val != (Object)null) { val2.mainTexture = (Texture)(object)val; SetTex(val2, "_MainTex", (Texture)(object)val); SetTex(val2, "_BaseMap", (Texture)(object)val); SetTex(val2, "_Albedo", (Texture)(object)val); val2.SetTextureScale("_MainTex", Vector2.one); val2.SetTextureOffset("_MainTex", Vector2.zero); } SetTex(val2, "_BumpMap", null); SetTex(val2, "_EmissionMap", null); if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", Color.black); } val2.DisableKeyword("_EMISSION"); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.white); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", Color.white); } if (val2.HasProperty("_Mode")) { val2.SetFloat("_Mode", 0f); } if (val2.HasProperty("_Cutoff")) { val2.SetFloat("_Cutoff", 0f); } val2.DisableKeyword("_ALPHATEST_ON"); val2.DisableKeyword("_ALPHABLEND_ON"); val2.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val2.renderQueue = 2000; HoardgoblinPlugin.Log.LogInfo((object)string.Format("Hoardgoblin: material cloned from '{0}', shader '{1}', albedo {2}.", ((Object)(object)sourceMaterial != (Object)null) ? ((Object)sourceMaterial).name : "none", ((Object)(object)val2.shader != (Object)null) ? ((Object)val2.shader).name : "none", ((Object)(object)val != (Object)null) ? (((Texture)val).width + "x" + ((Texture)val).height) : "missing")); return val2; } private static void SetTex(Material mat, string prop, Texture tex) { if (mat.HasProperty(prop)) { mat.SetTexture(prop, tex); } } private static Pose BuildPose(Doc doc, Dictionary<int, string> paths, JObject anim) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026c: 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) string text = (string)anim["name"]; if (string.IsNullOrEmpty(text)) { return null; } Dictionary<string, Pose.Track> dictionary = new Dictionary<string, Pose.Track>(); float num = 0f; float travel = 0f; JArray val = (JArray)anim["channels"]; JArray val2 = (JArray)anim["samplers"]; for (int i = 0; i < ((JContainer)val).Count; i++) { JObject val3 = (JObject)val[i]; JObject val4 = (JObject)val2[(int)val3["sampler"]]; int key = (int)val3["target"][(object)"node"]; string text2 = (string)val3["target"][(object)"path"]; if (!paths.TryGetValue(key, out var value) || string.IsNullOrEmpty(value)) { continue; } bool flag = string.Equals((string)val4["interpolation"], "STEP", StringComparison.OrdinalIgnoreCase); float[] array = doc.ReadFloats((int)val4["input"]); float[] array2 = doc.ReadFloats((int)val4["output"]); if (array.Length != 0 && array[^1] > num) { num = array[^1]; } if (!dictionary.TryGetValue(value, out var value2)) { Pose.Track obj = new Pose.Track { Path = value }; value2 = (dictionary[value] = obj); } switch (text2) { case "rotation": { Quaternion[] array5 = (Quaternion[])(object)new Quaternion[array.Length]; for (int m = 0; m < array.Length; m++) { array5[m] = new Quaternion(array2[m * 4], array2[m * 4 + 1], 0f - array2[m * 4 + 2], 0f - array2[m * 4 + 3]); } value2.RotTimes = array; value2.Rotations = array5; value2.RotationStep = flag; break; } case "translation": { bool flag2 = IsRootMotionBone(value); Vector3[] array4 = (Vector3[])(object)new Vector3[array.Length]; for (int k = 0; k < array.Length; k++) { array4[k] = new Vector3(array2[k * 3], array2[k * 3 + 1], 0f - array2[k * 3 + 2]); } if (flag2 && array.Length > 1) { Vector3 val5 = array4[array.Length - 1] - array4[0]; val5.y = 0f; float num2 = array[^1] - array[0]; travel = ((num2 > 0.0001f) ? (((Vector3)(ref val5)).magnitude / num2) : 0f); for (int l = 1; l < array.Length; l++) { array4[l].x = array4[0].x; array4[l].z = array4[0].z; } } value2.PosTimes = array; value2.Positions = array4; value2.PositionStep = flag; break; } case "scale": { Vector3[] array3 = (Vector3[])(object)new Vector3[array.Length]; for (int j = 0; j < array.Length; j++) { array3[j] = new Vector3(array2[j * 3], array2[j * 3 + 1], array2[j * 3 + 2]); } value2.ScaleTimes = array; value2.Scales = array3; value2.ScaleStep = flag; break; } } } Pose pose = new Pose { Name = text, Length = num, Travel = travel, Tracks = new Pose.Track[dictionary.Count] }; dictionary.Values.CopyTo(pose.Tracks, 0); return pose; } private static bool IsRootMotionBone(string path) { int num = path.LastIndexOf('/'); string value = ((num >= 0) ? path.Substring(num + 1) : path); return Array.IndexOf(RootMotionBones, value) >= 0; } } public sealed class Pose { public sealed class Track { public string Path; public float[] PosTimes; public Vector3[] Positions; public bool PositionStep; public float[] RotTimes; public Quaternion[] Rotations; public bool RotationStep; public float[] ScaleTimes; public Vector3[] Scales; public bool ScaleStep; public bool SamplePosition(float time, out Vector3 value) { return Sample(PosTimes, Positions, PositionStep, time, out value); } public bool SampleScale(float time, out Vector3 value) { return Sample(ScaleTimes, Scales, ScaleStep, time, out value); } public bool SampleRotation(float time, out Quaternion value) { //IL_0001: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) value = Quaternion.identity; if (RotTimes == null || Rotations == null || RotTimes.Length == 0) { return false; } int num = Index(RotTimes, time); if (RotationStep || num + 1 >= RotTimes.Length) { value = Rotations[num]; return true; } value = Quaternion.Slerp(Rotations[num], Rotations[num + 1], Blend(RotTimes, num, time)); return true; } private static bool Sample(float[] times, Vector3[] values, bool step, float time, out Vector3 value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) value = default(Vector3); if (times == null || values == null || times.Length == 0) { return false; } int num = Index(times, time); if (step || num + 1 >= times.Length) { value = values[num]; return true; } value = Vector3.Lerp(values[num], values[num + 1], Blend(times, num, time)); return true; } private static int Index(float[] times, float time) { int num = 0; int num2 = times.Length - 1; if (time <= times[0]) { return 0; } if (time >= times[num2]) { return num2; } while (num2 - num > 1) { int num3 = num + num2 >> 1; if (times[num3] <= time) { num = num3; } else { num2 = num3; } } return num; } private static float Blend(float[] times, int i, float time) { float num = times[i + 1] - times[i]; if (!(num <= 1E-05f)) { return Mathf.Clamp01((time - times[i]) / num); } return 0f; } } public string Name; public float Length; public float Travel; public Track[] Tracks; } public static class HoardgoblinLoot { private static readonly string[] TrailGems = new string[3] { "Amber", "Ruby", "AmberPearl" }; private static readonly string[] Valuables = new string[4] { "Amber", "AmberPearl", "Ruby", "SilverNecklace" }; public static void DropTrailPouch(Vector3 position) { //IL_0021: 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) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) try { int amount = Random.Range(HoardgoblinSettings.CoinTrailMin.Value, HoardgoblinSettings.CoinTrailMax.Value + 1); DropItemPrefab("Coins", position + Vector3.up * 0.4f, amount, 1.8f); if (Random.value < HoardgoblinSettings.TrailGemChance.Value) { DropItemPrefab(TrailGems[Random.Range(0, TrailGems.Length)], position + Vector3.up * 0.5f, 1, 2.2f); } SpawnCoinSparkle(position + Vector3.up * 0.3f); } catch (Exception ex) { HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: trail drop failed: " + ex.Message)); } } public static void DropJackpot(Vector3 position, Biome biome) { //IL_0032: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) try { int num = Random.Range(HoardgoblinSettings.JackpotCoinMin.Value, HoardgoblinSettings.JackpotCoinMax.Value + 1); while (num > 0) { int num2 = Mathf.Min(num, Random.Range(20, 60)); num -= num2; Vector3 val = Random.insideUnitSphere * 1.5f; val.y = Mathf.Abs(val.y) + 0.3f; DropItemPrefab("Coins", position + val, num2, 3.5f); } int num3 = Random.Range(HoardgoblinSettings.JackpotGemsMin.Value, HoardgoblinSettings.JackpotGemsMax.Value + 1); for (int i = 0; i < num3; i++) { string prefabName = Valuables[Random.Range(0, Valuables.Length)]; int amount = Random.Range(1, 3); Vector3 val2 = Random.insideUnitSphere * 1.8f; val2.y = Mathf.Abs(val2.y) + 0.4f; DropItemPrefab(prefabName, position + val2, amount, 3.8f); } if (HoardgoblinSettings.JackpotBonusMaterials.Value) { DropBiomeMaterials(position, biome); } SpawnJackpotBurst(position); } catch (Exception ex) { HoardgoblinPlugin.Log.LogWarning((object)("Hoardgoblin: jackpot drop failed: " + ex.Message)); } } private static void DropBiomeMaterials(Vector3 position, Biome biome) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_000a: 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_0022: Expected I4, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) List<Tuple<string, int>> list = new List<Tuple<string, int>>(); if ((int)biome <= 8) { switch (biome - 1) { case 0: goto IL_004b; case 1: goto IL_00e1; case 3: goto IL_012d; case 2: goto IL_0288; } if ((int)biome != 8) { goto IL_0288; } list.Add(Tuple.Create("CopperOre", Random.Range(3, 8))); list.Add(Tuple.Create("TinOre", Random.Range(2, 6))); list.Add(Tuple.Create("Bronze", Random.Range(1, 4))); list.Add(Tuple.Create("SurtlingCore", Random.Range(1, 3))); } else if ((int)biome != 16) { if ((int)biome != 32) { if ((int)biome != 512) { goto IL_0288; } list.Add(Tuple.Create("Softtissue", Random.Range(4, 10))); list.Add(Tuple.Create("Eitr", Random.Range(2, 5))); list.Add(Tuple.Create("BlackMarble", Random.Range(8, 18))); list.Add(Tuple.Create("Carapace", Random.Range(4, 10))); } else { list.Add(Tuple.Create("FlametalOreNew", Random.Range(4, 10))); list.Add(Tuple.Create("CharredBone", Random.Range(4, 10))); list.Add(Tuple.Create("MorgenSinew", Random.Range(1, 3))); } } else { list.Add(Tuple.Create("BlackMetalScrap", Random.Range(5, 12))); list.Add(Tuple.Create("Barley", Random.Range(8, 20))); list.Add(Tuple.Create("Flax", Random.Range(8, 20))); list.Add(Tuple.Create("Needle", Random.Range(4, 10))); } goto IL_02a4; IL_02a4: foreach (Tuple<string, int> item in list) { Vector3 val = Random.insideUnitSphere * 2f; val.y = Mathf.Abs(val.y) + 0.5f; DropItemPrefab(item.Item1, position + val, item.Item2, 4f); } return; IL_004b: list.Add(Tuple.Create("FineWood", Random.Range(5, 12))); list.Add(Tuple.Create("Feathers", Random.Range(4, 10))); goto IL_02a4; IL_012d: list.Add(Tuple.Create("SilverOre", Random.Range(4, 10))); list.Add(Tuple.Create("Obsidian", Random.Range(6, 15))); list.Add(Tuple.Create("FreezeGland", Random.Range(2, 6))); goto IL_02a4; IL_0288: list.Add(Tuple.Create("Coins", Random.Range(50, 150))); goto IL_02a4; IL_00e1: list.Add(Tuple.Create("IronScrap", Random.Range(4, 10))); list.Add(Tuple.Create("Chain", Random.Range(1, 3))); list.Add(Tuple.Create("AncientBark", Random.Range(6, 14))); goto IL_02a4; } private static void DropItemPrefab(string prefabName, Vector3 spawnPos, int amount, float burstSpeed) { //IL_0056: 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_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) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(prefabName) || amount <= 0) { return; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { val = ZNetScene.instance.GetPrefab(prefabName); } if (!((Object)(object)val == (Object)null)) { GameObject obj = Object.Instantiate<GameObject>(val, spawnPos, Quaternion.identity); ItemDrop component = obj.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { component.m_itemData.m_stack = amount; } Rigidbody component2 = obj.GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { Vector3 val2 = Random.onUnitSphere + Vector3.up * 1.5f; Vector3 velocity = ((Vector3)(ref val2)).normalized * Random.Range(burstSpeed * 0.6f, burstSpeed); component2.velocity = velocity; } } } private static void SpawnCoinSparkle(Vector3 position) { //IL_0028: 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) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("vfx_Place_wood_wall"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); } } } private static void SpawnJackpotBurst(Vector3 position) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("vfx_lootchest_open"); if ((Object)(object)prefab == (Object)null) { prefab = ZNetScene.instance.GetPrefab("vfx_troll_death"); } if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); } } } } [BepInPlugin("com.dfg.hoardgoblin", "Hoardgoblin", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class HoardgoblinPlugin : BaseUnityPlugin { public const string PluginGUID = "com.dfg.hoardgoblin"; public const string PluginName = "Hoardgoblin"; public const string PluginVersion = "0.1.0"; internal static ManualLogSource Log; private Harmony m_harmony; internal static HoardgoblinPlugin Instance { get; private set; } private void Awake() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; HoardgoblinSettings.Bind(((BaseUnityPlugin)this).Config); if (!HoardgoblinSettings.Enabled.Value) { Log.LogInfo((object)"Hoardgoblin is disabled in config."); return; } HoardgoblinPrefabs.Init(); try { m_harmony = new Harmony("com.dfg.hoardgoblin"); m_harmony.PatchAll(); } catch (Exception ex) { Log.LogError((object)("Hoardgoblin: failed to apply Harmony patches: " + ex)); } CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SpawnHoardgoblinCommand()); Log.LogInfo((object)"Hoardgoblin v0.1.0 initialized."); } private void OnDestroy() { Harmony harmony = m_harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public class SpawnHoardgoblinCommand : ConsoleCommand { public override string Name => "spawn_hoardgoblin"; public override string Help => "Spawns a Hoardgoblin near the player for testing."; public unsafe override void Run(string[] args) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { Console.instance.Print("Must be in game to spawn a Hoardgoblin."); return; } GameObject prefab = PrefabManager.Instance.GetPrefab("DFG_Hoardgoblin"); if ((Object)(object)prefab == (Object)null) { Console.instance.Print("Hoardgoblin prefab 'DFG_Hoardgoblin' not found."); return; } Vector3 val = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 4f + Vector3.up * 0.5f; Object.Instantiate<GameObject>(prefab, val, Quaternion.identity); Console instance = Console.instance; Vector3 val2 = val; instance.Print("Spawned Hoardgoblin at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString()); } } public static class HoardgoblinPrefabs { public const string PrefabName = "DFG_Hoardgoblin"; public const string SourcePrefab = "Goblin"; public const string ModelFile = "Hoardgoblin.glb"; public static GameObject HoardgoblinPrefab { get; private set; } public static void Init() { PrefabManager.OnVanillaPrefabsAvailable += Register; LocalizationManager.Instance.AddToken("hoardgoblin_name", "Hoardgoblin", false); LocalizationManager.Instance.AddToken("hoardgoblin_desc", "A cowardly hoarder weighed down by a massive sack of stolen treasures. Catch it if you can!", false); } private static void Register() { PrefabManager.OnVanillaPrefabsAvailable -= Register; try { BuildCreature(); } catch (Exception ex) { HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: registration failed: " + ex)); } } private static void BuildCreature() { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("Goblin"); if ((Object)(object)prefab == (Object)null) { prefab = PrefabManager.Instance.GetPrefab("Greydwarf"); } if ((Object)(object)prefab == (Object)null) { HoardgoblinPlugin.Log.LogError((object)"Hoardgoblin: base creature prefab not found!"); return; } Material sourceMaterial = null; SkinnedMeshRenderer componentInChildren = prefab.GetComponentInChildren<SkinnedMeshRenderer>(true); if ((Object)(object)componentInChildren != (Object)null) { sourceMaterial = ((Renderer)componentInChildren).sharedMaterial; } string text = Path.Combine(Path.GetDirectoryName(typeof(HoardgoblinPrefabs).Assembly.Location) ?? "", "Hoardgoblin.glb"); if (!File.Exists(text)) { HoardgoblinPlugin.Log.LogError((object)("Hoardgoblin: Hoardgoblin.glb is missing beside DLL at " + text)); } else { if (!HoardgoblinGlb.Load(text, sourceMaterial, ((Component)HoardgoblinPlugin.Instance).transform)) { return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab("DFG_Hoardgoblin", prefab); ((Object)val).name = "DFG_Hoardgoblin"; Character component = val.GetComponent<Character>(); if ((Object)(object)component != (Object)null) { component.m_name = "$hoardgoblin_name"; component.m_health = HoardgoblinSettings.BaseHealth.Value; component.m_speed = HoardgoblinSettings.RunSpeed.Value; component.m_walkSpeed = HoardgoblinSettings.WalkSpeed.Value; component.m_runSpeed = HoardgoblinSettings.RunSpeed.Value; component.m_acceleration = 25f; component.m_turnSpeed = 600f; component.m_runTurnSpeed = 600f; component.m_jumpForce = HoardgoblinSettings.JumpForce.Value; component.m_deathEffects = new EffectList(); } Humanoid component2 = val.GetComponent<Humanoid>(); if ((Object)(object)component2 != (Object)null) { component2.m_defaultItems = (GameObject[])(object)new GameObject[0]; component2.m_randomWeapon = (GameObject[])(object)new GameObject[0]; component2.m_randomArmor = (GameObject[])(object)new GameObject[0]; component2.m_randomShield = (GameObject[])(object)new GameObject[0]; component2.m_randomSets = (ItemSet[])(object)new ItemSet[0]; component2.m_unarmedWeapon = null; } MonsterAI component3 = val.GetComponent<MonsterAI>(); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } AnimalAI obj = val.GetComponent<AnimalAI>() ?? val.AddComponent<AnimalAI>(); ((BaseAI)obj).m_viewRange = HoardgoblinSettings.AlertRange.Value * 1.5f; ((BaseAI)obj).m_hearRange = HoardgoblinSettings.AlertRange.Value; ((BaseAI)obj).m_viewAngle = 360f; ((BaseAI)obj).m_fleeRange = HoardgoblinSettings.FleeDistance.Value; ((BaseAI)obj).m_fleeAngle = 180f; ((BaseAI)obj).m_fleeInterval = 0.4f; obj.m_timeToSafe = 10f; ((BaseAI)obj).m_jumpInterval = 0f; ((BaseAI)obj).m_avoidFire = true; ((BaseAI)obj).m_avoidWater = true; ((BaseAI)obj).m_avoidLava = true; ((BaseAI)obj).m_canBeAlerted = true; ((BaseAI)obj).m_smoothMovement = true; CharacterDrop[] componentsInChildren = val.GetComponentsInChildren<CharacterDrop>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } val.AddComponent<HoardgoblinController>(); CreatureConfig val2 = new CreatureConfig { Name = "$hoardgoblin_name" }; List<SpawnConfig> list = ParseBiomeSpawns(); if (list.Count > 0) { foreach (SpawnConfig item in list) { val2.AddSpawnConfig(item); } } CustomCreature val3 = new CustomCreature(val, false, val2); CreatureManager.Instance.AddCreature(val3); HoardgoblinPrefab = val; HoardgoblinPlugin.Log.LogInfo((object)("Hoardgoblin: successfully registered 'DFG_Hoardgoblin' with biomes: " + HoardgoblinSettings.EnabledBiomes.Value)); } } private static List<SpawnConfig> ParseBiomeSpawns() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00b8: 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) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown List<SpawnConfig> list = new List<SpawnConfig>(); string[] array = (HoardgoblinSettings.EnabledBiomes.Value ?? "").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (string.Equals(text, "Ashlands", StringComparison.OrdinalIgnoreCase)) { text = "AshLands"; } if (Enum.TryParse<Biome>(text, ignoreCase: true, out Biome result)) { list.Add(new SpawnConfig { Name = "Spawn_DFG_Hoardgoblin_" + text, Biome = result, BiomeArea = (BiomeArea)3, MaxSpawned = HoardgoblinSettings.MaxSpawned.Value, SpawnInterval = HoardgoblinSettings.SpawnInterval.Value, SpawnChance = HoardgoblinSettings.SpawnChance.Value, SpawnDistance = 30f, MinLevel = 1, MaxLevel = 1, SpawnAtDay = true, SpawnAtNight = true }); } } return list; } } public static class HoardgoblinSettings { public static ConfigEntry<bool> Enabled { get; private set; } public static ConfigEntry<float> ModelScale { get; private set; } public static ConfigEntry<float> BaseHealth { get; private set; } public static ConfigEntry<float> RunSpeed { get; private set; } public static ConfigEntry<float> WalkSpeed { get; private set; } public static ConfigEntry<float> AlertRange { get; private set; } public static ConfigEntry<float> FleeDistance { get; private set; } public static ConfigEntry<bool> JumpObstacles { get; private set; } public static ConfigEntry<float> JumpForce { get; private set; } public static ConfigEntry<float> ChaseTimeBeforeEscape { get; private set; } public static ConfigEntry<float> EscapeChannelDuration { get; private set; } public static ConfigEntry<float> CoinTrailInterval { get; private set; } public static ConfigEntry<int> CoinTrailMin { get; private set; } public static ConfigEntry<int> CoinTrailMax { get; private set; } public static ConfigEntry<float> TrailGemChance { get; private set; } public static ConfigEntry<int> JackpotCoinMin { get; private set; } public static ConfigEntry<int> JackpotCoinMax { get; private set; } public static ConfigEntry<int> JackpotGemsMin { get; private set; } public static ConfigEntry<int> JackpotGemsMax { get; private set; } public static ConfigEntry<bool> JackpotBonusMaterials { get; private set; } public static ConfigEntry<float> SpawnChance { get; private set; } public static ConfigEntry<float> SpawnInterval { get; private set; } public static ConfigEntry<int> MaxSpawned { get; private set; } public static ConfigEntry<string> EnabledBiomes { get; private set; } public static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("1 - General", "Enabled", true, "Enable the Hoardgoblin mod."); ModelScale = config.Bind<float>("1 - General", "ModelScale", 1.2f, "Visual scale of the Hoardgoblin model."); BaseHealth = config.Bind<float>("1 - General", "BaseHealth", 200f, "Base health of the Hoardgoblin."); RunSpeed = config.Bind<float>("1 - General", "RunSpeed", 22f, "Sprint speed when fleeing in terror (fast and frantic)."); WalkSpeed = config.Bind<float>("1 - General", "WalkSpeed", 8f, "Wander/walk speed."); AlertRange = config.Bind<float>("1 - General", "AlertRange", 25f, "Distance at which the goblin spots the player and flees."); FleeDistance = config.Bind<float>("1 - General", "FleeDistance", 55f, "Distance the goblin tries to put between itself and players."); JumpObstacles = config.Bind<bool>("1 - General", "JumpObstacles", true, "Enable jumping over rocks, fences, and obstacles when fleeing."); JumpForce = config.Bind<float>("1 - General", "JumpForce", 8.5f, "Upward jump velocity when encountering obstacles or getting stuck."); ChaseTimeBeforeEscape = config.Bind<float>("2 - Escape Portal", "ChaseTimeBeforeEscape", 30f, "Seconds of continuous chase before the goblin attempts to summon an escape portal."); EscapeChannelDuration = config.Bind<float>("2 - Escape Portal", "EscapeChannelDuration", 5f, "Seconds needed to channel the escape portal before disappearing. Stagger or damage interrupts it!"); CoinTrailInterval = config.Bind<float>("3 - Loot Trail", "CoinTrailInterval", 3f, "Seconds between coin/gem breadcrumb drops while sprinting."); CoinTrailMin = config.Bind<int>("3 - Loot Trail", "CoinTrailMin", 4, "Minimum coins dropped per breadcrumb tick."); CoinTrailMax = config.Bind<int>("3 - Loot Trail", "CoinTrailMax", 10, "Maximum coins dropped per breadcrumb tick."); TrailGemChance = config.Bind<float>("3 - Loot Trail", "TrailGemChance", 0.25f, "Chance (0-1) to drop a loose Amber, Ruby, or Amber Pearl while sprinting."); JackpotCoinMin = config.Bind<int>("4 - Jackpot Loot", "JackpotCoinMin", 300, "Minimum coins dropped upon slaying the Hoardgoblin."); JackpotCoinMax = config.Bind<int>("4 - Jackpot Loot", "JackpotCoinMax", 700, "Maximum coins dropped upon slaying the Hoardgoblin."); JackpotGemsMin = config.Bind<int>("4 - Jackpot Loot", "JackpotGemsMin", 6, "Minimum assorted gems/valuables dropped upon death."); JackpotGemsMax = config.Bind<int>("4 - Jackpot Loot", "JackpotGemsMax", 14, "Maximum assorted gems/valuables dropped upon death."); JackpotBonusMaterials = config.Bind<bool>("4 - Jackpot Loot", "JackpotBonusMaterials", true, "Drop biome-scaled rare materials (e.g. Copper/Bronze in Black Forest, Iron in Swamp, Silver in Mountains, Black Metal in Plains, Eitr in Mistlands, Flametal in Ashlands)."); SpawnChance = config.Bind<float>("5 - Spawning", "SpawnChance", 15f, "Spawn check percentage chance (0-100%)."); SpawnInterval = config.Bind<float>("5 - Spawning", "SpawnInterval", 1000f, "Seconds between spawn check attempts."); MaxSpawned = config.Bind<int>("5 - Spawning", "MaxSpawned", 1, "Maximum simultaneous Hoardgoblins per loaded zone."); EnabledBiomes = config.Bind<string>("5 - Spawning", "EnabledBiomes", "Meadows,BlackForest,Swamp,Mountain,Plains,Mistlands,Ashlands", "Comma-separated biomes where Hoardgoblins can spawn."); } } }