using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using StartingAbilityPicker; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("SkillRandomizerMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("SkillRandomizerMod")] [assembly: AssemblyTitle("SkillRandomizerMod")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourName/SkillRandomizerMod")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 SkillTriggerMod { [Serializable] public class TriggerPosition { public string sceneName; public Vector3 position; public int index; public TriggerPosition() { } public TriggerPosition(string scene, float x, float y, float z, int idx = -1) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) sceneName = scene; position = new Vector3(x, y, z); index = idx; } } public class SkillTriggerConfig { public int Seed; public bool Enabled = true; public List TriggerPositions = new List(); public bool AutoDisableShrines = true; } public static class SkillTriggerAPI { private static SkillTriggerConfig _cachedConfig; private static bool _pendingChanges = false; private static bool _isGameReady = false; private static bool _initialized = false; private static HashSet _triggeredRecords = new HashSet(); private static List _activeTriggers = new List(); private static bool _eventsSubscribed = false; private static string TriggerRecordsPath => Path.Combine(Paths.ConfigPath, "SkillTriggerMod", "trigger_records.json"); public static void Initialize(SkillTriggerConfig config) { if (!_initialized) { _cachedConfig = config ?? new SkillTriggerConfig(); _initialized = true; _pendingChanges = true; LoadTriggerRecords(); } } public static void MarkGameReady() { _isGameReady = true; if (_pendingChanges) { ApplyPending(); } } public static void SetEnabled(bool enabled) { _cachedConfig.Enabled = enabled; MarkPendingAndApply(); } public static void SetSeed(int seed) { _cachedConfig.Seed = seed; MarkPendingAndApply(); } public static void SetTriggerPositions(List positions) { _cachedConfig.TriggerPositions = positions; MarkPendingAndApply(); } public static void SetAutoDisableShrines(bool auto) { _cachedConfig.AutoDisableShrines = auto; MarkPendingAndApply(); } public static void ApplyNow() { if (_isGameReady || _initialized) { ApplyPending(); } } public static bool IsEnabled() { return _cachedConfig.Enabled; } public static int GetSeed() { return _cachedConfig.Seed; } public static List GetTriggerPositions() { return new List(_cachedConfig.TriggerPositions); } public static bool IsAutoDisableShrines() { return _cachedConfig.AutoDisableShrines; } public static void ResetAllRecords() { _triggeredRecords.Clear(); SaveTriggerRecords(); } private static void MarkPendingAndApply() { _pendingChanges = true; if (_isGameReady) { ApplyPending(); } } private static void ApplyPending() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) if (!_isGameReady && !_pendingChanges) { return; } SkillRandomizer.SetSeed(_cachedConfig.Seed); ClearAllTriggers(); if (_cachedConfig.Enabled && !_eventsSubscribed) { SceneManager.sceneLoaded += OnSceneLoaded; _eventsSubscribed = true; } else if (!_cachedConfig.Enabled && _eventsSubscribed) { SceneManager.sceneLoaded -= OnSceneLoaded; _eventsSubscribed = false; } if (_cachedConfig.Enabled && _isGameReady) { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).isLoaded) { if (_cachedConfig.AutoDisableShrines && IsItemRandomEnabled()) { DisableShrinesInScene(activeScene); } CreateTriggersForScene(activeScene); } } _pendingChanges = false; } private static void ClearAllTriggers() { foreach (GameObject activeTrigger in _activeTriggers) { if ((Object)(object)activeTrigger != (Object)null) { Object.Destroy((Object)(object)activeTrigger); } } _activeTriggers.Clear(); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (_cachedConfig.Enabled) { if (_cachedConfig.AutoDisableShrines && IsItemRandomEnabled()) { DisableShrinesInScene(scene); } CreateTriggersForScene(scene); } } private static void DisableShrinesInScene(Scene scene) { string[] array = new string[5] { "bind orb", "shrine weaver ability", "weaver_shrine", "bellshrine", "dash shrine" }; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { string text = ((Object)((Component)val).gameObject).name.ToLower(); string[] array2 = array; foreach (string value in array2) { if (text.Contains(value)) { Collider2D[] components = ((Component)val).GetComponents(); for (int l = 0; l < components.Length; l++) { ((Behaviour)components[l]).enabled = false; } Collider[] components2 = ((Component)val).GetComponents(); for (int l = 0; l < components2.Length; l++) { components2[l].enabled = false; } PlayMakerFSM[] components3 = ((Component)val).GetComponents(); for (int l = 0; l < components3.Length; l++) { ((Behaviour)components3[l]).enabled = false; } break; } } } } } private static void CreateTriggersForScene(Scene scene) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_0090: 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_00d3: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _cachedConfig.TriggerPositions.Count; i++) { TriggerPosition triggerPosition = _cachedConfig.TriggerPositions[i]; if (!(triggerPosition.sceneName != ((Scene)(ref scene)).name)) { int num = ((triggerPosition.index >= 0) ? triggerPosition.index : i); string text = $"SkillTriggered_{((Scene)(ref scene)).name}_{num}"; if (!_triggeredRecords.Contains(text)) { GameObject val = new GameObject($"SkillTrigger_{((Scene)(ref scene)).name}_{num}"); val.transform.position = triggerPosition.position; BoxCollider2D obj = val.AddComponent(); ((Collider2D)obj).isTrigger = true; obj.size = new Vector2(8f, 8f); val.AddComponent().SetInfo(((Scene)(ref scene)).name, num, text); SceneManager.MoveGameObjectToScene(val, scene); _activeTriggers.Add(val); Plugin.Log.LogInfo((object)$"触发器创建: {((Scene)(ref scene)).name} 索引 {num}"); } } } } private static bool IsItemRandomEnabled() { try { PropertyInfo propertyInfo = Type.GetType("SilksongItemRandomizer.Plugin, SilksongItemRandomizer")?.GetProperty("PublicItemRandomEnabled", BindingFlags.Static | BindingFlags.Public); if (propertyInfo != null) { return (bool)propertyInfo.GetValue(null); } } catch { } return false; } private static void LoadTriggerRecords() { try { if (File.Exists(TriggerRecordsPath)) { _triggeredRecords = JsonConvert.DeserializeObject>(File.ReadAllText(TriggerRecordsPath)) ?? new HashSet(); } else { _triggeredRecords.Clear(); } } catch { _triggeredRecords.Clear(); } } private static void SaveTriggerRecords() { try { string directoryName = Path.GetDirectoryName(TriggerRecordsPath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } string contents = JsonConvert.SerializeObject((object)_triggeredRecords, (Formatting)1); File.WriteAllText(TriggerRecordsPath, contents); } catch { } } internal static void RecordTriggered(string key) { if (_triggeredRecords.Add(key)) { SaveTriggerRecords(); } } } [BepInPlugin("YourName.SkillTriggerMod", "Skill Trigger Mod", "1.0.0.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__18 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_003f; case 1: <>1__state = -1; goto IL_003f; case 2: <>1__state = -1; goto IL_0065; case 3: { <>1__state = -1; SkillTriggerAPI.MarkGameReady(); return false; } IL_003f: if ((Object)(object)GameManager.instance == (Object)null) { <>2__current = null; <>1__state = 1; return true; } goto IL_0065; IL_0065: if (string.IsNullOrEmpty(GameManager.instance.sceneName)) { <>2__current = null; <>1__state = 2; return true; } <>2__current = null; <>1__state = 3; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static ManualLogSource Log; internal static Plugin Instance { get; private set; } public static ConfigEntry RandomSeed { get; private set; } public static ConfigEntry ModEnabled { get; private set; } public static ConfigEntry CustomPositionsJson { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; RandomSeed = ((BaseUnityPlugin)this).Config.Bind("General", "RandomSeed", 0, "随机种子 (0 表示随机)"); ModEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "ModEnabled", true, "启用技能触发器模组"); CustomPositionsJson = ((BaseUnityPlugin)this).Config.Bind("General", "CustomPositionsJson", "", "自定义触发器坐标 JSON(高级)"); SkillTriggerAPI.Initialize(new SkillTriggerConfig { Seed = RandomSeed.Value, Enabled = ModEnabled.Value, AutoDisableShrines = true, TriggerPositions = ParseTriggerPositions() }); ModEnabled.SettingChanged += delegate { SkillTriggerAPI.SetEnabled(ModEnabled.Value); }; RandomSeed.SettingChanged += delegate { SkillTriggerAPI.SetSeed(RandomSeed.Value); }; CustomPositionsJson.SettingChanged += delegate { SkillTriggerAPI.SetTriggerPositions(ParseTriggerPositions()); }; ((MonoBehaviour)this).StartCoroutine(WaitForGameReady()); } [IteratorStateMachine(typeof(d__18))] private IEnumerator WaitForGameReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__18(0); } private List ParseTriggerPositions() { List result = new List { new TriggerPosition("Mosstown_02", 86.922f, 52.568f, 0.004f, 0), new TriggerPosition("Crawl_05", 23.032f, 16.568f, 0.004f, 1), new TriggerPosition("Shellwood_10", 40.643f, 79.57f, 0.004f, 2), new TriggerPosition("Greymoor_22", 39.783f, 36.826f, 0.004f, 3), new TriggerPosition("Bone_East_05", 100.062f, 13.568f, 0.004f, 4), new TriggerPosition("Under_18", 26f, 13f, 0.004f, 5) }; string text = CustomPositionsJson.Value?.Trim(); if (string.IsNullOrEmpty(text)) { return result; } try { List list = JsonConvert.DeserializeObject>(text); if (list != null && list.Count > 0) { return list; } } catch (Exception ex) { Log.LogError((object)("解析自定义坐标失败: " + ex.Message)); } return result; } public static void ResetAllRecords() { SkillTriggerAPI.ResetAllRecords(); } } public class SkillTrigger : MonoBehaviour { private bool _triggered; private string _sceneName; private int _index; private string _recordKey; public void SetInfo(string sceneName, int index, string recordKey) { _sceneName = sceneName; _index = index; _recordKey = recordKey; } private void OnTriggerEnter2D(Collider2D other) { if (!_triggered && !((Object)(object)((Component)other).GetComponent() == (Object)null)) { _triggered = true; if (_sceneName == "Shellwood_10") { SkillRandomizer.GiveWallJump(); } else if (_sceneName == "Under_18") { SkillRandomizer.GiveHarpoonDash(); } else { SkillRandomizer.GiveRandomSkill(); } SkillTriggerAPI.RecordTriggered(_recordKey); Object.Destroy((Object)(object)((Component)this).gameObject); } } } public static class SkillRandomizer { private static readonly Dictionary DisplayNames = new Dictionary { { "hasNeedleThrow", "丝之矛" }, { "hasThreadSphere", "灵丝风暴" }, { "hasHarpoonDash", "飞针" }, { "hasSilkCharge", "丝刃标" }, { "hasSilkBomb", "符文之怒" }, { "hasSilkBossNeedle", "苍白之爪" }, { "hasNeedolin", "丝忆弦针" }, { "hasDash", "疾风步" }, { "hasBrolly", "流浪者披风" }, { "hasDoubleJump", "雪绒披风" }, { "hasChargeSlash", "蓄力斩" }, { "hasSuperJump", "灵丝升腾" }, { "hasWallJump", "蛛攀术" } }; private static readonly List AllFields = DisplayNames.Keys.ToList(); private static Random _rng; private static int _seed; private static Dictionary _icons = new Dictionary(); private static Sprite _fallback; private static bool _cacheBuilt; private static readonly Dictionary BestPickNames = new Dictionary { { "hasNeedleThrow", "Silk Spear" }, { "hasThreadSphere", "Thread Sphere" }, { "hasHarpoonDash", "prompt_hornet_silk_dash" }, { "hasSilkCharge", "Silk Charge" }, { "hasSilkBomb", "Silk Bomb" }, { "hasSilkBossNeedle", "Silk Boss Needle" }, { "hasNeedolin", "Needolin_Prompt" }, { "hasDash", "prompt_swiftstep" }, { "hasBrolly", "prompt_hornet_umbrella" }, { "hasDoubleJump", "Hornet_Double_Jump_Prompt" }, { "hasChargeSlash", "charge_dash_slash" }, { "hasSuperJump", "prompt_super_jump" }, { "hasWallJump", "Wall_Jump_Prompt" } }; private static readonly Dictionary FallbackKeywords = new Dictionary { { "hasNeedleThrow", new string[5] { "Silk Spear", "SilkSpear", "NeedleThrow", "needle", "spear" } }, { "hasThreadSphere", new string[6] { "Thread Storm", "ThreadStorm", "ThreadSphere", "thread", "storm", "sphere" } }, { "hasHarpoonDash", new string[5] { "Clawline", "Harpoon Dash", "HarpoonDash", "harpoon", "dash" } }, { "hasSilkCharge", new string[5] { "Sharpdart", "Silk Charge", "SilkCharge", "sharpdart", "silk charge" } }, { "hasSilkBomb", new string[7] { "Rune Rage", "RuneRage", "Silk Bomb", "SilkBomb", "rune", "rage", "silk bomb" } }, { "hasSilkBossNeedle", new string[8] { "Pale Nails", "PaleNails", "Silk Boss Needle", "SilkBossNeedle", "pale", "nail", "needle", "boss" } }, { "hasNeedolin", new string[2] { "Needolin", "needolin" } }, { "hasDash", new string[6] { "Swift Step", "SwiftStep", "Dash", "dash", "swift", "step" } }, { "hasBrolly", new string[8] { "Drifter's Cloak", "DriftersCloak", "Drifter", "Brolly", "Umbrella", "brolly", "drifter", "cloak" } }, { "hasDoubleJump", new string[7] { "Faydown Cloak", "FaydownCloak", "Double Jump", "DoubleJump", "faydown", "double", "jump" } }, { "hasChargeSlash", new string[7] { "Needle Strike", "NeedleStrike", "Charge Slash", "ChargeSlash", "needle strike", "charge", "slash" } }, { "hasSuperJump", new string[7] { "Silk Soar", "SilkSoar", "Super Jump", "SuperJump", "silk soar", "super", "jump" } }, { "hasWallJump", new string[8] { "Cling Grip", "ClingGrip", "Wall Jump", "WallJump", "cling", "grip", "wall", "jump" } } }; public static void SetSeed(int seed) { _seed = seed; _rng = ((seed == 0) ? new Random() : new Random(seed)); _cacheBuilt = false; } private static void BuildIconCache() { if (_cacheBuilt) { return; } _cacheBuilt = true; _icons.Clear(); SavedItem[] source = Resources.FindObjectsOfTypeAll(); Sprite[] source2 = Resources.FindObjectsOfTypeAll(); foreach (string allField in AllFields) { bool flag = false; if (BestPickNames.TryGetValue(allField, out var bestName)) { SavedItem val = ((IEnumerable)source).FirstOrDefault((Func)((SavedItem i) => Object.op_Implicit((Object)(object)i) && string.Equals(((Object)i).name, bestName, StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val != (Object)null) { try { Sprite popupIcon = val.GetPopupIcon(); if (Object.op_Implicit((Object)(object)popupIcon)) { _icons[allField] = popupIcon; flag = true; } } catch { } } if (!flag) { Sprite val2 = ((IEnumerable)source2).FirstOrDefault((Func)((Sprite s) => Object.op_Implicit((Object)(object)s) && string.Equals(((Object)s).name, bestName, StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val2 != (Object)null) { _icons[allField] = val2; flag = true; } } } if (!flag && FallbackKeywords.TryGetValue(allField, out var keywords)) { SavedItem val3 = ((IEnumerable)source).FirstOrDefault((Func)((SavedItem i) => Object.op_Implicit((Object)(object)i) && !string.IsNullOrEmpty(((Object)i).name) && keywords.Any((string k) => ((Object)i).name.ToLower().Contains(k.ToLower())))); if ((Object)(object)val3 != (Object)null) { try { Sprite popupIcon2 = val3.GetPopupIcon(); if (Object.op_Implicit((Object)(object)popupIcon2)) { _icons[allField] = popupIcon2; flag = true; } } catch { } } if (!flag) { Sprite val4 = ((IEnumerable)source2).FirstOrDefault((Func)((Sprite s) => Object.op_Implicit((Object)(object)s) && !string.IsNullOrEmpty(((Object)s).name) && keywords.Any((string k) => ((Object)s).name.ToLower().Contains(k.ToLower())))); if ((Object)(object)val4 != (Object)null) { _icons[allField] = val4; flag = true; } } } if (!flag) { Plugin.Log.LogWarning((object)("✗ " + allField + " 未找到图标")); } } if (!((Object)(object)_fallback == (Object)null)) { return; } SavedItem val5 = ((IEnumerable)source).FirstOrDefault((Func)((SavedItem i) => Object.op_Implicit((Object)(object)i) && ((Object)i).name.Contains("Rosary"))); if (Object.op_Implicit((Object)(object)val5)) { try { _fallback = val5.GetPopupIcon(); } catch { } } if ((Object)(object)_fallback == (Object)null) { _fallback = ((IEnumerable)source2).FirstOrDefault((Func)((Sprite s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name.Contains("Rosary"))); } } private static Sprite GetIcon(string field) { BuildIconCache(); if (!_icons.TryGetValue(field, out var value)) { return _fallback; } return value; } public static void GiveRandomSkill() { try { PlayerData instance = PlayerData.instance; if (instance == null) { return; } List list = new List(); foreach (string allField in AllFields) { FieldInfo field = typeof(PlayerData).GetField(allField, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(bool) && !(bool)field.GetValue(instance)) { list.Add(allField); } } if (list.Count == 0) { GiveWallJump(); } else { SkillRandomizer.GiveSkill(list[(_rng ?? (_rng = new Random())).Next(list.Count)]); } } catch (Exception arg) { Plugin.Log.LogError((object)$"GiveRandomSkill 异常: {arg}"); } } public static void GiveWallJump() { try { string text = "hasWallJump"; PlayerData instance = PlayerData.instance; FieldInfo field = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (!(field == null) && !(bool)field.GetValue(instance)) { SkillRandomizer.GiveSkill(text); } } catch (Exception arg) { Plugin.Log.LogError((object)$"GiveWallJump 异常: {arg}"); } } public static void GiveHarpoonDash() { try { string text = "hasHarpoonDash"; PlayerData instance = PlayerData.instance; FieldInfo field = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public); if (!(field == null) && !(bool)field.GetValue(instance)) { SkillRandomizer.GiveSkill(text); } } catch (Exception arg) { Plugin.Log.LogError((object)$"GiveHarpoonDash 异常: {arg}"); } } } }