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 SuperHornMod v2.1.1
SuperHornMod/SuperHornMod.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyCompany("SuperHornMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("SuperHornMod")] [assembly: AssemblyTitle("SuperHornMod")] [assembly: AssemblyVersion("1.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 MyCoolMod { public static class HornCreator { public static Sprite HornIcon; public static void Init() { LoadIcon(); PrefabManager.OnVanillaPrefabsAvailable += CreateHorn; ItemManager.OnItemsRegistered += OnItemsRegistered; } private static void LoadIcon() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) string path = Path.Combine(MyMod.ModFolder, "horn_icon.png"); if (!File.Exists(path)) { Debug.LogWarning((object)"[Рог Хеймдалля] horn_icon.png не найден."); return; } byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); HornIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); Debug.Log((object)"[Рог Хеймдалля] Иконка загружена."); } private static void CreateHorn() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= CreateHorn; ItemConfig val = new ItemConfig(); val.Name = Loc.GetRaw("item_name"); val.Description = Loc.GetRaw("item_description"); val.CraftingStation = CraftingStations.Workbench; val.MinStationLevel = 2; val.AddRequirement(new RequirementConfig("FineWood", 2, 0, true)); val.AddRequirement(new RequirementConfig("TrophyEikthyr", 1, 0, true)); val.AddRequirement(new RequirementConfig("LeatherScraps", 2, 1, true)); val.AddRequirement(new RequirementConfig("Copper", 2, 0, true)); val.AddRequirement(new RequirementConfig("Bronze", 0, 3, true)); if ((Object)(object)HornIcon != (Object)null) { val.Icons = (Sprite[])(object)new Sprite[1] { HornIcon }; } CustomItem val2 = new CustomItem("SuperHorn", "Club", val); ItemManager.Instance.AddItem(val2); Debug.Log((object)"[Рог Хеймдалля] Предмет зарегистрирован!"); } private static void OnItemsRegistered() { ItemManager.OnItemsRegistered -= OnItemsRegistered; ReplaceModel(); } private static void ReplaceModel() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SuperHorn"); GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab("TankardAnniversary"); if ((Object)(object)itemPrefab == (Object)null || (Object)(object)itemPrefab2 == (Object)null) { Debug.LogWarning((object)"[Рог Хеймдалля] Замена модели не удалась — префабы не найдены."); return; } Transform val = itemPrefab.transform.Find("attach"); Transform val2 = itemPrefab2.transform.Find("attach"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { Debug.LogWarning((object)"[Рог Хеймдалля] Transform 'attach' не найден."); return; } foreach (object item in val) { Transform val3 = (Transform)item; Object.Destroy((Object)(object)((Component)val3).gameObject); } GameObject val4 = Object.Instantiate<GameObject>(((Component)val2.GetChild(0)).gameObject, val); val4.transform.localPosition = Vector3.zero; val4.transform.localRotation = Quaternion.identity; val4.transform.localScale = Vector3.one; Debug.Log((object)"[Рог Хеймдалля] Модель заменена успешно."); } } [HarmonyPatch(typeof(Player), "LateUpdate")] public static class HornHandAdjust { private static readonly FieldInfo RightItemInstanceField = AccessTools.Field(typeof(VisEquipment), "m_rightItemInstance"); private static bool logged; private static void Postfix(Player __instance) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon(); if (currentWeapon == null || (Object)(object)currentWeapon.m_dropPrefab == (Object)null || ((Object)currentWeapon.m_dropPrefab).name != "SuperHorn") { return; } VisEquipment component = ((Component)__instance).GetComponent<VisEquipment>(); if ((Object)(object)component == (Object)null || RightItemInstanceField == null) { return; } object? value = RightItemInstanceField.GetValue(component); GameObject val = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val == (Object)null)) { if (MyMod.DebugLogging != null && MyMod.DebugLogging.Value && !logged) { LogHierarchy(val.transform, ""); logged = true; } val.transform.localPosition = new Vector3(0f, 0.05f, 0.05f); val.transform.localRotation = Quaternion.Euler(-10f, 0f, -100f); for (int i = 0; i < val.transform.childCount; i++) { Transform child = val.transform.GetChild(i); child.localPosition = Vector3.zero; child.localRotation = Quaternion.Euler(0f, 0f, 90f); } } } private static void LogHierarchy(Transform t, string indent) { //IL_001c: 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_0038: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)$"[Рог Хеймдалля] {indent}{((Object)t).name} pos={t.localPosition} rot={t.localEulerAngles} scale={t.localScale}"); for (int i = 0; i < t.childCount; i++) { LogHierarchy(t.GetChild(i), indent + " "); } } } [HarmonyPatch] public static class HornLogic { private const string RPC_HORN_SIGNAL = "HornOfHeimdall_Signal"; private const float REPLY_WINDOW = 10f; private static Dictionary<HornSignalType, float> lastUseTime = new Dictionary<HornSignalType, float>(); private static float globalLastUse = -999f; private static float lastReplyTime = -999f; private const float REPLY_COOLDOWN = 5f; private static float lastBuffTime = -999f; private static float lastHeardTime = -100f; private static HornSignalType lastHeardType = HornSignalType.Navigation; private static float lastBuffReceivedTime = -999f; private static ZRoutedRpc registeredOn; private static string cachedActivationKeyString; private static KeyCode cachedActivationKey = (KeyCode)103; private static void InitCooldowns() { lastUseTime.Clear(); foreach (object value in Enum.GetValues(typeof(HornSignalType))) { HornSignalType key = (HornSignalType)value; lastUseTime[key] = -999f; } lastReplyTime = -999f; lastBuffTime = -999f; } private static bool IsOnCooldown(HornSignalType type, bool isReply, out float remaining) { float num = Time.time - globalLastUse; float value = MyMod.GlobalCooldown.Value; if (num < value) { remaining = value - num; return true; } if (isReply) { float num2 = Time.time - lastReplyTime; if (num2 < 5f) { remaining = 5f - num2; return true; } remaining = 0f; return false; } float num3 = (lastUseTime.ContainsKey(type) ? lastUseTime[type] : (-999f)); float cooldown = HornSignalRegistry.GetConfig(type).Cooldown; float num4 = Time.time - num3; if (num4 < cooldown) { remaining = cooldown - num4; return true; } remaining = 0f; return false; } private static void StartCooldown(HornSignalType type, bool isReply) { globalLastUse = Time.time; if (isReply) { lastReplyTime = Time.time; } else { lastUseTime[type] = Time.time; } } private static bool IsBuffOnCooldown(out float remaining) { float num = Time.time - lastBuffTime; float value = MyMod.AlarmBuffCooldown.Value; if (num < value) { remaining = value - num; return true; } remaining = 0f; return false; } private static string GetSignalName(HornSignalType type) { return type switch { HornSignalType.Alarm => "Боевой сигнал", HornSignalType.Navigation => "Сигнальный зов", _ => type.ToString(), }; } [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] private static void InitOnWorldLoad() { InitCooldowns(); HornSignalRegistry.Init(); RegisterRPC(); } private static void RegisterRPC() { if (ZRoutedRpc.instance != null && registeredOn != ZRoutedRpc.instance) { ZRoutedRpc.instance.Register<Vector3, Vector3, int, bool>("HornOfHeimdall_Signal", (Method<Vector3, Vector3, int, bool>)OnSignalReceived); registeredOn = ZRoutedRpc.instance; Debug.Log((object)"[Рог Хеймдалля] RPC зарегистрирован."); } } private static void OnSignalReceived(long sender, Vector3 hornPos, Vector3 hornForward, int signalTypeInt, bool isReply) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { HornSignalConfig config = HornSignalRegistry.GetConfig((HornSignalType)signalTypeInt); float num = Vector3.Distance(hornPos, ((Component)localPlayer).transform.position); bool flag = num < 3f; HornSoundEngine.Play(hornPos, hornForward, (HornSignalType)signalTypeInt, isReply); if (!flag && config.ApplyBuff && num <= config.Radius) { TryApplyBuffToPlayer(localPlayer); } if (!flag && num <= config.Radius) { lastHeardTime = Time.time; lastHeardType = (HornSignalType)signalTypeInt; string text = ((!isReply || config.ReplyMessage == null) ? string.Format(config.HeardMessage, num.ToString("F0"), MyMod.ActivationKey.Value) : config.ReplyMessage); ((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } } [HarmonyPatch(typeof(Player), "Update")] [HarmonyPostfix] private static void HornInput(Player __instance) { //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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (cachedActivationKeyString != MyMod.ActivationKey.Value) { if (!Enum.TryParse<KeyCode>(MyMod.ActivationKey.Value, ignoreCase: true, out cachedActivationKey)) { cachedActivationKey = (KeyCode)103; Debug.LogWarning((object)("[Рог Хеймдалля] Неверная клавиша активации в конфиге ('" + MyMod.ActivationKey.Value + "'), использую G.")); } cachedActivationKeyString = MyMod.ActivationKey.Value; } KeyCode val = cachedActivationKey; if (!Input.GetKeyDown(val)) { return; } ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon(); if (currentWeapon == null || (Object)(object)currentWeapon.m_dropPrefab == (Object)null || ((Object)currentWeapon.m_dropPrefab).name != "SuperHorn") { return; } HornSignalType hornSignalType = HornSignalType.Navigation; if (Input.GetKey((KeyCode)304)) { hornSignalType = HornSignalType.Alarm; } bool flag = Time.time - lastHeardTime < 10f; if (flag) { hornSignalType = lastHeardType; } HornSignalConfig config = HornSignalRegistry.GetConfig(hornSignalType); if (IsOnCooldown(hornSignalType, flag, out var remaining)) { ((Character)__instance).Message((MessageType)2, Loc.Get("cooldown_generic", remaining), 0, (Sprite)null, false); return; } if (hornSignalType == HornSignalType.Alarm && config.ApplyBuff && IsBuffOnCooldown(out var remaining2)) { ((Character)__instance).Message((MessageType)2, Loc.Get("buff_cooldown_input", remaining2), 0, (Sprite)null, false); return; } if (currentWeapon.m_durability < config.DurabilityCost) { ((Character)__instance).Message((MessageType)2, Loc.Get("horn_worn_out"), 0, (Sprite)null, false); return; } if (config.StaminaCost > 0f && !((Character)__instance).HaveStamina(config.StaminaCost)) { ((Character)__instance).Message((MessageType)2, Loc.Get("not_enough_stamina"), 0, (Sprite)null, false); return; } StartCooldown(hornSignalType, flag); currentWeapon.m_durability -= config.DurabilityCost; if (config.StaminaCost > 0f) { ((Character)__instance).UseStamina(config.StaminaCost); } if (flag) { lastHeardTime = -100f; } ((MonoBehaviour)__instance).StartCoroutine(ActivateHorn(__instance, hornSignalType, flag)); } private static IEnumerator ActivateHorn(Player player, HornSignalType signalType, bool isReply) { HornSignalConfig config = HornSignalRegistry.GetConfig(signalType); player.StartEmote(config.Emote, true); yield return (object)new WaitForSeconds(0.35f); if (ZRoutedRpc.instance != null) { Vector3 pos = ((Component)player).transform.position + Vector3.up * 1.8f; Vector3 forward = ((Component)player).transform.forward; ZRoutedRpc.instance.InvokeRoutedRPC(0L, "HornOfHeimdall_Signal", new object[4] { pos, forward, (int)signalType, isReply }); if (config.ApplyBuff) { TryApplyBuffToPlayer(player); } ((Character)player).Message((MessageType)2, isReply ? Loc.GetRaw("activate_reply") : config.ActivateMessage, 0, (Sprite)null, false); } } private static void TryApplyBuffToPlayer(Player player) { if ((Object)(object)player == (Object)null) { return; } SEMan sEMan = ((Character)player).GetSEMan(); StatusEffect val = sEMan.GetStatusEffects().Find((StatusEffect se) => ((Object)se).name == "SE_HornBuff"); if ((Object)(object)val != (Object)null) { Debug.Log((object)"[Рог Хеймдалля] Баф уже активен — не обновляем."); return; } float num = Time.time - lastBuffReceivedTime; float value = MyMod.AlarmBuffCooldown.Value; if (num < value) { float num2 = value - num; Debug.Log((object)$"[Рог Хеймдалля] Баф на кулдауне — {num2:F0} сек."); ((Character)player).Message((MessageType)1, Loc.Get("buff_cooldown_apply", num2), 0, (Sprite)null, false); } else { SE_HornBuff sE_HornBuff = ScriptableObject.CreateInstance<SE_HornBuff>(); ((Object)sE_HornBuff).name = "SE_HornBuff"; sEMan.AddStatusEffect((StatusEffect)(object)sE_HornBuff, false, 0, 0f, (short)(-1)); lastBuffReceivedTime = Time.time; lastBuffTime = Time.time; Debug.Log((object)("[Рог Хеймдалля] Баф наложен на " + ((Character)player).GetHoverName() + ".")); } } } public class HornSignalConfig { public string Name; public float Radius; public float Cooldown; public float DurabilityCost; public float StaminaCost; public string SoundFile; public string ReplySoundFile; public bool ApplyBuff; public bool AffectsEnemies; public bool AffectsAllies; public float EnemyScareRadius; public string Emote; public string ActivateMessage; public string HeardMessage; public string ReplyMessage; } public static class HornSignalRegistry { public static Dictionary<HornSignalType, HornSignalConfig> Configs = new Dictionary<HornSignalType, HornSignalConfig>(); private static Dictionary<string, AudioClip> loadedClips = new Dictionary<string, AudioClip>(); public static void Init() { RegisterSignals(); LoadAllSounds(); Debug.Log((object)$"[Рог Хеймдалля] Зарегистрировано {Configs.Count} типов сигналов."); } private static void RegisterSignals() { Configs.Clear(); Configs[HornSignalType.Navigation] = new HornSignalConfig { Name = "Сигнальный зов", Radius = MyMod.NavRadius.Value, Cooldown = MyMod.NavCooldown.Value, DurabilityCost = MyMod.NavDurabilityCost.Value, StaminaCost = 0f, SoundFile = "horn.wav", ReplySoundFile = "horn_reply.wav", ApplyBuff = false, AffectsEnemies = false, AffectsAllies = true, EnemyScareRadius = 0f, Emote = "cheer", ActivateMessage = "Сигнальный зов!", HeardMessage = "Слышен рог! ({0}м) [Нажми {1} чтобы ответить]", ReplyMessage = "Ответный сигнал!" }; Configs[HornSignalType.Alarm] = new HornSignalConfig { Name = "Боевой сигнал", Radius = MyMod.AlarmRadius.Value, Cooldown = MyMod.AlarmCooldown.Value, DurabilityCost = MyMod.AlarmDurabilityCost.Value, StaminaCost = MyMod.AlarmStaminaCost.Value, SoundFile = "horn_alarm.wav", ReplySoundFile = null, ApplyBuff = true, AffectsEnemies = true, AffectsAllies = true, EnemyScareRadius = MyMod.AlarmScareRadius.Value, Emote = "challenge", ActivateMessage = "БОЕВОЙ СИГНАЛ!", HeardMessage = "Боевой сигнал! ({0}м)", ReplyMessage = null }; } private static void LoadAllSounds() { loadedClips.Clear(); foreach (KeyValuePair<HornSignalType, HornSignalConfig> config in Configs) { LoadClipIfNeeded(config.Value.SoundFile); if (config.Value.ReplySoundFile != null) { LoadClipIfNeeded(config.Value.ReplySoundFile); } } } private static void LoadClipIfNeeded(string fileName) { if (string.IsNullOrEmpty(fileName) || loadedClips.ContainsKey(fileName)) { return; } string path = Path.Combine(MyMod.ModFolder, fileName); if (!File.Exists(path)) { Debug.LogWarning((object)("[Рог Хеймдалля] " + fileName + " не найден.")); return; } AudioClip val = WavLoader.LoadWav(path); if ((Object)(object)val != (Object)null) { loadedClips[fileName] = val; Debug.Log((object)("[Рог Хеймдалля] " + fileName + " загружен.")); } } public static AudioClip GetClip(HornSignalType type, bool isReply) { if (!Configs.ContainsKey(type)) { return null; } HornSignalConfig hornSignalConfig = Configs[type]; AudioClip value = null; if (isReply && hornSignalConfig.ReplySoundFile != null && loadedClips.TryGetValue(hornSignalConfig.ReplySoundFile, out value)) { return value; } AudioClip value2 = null; if (hornSignalConfig.SoundFile != null && loadedClips.TryGetValue(hornSignalConfig.SoundFile, out value2)) { return value2; } AudioClip value3 = null; if (type != HornSignalType.Navigation && loadedClips.TryGetValue("horn.wav", out value3)) { return value3; } return null; } public static HornSignalConfig GetConfig(HornSignalType type) { return Configs.ContainsKey(type) ? Configs[type] : Configs[HornSignalType.Navigation]; } } public enum HornSignalType { Navigation, Alarm } public static class HornSoundEngine { public static void Play(Vector3 hornPos, Vector3 hornForward, HornSignalType signalType, bool isReply) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_005f: 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_00ba: 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_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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_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_0191: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_025d: 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_0265: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } HornSignalConfig config = HornSignalRegistry.GetConfig(signalType); Vector3 position = ((Component)localPlayer).transform.position; float num = Vector3.Distance(hornPos, position); bool flag = num < 3f; float num2 = config.Radius; if (!MyMod.IsArcade) { float num3 = Mathf.Clamp((hornPos.y - position.y) / 40f, -0.4f, 0.4f); num2 *= 1f + num3; num2 *= GetWeatherMultiplier(); } if (flag || !(num > num2)) { Vector3 val = position - hornPos; Vector3 normalized = ((Vector3)(ref val)).normalized; float num4 = Vector3.Dot(((Vector3)(ref hornForward)).normalized, normalized); float directionMul = (MyMod.IsArcade ? 1f : Mathf.Lerp(0.3f, 1f, (num4 + 1f) / 2f)); if (flag) { directionMul = 1f; } bool flag2 = false; if (!flag && !MyMod.IsArcade) { flag2 = Physics.Raycast(hornPos, normalized, num, LayerMask.GetMask(new string[2] { "Default", "terrain" })); } float headMul = 1f; if (MyMod.IsSimulation && !flag) { val = hornPos - position; Vector3 normalized2 = ((Vector3)(ref val)).normalized; float num5 = Vector3.Dot(((Component)localPlayer).transform.forward, normalized2); headMul = Mathf.Lerp(0.85f, 1.1f, (num5 + 1f) / 2f); } float echoStrength = 0.5f; if (MyMod.IsSimulation && !flag) { echoStrength = CalculateSpaceOpenness(hornPos, hornForward); } float weatherCutoffMul = 1f; if (!MyMod.IsArcade) { float weatherMultiplier = GetWeatherMultiplier(); weatherCutoffMul = Mathf.Lerp(1f, 0.7f, 1f - weatherMultiplier); } float dist = (flag ? 0f : Mathf.Clamp01(num / num2)); SoundContext ctx = new SoundContext { hornPos = hornPos, listenerPos = position, hornForward = hornForward, distance = num, dist01 = dist, directionMul = directionMul, headMul = headMul, isSelf = flag, isReply = isReply, obstructed = flag2, echoStrength = echoStrength, weatherCutoffMul = weatherCutoffMul, signalType = signalType }; SpawnSound(ctx); SpawnVFX(hornPos); if (MyMod.IsSimulation && flag2 && !flag && num > 30f && (Object)(object)GameCamera.instance != (Object)null) { float delay = Random.Range(0.5f, 0.8f); ((MonoBehaviour)GameCamera.instance).StartCoroutine(PlayAcousticShadow(ctx, delay)); } if (config.AffectsEnemies && config.EnemyScareRadius > 0f) { AffectNearbyCreatures(hornPos, config.EnemyScareRadius); } } } private static void SpawnSound(SoundContext ctx) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) AudioClip clip = HornSignalRegistry.GetClip(ctx.signalType, ctx.isReply); if ((Object)(object)clip == (Object)null) { return; } GameObject val = new GameObject("HeimdallHornSound"); val.transform.position = ctx.hornPos; AudioSource val2 = val.AddComponent<AudioSource>(); val2.clip = clip; val2.spatialBlend = (ctx.isSelf ? 0.4f : 1f); val2.minDistance = 5f; val2.maxDistance = HornSignalRegistry.GetConfig(ctx.signalType).Radius * 1.2f; val2.rolloffMode = (AudioRolloffMode)1; val2.spread = (ctx.isSelf ? 120f : 30f); val2.dopplerLevel = 0f; float num = ctx.directionMul * ctx.headMul; if (ctx.obstructed) { num *= (MyMod.IsSimulation ? 0.3f : 0.5f); } if (!ctx.isSelf && ctx.distance > 50f) { float num2 = Mathf.Clamp01((ctx.distance - 50f) / 100f); num *= Mathf.Lerp(1f, 0.15f, num2); } num *= MyMod.MasterVolume.Value; val2.volume = Mathf.Clamp01(num); if (!MyMod.IsArcade) { AudioLowPassFilter val3 = val.AddComponent<AudioLowPassFilter>(); if (ctx.isSelf) { val3.cutoffFrequency = 22000f; } else { float num3 = 50f; float num4 = 150f; float num5 = Mathf.Clamp01((ctx.distance - num3) / (num4 - num3)); float num6 = Mathf.Lerp(14000f, 800f, num5 * num5); if (ctx.obstructed) { num6 = Mathf.Min(num6, MyMod.IsSimulation ? 1200f : 1800f); } num6 *= ctx.weatherCutoffMul; val3.cutoffFrequency = Mathf.Max(num6, 500f); } val3.lowpassResonanceQ = 1f; } val2.Play(); if (!MyMod.IsArcade && !ctx.isSelf && ctx.distance > 50f) { float delay = ctx.distance / 343f; float num7 = val2.volume * 0.3f * ctx.echoStrength; if (num7 > 0.02f && (Object)(object)GameCamera.instance != (Object)null) { ((MonoBehaviour)GameCamera.instance).StartCoroutine(PlayEcho(ctx.hornPos, clip, delay, num7, ctx.dist01, HornSignalRegistry.GetConfig(ctx.signalType).Radius)); } } Object.Destroy((Object)(object)val, clip.length + 3f); } private static IEnumerator PlayEcho(Vector3 pos, AudioClip clip, float delay, float vol, float dist01, float maxDist) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(delay); GameObject go = new GameObject("HeimdallHornEcho"); go.transform.position = pos; AudioSource src = go.AddComponent<AudioSource>(); src.clip = clip; src.spatialBlend = 1f; src.minDistance = 5f; src.maxDistance = maxDist; src.rolloffMode = (AudioRolloffMode)1; src.spread = 80f; src.dopplerLevel = 0f; src.volume = vol; src.pitch = 0.95f; AudioLowPassFilter lp = go.AddComponent<AudioLowPassFilter>(); lp.cutoffFrequency = Mathf.Lerp(3000f, 1000f, dist01); lp.lowpassResonanceQ = 1f; src.Play(); Object.Destroy((Object)(object)go, clip.length + 1f); } private static IEnumerator PlayAcousticShadow(SoundContext ctx, float delay) { yield return (object)new WaitForSeconds(delay); AudioClip clip = HornSignalRegistry.GetClip(ctx.signalType, ctx.isReply); if (!((Object)(object)clip == (Object)null)) { Vector3 val = new Vector3(Random.Range(-1f, 1f), Random.Range(0.2f, 0.5f), Random.Range(-1f, 1f)); Vector3 offset = ((Vector3)(ref val)).normalized * Random.Range(15f, 25f); GameObject go = new GameObject("HeimdallHornShadow"); go.transform.position = ctx.hornPos + offset; AudioSource src = go.AddComponent<AudioSource>(); src.clip = clip; src.spatialBlend = 1f; src.minDistance = 5f; src.maxDistance = HornSignalRegistry.GetConfig(ctx.signalType).Radius * 0.6f; src.rolloffMode = (AudioRolloffMode)1; src.spread = 120f; src.dopplerLevel = 0f; src.volume = ctx.directionMul * 0.4f; src.pitch = 0.92f; AudioLowPassFilter lp = go.AddComponent<AudioLowPassFilter>(); lp.cutoffFrequency = 1500f; lp.lowpassResonanceQ = 1.2f; src.Play(); Object.Destroy((Object)(object)go, clip.length + 1f); } } private static void AffectNearbyCreatures(Vector3 pos, float enemyRadius) { //IL_004d: 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) float value = MyMod.AlarmScareRadius.Value; float num = Mathf.Max(enemyRadius, value); int num2 = 0; int num3 = 0; foreach (BaseAI allInstance in BaseAI.GetAllInstances()) { if ((Object)(object)allInstance == (Object)null) { continue; } float num4 = Vector3.Distance(pos, ((Component)allInstance).transform.position); if (num4 > num) { continue; } try { Character component = ((Component)allInstance).GetComponent<Character>(); if (!((Object)(object)component == (Object)null) && !component.IsDead() && !component.IsTamed()) { AnimalAI val = (AnimalAI)(object)((allInstance is AnimalAI) ? allInstance : null); if ((Object)(object)val != (Object)null && num4 <= value) { allInstance.Alert(); num3++; } else if ((Object)(object)val == (Object)null && num4 <= enemyRadius) { allInstance.Alert(); allInstance.SetAggravated(true, (AggravatedReason)0); num2++; } } } catch (Exception ex) { Debug.LogWarning((object)("[Рог Хеймдалля] Ошибка: " + ex.Message)); } } Debug.Log((object)$"[Рог Хеймдалля] Боевой сигнал: {num2} врагов встревожено, {num3} животных напугано."); } private static float GetWeatherMultiplier() { if ((Object)(object)EnvMan.instance == (Object)null) { return 1f; } float windIntensity = EnvMan.instance.GetWindIntensity(); bool flag = false; EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); if (currentEnvironment != null) { string text = currentEnvironment.m_name.ToLower(); flag = text.Contains("rain") || text.Contains("thunder") || text.Contains("storm"); } float num = 1f; if (flag) { num *= 0.8f; } if (windIntensity > 0.5f) { num *= Mathf.Lerp(1f, 0.85f, (windIntensity - 0.5f) * 2f); } return num; } private static float CalculateSpaceOpenness(Vector3 pos, Vector3 forward) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_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) //IL_006d: 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_0087: 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_008f: 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) Vector3 val = Vector3.Cross(forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3[] obj = new Vector3[6] { Vector3.up, ((Vector3)(ref forward)).normalized, -((Vector3)(ref forward)).normalized, normalized, -normalized, default(Vector3) }; val = forward + Vector3.up; obj[5] = ((Vector3)(ref val)).normalized; Vector3[] array = (Vector3[])(object)obj; int num = 0; Vector3[] array2 = array; foreach (Vector3 val2 in array2) { if (!Physics.Raycast(pos, val2, 50f, LayerMask.GetMask(new string[2] { "Default", "terrain" }))) { num++; } } return (float)num / (float)array.Length; } private static void SpawnVFX(Vector3 pos) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("vfx_WishbonePing"); if (!((Object)(object)prefab == (Object)null)) { bool activeSelf = prefab.activeSelf; prefab.SetActive(false); GameObject val = Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); prefab.SetActive(activeSelf); ZNetView component = val.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } val.SetActive(true); Object.Destroy((Object)(object)val, 5f); } } } public static class Loc { private static readonly Dictionary<string, string> En = new Dictionary<string, string> { ["item_name"] = "Horn of Heimdall", ["item_description"] = "An ancient horn of Bifrost's guardian.\nG - navigation call\nShift+G - battle alarm", ["signal_navigation_name"] = "Navigation Call", ["signal_alarm_name"] = "Battle Alarm", ["activate_navigation"] = "Navigation call!", ["activate_alarm"] = "BATTLE ALARM!", ["activate_reply"] = "Reply signal!", ["heard_navigation"] = "A horn call! ({0}m) [Press {1} to reply]", ["heard_alarm"] = "Battle alarm! ({0}m)", ["reply_navigation"] = "Reply signal!", ["cooldown_generic"] = "Catching your breath... ({0:F0}s)", ["buff_cooldown_input"] = "Battle spirit hasn't recovered yet... ({0:F0}s)", ["buff_cooldown_apply"] = "Battle spirit hasn't recovered yet ({0:F0}s)", ["horn_worn_out"] = "The horn is too worn out!", ["not_enough_stamina"] = "Not enough stamina!", ["buff_name"] = "Battle Horn", ["buff_tooltip_header"] = "The spirit of war fills you!\n", ["buff_tooltip_stamina_regen"] = "+{0:F0}% stamina regen\n", ["buff_tooltip_stamina_drain"] = "-{0:F0}% stamina drain\n", ["buff_tooltip_adrenaline_instant"] = "+{0:F0} instant adrenaline\n", ["buff_tooltip_adrenaline_gain"] = "+{0:F0}% adrenaline gain" }; private static readonly Dictionary<string, string> Ru = new Dictionary<string, string> { ["item_name"] = "Рог Хеймдалля", ["item_description"] = "Древний рог стража Биврёста.\nG — сигнальный зов\nShift+G — боевой сигнал", ["signal_navigation_name"] = "Сигнальный зов", ["signal_alarm_name"] = "Боевой сигнал", ["activate_navigation"] = "Сигнальный зов!", ["activate_alarm"] = "БОЕВОЙ СИГНАЛ!", ["activate_reply"] = "Ответный сигнал!", ["heard_navigation"] = "Слышен рог! ({0}м) [Нажми {1} чтобы ответить]", ["heard_alarm"] = "Боевой сигнал! ({0}м)", ["reply_navigation"] = "Ответный сигнал!", ["cooldown_generic"] = "Надо перевести дыхание... ({0:F0} сек)", ["buff_cooldown_input"] = "Боевой дух ещё не восстановился... ({0:F0} сек)", ["buff_cooldown_apply"] = "Боевой дух ещё не восстановился ({0:F0} сек)", ["horn_worn_out"] = "Рог слишком изношен!", ["not_enough_stamina"] = "Недостаточно выносливости!", ["buff_name"] = "Боевой рог", ["buff_tooltip_header"] = "Воинский дух наполняет тебя!\n", ["buff_tooltip_stamina_regen"] = "+{0:F0}% реген выносливости\n", ["buff_tooltip_stamina_drain"] = "-{0:F0}% расход выносливости\n", ["buff_tooltip_adrenaline_instant"] = "+{0:F0} адреналин мгновенно\n", ["buff_tooltip_adrenaline_gain"] = "+{0:F0}% набор адреналина" }; private static bool IsRussian() { try { return PlayerPrefs.GetString("language", "English") == "Russian"; } catch { return false; } } public static string GetRaw(string key) { Dictionary<string, string> dictionary = (IsRussian() ? Ru : En); if (!dictionary.TryGetValue(key, out var value)) { return key; } return value; } public static string Get(string key, params object[] args) { string raw = GetRaw(key); return (args != null && args.Length != 0) ? string.Format(raw, args) : raw; } } [BepInPlugin("com.rodogor.hornofheimdall", "Рог Хеймдалля", "2.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class MyMod : BaseUnityPlugin { public static ConfigEntry<string> ActivationKey; public static ConfigEntry<string> HornMode; public static ConfigEntry<float> GlobalCooldown; public static ConfigEntry<float> MasterVolume; public static ConfigEntry<float> NavRadius; public static ConfigEntry<float> NavCooldown; public static ConfigEntry<float> NavDurabilityCost; public static ConfigEntry<float> AlarmRadius; public static ConfigEntry<float> AlarmCooldown; public static ConfigEntry<float> AlarmDurabilityCost; public static ConfigEntry<float> AlarmStaminaCost; public static ConfigEntry<float> AlarmBuffDuration; public static ConfigEntry<float> AlarmBuffCooldown; public static ConfigEntry<float> AlarmStaminaRegenBonus; public static ConfigEntry<float> AlarmStaminaDrainReduction; public static ConfigEntry<float> AlarmAdrenalineInstant; public static ConfigEntry<float> AlarmAdrenalineGainBonus; public static ConfigEntry<float> AlarmScareRadius; public static ConfigEntry<bool> DebugLogging; public static Sprite HornBuffIcon; public static string ModFolder; public static bool IsArcade => HornMode.Value == "Arcade"; public static bool IsRealistic => HornMode.Value == "Realistic"; public static bool IsSimulation => HornMode.Value == "Simulation"; private void Awake() { ModFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Debug.Log((object)("[Рог Хеймдалля] Папка мода: " + ModFolder)); ActivationKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ActivationKey", "G", "Key used to blow the horn"); HornMode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "HornMode", "Simulation", "Sound behaviour: Arcade / Realistic / Simulation"); GlobalCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GlobalCooldown", 3f, "Global cooldown between any two signals (sec)"); MasterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sound", "MasterVolume", 0.5f, "Overall horn volume (0.0 - 1.0)"); NavRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation Call", "Radius", 300f, "Navigation call radius (m)"); NavCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation Call", "Cooldown", 20f, "Navigation call cooldown (sec)"); NavDurabilityCost = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation Call", "DurabilityCost", 3f, "Durability cost per navigation call"); AlarmRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "Radius", 50f, "Battle alarm radius (m)"); AlarmCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "Cooldown", 60f, "Battle alarm cooldown (sec)"); AlarmDurabilityCost = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "DurabilityCost", 8f, "Durability cost per battle alarm"); AlarmStaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "StaminaCost", 20f, "Stamina cost per battle alarm"); AlarmBuffDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "BuffDuration", 60f, "Battle buff duration (sec)"); AlarmBuffCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "BuffCooldown", 120f, "Buff cooldown - cannot be refreshed until it passes (sec)"); AlarmStaminaRegenBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "StaminaRegenBonus", 0.3f, "Stamina regen bonus (+30% = 0.30)"); AlarmStaminaDrainReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "StaminaDrainReduction", 0.3f, "Stamina drain reduction (-30% = 0.30)"); AlarmAdrenalineInstant = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "AdrenalineInstant", 25f, "Instant adrenaline on activation"); AlarmAdrenalineGainBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "AdrenalineGainBonus", 0.4f, "Adrenaline gain bonus (+40% = 0.40)"); AlarmScareRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Battle Alarm", "ScareRadius", 40f, "Radius for scaring wild animals (m)"); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Verbose debug logging (e.g. hand-position hierarchy)"); LoadBuffIcon(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); HornCreator.Init(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Рог Хеймдалля загружен!"); } private void LoadBuffIcon() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) string path = Path.Combine(ModFolder, "horn_buff_icon.png"); if (!File.Exists(path)) { Debug.LogWarning((object)"[Рог Хеймдалля] horn_buff_icon.png не найден!"); return; } byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); HornBuffIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); Debug.Log((object)"[Рог Хеймдалля] Иконка бафа загружена."); } } public class SE_HornBuff : SE_Stats { public override void Setup(Character character) { base.m_staminaRegenMultiplier = 1f + MyMod.AlarmStaminaRegenBonus.Value; base.m_runStaminaDrainModifier = 0f - MyMod.AlarmStaminaDrainReduction.Value; base.m_adrenalineUpFront = MyMod.AlarmAdrenalineInstant.Value; base.m_adrenalineModifier = MyMod.AlarmAdrenalineGainBonus.Value; ((StatusEffect)this).m_ttl = MyMod.AlarmBuffDuration.Value; ((StatusEffect)this).m_name = "Боевой рог"; ((StatusEffect)this).m_tooltip = "Воинский дух наполняет тебя!\n" + $"+{MyMod.AlarmStaminaRegenBonus.Value * 100f:F0}% реген выносливости\n" + $"-{MyMod.AlarmStaminaDrainReduction.Value * 100f:F0}% расход выносливости\n" + $"+{MyMod.AlarmAdrenalineInstant.Value:F0} адреналин мгновенно\n" + $"+{MyMod.AlarmAdrenalineGainBonus.Value * 100f:F0}% набор адреналина"; ((StatusEffect)this).m_icon = MyMod.HornBuffIcon; ((SE_Stats)this).Setup(character); Debug.Log((object)("[Рог Хеймдалля] Боевой баф наложен на " + character.GetHoverName() + ": " + $"стамина ×{base.m_staminaRegenMultiplier:F2}, " + $"адреналин +{base.m_adrenalineUpFront:F0}")); } } public struct SoundContext { public Vector3 hornPos; public Vector3 listenerPos; public Vector3 hornForward; public float distance; public float dist01; public float directionMul; public float headMul; public bool isSelf; public bool isReply; public bool obstructed; public float echoStrength; public float weatherCutoffMul; public HornSignalType signalType; } public static class WavLoader { public static AudioClip LoadWav(string path) { try { byte[] array = File.ReadAllBytes(path); if (array.Length < 12 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70 || array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69) { Debug.LogWarning((object)("[Рог Хеймдалля] " + Path.GetFileName(path) + ": не RIFF/WAVE файл.")); return null; } int num = 0; int num2 = 0; int num3 = 0; int num4 = -1; int num5 = 0; int num6 = 12; while (num6 + 8 <= array.Length) { char c = (char)array[num6]; char c2 = (char)array[num6 + 1]; char c3 = (char)array[num6 + 2]; char c4 = (char)array[num6 + 3]; int num7 = BitConverter.ToInt32(array, num6 + 4); int num8 = num6 + 8; bool flag = c == 'f' && c2 == 'm' && c3 == 't' && c4 == ' '; bool flag2 = c == 'd' && c2 == 'a' && c3 == 't' && c4 == 'a'; if (flag && num8 + 16 <= array.Length) { num = BitConverter.ToInt16(array, num8 + 2); num2 = BitConverter.ToInt32(array, num8 + 4); num3 = BitConverter.ToInt16(array, num8 + 14); } else if (flag2) { num4 = num8; num5 = num7; } if (num7 < 0) { break; } num6 = num8 + num7 + num7 % 2; } if (num4 < 0 || num <= 0 || num2 <= 0) { Debug.LogWarning((object)("[Рог Хеймдалля] " + Path.GetFileName(path) + ": не найден корректный chunk 'fmt ' или 'data'.")); return null; } if (num3 != 16) { Debug.LogWarning((object)$"[Рог Хеймдалля] {Path.GetFileName(path)}: поддерживается только 16-bit PCM, а тут {num3}-bit. Файл пропущен."); return null; } if (num4 + num5 > array.Length) { num5 = array.Length - num4; } int num9 = num5 / 2; if (num9 <= 0) { Debug.LogWarning((object)("[Рог Хеймдалля] " + Path.GetFileName(path) + ": пустой data-chunk.")); return null; } float[] array2 = new float[num9]; for (int i = 0; i < num9; i++) { short num10 = BitConverter.ToInt16(array, num4 + i * 2); array2[i] = (float)num10 / 32768f; } AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num9 / num, num, num2, false); val.SetData(array2, 0); return val; } catch (Exception ex) { Debug.LogWarning((object)("[Рог Хеймдалля] Не удалось загрузить " + Path.GetFileName(path) + ": " + ex.Message)); return null; } } } }