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 SorceryRedux v1.0.0
SorceryRedux.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.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 SorceryRedux { internal sealed class SE_Haste : StatusEffect { private const float GreenHue = 0.33f; public float m_speedBonus; public override void Setup(Character character) { ((StatusEffect)this).Setup(character); ShieldTint.Apply(base.m_startEffectInstances, 1f, 0.33f); } public override void ResetTime() { ((StatusEffect)this).ResetTime(); ((StatusEffect)this).TriggerStartEffects(); ShieldTint.Apply(base.m_startEffectInstances, 1f, 0.33f); } public override void ModifySpeed(float baseSpeed, ref float speed, Character character, Vector3 dir) { speed += baseSpeed * m_speedBonus; } } internal sealed class HasteSpell : StatusSpell { private const string SoundResource = "haste_cast.wav"; internal ConfigEntry<float> SpeedBonus; internal ConfigEntry<float> SoundVolume; internal string MeadItem; private AudioClip _clip; internal override void Cast(Player player, Spell spell) { PlaySound(player); base.Cast(player, spell); } protected override StatusEffect CreateEffect(ObjectDB db) { SE_Haste sE_Haste = ScriptableObject.CreateInstance<SE_Haste>(); sE_Haste.m_speedBonus = SpeedBonus.Value; StatusEffect val = StatusSpell.ConsumeEffectOf(db, MeadItem); if ((Object)(object)val != (Object)null) { ((StatusEffect)sE_Haste).m_startEffects = val.m_startEffects; ((StatusEffect)sE_Haste).m_effectsOnlyOnPlayer = val.m_effectsOnlyOnPlayer; } return (StatusEffect)(object)sE_Haste; } private void PlaySound(Player player) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown if ((Object)(object)_clip == (Object)null) { _clip = LoadClip(); } if (!((Object)(object)_clip == (Object)null)) { GameObject val = new GameObject("SorceryRedux_HasteSound"); val.transform.SetParent(((Component)player).transform, false); val.transform.localPosition = Vector3.up; AudioSource obj = val.AddComponent<AudioSource>(); obj.clip = _clip; obj.spatialBlend = 1f; obj.minDistance = 5f; obj.maxDistance = 50f; obj.volume = SoundVolume.Value * AudioMan.GetSFXVolume(); obj.Play(); Object.Destroy((Object)val, _clip.length + 0.5f); } } private static AudioClip LoadClip() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("haste_cast.wav"); using BinaryReader binaryReader = new BinaryReader(stream); binaryReader.ReadBytes(12); int num = 0; int num2 = 0; int num3 = 0; byte[] array = null; while (stream.Position + 8 <= stream.Length) { string text = Encoding.ASCII.GetString(binaryReader.ReadBytes(4)); int num4 = binaryReader.ReadInt32(); if (text == "fmt ") { binaryReader.ReadInt16(); num = binaryReader.ReadInt16(); num2 = binaryReader.ReadInt32(); binaryReader.ReadInt32(); binaryReader.ReadInt16(); num3 = binaryReader.ReadInt16(); binaryReader.ReadBytes(num4 - 16); } else { if (text == "data") { array = binaryReader.ReadBytes(num4); break; } binaryReader.ReadBytes(num4 + (num4 & 1)); } } if (array == null || num3 != 16 || num < 1) { Plugin.Log.LogWarning((object)"Haste sound could not be loaded (needs 16-bit PCM wav)."); return null; } float[] array2 = new float[array.Length / 2]; for (int i = 0; i < array2.Length; i++) { array2[i] = (float)BitConverter.ToInt16(array, i * 2) / 32768f; } AudioClip val = AudioClip.Create("SorceryRedux_Haste", array2.Length / num, num, num2, false); typeof(AudioClip).GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) }).Invoke(val, new object[2] { array2, 0 }); return val; } } internal sealed class SE_SpellHeal : StatusEffect { public float m_healPerTick; public int m_ticks; internal Spell Spell; private int _done; private bool _awardedSkill; public override void Setup(Character character) { ((StatusEffect)this).Setup(character); _done = 0; _awardedSkill = false; } public override void ResetTime() { ((StatusEffect)this).ResetTime(); _done = 0; _awardedSkill = false; ((StatusEffect)this).TriggerStartEffects(); } public override void UpdateStatusEffect(float dt) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) ((StatusEffect)this).UpdateStatusEffect(dt); while (_done < m_ticks && base.m_time >= (float)(_done + 1)) { float health = base.m_character.GetHealth(); base.m_character.Heal(m_healPerTick, true); if (!_awardedSkill && base.m_character.GetHealth() > health) { _awardedSkill = true; if ((Object)(object)base.m_character == (Object)(object)Player.m_localPlayer) { ((Character)Player.m_localPlayer).RaiseSkill(Spell.Skill, Spell.SkillGain.Value); } } _done++; } } public override bool IsDone() { if (_done >= m_ticks) { return ((StatusEffect)this).IsDone(); } return false; } } internal sealed class HealSpell : StatusSpell { internal ConfigEntry<float> HealPerSecond; internal string MeadItem; internal override void Cast(Player player, Spell spell) { ((Character)player).GetSEMan().AddStatusEffect(base.EffectHash, true, 0, 0f, (short)(-1)); } protected override StatusEffect CreateEffect(ObjectDB db) { SE_SpellHeal sE_SpellHeal = ScriptableObject.CreateInstance<SE_SpellHeal>(); sE_SpellHeal.Spell = Spell; sE_SpellHeal.m_healPerTick = HealPerSecond.Value; sE_SpellHeal.m_ticks = Mathf.Max(1, Mathf.RoundToInt(Spell.DurationSeconds.Value)); StatusEffect val = StatusSpell.ConsumeEffectOf(db, MeadItem); if ((Object)(object)val != (Object)null) { ((StatusEffect)sE_SpellHeal).m_startEffects = val.m_startEffects; ((StatusEffect)sE_SpellHeal).m_effectsOnlyOnPlayer = val.m_effectsOnlyOnPlayer; } return (StatusEffect)(object)sE_SpellHeal; } } internal static class ShieldTint { private const float BlueHue = 0.6f; private static readonly string[] AlphaProperties = new string[3] { "_Color", "_TintColor", "_BaseColor" }; private static readonly string[] GlowProperties = new string[3] { "_EmissionColor", "_FresnelColor", "_RimColor" }; private static bool _loggedShaders; private static float _hue = 0.6f; internal static void Apply(GameObject[] objects, float opacity = 1f, float hue = 0.6f) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) _hue = hue; if (objects == null) { return; } foreach (GameObject val in objects) { if ((Object)(object)val == (Object)null) { continue; } ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem obj in componentsInChildren) { MainModule main = obj.main; ((MainModule)(ref main)).startColor = Tint(((MainModule)(ref main)).startColor, opacity); ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = Tint(((ColorOverLifetimeModule)(ref colorOverLifetime)).color, opacity); } } Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { Material[] materials = componentsInChildren2[j].materials; foreach (Material val2 in materials) { LogShader(val2); string[] alphaProperties = AlphaProperties; foreach (string text in alphaProperties) { if (val2.HasProperty(text)) { val2.SetColor(text, Tint(val2.GetColor(text), opacity)); } } alphaProperties = GlowProperties; foreach (string text2 in alphaProperties) { if (val2.HasProperty(text2)) { Color val3 = Tint(val2.GetColor(text2), 1f); val2.SetColor(text2, new Color(val3.r * opacity, val3.g * opacity, val3.b * opacity, val3.a)); } } } } Light[] componentsInChildren3 = val.GetComponentsInChildren<Light>(true); foreach (Light obj2 in componentsInChildren3) { obj2.color = Tint(obj2.color, 1f); obj2.intensity *= opacity; } } } private static void LogShader(Material material) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (!_loggedShaders && !((Object)(object)material.shader == (Object)null)) { _loggedShaders = true; Shader shader = material.shader; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < shader.GetPropertyCount(); i++) { stringBuilder.Append(shader.GetPropertyName(i)).Append(" (").Append(shader.GetPropertyType(i)) .Append("), "); } Plugin.Log.LogInfo((object)("Bubble material " + ((Object)material).name + " uses shader " + ((Object)shader).name + ": " + stringBuilder)); } } private static Color Tint(Color color, float opacity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(color, ref num, ref num2, ref num3); Color result = Color.HSVToRGB(_hue, Mathf.Max(num2, 0.55f), num3, true); result.a = color.a * opacity; return result; } private static Gradient Tint(Gradient gradient, float opacity) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown GradientColorKey[] colorKeys = gradient.colorKeys; for (int i = 0; i < colorKeys.Length; i++) { colorKeys[i].color = Tint(colorKeys[i].color, 1f); } GradientAlphaKey[] alphaKeys = gradient.alphaKeys; for (int j = 0; j < alphaKeys.Length; j++) { alphaKeys[j].alpha *= opacity; } Gradient val = new Gradient(); val.SetKeys(colorKeys, alphaKeys); return val; } private static MinMaxGradient Tint(MinMaxGradient source, float opacity) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0029: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref source)).mode; switch ((int)mode) { case 0: return new MinMaxGradient(Tint(((MinMaxGradient)(ref source)).color, opacity)); case 2: return new MinMaxGradient(Tint(((MinMaxGradient)(ref source)).colorMin, opacity), Tint(((MinMaxGradient)(ref source)).colorMax, opacity)); case 1: return new MinMaxGradient(Tint(((MinMaxGradient)(ref source)).gradient, opacity)); case 3: return new MinMaxGradient(Tint(((MinMaxGradient)(ref source)).gradientMin, opacity), Tint(((MinMaxGradient)(ref source)).gradientMax, opacity)); case 4: { MinMaxGradient result = default(MinMaxGradient); ((MinMaxGradient)(ref result))..ctor(Tint(((MinMaxGradient)(ref source)).gradient, opacity)); ((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4; return result; } default: return source; } } } internal sealed class SE_MagicShield : StatusEffect { public EffectList m_hitEffects = new EffectList(); public EffectList m_breakEffects = new EffectList(); private GameObject _fallbackBubble; public override void Setup(Character character) { ((StatusEffect)this).Setup(character); ShieldTint.Apply(base.m_startEffectInstances, 0.05f); if (base.m_startEffectInstances == null || base.m_startEffectInstances.Length == 0) { _fallbackBubble = CreateFallbackBubble(); } } public override void Stop() { //IL_001a: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.m_character != (Object)null) { ShieldTint.Apply(m_breakEffects.Create(base.m_character.GetCenterPoint(), ((Component)base.m_character).transform.rotation, ((Component)base.m_character).transform, base.m_character.GetRadius() * 2f, -1, default(ZDOID))); } if ((Object)(object)_fallbackBubble != (Object)null) { Object.Destroy((Object)(object)_fallbackBubble); } ((StatusEffect)this).Stop(); } internal void OnAbsorb(HitData hit) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Quaternion val = ((((Vector3)(ref hit.m_dir)).sqrMagnitude > 0.0001f) ? Quaternion.LookRotation(-hit.m_dir) : Quaternion.identity); ShieldTint.Apply(m_hitEffects.Create(hit.m_point, val, ((Component)base.m_character).transform, 1f, -1, default(ZDOID))); } private GameObject CreateFallbackBubble() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00b3: 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) Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null || (Object)(object)base.m_character == (Object)null) { return null; } GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = "MagicShieldBubble"; Component component = obj.GetComponent("Collider"); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent<Renderer>(); component2.material = new Material(val) { color = new Color(0.3f, 0.55f, 1f, 0.2f) }; component2.shadowCastingMode = (ShadowCastingMode)0; obj.transform.SetParent(((Component)base.m_character).transform, false); obj.transform.localPosition = new Vector3(0f, 1f, 0f); obj.transform.localScale = new Vector3(2.4f, 2.4f, 2.4f); return obj; } } internal sealed class ShieldSpell : StatusSpell { internal static ShieldSpell Instance; internal ConfigEntry<float> EitrPerDamageAtRequired; internal ConfigEntry<float> EitrPerDamageAtMax; internal const float BubbleOpacity = 0.05f; private const float BubbleDelay = 1.5f; private EffectList[] _castEffects; internal override void Cast(Player player, Spell spell) { //IL_0017: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (_castEffects != null) { EffectList[] castEffects = _castEffects; for (int i = 0; i < castEffects.Length; i++) { ShieldTint.Apply(castEffects[i].Create(((Character)player).GetCenterPoint(), ((Component)player).transform.rotation, ((Component)player).transform, 1f, -1, default(ZDOID)), 0.05f); } } ((MonoBehaviour)Plugin.Instance).StartCoroutine(AddAfterDelay(player)); } private IEnumerator AddAfterDelay(Player player) { yield return (object)new WaitForSeconds(1.5f); if ((Object)(object)player != (Object)null && !((Character)player).IsDead()) { base.Cast(player, Spell); } } internal float EitrPerDamage(Player player) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.InverseLerp(Spell.MinSkillLevel.Value, 100f, ((Character)player).GetSkillLevel(Spell.Skill)); float num2 = Mathf.Max(0.01f, EitrPerDamageAtRequired.Value); float num3 = Mathf.Max(0.01f, EitrPerDamageAtMax.Value); return num2 * Mathf.Pow(num3 / num2, num); } protected override StatusEffect CreateEffect(ObjectDB db) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) SE_MagicShield sE_MagicShield = ScriptableObject.CreateInstance<SE_MagicShield>(); ((StatusEffect)sE_MagicShield).m_stopMessageType = (MessageType)2; ((StatusEffect)sE_MagicShield).m_stopMessage = "Arcane Cloak has ended"; GameObject itemPrefab = db.GetItemPrefab("StaffShield"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null) { SharedData shared = val.m_itemData.m_shared; _castEffects = (EffectList[])(object)new EffectList[3] { shared.m_triggerEffect, shared.m_attack.m_startEffect, shared.m_attack.m_triggerEffect }; Plugin.Log.LogInfo((object)("Staff cast effects: " + shared.m_triggerEffect.m_effectPrefabs.Length + " trigger, " + shared.m_attack.m_startEffect.m_effectPrefabs.Length + " attack start, " + shared.m_attack.m_triggerEffect.m_effectPrefabs.Length + " attack trigger")); } StatusEffect val2 = StatusSpell.ConsumeEffectOf(db, "StaffShield"); foreach (StatusEffect statusEffect in db.m_StatusEffects) { SE_Shield val3 = (SE_Shield)(object)((statusEffect is SE_Shield) ? statusEffect : null); if (val3 != null) { Plugin.Log.LogInfo((object)("Shield effect " + ((Object)statusEffect).name + ": " + ((StatusEffect)val3).m_startEffects.m_effectPrefabs.Length + " start, " + val3.m_hitEffects.m_effectPrefabs.Length + " hit, " + val3.m_breakEffects.m_effectPrefabs.Length + " break effects")); if (((Object)(object)val2 == (Object)null || val2.m_startEffects.m_effectPrefabs.Length == 0) && ((StatusEffect)val3).m_startEffects.m_effectPrefabs.Length != 0) { val2 = statusEffect; } } } Plugin.Log.LogInfo((object)("Magic Shield borrows effects from: " + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "nothing, using the fallback bubble"))); if ((Object)(object)val2 != (Object)null) { ((StatusEffect)sE_MagicShield).m_startEffects = val2.m_startEffects; ((StatusEffect)sE_MagicShield).m_effectsOnlyOnPlayer = val2.m_effectsOnlyOnPlayer; SE_Shield val4 = (SE_Shield)(object)((val2 is SE_Shield) ? val2 : null); if ((Object)(object)val4 != (Object)null) { sE_MagicShield.m_hitEffects = val4.m_hitEffects; sE_MagicShield.m_breakEffects = val4.m_breakEffects; } } return (StatusEffect)(object)sE_MagicShield; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] internal static class MagicShieldPatch { private static void Prefix(Character __instance, HitData hit) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || ShieldSpell.Instance == null || !((Character)val).GetSEMan().HaveStatusEffect(ShieldSpell.Instance.EffectHash)) { return; } float totalDamage = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage(); float eitr = val.GetEitr(); if (!(totalDamage <= 0f) && !(eitr <= 0f)) { float num = Mathf.Max(0.01f, ShieldSpell.Instance.EitrPerDamage(val)); float num2 = Mathf.Min(totalDamage, eitr / num); float num3 = num2 * num; ((Character)val).UseEitr(num3); ((DamageTypes)(ref hit.m_damage)).Modify((totalDamage - num2) / totalDamage); (((Character)val).GetSEMan().GetStatusEffect(ShieldSpell.Instance.EffectHash) as SE_MagicShield)?.OnAbsorb(hit); if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.EitrBarEmptyFlash(); } if (num3 >= eitr - 0.01f) { ((Character)val).GetSEMan().RemoveStatusEffect(ShieldSpell.Instance.EffectHash, false); } } } } internal sealed class LightSpell : StatusSpell { private const string EndKey = "rainb_LightEnd"; private const string KindKey = "rainb_LightKind"; internal static readonly List<LightSpell> All = new List<LightSpell>(); internal static ConfigEntry<float> LightHeight; internal string[] Prefabs; internal Color FallbackColor = new Color(1f, 0.65f, 0.3f); internal ConfigEntry<float> RangeMultiplier; protected override bool IsActiveForSkillGain(Player player) { foreach (LightSpell item in All) { if (((Character)player).GetSEMan().HaveStatusEffect(item.EffectHash)) { return true; } } return false; } internal override void Cast(Player player, Spell spell) { SEMan sEMan = ((Character)player).GetSEMan(); base.Cast(player, spell); foreach (LightSpell item in All) { if (item != this) { sEMan.RemoveStatusEffect(item.EffectHash, true); } } SetActive(((Component)player).GetComponent<ZNetView>(), spell.DurationSeconds.Value); } private void SetActive(ZNetView nview, float secondsFromNow) { if ((Object)(object)nview != (Object)null && nview.IsValid() && (Object)(object)ZNet.instance != (Object)null) { ZDO zDO = nview.GetZDO(); zDO.Set("rainb_LightKind", base.EffectHash); zDO.Set("rainb_LightEnd", (long)((ZNet.instance.GetTimeSeconds() + (double)secondsFromNow) * 1000.0)); } } internal static LightSpell GetActive(Player player, ZNetView nview) { if ((Object)(object)nview == (Object)null || !nview.IsValid() || (Object)(object)ZNet.instance == (Object)null) { return null; } ZDO zDO = nview.GetZDO(); if (ZNet.instance.GetTimeSeconds() * 1000.0 < (double)zDO.GetLong("rainb_LightEnd", 0L)) { int num = zDO.GetInt("rainb_LightKind", 0); foreach (LightSpell item in All) { if (item.EffectHash == num) { return item; } } } if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { foreach (LightSpell item2 in All) { StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(item2.EffectHash); if ((Object)(object)statusEffect != (Object)null) { item2.SetActive(nview, statusEffect.GetRemaningTime()); return item2; } } } return null; } private static Light FindLight(string[] prefabs) { foreach (string text in prefabs) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(text) : null); if ((Object)(object)val == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { val = ObjectDB.instance.GetItemPrefab(text); } Light val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<Light>(true) : null); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } internal GameObject CreateLight(Transform parent) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) Light val = FindLight(Prefabs); GameObject val2; if ((Object)(object)val != (Object)null) { val2 = Object.Instantiate<GameObject>(((Component)val).gameObject); ((Object)val2).name = EffectName + "Light"; StripVisuals(val2); LightFlicker[] componentsInChildren = val2.GetComponentsInChildren<LightFlicker>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].m_fadeInDuration = 0.6f; } val2.SetActive(true); } else { val2 = new GameObject(EffectName + "Light"); Light obj = val2.AddComponent<Light>(); obj.type = (LightType)2; obj.color = FallbackColor; obj.range = 12f; obj.intensity = 1.6f; obj.shadows = (LightShadows)0; } if (RangeMultiplier != null) { Light val3 = FindLight(All[0].Prefabs); Light componentInChildren = val2.GetComponentInChildren<Light>(true); if ((Object)(object)val3 != (Object)null && (Object)(object)componentInChildren != (Object)null) { componentInChildren.range = val3.range * RangeMultiplier.Value; } } val2.transform.SetParent(parent, false); val2.transform.localPosition = new Vector3(0f, LightHeight.Value, 0f); val2.transform.localRotation = Quaternion.identity; return val2; } private static void StripVisuals(GameObject root) { ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { if ((Object)(object)((Component)val).GetComponentInChildren<Light>(true) == (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } else { val.Stop(true, (ParticleSystemStopBehavior)0); } } } Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } AudioSource[] componentsInChildren3 = root.GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { ((Behaviour)componentsInChildren3[i]).enabled = false; } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDBAwakePatch { private static void Postfix(ObjectDB __instance) { StatusSpell.RegisterEffects(__instance); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class ObjectDBCopyPatch { private static void Postfix(ObjectDB __instance) { StatusSpell.RegisterEffects(__instance); } } internal sealed class PlayerLight : MonoBehaviour { private Player _player; private ZNetView _nview; private LightSpell _current; private GameObject _light; private void Awake() { _player = ((Component)this).GetComponent<Player>(); } private void Update() { if ((Object)(object)_nview == (Object)null) { _nview = ((Component)this).GetComponent<ZNetView>(); } LightSpell active = LightSpell.GetActive(_player, _nview); if (active != _current || (active != null && !((Object)(object)_light != (Object)null))) { if ((Object)(object)_light != (Object)null) { LightFader.FadeOutAndDestroy(_light, 1.5f); _light = null; } _current = active; if (active != null) { _light = active.CreateLight(((Component)this).transform); } } } private void OnDestroy() { if ((Object)(object)_light != (Object)null) { Object.Destroy((Object)(object)_light); } } } internal sealed class LightFader : MonoBehaviour { private Light[] _lights; private float[] _start; private float _elapsed; private float _duration; internal static void FadeOutAndDestroy(GameObject go, float duration) { LightFlicker[] componentsInChildren = go.GetComponentsInChildren<LightFlicker>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } LightFader lightFader = go.AddComponent<LightFader>(); lightFader._duration = duration; lightFader._lights = go.GetComponentsInChildren<Light>(true); lightFader._start = new float[lightFader._lights.Length]; for (int j = 0; j < lightFader._lights.Length; j++) { lightFader._start[j] = lightFader._lights[j].intensity; } } private void Update() { _elapsed += Time.deltaTime; float num = 1f - Mathf.Clamp01(_elapsed / _duration); for (int i = 0; i < _lights.Length; i++) { if ((Object)(object)_lights[i] != (Object)null) { _lights[i].intensity = _start[i] * num; } } if (_elapsed >= _duration) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } [HarmonyPatch(typeof(Player), "Awake")] internal static class PlayerAwakePatch { private static void Postfix(Player __instance) { ((Component)__instance).gameObject.AddComponent<PlayerLight>(); } } [HarmonyPatch(typeof(Player), "Update")] internal static class PlayerUpdatePatch { private static readonly MethodInfo TakeInput = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); private static Player _checkedPlayer; private static float _checkAt; private static void Postfix(Player __instance) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if ((Object)(object)_checkedPlayer != (Object)(object)__instance) { _checkedPlayer = __instance; _checkAt = Time.time + 5f; } else if (_checkAt > 0f && Time.time >= _checkAt) { _checkAt = 0f; SpellBook.CheckNewSpells(__instance, playEffect: true); } foreach (Spell item in Spells.All) { if (Plugin.HotkeysEnabled.Value) { KeyboardShortcut value = item.Hotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && (bool)TakeInput.Invoke(__instance, null)) { Spells.Cast(__instance, item, Plugin.SayWords.Value); } } } } } [HarmonyPatch(typeof(Chat), "InputText")] internal static class ChatInputPatch { private static void Prefix(Chat __instance) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead()) { Spell spell = Spells.Find(((TMP_InputField)((Terminal)__instance).m_input).text); if (spell != null) { Spells.Cast(localPlayer, spell, sayWords: false); } } } } [BepInPlugin("rainb.SorceryRedux", "Sorcery Redux", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "rainb.SorceryRedux"; public const string Name = "Sorcery Redux"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static Plugin Instance; internal static ConfigEntry<bool> HotkeysEnabled; internal static ConfigEntry<bool> SayWords; private void Awake() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Instance = this; HotkeysEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable hotkeys", true, "Cast spells with their hotkeys. Turn this off to cast only by typing the spell words in chat."); SayWords = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Say words on hotkey cast", true, "When you cast with a hotkey, also say the spell's words so everyone nearby sees what you are casting. Spells typed in chat always show them."); Spells.Register(((BaseUnityPlugin)this).Config); new Harmony("rainb.SorceryRedux").PatchAll(); } } internal static class SpellBook { private const string LearnedKey = "SorceryRedux_Learned"; internal static bool IsLearned(Player player, Spell spell) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return ((Character)player).GetSkillLevel(spell.Skill) >= spell.MinSkillLevel.Value; } internal static void CheckNewSpells(Player player, bool playEffect = false) { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) HashSet<string> hashSet = new HashSet<string>(); if (player.m_customData.TryGetValue("SorceryRedux_Learned", out var value)) { hashSet.UnionWith(value.Split(new char[1] { '|' })); } StringBuilder stringBuilder = new StringBuilder(); foreach (Spell item in Spells.All) { if (!hashSet.Contains(item.Name) && IsLearned(player, item)) { hashSet.Add(item.Name); stringBuilder.Append('\n').Append(item.Name).Append(": ") .Append(item.Words); } } if (stringBuilder.Length > 0) { player.m_customData["SorceryRedux_Learned"] = string.Join("|", hashSet); ((Character)player).Message((MessageType)2, "You have learned a new spell!" + stringBuilder, 0, (Sprite)null, false); if (playEffect) { player.m_skillLevelupEffects.Create(((Component)player).transform.position, Quaternion.identity, ((Component)player).transform, 1f, -1, default(ZDOID)); } } } internal static string Overview(Player player) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) StringBuilder stringBuilder = new StringBuilder(); foreach (Spell item in Spells.All) { if (IsLearned(player, item)) { StringBuilder stringBuilder2 = stringBuilder.Append("<color=orange>").Append(item.Name).Append("</color> ") .Append(item.Words) .Append(" ["); KeyboardShortcut value = item.Hotkey.Value; stringBuilder2.Append(((KeyboardShortcut)(ref value)).MainKey).Append("]\n"); } else { stringBuilder.Append("??? requires ").Append(SkillName(item)).Append(' ') .Append(Mathf.CeilToInt(item.MinSkillLevel.Value)) .Append('\n'); } } return stringBuilder.ToString(); } internal static string Details(Spell spell) { //IL_0034: 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_003c: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("<color=orange>Words:</color> ").Append(spell.Words).Append('\n'); StringBuilder stringBuilder2 = stringBuilder.Append("<color=orange>Hotkey:</color> "); KeyboardShortcut value = spell.Hotkey.Value; stringBuilder2.Append(((KeyboardShortcut)(ref value)).MainKey).Append('\n'); stringBuilder.Append("<color=orange>Requires:</color> ").Append(SkillName(spell)).Append(' ') .Append(Mathf.CeilToInt(spell.MinSkillLevel.Value)) .Append('\n'); stringBuilder.Append("<color=orange>Eitr cost:</color> ").Append(spell.EitrCost.Value.ToString("0.##")).Append('\n'); stringBuilder.Append("<color=orange>Duration:</color> ").Append(Duration(spell.DurationSeconds.Value)).Append("\n\n"); stringBuilder.Append(spell.Description); return stringBuilder.ToString(); } private static string SkillName(Spell spell) { return "$skill_" + ((object)Unsafe.As<SkillType, SkillType>(ref spell.Skill)/*cast due to .constrained prefix*/).ToString().ToLower(); } private static string Duration(float seconds) { int num = Mathf.RoundToInt(seconds); if (num < 60) { return num + " s"; } return num / 60 + " min " + num % 60 + " s"; } } [HarmonyPatch(typeof(Player), "OnSkillLevelup")] internal static class SkillLevelupPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { SpellBook.CheckNewSpells(__instance); } } } [HarmonyPatch(typeof(TextsDialog), "UpdateTextsList")] internal static class SpellBookDialogPatch { private static readonly FieldInfo TextsField = AccessTools.Field(typeof(TextsDialog), "m_texts"); private static void Postfix(TextsDialog __instance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } List<TextInfo> list = (List<TextInfo>)TextsField.GetValue(__instance); list.Add(new TextInfo("Spellbook", SpellBook.Overview(localPlayer))); foreach (Spell item in Spells.All) { if (SpellBook.IsLearned(localPlayer, item)) { list.Add(new TextInfo("Spell: " + item.Name, SpellBook.Details(item))); } } } } internal sealed class Spell { public string Name; public string Words; public string Description; public SkillType Skill; public Action<Player, Spell> Effect; public ConfigEntry<KeyboardShortcut> Hotkey; public ConfigEntry<float> EitrCost; public ConfigEntry<float> MinSkillLevel; public ConfigEntry<float> SkillGain; public ConfigEntry<float> DurationSeconds; } internal static class Spells { internal static readonly List<Spell> All = new List<Spell>(); internal static void Register(ConfigFile config) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_012a: Expected O, but got Unknown //IL_014e: 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_01a8: Expected O, but got Unknown //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Expected O, but got Unknown //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Expected O, but got Unknown AddLight(config, new Spell { Name = "Light", Words = "ljos", Skill = (SkillType)9, Description = "Surrounds you with the light of a standing wood torch. Recasting refreshes the timer." }, new LightSpell { EffectName = "SorceryRedux_Light", Title = "Light", Tooltip = "A magical light shines around you.", IconResource = "light_icon.png", Prefabs = new string[2] { "piece_groundtorch_wood", "Torch" } }, (KeyCode)118, 20f, 0f, 370f); LightSpell lightSpell = new LightSpell(); lightSpell.EffectName = "SorceryRedux_GreatLight"; lightSpell.Title = "Great Light"; lightSpell.Tooltip = "A great magical light shines around you."; lightSpell.IconResource = "greatlight_icon.png"; lightSpell.Prefabs = new string[1] { "piece_groundtorch_blue" }; lightSpell.FallbackColor = new Color(0.4f, 0.6f, 1f); LightSpell lightSpell2 = lightSpell; lightSpell2.RangeMultiplier = config.Bind<float>("Great Light", "Light range multiplier", 1.3333f, new ConfigDescription("Light range relative to the Light spell's light range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); AddLight(config, new Spell { Name = "Great Light", Words = "ljos mikil", Skill = (SkillType)9, Description = "Surrounds you with a wider blue light, like a standing blue-burning iron torch. Replaces Light while active." }, lightSpell2, (KeyCode)98, 40f, 13f, 695f); LightSpell.LightHeight = config.Bind<float>("Light", "Light height", 2.5f, new ConfigDescription("Height of the light spells' light above the ground, in metres. Keep it above your head so it doesn't clip into your model (a player is about 1.8 m tall).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); AddHeal(config, "Light Healing", "heil", "SorceryRedux_LightHealing", "lighthealing_icon.png", "MeadHealthMinor", (KeyCode)104, 20f, 8f, 4f, 10f); AddHeal(config, "Intense Healing", "heil mikil", "SorceryRedux_IntenseHealing", "intensehealing_icon.png", "MeadHealthMedium", (KeyCode)106, 70f, 20f, 4f, 30f); HasteSpell hasteSpell = new HasteSpell { EffectName = "SorceryRedux_Haste", Title = "Haste", Tooltip = "You move faster.", IconResource = "haste_icon.png", MeadItem = "MeadHealthMinor" }; hasteSpell.SpeedBonus = config.Bind<float>("Haste", "Speed bonus", 0.3f, new ConfigDescription("Extra movement speed as a fraction: 0.3 is 30% faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); hasteSpell.SoundVolume = config.Bind<float>("Haste", "Sound volume", 0.8f, new ConfigDescription("Volume of the cast sound, on top of the game's sound effects volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); AddStatus(config, new Spell { Name = "Haste", Words = "hradr", Skill = (SkillType)9, Description = "Makes you move " + (hasteSpell.SpeedBonus.Value * 100f).ToString("0.##") + "% faster for the duration." }, hasteSpell, (KeyCode)107, 60f, 4f, 30f); ShieldSpell.Instance = new ShieldSpell { EffectName = "SorceryRedux_ArcaneCloak", Title = "Arcane Cloak", Tooltip = "Damage you take after armor is paid from Eitr first, then health. Ends when your Eitr runs out.", IconResource = "magicshield_icon.png" }; AddStatus(config, new Spell { Name = "Arcane Cloak", Words = "galdra kapa", Skill = (SkillType)9, Description = "Damage you take, after armor, is paid from Eitr first and only the rest hits your health. The Eitr cost per damage drops as your skill grows. Ends when your Eitr runs out." }, ShieldSpell.Instance, (KeyCode)110, 50f, 14f, 180f); ShieldSpell.Instance.EitrPerDamageAtRequired = config.Bind<float>("Arcane Cloak", "Eitr per damage at required level", 2f, new ConfigDescription("Eitr paid for each point of damage the cloak absorbs, at the required skill level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>())); ShieldSpell.Instance.EitrPerDamageAtMax = config.Bind<float>("Arcane Cloak", "Eitr per damage at level 100", 0.6f, new ConfigDescription("Eitr per point of damage at skill level 100. In between, the cost falls smoothly (exponentially), reaching about 1 at level 65 with the defaults.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>())); } private static void AddHeal(ConfigFile config, string name, string words, string effectName, string icon, string meadItem, KeyCode key, float eitrCost, float minSkill, float duration, float healPerSecond) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) HealSpell healSpell = new HealSpell { EffectName = effectName, Title = name, Tooltip = "Heals you over time.", IconResource = icon, MeadItem = meadItem }; healSpell.HealPerSecond = config.Bind<float>(name, "Heal per second", healPerSecond, new ConfigDescription("Health restored every second for the spell's duration.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); Spell spell = new Spell { Name = name, Words = words, Skill = (SkillType)9, Description = "Heals " + healSpell.HealPerSecond.Value.ToString("0.##") + " health every second for the duration, like a healing mead but with no cooldown." }; AddStatus(config, spell, healSpell, key, eitrCost, minSkill, duration); } private static void AddLight(ConfigFile config, Spell spell, LightSpell light, KeyCode key, float eitrCost, float minSkill, float duration) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) AddStatus(config, spell, light, key, eitrCost, minSkill, duration); LightSpell.All.Add(light); } private static void AddStatus(ConfigFile config, Spell spell, StatusSpell status, KeyCode key, float eitrCost, float minSkill, float duration) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) spell.Effect = status.Cast; status.Spell = Add(config, spell, key, eitrCost, minSkill, duration); StatusSpell.Registry.Add(status); } private static Spell Add(ConfigFile config, Spell spell, KeyCode key, float eitrCost, float minSkill, float duration) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown string name = spell.Name; spell.Hotkey = config.Bind<KeyboardShortcut>(name, "Hotkey", new KeyboardShortcut(key, Array.Empty<KeyCode>()), "Key that casts this spell. Typing the words in chat also casts it."); spell.EitrCost = config.Bind<float>(name, "Eitr cost", eitrCost, new ConfigDescription("Eitr spent per cast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>())); spell.MinSkillLevel = config.Bind<float>(name, "Required " + ((object)Unsafe.As<SkillType, SkillType>(ref spell.Skill)/*cast due to .constrained prefix*/).ToString() + " level", minSkill, new ConfigDescription("Minimum skill level needed to cast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); spell.SkillGain = config.Bind<float>(name, "Skill gain", (float)Math.Round(eitrCost / 60f, 2), new ConfigDescription("Skill training amount per qualifying cast, not whole skill levels. Buff refreshes give no gain; healing awards gain once when health is actually restored.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); spell.DurationSeconds = config.Bind<float>(name, "Duration seconds", duration, new ConfigDescription("How long the effect lasts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 7200f), Array.Empty<object>())); All.Add(spell); return spell; } internal static Spell Find(string text) { text = text.Trim(); foreach (Spell item in All) { if (string.Equals(text, item.Words, StringComparison.OrdinalIgnoreCase)) { return item; } } return null; } internal static bool Cast(Player player, Spell spell, bool sayWords) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (((Character)player).GetSkillLevel(spell.Skill) < spell.MinSkillLevel.Value) { ((Character)player).Message((MessageType)2, "You need " + ((object)Unsafe.As<SkillType, SkillType>(ref spell.Skill)/*cast due to .constrained prefix*/).ToString() + " level " + Mathf.CeilToInt(spell.MinSkillLevel.Value) + " to cast " + spell.Name, 0, (Sprite)null, false); return false; } if (!((Character)player).TryUseEitr(spell.EitrCost.Value)) { return false; } ((Character)player).UseEitr(spell.EitrCost.Value); if (sayWords) { Talker component = ((Component)player).GetComponent<Talker>(); if (component != null) { component.Say((Type)1, spell.Words); } } spell.Effect(player, spell); return true; } } internal abstract class StatusSpell { internal static readonly List<StatusSpell> Registry = new List<StatusSpell>(); internal string EffectName; internal string Title; internal string Tooltip; internal string IconResource; internal Spell Spell; private int _hash; private Sprite _icon; internal int EffectHash { get { if (_hash == 0) { return _hash = StringExtensionMethods.GetStableHashCode(EffectName); } return _hash; } } internal virtual void Cast(Player player, Spell spell) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) bool num = IsActiveForSkillGain(player); StatusEffect val = ((Character)player).GetSEMan().AddStatusEffect(EffectHash, true, 0, 0f, (short)(-1)); if (!num && (Object)(object)val != (Object)null) { ((Character)player).RaiseSkill(spell.Skill, spell.SkillGain.Value); } } protected virtual bool IsActiveForSkillGain(Player player) { return ((Character)player).GetSEMan().HaveStatusEffect(EffectHash); } protected virtual StatusEffect CreateEffect(ObjectDB db) { return ScriptableObject.CreateInstance<StatusEffect>(); } protected static StatusEffect ConsumeEffectOf(ObjectDB db, string itemName) { GameObject itemPrefab = db.GetItemPrefab(itemName); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_itemData.m_shared.m_consumeStatusEffect; } internal static void RegisterEffects(ObjectDB db) { if (db.m_StatusEffects == null) { return; } foreach (StatusSpell item in Registry) { if (!((Object)(object)db.GetStatusEffect(item.EffectHash) != (Object)null)) { StatusEffect val = item.CreateEffect(db); ((Object)val).name = item.EffectName; val.m_name = item.Title; val.m_tooltip = item.Tooltip; val.m_icon = item.GetIcon(); val.m_ttl = item.Spell.DurationSeconds.Value; db.m_StatusEffects.Add(val); } } } private Sprite GetIcon() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_icon == (Object)null) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(IconResource); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule").GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }).Invoke(null, new object[2] { val, memoryStream.ToArray() }); _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } return _icon; } } }