using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using SideLoader; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace CraftableRunicBlades; [BepInPlugin("com.merofos.outward.craftablerunicblades", "Craftable Runic Blades", "0.1.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class CraftableRunicBladesPlugin : BaseUnityPlugin { private sealed class RunicWeaponDefinition { public readonly int ItemId; public readonly string Marker; public readonly string DisplayName; public readonly string IconRelativePath; public readonly string IconId; public readonly string[] VisualNameTokens; public RunicWeaponDefinition(int itemId, string marker, string displayName, string iconRelativePath, string iconId, params string[] visualNameTokens) { ItemId = itemId; Marker = marker; DisplayName = displayName; IconRelativePath = iconRelativePath; IconId = iconId; VisualNameTokens = visualNameTokens; } } private const string PluginGuid = "com.merofos.outward.craftablerunicblades"; private const string SideLoaderGuid = "com.sinai.SideLoader"; private const string PluginName = "Craftable Runic Blades"; private const string PluginVersion = "0.1.4"; private const int VanillaRunicBladeItemId = 2000100; private const string CapturedRunicBladeMaterialName = "mat_itm_crystalBladeRunicBladeLight"; private const string CapturedRunicBladeMainTextureName = "tex_fx_PerlinNoiseGray"; private const string CapturedRunicBladeWaveTextureName = "tex_env_waterWave_n"; private static readonly float[] VisualRetryDelays = new float[8] { 0f, 0.1f, 0.25f, 0.5f, 1f, 2f, 4f, 8f }; private static readonly HashSet s_missingTextureWarnings = new HashSet(); private static readonly FieldInfo ItemIconField = typeof(Item).GetField("m_itemIcon", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo ItemIconPathField = typeof(Item).GetField("m_itemIconPath", BindingFlags.Instance | BindingFlags.NonPublic); private static Texture s_capturedMainTexture; private static Texture s_capturedWaveTexture; private static readonly RunicWeaponDefinition[] WeaponDefinitions = new RunicWeaponDefinition[2] { new RunicWeaponDefinition(-2525300, "RunicBlade", "Runic Blade", "SideLoader/Items/-2525300-Runic_Blade/runic_blade_item_icon.png", "MEROFOS_CraftableRunicBladeIcon", "2000090", "oldlegiongladius", "old legion gladius", "runicblade", "runic blade", "-2525300", "2525300"), new RunicWeaponDefinition(-2525310, "GreatRunicBlade", "Great Runic Blade", "SideLoader/Items/-2525310-Great_Runic_Blade/great_runic_blade_item_icon.png", "MEROFOS_CraftableGreatRunicBladeIcon", "2100130", "pathfinderclaymore", "pathfinder claymore", "greatrunicblade", "great runic blade", "-2525310", "2525310") }; private readonly Dictionary _materialCache = new Dictionary(); private readonly Dictionary _iconCache = new Dictionary(); private readonly Dictionary _knownRunicItems = new Dictionary(); private readonly HashSet _loggedIconFailures = new HashSet(); private readonly HashSet _pendingVisualRetries = new HashSet(); private Material _runicBladeSourceMaterial; private bool _capturedTexturesReady; private bool _loggedNoRenderer; private int _runicMaterialGeneration; private bool _loggedPrefabMaterialFailure; private static string PluginDirectory { get { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (!string.IsNullOrEmpty(directoryName)) { return directoryName; } return "."; } } private void Awake() { SL.OnPacksLoaded += OnSideLoaderPacksLoaded; for (int i = 0; i < WeaponDefinitions.Length; i++) { SL_Item.AddOnInstanceStartListener(WeaponDefinitions[i].ItemId, (Action)OnRunicWeaponInstanceStart); } TryRefreshCapturedTextureState(); TryRefreshRunicBladeSourceMaterial(allowLoadedMaterialSearch: false); Debug.Log((object)"[Craftable Runic Blades] Loaded."); } private void OnSideLoaderPacksLoaded() { for (int i = 0; i < WeaponDefinitions.Length; i++) { ApplyRunicWeaponIconToPrefab(WeaponDefinitions[i]); } ((MonoBehaviour)this).StartCoroutine(PreloadRunicBladeMaterialWhenReady()); } private void OnRunicWeaponInstanceStart(Item item) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown RunicWeaponDefinition runicWeaponDefinition = FindDefinition(item); if (runicWeaponDefinition != null) { ApplyRunicWeaponIcon(item, runicWeaponDefinition); _knownRunicItems[((Object)item).GetInstanceID()] = item; item.OnProcessVisual -= new ProcessVisual(OnRunicWeaponProcessVisual); item.OnProcessVisual += new ProcessVisual(OnRunicWeaponProcessVisual); QueueRunicVisualApply(item); } } private void OnRunicWeaponProcessVisual(Item item) { QueueRunicVisualApply(item); } private void QueueRunicVisualApply(Item item) { RunicWeaponDefinition runicWeaponDefinition = FindDefinition(item); if (runicWeaponDefinition != null) { TryRefreshCapturedTextureState(); TryRefreshRunicBladeSourceMaterial(allowLoadedMaterialSearch: true); ApplyRunicVisual(item, runicWeaponDefinition, logMissingRenderer: false); int instanceID = ((Object)item).GetInstanceID(); if (_pendingVisualRetries.Add(instanceID)) { ((MonoBehaviour)this).StartCoroutine(ApplyRunicVisualWhenReady(item, runicWeaponDefinition.ItemId, instanceID)); } } } private IEnumerator ApplyRunicVisualWhenReady(Item item, int itemId, int instanceId) { bool applied = false; RunicWeaponDefinition definition = FindDefinition(itemId); for (int i = 0; i < VisualRetryDelays.Length; i++) { float num = VisualRetryDelays[i]; if (num > 0f) { yield return (object)new WaitForSecondsRealtime(num); } else { yield return null; } if ((Object)(object)item == (Object)null || definition == null) { break; } TryRefreshCapturedTextureState(); TryRefreshRunicBladeSourceMaterial(allowLoadedMaterialSearch: true); applied |= ApplyRunicVisual(item, definition, logMissingRenderer: false); } if (!applied && (Object)(object)item != (Object)null && definition != null) { ApplyRunicVisual(item, definition, logMissingRenderer: true); } _pendingVisualRetries.Remove(instanceId); } private bool ApplyRunicVisual(Item item, RunicWeaponDefinition definition, bool logMissingRenderer) { if ((Object)(object)item == (Object)null || definition == null || item.ItemID != definition.ItemId) { return false; } if (ApplyToKnownVisualRoots(item, definition)) { return true; } if (logMissingRenderer && !_loggedNoRenderer) { _loggedNoRenderer = true; Debug.LogWarning((object)"[Craftable Runic Blades] Could not find a safe renderer to recolor."); } return false; } private void TryRefreshRunicBladeSourceMaterial(bool allowLoadedMaterialSearch) { if (!((Object)(object)_runicBladeSourceMaterial != (Object)null)) { Material val = LoadCapturedRunicBladeMaterial(); if ((Object)(object)val == (Object)null) { val = FindRunicBladePrefabMaterial(); } if ((Object)(object)val == (Object)null && allowLoadedMaterialSearch) { val = FindLoadedCapturedRunicBladeMaterial(); } if (!((Object)(object)val == (Object)null)) { _runicBladeSourceMaterial = val; _runicMaterialGeneration++; _materialCache.Clear(); Debug.Log((object)("[Craftable Runic Blades] Captured Runic Blade material '" + ((Object)val).name + "' with shader '" + ((Object)val.shader).name + "'.")); RefreshKnownRunicItems(); } } } private IEnumerator PreloadRunicBladeMaterialWhenReady() { float[] delays = new float[5] { 0f, 0.25f, 1f, 2f, 4f }; for (int i = 0; i < delays.Length; i++) { if (delays[i] > 0f) { yield return (object)new WaitForSecondsRealtime(delays[i]); } else { yield return null; } TryRefreshRunicBladeSourceMaterial(allowLoadedMaterialSearch: true); if ((Object)(object)_runicBladeSourceMaterial != (Object)null) { break; } } } private void RefreshKnownRunicItems() { List list = new List(); foreach (KeyValuePair knownRunicItem in _knownRunicItems) { Item value = knownRunicItem.Value; if ((Object)(object)value == (Object)null) { list.Add(knownRunicItem.Key); } else { QueueRunicVisualApply(value); } } for (int i = 0; i < list.Count; i++) { _knownRunicItems.Remove(list[i]); } } private void ApplyRunicWeaponIconToPrefab(RunicWeaponDefinition definition) { try { if (ResourcesPrefabManager.Instance != null) { Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab(definition.ItemId); ApplyRunicWeaponIcon(itemPrefab, definition); } } catch (Exception ex) { LogIconFailure(definition, "Could not apply custom icon to prefab: " + ex.Message); } } private void ApplyRunicWeaponIcon(Item item, RunicWeaponDefinition definition) { if ((Object)(object)item == (Object)null || definition == null || item.ItemID != definition.ItemId) { return; } Sprite runicWeaponIcon = GetRunicWeaponIcon(definition); if ((Object)(object)runicWeaponIcon == (Object)null) { return; } try { if (ItemIconField != null) { ItemIconField.SetValue(item, runicWeaponIcon); } if (ItemIconPathField != null) { ItemIconPathField.SetValue(item, definition.IconId); } else { item.ItemIconPath = definition.IconId; } } catch (Exception ex) { LogIconFailure(definition, "Could not apply custom icon: " + ex.Message); } } private Sprite GetRunicWeaponIcon(RunicWeaponDefinition definition) { if (_iconCache.TryGetValue(definition.IconId, out var value) && (Object)(object)value != (Object)null) { return value; } string text = Path.Combine(PluginDirectory, definition.IconRelativePath.Replace('/', Path.DirectorySeparatorChar)); try { Texture2D val = CustomTextures.LoadTexture(text, false, false); if ((Object)(object)val == (Object)null) { LogIconFailure(definition, "Could not load custom icon from " + text); return null; } ((Object)val).name = definition.IconId; Sprite val2 = CustomTextures.CreateSprite(val, (SpriteBorderTypes)1); ((Object)val2).name = definition.IconId; _iconCache[definition.IconId] = val2; return val2; } catch (Exception ex) { LogIconFailure(definition, "Could not create custom icon: " + ex.Message); return null; } } private void LogIconFailure(RunicWeaponDefinition definition, string message) { string item = ((definition == null) ? "unknown" : definition.IconId); if (_loggedIconFailures.Add(item)) { Debug.LogWarning((object)("[Craftable Runic Blades] " + message)); } } private void TryRefreshCapturedTextureState() { bool flag = CapturedRunicBladeTexturesReady(); if (flag != _capturedTexturesReady) { _capturedTexturesReady = flag; if (flag) { _runicMaterialGeneration++; _materialCache.Clear(); Debug.Log((object)"[Craftable Runic Blades] Captured Runic Blade fallback textures are ready."); } } } private bool ApplyToKnownVisualRoots(Item item, RunicWeaponDefinition definition) { HashSet visitedRoots = new HashSet(); bool flag = false; bool flag2 = SafeIsInWorld(item); bool flag3 = SafeIsEquipped(item); if (!flag2 && !flag3) { HideKnownItemVisuals(item); return false; } ItemVisual val = SafeGetCurrentVisual(item); if ((Object)(object)val != (Object)null) { flag |= ApplyToVisualRoot(((Component)val).gameObject, visitedRoots, definition); } ItemVisual val2 = SafeGetLoadedVisual(item); if ((Object)(object)val2 != (Object)null) { flag |= ApplyToVisualRoot(((Component)val2).gameObject, visitedRoots, definition); } if (flag2) { flag |= ApplyToVisualRoot(((Component)item).gameObject, visitedRoots, definition); } return flag; } private bool ApplyToVisualRoot(GameObject root, HashSet visitedRoots, RunicWeaponDefinition definition) { if ((Object)(object)root == (Object)null) { return false; } int instanceID = ((Object)root).GetInstanceID(); if (!visitedRoots.Add(instanceID)) { return false; } Renderer[] componentsInChildren = root.GetComponentsInChildren(true); if (!ApplyToRenderers(componentsInChildren, definition, requireVisualName: true)) { return ApplyToRenderers(componentsInChildren, definition, requireVisualName: false); } return true; } private bool ApplyToRenderers(Renderer[] renderers, RunicWeaponDefinition definition, bool requireVisualName) { bool result = false; foreach (Renderer val in renderers) { if (!ShouldPatchRenderer(val, definition, requireVisualName)) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; bool flag = false; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; if ((Object)(object)val2 == (Object)null || ShouldSkipMaterial(val2)) { array[j] = val2; } else if (IsPermanentRunicBladeMaterial(val2) && !ShouldRefreshRunicMaterial(val2)) { result = true; array[j] = val2; } else { array[j] = GetRunicMaterial(val2, definition); flag = true; result = true; } } if (flag) { val.sharedMaterials = array; } } return result; } private Material GetRunicMaterial(Material original, RunicWeaponDefinition definition) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown string text = ((Object)original).name ?? string.Empty; int itemId = definition.ItemId; string key = itemId + "|" + ((Object)original).GetInstanceID(); if (_materialCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return value; } Material runicBladeSourceMaterial = GetRunicBladeSourceMaterial(); Material val; if ((Object)(object)runicBladeSourceMaterial != (Object)null) { val = new Material(runicBladeSourceMaterial); ((Object)val).name = "MEROFOS_PermanentRunicBlades_Exact_" + definition.Marker + "_" + ((Object)runicBladeSourceMaterial).name; } else { val = new Material(original); ApplyCapturedRunicBladeMaterial(val, definition.Marker); Material obj = val; ((Object)obj).name = ((Object)obj).name + "_" + text; } _materialCache[key] = val; return val; } private bool ShouldRefreshRunicMaterial(Material material) { string text = ((Object)material).name ?? string.Empty; if ((Object)(object)_runicBladeSourceMaterial != (Object)null && text.StartsWith("MEROFOS_PermanentRunicBlades_Captured_", StringComparison.Ordinal)) { return true; } if (CapturedRunicBladeTexturesReady() && text.StartsWith("MEROFOS_PermanentRunicBlades_Captured_", StringComparison.Ordinal)) { if (HasTexture(material, "_MainTex") && HasTexture(material, "_NormalMap")) { return !HasTexture(material, "_DistortMap"); } return true; } return false; } private Material GetRunicBladeSourceMaterial() { if ((Object)(object)_runicBladeSourceMaterial != (Object)null) { return _runicBladeSourceMaterial; } TryRefreshRunicBladeSourceMaterial(allowLoadedMaterialSearch: true); return _runicBladeSourceMaterial; } private static void ApplyRunicShader(Material material) { Shader val = Shader.Find("Custom/Distort/DistortTextureSpec"); if ((Object)(object)val != (Object)null) { material.shader = val; } } private static Material LoadCapturedRunicBladeMaterial() { string[] array = new string[5] { "mat_itm_crystalBladeRunicBladeLight", "Materials/mat_itm_crystalBladeRunicBladeLight", "_Materials/mat_itm_crystalBladeRunicBladeLight", "Items/mat_itm_crystalBladeRunicBladeLight", "Weapons/mat_itm_crystalBladeRunicBladeLight" }; for (int i = 0; i < array.Length; i++) { Material val = Resources.Load(array[i]); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Material FindLoadedCapturedRunicBladeMaterial() { Material[] array = Resources.FindObjectsOfTypeAll(); foreach (Material val in array) { if (!((Object)(object)val == (Object)null) && ((Object)val).name != null && !((Object)val).name.StartsWith("MEROFOS_PermanentRunicBlades_", StringComparison.Ordinal)) { string name = ((Object)val).name; if (string.Equals(name, "mat_itm_crystalBladeRunicBladeLight", StringComparison.Ordinal) || name.StartsWith("mat_itm_crystalBladeRunicBladeLight ", StringComparison.Ordinal) || name.StartsWith("mat_itm_crystalBladeRunicBladeLight(", StringComparison.Ordinal)) { return val; } } } return null; } private Material FindRunicBladePrefabMaterial() { try { if (ResourcesPrefabManager.Instance == null) { return null; } Material val = FindMaterialOnItem(ResourcesPrefabManager.Instance.GetItemPrefab(2000100)); if ((Object)(object)val != (Object)null) { return val; } } catch (Exception ex) { if (!_loggedPrefabMaterialFailure) { _loggedPrefabMaterialFailure = true; Debug.LogWarning((object)("[Craftable Runic Blades] Could not inspect vanilla Runic Blade prefab material: " + ex.Message)); } } return null; } private static Material FindMaterialOnItem(Item item) { if ((Object)(object)item == (Object)null) { return null; } Material val = FindMaterialInRenderers(((Component)item).GetComponentsInChildren(true)); if ((Object)(object)val != (Object)null) { return val; } ItemVisual val2 = SafeGetCurrentVisual(item); if ((Object)(object)val2 != (Object)null) { val = FindMaterialInRenderers(((Component)val2).GetComponentsInChildren(true)); if ((Object)(object)val != (Object)null) { return val; } } ItemVisual val3 = SafeGetLoadedVisual(item); if ((Object)(object)val3 != (Object)null) { val = FindMaterialInRenderers(((Component)val3).GetComponentsInChildren(true)); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Material FindMaterialInRenderers(Renderer[] renderers) { if (renderers == null) { return null; } foreach (Renderer val in renderers) { if ((Object)(object)val == (Object)null || val is TrailRenderer || val is LineRenderer || val is ParticleSystemRenderer) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null) { continue; } foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 != (Object)null && IsCapturedRunicBladeMaterialName(((Object)val2).name)) { return val2; } } } return null; } private static bool IsCapturedRunicBladeMaterialName(string materialName) { if (string.IsNullOrEmpty(materialName)) { return false; } if (materialName.StartsWith("MEROFOS_PermanentRunicBlades_", StringComparison.Ordinal)) { return false; } if (!string.Equals(materialName, "mat_itm_crystalBladeRunicBladeLight", StringComparison.Ordinal) && !materialName.StartsWith("mat_itm_crystalBladeRunicBladeLight ", StringComparison.Ordinal) && !materialName.StartsWith("mat_itm_crystalBladeRunicBladeLight(", StringComparison.Ordinal) && !materialName.StartsWith("MEROFOS_RunicDagger_Exact_mat_itm_crystalBladeRunicBladeLight", StringComparison.Ordinal)) { return materialName.StartsWith("MEROFOS_RunicArsenal_Exact_mat_itm_crystalBladeRunicBladeLight", StringComparison.Ordinal); } return true; } private static void ApplyCapturedRunicBladeMaterial(Material material, string marker) { //IL_0071: 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) ((Object)material).name = "MEROFOS_PermanentRunicBlades_Captured_" + marker + "_mat_itm_crystalBladeRunicBladeLight"; material.renderQueue = 2000; ApplyRunicShader(material); SetTexture(material, "_MainTex", GetCapturedMainTexture()); SetTexture(material, "_NormalMap", GetCapturedWaveTexture()); SetTexture(material, "_DistortMap", GetCapturedWaveTexture()); SetColor(material, "_Color", new Color(14.55578f, 6.948529f, 15f, 1f)); SetColor(material, "_SpecColor", new Color(0.3455882f, 0.3455882f, 0.3455882f, 0.759f)); SetFloat(material, "_NormalStrength", 1f); SetFloat(material, "_Speed", 1f); SetFloat(material, "_Scale", 2f); SetFloat(material, "_MaskPow", 0f); material.shaderKeywords = new string[2] { "_ALPHATEST_ON", "_NORMALMAP" }; material.EnableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_NORMALMAP"); } private static bool CapturedRunicBladeTexturesReady() { if ((Object)(object)GetCapturedMainTexture() != (Object)null) { return (Object)(object)GetCapturedWaveTexture() != (Object)null; } return false; } private static Texture GetCapturedMainTexture() { if ((Object)(object)s_capturedMainTexture == (Object)null) { s_capturedMainTexture = FindTexture("tex_fx_PerlinNoiseGray"); } return s_capturedMainTexture; } private static Texture GetCapturedWaveTexture() { if ((Object)(object)s_capturedWaveTexture == (Object)null) { s_capturedWaveTexture = FindTexture("tex_env_waterWave_n"); } return s_capturedWaveTexture; } private static Texture FindTexture(string textureName) { string[] array = new string[6] { textureName, "Textures/" + textureName, "_Textures/" + textureName, "FX/" + textureName, "VFX/" + textureName, "Environment/" + textureName }; for (int i = 0; i < array.Length; i++) { Texture val = Resources.Load(array[i]); if ((Object)(object)val != (Object)null) { return val; } } Texture[] array2 = Resources.FindObjectsOfTypeAll(); foreach (Texture val2 in array2) { if ((Object)(object)val2 != (Object)null && string.Equals(((Object)val2).name, textureName, StringComparison.Ordinal)) { return val2; } } if (!s_missingTextureWarnings.Contains(textureName)) { s_missingTextureWarnings.Add(textureName); Debug.LogWarning((object)("[Craftable Runic Blades] Could not find texture '" + textureName + "' for captured Runic Blade material.")); } return null; } private static void SetColor(Material material, string propertyName, Color value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyName)) { material.SetColor(propertyName, value); } } private static void SetFloat(Material material, string propertyName, float value) { if (material.HasProperty(propertyName)) { material.SetFloat(propertyName, value); } } private static void SetTexture(Material material, string propertyName, Texture texture) { if ((Object)(object)texture != (Object)null && material.HasProperty(propertyName)) { material.SetTexture(propertyName, texture); } } private static bool HasTexture(Material material, string propertyName) { if (material.HasProperty(propertyName)) { return (Object)(object)material.GetTexture(propertyName) != (Object)null; } return false; } private static bool IsPermanentRunicBladeMaterial(Material material) { if ((Object)(object)material != (Object)null && ((Object)material).name != null) { return ((Object)material).name.StartsWith("MEROFOS_PermanentRunicBlades_", StringComparison.Ordinal); } return false; } private static bool ShouldPatchRenderer(Renderer renderer, RunicWeaponDefinition definition, bool requireVisualName) { if ((Object)(object)renderer == (Object)null || renderer is TrailRenderer || renderer is LineRenderer || renderer is ParticleSystemRenderer) { return false; } if (requireVisualName && !HasRunicWeaponVisualName(((Component)renderer).transform, definition)) { return false; } string text = ((((Object)renderer).name == null) ? string.Empty : ((Object)renderer).name.ToLowerInvariant()); if (!text.Contains("highlight") && !text.Contains("trail") && !text.Contains("linecast") && !text.Contains("gateframe") && !text.Contains("hair") && !text.Contains("head")) { return !text.Contains("face"); } return false; } private static bool ShouldSkipMaterial(Material material) { string text = ((((Object)material).name == null) ? string.Empty : ((Object)material).name.ToLowerInvariant()); if (!text.Contains("hair") && !text.Contains("skin") && !text.Contains("head") && !text.Contains("face") && !text.Contains("beard")) { return text.StartsWith("mat_cha_", StringComparison.Ordinal); } return true; } private static bool HasRunicWeaponVisualName(Transform transform, RunicWeaponDefinition definition) { Transform val = transform; while ((Object)(object)val != (Object)null) { string text = ((((Object)val).name == null) ? string.Empty : ((Object)val).name.ToLowerInvariant()); for (int i = 0; i < definition.VisualNameTokens.Length; i++) { if (text.Contains(definition.VisualNameTokens[i])) { return true; } } val = val.parent; } return false; } private static ItemVisual SafeGetCurrentVisual(Item item) { try { return item.CurrentVisual; } catch { return null; } } private static ItemVisual SafeGetLoadedVisual(Item item) { try { return item.LoadedVisual; } catch { return null; } } private static bool SafeIsInWorld(Item item) { try { return (Object)(object)item != (Object)null && item.IsInWorld; } catch { return false; } } private static bool SafeIsEquipped(Item item) { try { return (Object)(object)item != (Object)null && item.IsEquipped; } catch { return false; } } private static void HideKnownItemVisuals(Item item) { ItemVisual val = SafeGetCurrentVisual(item); if ((Object)(object)val != (Object)null) { SafeHideVisual(val); } ItemVisual val2 = SafeGetLoadedVisual(item); if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val) { SafeHideVisual(val2); } } private static void SafeHideVisual(ItemVisual visual) { try { visual.Hide(); } catch { } } private static RunicWeaponDefinition FindDefinition(Item item) { if ((Object)(object)item == (Object)null) { return null; } return FindDefinition(item.ItemID); } private static RunicWeaponDefinition FindDefinition(int itemId) { for (int i = 0; i < WeaponDefinitions.Length; i++) { if (WeaponDefinitions[i].ItemId == itemId) { return WeaponDefinitions[i]; } } return null; } }