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 VikingMastery v0.1.1
BepInEx/plugins/JustQOL-VikingMastery/VikingMastery.Core.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("VikingMastery.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("VikingMastery.Core")] [assembly: AssemblyTitle("VikingMastery.Core")] [assembly: AssemblyVersion("1.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 VikingMastery.Core { public sealed class Perk { public string Id { get; set; } = ""; public string Name { get; set; } = ""; public string Description { get; set; } = ""; public string Branch { get; set; } = ""; public string Effect { get; set; } = ""; public string Prerequisite { get; set; } = ""; public double Value { get; set; } public int Cost { get; set; } = 2; public int Level { get; set; } = 5; public int MaxRank { get; set; } = 1; public int Tier { get; set; } public bool Mastery { get; set; } } public sealed class Tree { public string Id { get; set; } = ""; public string Name { get; set; } = ""; public string Vanilla { get; set; } = ""; public string Description { get; set; } = ""; public bool Magic { get; set; } public List<Perk> Perks { get; set; } = new List<Perk>(); public int Budget(int highestLevel) { return Math.Min(100, Math.Max(0, highestLevel)) / 5 + (Magic ? (Math.Min(100, Math.Max(0, highestLevel)) / 10) : 0); } public void Validate() { if (string.IsNullOrWhiteSpace(Id) || Perks.Count < 10) { throw new InvalidOperationException("Incomplete tree " + Id); } if (Perks.Select((Perk perk) => perk.Id).Distinct().Count() != Perks.Count) { throw new InvalidOperationException("Duplicate perk IDs"); } foreach (Perk p in Perks) { if (p.Cost < 1 || p.MaxRank < 1 || p.Level < 5 || p.Level > 100 || double.IsNaN(p.Value) || double.IsInfinity(p.Value)) { throw new InvalidOperationException("Invalid perk " + p.Id); } if (p.Prerequisite.Length > 0 && !Perks.Any((Perk x) => x.Id == p.Prerequisite && x.Tier < p.Tier)) { throw new InvalidOperationException("Invalid prerequisite " + p.Id); } } } } public sealed class Progress { public int HighestLevel { get; set; } public Dictionary<string, int> Ranks { get; set; } = new Dictionary<string, int>(); } public sealed class PersonalNote { public long World { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public string Name { get; set; } = ""; public int FirstDay { get; set; } public int LastDay { get; set; } public bool Visited { get; set; } public string Observation { get; set; } = ""; } public sealed class Record { public int Schema { get; set; } = 1; public Dictionary<string, Progress> Trees { get; set; } = new Dictionary<string, Progress>(); public Dictionary<string, double> Cooldowns { get; set; } = new Dictionary<string, double>(); public HashSet<string> Discoveries { get; set; } = new HashSet<string>(); public Dictionary<string, PersonalNote> Notes { get; set; } = new Dictionary<string, PersonalNote>(); public int LastSurveyDay { get; set; } = -1; public int Revision { get; set; } public string Familiar { get; set; } = "Wolf"; public double BloodDebt { get; set; } public double BloodDebtUntil { get; set; } public Progress Get(string id) { if (!Trees.TryGetValue(id, out var value)) { value = (Trees[id] = new Progress()); } return value; } public void Credit(string id, double level) { if (!double.IsNaN(level) && !double.IsInfinity(level)) { Progress progress = Get(id); int num = (int)Math.Floor(Math.Min(100.0, Math.Max(0.0, level))); if (num > progress.HighestLevel) { progress.HighestLevel = num; Revision++; } } } public int Rank(string tree, string perk) { if (!Trees.TryGetValue(tree, out var value) || !value.Ranks.TryGetValue(perk, out var value2)) { return 0; } return value2; } public int Spent(Tree tree) { return tree.Perks.Sum((Perk p) => p.Cost * Rank(tree.Id, p.Id)); } public int Available(Tree tree) { return Math.Max(0, tree.Budget(Get(tree.Id).HighestLevel) - Spent(tree)); } public string CanBuy(Tree tree, Perk perk, bool supported = true) { if (!tree.Perks.Contains(perk)) { return "Unknown perk."; } if (!supported) { return "This effect is not enabled in this development build."; } Progress progress = Get(tree.Id); if (Rank(tree.Id, perk.Id) >= perk.MaxRank) { return "Already learned."; } if (progress.HighestLevel < perk.Level) { return "Requires skill milestone " + perk.Level + "."; } if (perk.Tier > 0 && !tree.Perks.Any((Perk x) => x.Tier == 0 && Rank(tree.Id, x.Id) > 0)) { return "Learn a foundation first."; } if (perk.Prerequisite.Length > 0 && Rank(tree.Id, perk.Prerequisite) == 0) { return "Learn the preceding perk."; } if (perk.Mastery && tree.Perks.Any((Perk x) => x.Mastery && Rank(tree.Id, x.Id) > 0)) { return "Another mastery is chosen. Reset this tree to change."; } if (Available(tree) < perk.Cost) { return "Not enough points."; } return ""; } public bool Buy(Tree tree, Perk perk, bool supported = true) { if (CanBuy(tree, perk, supported).Length != 0) { return false; } Get(tree.Id).Ranks[perk.Id] = Rank(tree.Id, perk.Id) + 1; Revision++; return true; } public int ResetPrice(Tree tree, int coinsPerPoint) { if (Spent(tree) != 0) { return Math.Max(20, checked(Spent(tree) * Math.Max(0, Math.Min(10000, coinsPerPoint)))); } return 0; } public void Reset(Tree tree) { Get(tree.Id).Ranks.Clear(); Revision++; } public bool Ready(string key, double now) { if (Cooldowns.TryGetValue(key, out var value)) { return now >= value; } return true; } public bool Trigger(string key, double now, double seconds) { if (double.IsNaN(now) || double.IsNaN(seconds) || double.IsInfinity(now) || double.IsInfinity(seconds) || seconds < 0.0 || !Ready(key, now)) { return false; } Cooldowns[key] = now + seconds; Revision++; return true; } public void Validate(IEnumerable<Tree> catalog) { if (double.IsNaN(BloodDebt) || double.IsInfinity(BloodDebt) || BloodDebt < 0.0 || double.IsNaN(BloodDebtUntil) || double.IsInfinity(BloodDebtUntil)) { throw new InvalidOperationException("Invalid blood debt"); } if (Schema != 1 || Trees == null || Cooldowns == null || Discoveries == null) { throw new InvalidOperationException("Unsupported or corrupt VikingMastery record. Original retained."); } foreach (Tree t in catalog) { if (!Trees.TryGetValue(t.Id, out var value)) { continue; } if (value == null || value.Ranks == null || value.HighestLevel < 0 || value.HighestLevel > 100) { throw new InvalidOperationException("Invalid tree state"); } foreach (Perk perk in t.Perks) { int num = Rank(t.Id, perk.Id); if (num < 0 || num > perk.MaxRank || (num > 0 && (value.HighestLevel < perk.Level || (perk.Prerequisite.Length > 0 && Rank(t.Id, perk.Prerequisite) == 0)))) { throw new InvalidOperationException("Invalid perk purchase " + perk.Id); } } if (t.Perks.Any((Perk x) => x.Tier > 0 && Rank(t.Id, x.Id) > 0) && !t.Perks.Any((Perk x) => x.Tier == 0 && Rank(t.Id, x.Id) > 0)) { throw new InvalidOperationException("Missing foundation"); } if (Spent(t) > t.Budget(value.HighestLevel) || t.Perks.Count((Perk p) => p.Mastery && Rank(t.Id, p.Id) > 0) > 1) { throw new InvalidOperationException("Invalid point budget or mastery"); } } if (Notes == null) { Notes = new Dictionary<string, PersonalNote>(); } if (Trees.Count > 64 || Cooldowns.Count > 20000 || Discoveries.Count > 20000 || Notes.Count > 2000) { throw new InvalidOperationException("Progress record exceeds supported limits"); } foreach (KeyValuePair<string, PersonalNote> note in Notes) { PersonalNote value2 = note.Value; if (note.Key == null || note.Key.Length > 256 || value2 == null || value2.Name == null || value2.Name.Length > 128 || !WireLimits.Finite(value2.X) || !WireLimits.Finite(value2.Y) || !WireLimits.Finite(value2.Z)) { throw new InvalidOperationException("Invalid personal note"); } } if (Cooldowns.Any((KeyValuePair<string, double> x) => double.IsNaN(x.Value) || double.IsInfinity(x.Value))) { throw new InvalidOperationException("Invalid cooldown"); } } } public static class Balance { public static double Reduction(double sum) { return Math.Max(0.0, Math.Min(0.35, sum)); } public static double Damage(double sum) { return 1.0 + Math.Max(0.0, Math.Min(0.3, sum)); } public static double Speed(double sum) { return 1.0 + Math.Max(0.0, Math.Min(0.15, sum)); } public static double HealingShare(double total, int injured) { if (injured > 0) { return Math.Max(0.0, total) / (double)injured; } return 0.0; } public static int FamiliarCount(string selection, bool mastery) { if (!(selection == "Pack" && mastery)) { return 1; } return 3; } } public sealed class NetworkPolicy { public int Protocol { get; set; } = 1; public bool Enabled { get; set; } = true; public bool AllowPvpPerks { get; set; } public int CoinsPerPoint { get; set; } = 10; public string CatalogHash { get; set; } = ""; } public sealed class Envelope { public int Protocol { get; set; } = 1; public string Session { get; set; } = ""; public string Id { get; set; } = ""; public string Op { get; set; } = ""; public string Tree { get; set; } = ""; public string Perk { get; set; } = ""; public string Choice { get; set; } = ""; public string CatalogHash { get; set; } = ""; public string Message { get; set; } = ""; public int Revision { get; set; } public int Coins { get; set; } public long Target { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public bool Safe { get; set; } public Record State { get; set; } public NetworkPolicy Policy { get; set; } public Dictionary<string, float> Levels { get; set; } public double ServerTime { get; set; } public float Eitr { get; set; } public bool Paid { get; set; } public float Duration { get; set; } } public sealed class AuthorityProfile { public long Player { get; set; } public int Version { get; set; } public Record State { get; set; } = new Record(); public Dictionary<string, PendingTransaction> Transactions { get; set; } = new Dictionary<string, PendingTransaction>(); public Dictionary<string, string> Results { get; set; } = new Dictionary<string, string>(); } public sealed class PendingTransaction { public string Id { get; set; } = ""; public string Kind { get; set; } = ""; public string Tree { get; set; } = ""; public string Choice { get; set; } = ""; public int Coins { get; set; } public float Eitr { get; set; } public long Target { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public double Expires { get; set; } public double Cooldown { get; set; } public string CooldownKey { get; set; } = ""; public int Revision { get; set; } public bool Committed { get; set; } public bool Applying { get; set; } public string ApplyingSession { get; set; } = ""; } public sealed class ClientEscrow { public string Id { get; set; } = ""; public long World { get; set; } public int Coins { get; set; } public float Eitr { get; set; } public bool Paid { get; set; } public bool Refunded { get; set; } } public static class WireLimits { public const int MaxInflated = 8388608; public const int MaxEncoded = 4194304; public static bool Finite(float f) { if (!float.IsNaN(f)) { return !float.IsInfinity(f); } return false; } public static bool Identifier(string s) { if (s != null && s.Length > 0) { return s.Length <= 64; } return false; } public static bool Coordinates(Envelope m) { if (Finite(m.X) && Finite(m.Y) && Finite(m.Z) && Math.Abs(m.X) < 11000f && Math.Abs(m.Z) < 11000f) { return Math.Abs(m.Y) < 10000f; } return false; } } public sealed class TreePoint { public string Id { get; set; } = ""; public float X { get; set; } public float Y { get; set; } } public static class TalentLayout { public static List<TreePoint> Arrange(Tree tree) { List<TreePoint> list = new List<TreePoint>(); List<Perk> list2 = tree.Perks.Where((Perk p) => p.Tier == 0).ToList(); for (int num = 0; num < list2.Count; num++) { list.Add(new TreePoint { Id = list2[num].Id, X = ((float)num - (float)(list2.Count - 1) / 2f) * 64f, Y = 0f }); } List<string> branches = (from p in tree.Perks where p.Tier > 0 select p.Branch).Distinct().ToList(); int b; for (b = 0; b < branches.Count; b++) { List<Perk> list3 = (from p in tree.Perks where p.Tier > 0 && p.Branch == branches[b] orderby p.Tier select p).ToList(); for (int num2 = 0; num2 < list3.Count; num2++) { double num3 = (-90.0 + 360.0 * (double)b / (double)branches.Count + (double)((branches.Count == 4) ? (-45) : 0) + (double)(num2 * 10)) * Math.PI / 180.0; float num4 = 118 + num2 * 44; list.Add(new TreePoint { Id = list3[num2].Id, X = (float)Math.Cos(num3) * num4, Y = (float)Math.Sin(num3) * num4 }); } } return list; } } }
BepInEx/plugins/JustQOL-VikingMastery/VikingMastery.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Splatform; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using VikingMastery.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("VikingMastery")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1")] [assembly: AssemblyProduct("VikingMastery")] [assembly: AssemblyTitle("VikingMastery")] [assembly: AssemblyVersion("0.1.1.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 VikingMastery { internal static class AdvancedCombat { private static Plugin P => Plugin.Instance; internal static bool Has(string tree, string perk) { if (Object.op_Implicit((Object)(object)P)) { return P.Has(tree, perk); } return false; } private static bool Ready(string key, double seconds) { return P.Data.Trigger(key, Plugin.Now, seconds); } private static long Target(Character c) { return ((Object)c).GetInstanceID(); } internal static double Hit(Character target, HitData hit, CastContext ctx) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0691: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06f9: Unknown result type (might be due to invalid IL or missing references) //IL_0709: Unknown result type (might be due to invalid IL or missing references) //IL_0714: Unknown result type (might be due to invalid IL or missing references) //IL_0719: Unknown result type (might be due to invalid IL or missing references) if (ctx == null || (Object)(object)ctx.Owner != (Object)(object)Player.m_localPlayer || CastTracking.ProcessingDot) { return 0.0; } string text = P.TreeFor(hit.m_skill); bool flag = ctx.Targets.Add(((Object)target).GetInstanceID()); bool secondary = ctx.Secondary; double num = 0.0; bool flag2 = target.IsStaggering(); bool flag3 = Object.op_Implicit((Object)(object)((Component)target).GetComponent<BaseAI>()) && !((Component)target).GetComponent<BaseAI>().IsAlerted(); if (text == "axes") { if (Has(text, "blood_rhythm")) { num += 0.02 * (double)Math.Min(3, PerkState.Count("axe_rhythm")); } if (flag && ctx.Once("axe_rhythm")) { PerkState.Chain("axe_rhythm", 3, 4.0, 0L); } if (secondary && Has(text, "timberfall")) { hit.m_staggerMultiplier *= 1.15f; } if (secondary && flag2 && target.GetHealthPercentage() < 0.3f && Has(text, "headsman") && Ready("headsman", 12.0)) { num += 0.25; } if (Has(text, "red_harvest") && PerkState.Count("axe_rhythm") == 3 && Ready("red_harvest", 1.0)) { ((Character)ctx.Owner).AddStamina(3f); } } if (text == "clubs") { if (secondary && Has(text, "clear_space")) { hit.m_pushForce *= 1.1f; } if (flag2 && secondary && Has(text, "bell_ringer") && Ready("bell_ringer", 12.0)) { num += 0.2; } if (flag2 && Has(text, "finishing_weight") && Ready("finishing_weight:" + Target(target), 6.0)) { PerkState.Grant("club_discount", 2.0, 0.25f); } } if (text == "bows") { if (ctx.Settled && Has(text, "settled_aim")) { num += 0.06; } if (Has(text, "follow_through")) { PerkState.Grant("bow_follow", 4.0, 0.1f); } if (ctx.Once("bow_hit") && Has(text, "running_hunt") && PerkState.Chain("bow_hits", 3, 8.0, 0L) >= 3 && Ready("running_hunt", 15.0)) { PerkState.Grant("travel_speed", 4.0, 0.1f); } if (flag3 && Has(text, "first_arrow") && ctx.Once("first_arrow") && Ready("first_arrow", 20.0)) { TimedDamage.Apply(target, ctx.Owner, hit.GetTotalDamage() * 0.1f, 6); } } if (text == "crossbows") { if (ctx.Settled && Has(text, "braced_shot")) { num += 0.06; } if (target.GetHealthPercentage() < 0.3f && ctx.Settled && Has(text, "executioners_bolt") && Ready("executioners_bolt", 15.0)) { num += 0.2; } if (Has(text, "battle_mechanism") && PerkState.Count("fast_reloads") < 2) { PerkState.Grant("reload_speed", 5.0, 0.1f); } } if (text == "fists") { int num2 = (ctx.Once("fist_chain") ? PerkState.Chain("fist_chain", 4, 6.0, Target(target)) : PerkState.Count("fist_chain")); if (num2 == 3 && Has(text, "one_two")) { num += 0.08; } if (target.GetHealthPercentage() > 0.7f && Has(text, "body_work")) { hit.m_staggerMultiplier *= 1.06f; } if (Has(text, "counterpunch") && PerkState.Consume("parry_attack")) { num += 0.1; } if (Has(text, "iron_discipline") && (PerkState.On("parry_window") || PerkState.On("evade_window")) && Ready("iron_discipline", 8.0)) { hit.m_staggerMultiplier *= 1.2f; PerkState.Grant("stagger_guard", 3.0, 0.1f); } if (num2 == 4 && Has(text, "relentless") && ctx.Once("relentless")) { num += 0.1; ((Character)ctx.Owner).AddStamina(5f); PerkState.Clear("fist_chain"); } } if (text == "knives") { if (flag3 && Has(text, "clean_withdrawal")) { PerkState.Grant("travel_speed", 3.0, 0.08f); } if (flag3 && Has(text, "silent_hunter") && ctx.Once("silent_hunter") && Ready("silent_hunter", 20.0)) { TimedDamage.Apply(target, ctx.Owner, hit.GetTotalDamage() * 0.12f, 6); } if (flag && ctx.Once("knife_chain")) { PerkState.Chain("knife_rhythm", 3, 3.0, 0L); if (PerkState.Chain("knife_five", 5, 6.0, Target(target)) == 5 && Has(text, "death_by_cuts") && Ready("death_by_cuts", 10.0)) { num += 0.15; PerkState.Clear("knife_five"); } } } if (text == "polearms") { if (!secondary && ctx.Settled && Has(text, "set_point")) { hit.m_staggerMultiplier *= 1.08f; } if (!secondary && Vector3.Distance(((Component)ctx.Owner).transform.position, ((Component)target).transform.position) > 2f && Has(text, "keep_distance")) { num += 0.06; } if (secondary && Has(text, "wide_clearance")) { hit.m_pushForce *= 1.1f; } if (!secondary && Has(text, "gatekeeper") && Vector3.Dot(target.GetVelocity(), ((Component)ctx.Owner).transform.position - ((Component)target).transform.position) > 0f && Ready("gatekeeper", 10.0)) { hit.m_staggerMultiplier *= 1.2f; } } if (text == "spears") { if (!secondary && Has(text, "point_work")) { num += 0.02 * (double)PerkState.Count("spear_point"); } if (!secondary && ctx.Once("spear_point")) { PerkState.Chain("spear_point", 3, 4.0, Target(target)); } if (!secondary && PerkState.Count("spear_point") == 3 && Has(text, "spearwall")) { hit.m_staggerMultiplier *= 1.15f; } if (secondary && flag3 && Has(text, "hunting_cast")) { num += 0.08; } if (secondary && ctx.Settled && Has(text, "true_throw") && Ready("true_throw", 10.0)) { num += 0.15; } } if (text == "swords") { if (ctx.Once("sword_flow")) { PerkState.Chain("sword_flow", 3, 4.0, 0L); } if (ctx.Combo >= 2 && Has(text, "finishing_form")) { num += 0.08; } if (secondary && flag2 && Has(text, "measured_thrust")) { num += 0.1; } if (secondary && PerkState.On("parry_window") && Has(text, "kings_answer") && Ready("kings_answer", 12.0)) { num += 0.1; hit.m_staggerMultiplier *= 1.2f; } if (ctx.Once("sword_combo") && ctx.Combo >= 2 && Has(text, "perfect_sequence") && PerkState.Count("sword_landed") >= 2 && Ready("perfect_sequence", 8.0)) { ((Character)ctx.Owner).AddStamina(6f); } if (flag) { PerkState.Chain("sword_landed", 3, 4.0, Target(target)); } } if (PerkState.On("evade_window") && ctx.Once("evade_attack")) { if (Has("dodge", "counterstep")) { num += 0.06; } if (Has("dodge", "turning_point")) { hit.m_staggerMultiplier *= 1.12f; } if (PerkState.Consume("untouched")) { num += 0.15; } } if (PerkState.Consume("parry_attack") && Has("blocking", "opening_found")) { num += 0.08; } if (PerkState.On("parry_window") && Has("blocking", "perfect_answer") && Ready("perfect_answer", 8.0)) { hit.m_staggerMultiplier *= 1.2f; } if (flag3 && ((Character)ctx.Owner).IsSneaking() && ProfessionHooks.StationarySeconds >= 2.0) { if (Has("sneak", "patient_watch")) { num += 0.06; } if (Has("sneak", "read_the_prey")) { hit.m_staggerMultiplier *= 1.1f; } } return num; } internal static void Finish(CastContext ctx) { //IL_002b: 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_0056: Invalid comparison between Unknown and I4 //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 if ((Object)(object)ctx.Owner != (Object)(object)Player.m_localPlayer || ctx.Weapon == null) { return; } string text = P.TreeFor(ctx.Weapon.m_shared.m_skillType); int count = ctx.Targets.Count; if (count == 0 && (int)ctx.Weapon.m_shared.m_skillType != 8 && (int)ctx.Weapon.m_shared.m_skillType != 14) { string[] array = new string[7] { "axe_rhythm", "fist_chain", "knife_rhythm", "knife_five", "spear_point", "sword_flow", "sword_landed" }; for (int i = 0; i < array.Length; i++) { PerkState.Clear(array[i]); } } if (text == "clubs") { if (count >= 2 && Has(text, "crowd_rhythm") && ctx.Once("crowd_rhythm") && Ready("crowd_rhythm", 6.0)) { ((Character)ctx.Owner).AddStamina(4f); } if (count >= 3 && Has(text, "shockmaster") && Ready("shockmaster", 15.0)) { PerkState.Grant("stagger_guard", 5.0, 0.1f); } } if (text == "polearms" && ctx.Secondary) { if (count >= 2 && Has(text, "circle_of_steel")) { PerkState.Grant("stagger_guard", 3.0, 0.08f); } if (count >= 3 && Has(text, "whirlwind_discipline") && Ready("whirlwind_discipline", 12.0)) { ((Character)ctx.Owner).AddStamina(8f); } } } internal static void Killed(Character victim, HitData last) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (last != null && !((Object)(object)last.GetAttacker() != (Object)(object)Player.m_localPlayer)) { Killed(P.TreeFor(last.m_skill), Object.op_Implicit((Object)(object)((Component)victim).GetComponent<BaseAI>()) && !((Component)victim).GetComponent<BaseAI>().IsAlerted()); } } internal static void Killed(string tree, bool unaware) { if (Object.op_Implicit((Object)(object)P) && P.Active) { if (tree == "axes" && Has(tree, "unbroken_assault") && Ready("unbroken_assault", 6.0)) { PerkState.Grant("axe_kill", 5.0, 0.3f); } if (tree == "fists" && Has(tree, "keep_swinging") && Ready("keep_swinging", 6.0)) { ((Character)Player.m_localPlayer).AddStamina(6f); } if (Has("sneak", "fade_back") && unaware && Ready("fade_back", 20.0)) { PerkState.Grant("fade_back", 10.0, 0.2f); } } } } internal static class TimedDamage { private sealed class Dot { internal Character Target; internal Player Owner; internal float Amount; internal int Ticks; internal double Next; internal string Element; } private static readonly List<Dot> dots = new List<Dot>(); internal static void Apply(Character target, Player owner, float total, int seconds, string element = "pierce") { if (!(total <= 0f) && seconds > 0) { dots.Add(new Dot { Target = target, Owner = owner, Amount = total / (float)seconds, Ticks = seconds, Next = Plugin.Now + 1.0, Element = element }); } } internal static void Tick() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown Dot[] array = dots.ToArray(); foreach (Dot dot in array) { if (!Object.op_Implicit((Object)(object)dot.Target) || !Object.op_Implicit((Object)(object)dot.Owner) || dot.Target.IsDead() || ((Character)dot.Owner).IsDead() || dot.Ticks <= 0) { dots.Remove(dot); } else if (!(Plugin.Now < dot.Next)) { dot.Next = Plugin.Now + 1.0; dot.Ticks--; HitData val = new HitData(); if (dot.Element == "fire") { val.m_damage.m_fire = dot.Amount; } else { val.m_damage.m_pierce = dot.Amount; } val.SetAttacker((Character)(object)dot.Owner); val.m_dodgeable = false; val.m_blockable = false; try { CastTracking.ProcessingDot = true; dot.Target.Damage(val); } finally { CastTracking.ProcessingDot = false; } } } } } internal static class AlchemyPerks { private sealed class Recovery { internal float Health; internal float Stamina; internal float BaseHealing; internal int Ticks; internal double Next; internal double MasteryAt; internal bool Mastery; } [HarmonyPatch(typeof(Player), "ConsumeItem")] private static class Consume { private static void Prefix(ItemData item, out ItemData __state) { __state = consumed; consumed = item; } private static Exception Finalizer(ItemData __state, Exception __exception) { consumed = __state; return __exception; } } [HarmonyPatch(typeof(SE_Stats), "Setup")] private static class Effect { private static void Prefix(SE_Stats __instance, Character character) { if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)character != (Object)(object)Player.m_localPlayer || (Object)(object)consumed?.m_dropPrefab == (Object)null) { return; } string name = ((Object)consumed.m_dropPrefab).name; if (!name.StartsWith("Mead", StringComparison.Ordinal) || name.StartsWith("MeadBase", StringComparison.Ordinal)) { return; } if (__instance.m_healthUpFront > 0f || __instance.m_healthOverTime > 0f || __instance.m_staminaUpFront > 0f || __instance.m_staminaOverTime > 0f || __instance.m_eitrUpFront > 0f || __instance.m_eitrOverTime > 0f) { float num = Mathf.Max(0f, __instance.m_healthUpFront) + Mathf.Max(0f, __instance.m_healthOverTime); float num2 = Mathf.Max(0f, __instance.m_staminaUpFront) + Mathf.Max(0f, __instance.m_staminaOverTime); if (num > 0f) { float num3 = ((!P.Has("alchemy", "gentle_finish")) ? 0f : ((P.Has("alchemy", "measured_dose") && character.GetHealthPercentage() < 0.35f) ? 0.1f : 0.05f)); recovery.Add(new Recovery { Health = num * num3, Ticks = 6, Next = Plugin.Now + 1.0, BaseHealing = num, Mastery = P.Has("alchemy", "measured_remedy"), MasteryAt = Plugin.Now + (double)Mathf.Max(0f, __instance.m_healthOverTimeDuration) }); if (P.Has("alchemy", "steady_recovery")) { PerkState.Grant("medicine_stagger", Mathf.Max(1f, __instance.m_healthOverTimeDuration), 0.08f); } } if (num2 > 0f && P.Has("alchemy", "restorative_practice")) { recovery.Add(new Recovery { Stamina = num2 * 0.05f, Ticks = 4, Next = Plugin.Now + 1.0 }); } } else { bool flag = name.IndexOf("Resist", StringComparison.OrdinalIgnoreCase) >= 0; float num4 = 1f; if (P.Has("alchemy", "long_preparation")) { num4 = (flag ? 1.12f : 1.15f); } else if (flag && P.Has("alchemy", "lasting_preparation")) { num4 = 1.05f; } else if (!flag && P.Has("alchemy", "travel_draughts")) { num4 = 1.08f; } if (((StatusEffect)__instance).m_ttl > 0f) { ((StatusEffect)__instance).m_ttl = ((StatusEffect)__instance).m_ttl * num4; } } } } [ThreadStatic] private static ItemData consumed; private static readonly List<Recovery> recovery = new List<Recovery>(); private static Plugin P => Plugin.Instance; internal static void Clear() { recovery.Clear(); } internal static void Tick() { Recovery[] array = AlchemyPerks.recovery.ToArray(); foreach (Recovery recovery in array) { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead()) { AlchemyPerks.recovery.Remove(recovery); continue; } if (recovery.Mastery && Plugin.Now >= recovery.MasteryAt) { recovery.Mastery = false; if (((Character)localPlayer).GetHealthPercentage() < 0.5f) { AlchemyPerks.recovery.Add(new Recovery { Health = recovery.BaseHealing * 0.08f, Ticks = 8, Next = Plugin.Now + 1.0 }); } } if (recovery.Ticks > 0 && Plugin.Now >= recovery.Next) { recovery.Next = Plugin.Now + 1.0; float num = recovery.Health / (float)recovery.Ticks; float num2 = recovery.Stamina / (float)recovery.Ticks; recovery.Health -= num; recovery.Stamina -= num2; recovery.Ticks--; if (num > 0f) { ((Character)localPlayer).Heal(num, true); } if (num2 > 0f) { ((Character)localPlayer).AddStamina(num2); } } if (recovery.Ticks <= 0 && !recovery.Mastery) { AlchemyPerks.recovery.Remove(recovery); } } } } internal static class BloodbinderRuntime { private sealed class Recovery { internal float Remaining; internal int Ticks; } [HarmonyPatch(typeof(Character), "UseHealth")] private static class Sacrifice { private static void Prefix(Character __instance, out float __state) { __state = __instance.GetHealth(); } private static void Postfix(Character __instance, float __state) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon == null || (int)currentWeapon.m_shared.m_skillType != 10) { return; } float num = Mathf.Max(0f, __state - __instance.GetHealth()); if (!(num <= 0f)) { P.Data.BloodDebt = ((Plugin.Now < P.Data.BloodDebtUntil) ? P.Data.BloodDebt : 0.0) + (double)num; P.Data.BloodDebtUntil = Plugin.Now + 10.0; if (P.Network.Connected) { P.Network.Support(new Envelope { Op = "support", Choice = "blood_spend", Eitr = num }); } } } } [HarmonyPatch(typeof(SE_Shield), "Setup")] private static class Applied { private static void Postfix(SE_Shield __instance, Character character) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)P) || !P.Active || P.Network.Connected || (Object)(object)character != (Object)(object)Player.m_localPlayer || character.IsDead()) { return; } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 10 && P.Has("blood_magic", "mending_thread") && P.Data.Trigger("mending_thread:" + Player.m_localPlayer.GetPlayerID(), Plugin.Now, 20.0)) { HealOverTime(character.GetMaxHealth() * 0.06f, 6); if (P.Has("blood_magic", "woven_recovery")) { PerkState.Grant("blood_food_regen", 12.0, 0.1f); } } } } [HarmonyPatch(typeof(SE_Shield), "SetLevel")] private static class Strength { private static void Postfix(SE_Shield __instance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)P) && P.Active && !P.Network.Connected && P.Has("blood_magic", "sanguine_shelter") && !((Object)(object)Traverse.Create((object)__instance).Field("m_character").GetValue<Character>() != (Object)(object)Player.m_localPlayer)) { ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 10) { Traverse obj = Traverse.Create((object)__instance).Field("m_totalAbsorbDamage"); obj.SetValue((object)(obj.GetValue<float>() * 1.08f)); } } } } [HarmonyPatch(typeof(SE_Shield), "OnDamaged")] private static class Broken { private static void Prefix(SE_Shield __instance, out bool __state) { Traverse val = Traverse.Create((object)__instance); __state = val.Field("m_damage").GetValue<float>() < val.Field("m_totalAbsorbDamage").GetValue<float>(); } private static void Postfix(SE_Shield __instance, Character attacker, bool __state) { if (!__state || !Object.op_Implicit((Object)(object)P) || !P.Active || P.Network.Connected || !Object.op_Implicit((Object)(object)attacker) || !BaseAI.IsEnemy(attacker, (Character)(object)Player.m_localPlayer)) { return; } Traverse val = Traverse.Create((object)__instance); if (!((Object)(object)val.Field("m_character").GetValue<Character>() != (Object)(object)Player.m_localPlayer) && !(val.Field("m_damage").GetValue<float>() < val.Field("m_totalAbsorbDamage").GetValue<float>())) { Player localPlayer = Player.m_localPlayer; if (P.Has("blood_magic", "crimson_covenant") && ((Character)localPlayer).GetHealthPercentage() < 0.4f && P.Data.Trigger("crimson_covenant:" + localPlayer.GetPlayerID(), Plugin.Now, 45.0)) { float num = (P.Data.Ready("mending_thread:" + localPlayer.GetPlayerID(), Plugin.Now - 14.0) ? 0.1f : 0.06f); HealOverTime(((Character)localPlayer).GetMaxHealth() * num, 5); PerkState.Grant("blood_guard", 3.0, 0.1f); } } } } private static readonly List<Recovery> recoveries = new List<Recovery>(); private static double nextTick; private static Plugin P => Plugin.Instance; internal static void Clear() { recoveries.Clear(); } internal static void Tick(Player player) { if (Plugin.Now < nextTick) { return; } nextTick = Plugin.Now + 1.0; if (((Character)player).IsDead()) { recoveries.Clear(); return; } Recovery[] array = recoveries.ToArray(); foreach (Recovery recovery in array) { float num = recovery.Remaining / (float)recovery.Ticks; recovery.Remaining -= num; recovery.Ticks--; if (Plugin.Now < P.Data.BloodDebtUntil && P.Data.BloodDebt > 0.0) { float num2 = Mathf.Min(num, (float)P.Data.BloodDebt); num -= num2; Record data = P.Data; data.BloodDebt -= (double)num2; } if (num > 0f) { ((Character)player).Heal(num, true); } if (recovery.Ticks <= 0) { recoveries.Remove(recovery); } } } private static void HealOverTime(float amount, int seconds) { recoveries.Add(new Recovery { Remaining = amount, Ticks = seconds }); } } internal static class BloodbinderNetwork { private sealed class Ward { internal long Caster; internal double Until; } private sealed class Recovery { internal long Caster; internal long Recipient; internal float Remaining; internal int Ticks; } private sealed class Boost { internal bool Applied; internal float Baseline; } [HarmonyPatch(typeof(Aoe), "OnHit")] private static class BarrierHit { private static void Postfix(Aoe __instance, Collider collider, bool __result) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 Plugin instance = Plugin.Instance; if (!Object.op_Implicit((Object)(object)instance) || !instance.Active || !instance.Network.Connected || !__result) { return; } Character value = Traverse.Create((object)__instance).Field("m_owner").GetValue<Character>(); Player val = (Object.op_Implicit((Object)(object)collider) ? ((Component)collider).GetComponentInParent<Player>() : null); if (!((Object)(object)value != (Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)val) && (int)__instance.m_skill == 10) { Humanoid component = ((Component)value).GetComponent<Humanoid>(); ItemData val2 = ((component != null) ? component.GetCurrentWeapon() : null); if (Object.op_Implicit((Object)(object)val2?.m_dropPrefab) && ((Object)val2.m_dropPrefab).name == "StaffShield") { Applied(Player.m_localPlayer.GetPlayerID(), val.GetPlayerID()); } } } } [HarmonyPatch(typeof(SE_Shield), "SetLevel")] private static class NewShield { private static void Postfix(SE_Shield __instance) { Boost orCreateValue = boosted.GetOrCreateValue(__instance); orCreateValue.Applied = false; orCreateValue.Baseline = Traverse.Create((object)__instance).Field("m_totalAbsorbDamage").GetValue<float>(); if (Object.op_Implicit((Object)(object)Plugin.Instance) && Plugin.Instance.Active && Plugin.Instance.Network.Connected && (Object)(object)Traverse.Create((object)__instance).Field("m_character").GetValue<Character>() == (Object)(object)Player.m_localPlayer && PerkState.On("blood_shield")) { ApplyBoost(__instance, PerkState.Amount("blood_shield")); } } } [HarmonyPatch(typeof(SE_Shield), "OnDamaged")] private static class Broken { private static void Prefix(SE_Shield __instance, out bool __state) { Traverse val = Traverse.Create((object)__instance); __state = val.Field("m_damage").GetValue<float>() < val.Field("m_totalAbsorbDamage").GetValue<float>(); } private static void Postfix(SE_Shield __instance, Character attacker, bool __state) { //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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown Plugin instance = Plugin.Instance; if (__state && Object.op_Implicit((Object)(object)instance) && instance.Active && instance.Network.Connected && Object.op_Implicit((Object)(object)attacker) && BaseAI.IsEnemy(attacker, (Character)(object)Player.m_localPlayer)) { Traverse val = Traverse.Create((object)__instance); if ((Object)(object)val.Field("m_character").GetValue<Character>() == (Object)(object)Player.m_localPlayer && val.Field("m_damage").GetValue<float>() >= val.Field("m_totalAbsorbDamage").GetValue<float>()) { instance.Network.Support(new Envelope { Op = "support", Choice = "barrier_break" }); } } } } private static readonly Dictionary<long, Ward> wards = new Dictionary<long, Ward>(); private static readonly List<Recovery> recoveries = new List<Recovery>(); private static readonly Dictionary<long, Queue<(double time, float amount)>> budget = new Dictionary<long, Queue<(double, float)>>(); private static readonly ConditionalWeakTable<SE_Shield, Boost> boosted = new ConditionalWeakTable<SE_Shield, Boost>(); private static double next; internal static void Applied(long caster, long target) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Multiplayer network = Plugin.Instance.Network; if (network.Connected) { network.Support(new Envelope { Op = "support", Choice = "barrier_apply", Target = target }); } } internal static void Handle(AuthorityProfile actor, Envelope message) { //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Invalid comparison between Unknown and I4 //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Expected O, but got Unknown //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_058d: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Expected O, but got Unknown //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Expected O, but got Unknown Multiplayer network = Plugin.Instance.Network; Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == actor.Player)); if (!Object.op_Implicit((Object)(object)val) || ((Character)val).IsDead()) { return; } if (message.Choice == "blood_spend") { if (WireLimits.Finite(message.Eitr) && !(message.Eitr <= 0f) && !(message.Eitr > ((Character)val).GetMaxHealth())) { ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon(); if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 10) { actor.State.BloodDebt = ((Plugin.Now < actor.State.BloodDebtUntil) ? actor.State.BloodDebt : 0.0) + (double)message.Eitr; actor.State.BloodDebtUntil = Plugin.Now + 10.0; } } } else if (message.Choice == "barrier_apply") { Player val2 = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == message.Target)); if (!Object.op_Implicit((Object)(object)val2) || ((Character)val2).IsDead() || ((Character)val2).IsPVPEnabled() || Vector3.Distance(((Component)val).transform.position, ((Component)val2).transform.position) > 12f) { return; } ItemData currentWeapon2 = ((Humanoid)val).GetCurrentWeapon(); if (currentWeapon2 == null || (int)currentWeapon2.m_shared.m_skillType != 10 || !actor.State.Trigger("ward_report:" + message.Target, Plugin.Now, 0.5)) { return; } wards[message.Target] = new Ward { Caster = actor.Player, Until = Plugin.Now + 300.0 }; float eitr = ((actor.State.Rank("blood_magic", "sanguine_shelter") > 0) ? 0.08f : 0f); network.NotifyPlayer(message.Target, new Envelope { Op = "buff", Choice = "blood_shield", Eitr = eitr, Duration = 3f }); AuthorityProfile val3 = network.Authority(message.Target); if (val3 == null) { return; } if (actor.State.Rank("blood_magic", "mending_thread") > 0 && val3.State.Trigger("mending_thread", Plugin.Now, 20.0)) { recoveries.RemoveAll((Recovery r) => r.Recipient == message.Target && r.Ticks == 6); recoveries.Add(new Recovery { Caster = actor.Player, Recipient = message.Target, Remaining = ((Character)val2).GetMaxHealth() * 0.06f, Ticks = 6 }); if (actor.State.Rank("blood_magic", "woven_recovery") > 0) { network.NotifyPlayer(message.Target, new Envelope { Op = "buff", Choice = "blood_food_regen", Eitr = 0.1f, Duration = 12f }); } } network.Store(val3); network.Store(actor); } else { if (!(message.Choice == "barrier_break") || !wards.TryGetValue(actor.Player, out var value) || !(value.Until > Plugin.Now)) { return; } wards.Remove(actor.Player); AuthorityProfile val4 = network.Authority(value.Caster); if (val4 != null) { if (value.Caster != actor.Player && val4.State.Rank("blood_magic", "shared_burden") > 0 && val4.State.Trigger("shared_burden", Plugin.Now, 10.0)) { network.NotifyPlayer(value.Caster, new Envelope { Op = "buff", Choice = "shared_burden", Eitr = 0.15f, Duration = 8f }); } if (((Character)val).GetHealthPercentage() < 0.4f && val4.State.Rank("blood_magic", "crimson_covenant") > 0 && actor.State.Trigger("crimson_covenant", Plugin.Now, 45.0)) { recoveries.Add(new Recovery { Caster = value.Caster, Recipient = actor.Player, Remaining = ((Character)val).GetMaxHealth() * 0.1f, Ticks = 5 }); network.NotifyPlayer(actor.Player, new Envelope { Op = "buff", Choice = "blood_guard", Eitr = 0.1f, Duration = 3f }); } network.Store(val4); network.Store(actor); } } } internal static void Tick() { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || Plugin.Now < next) { return; } next = Plugin.Now + 1.0; Recovery[] array = recoveries.ToArray(); foreach (Recovery r in array) { Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == r.Recipient)); if (!Object.op_Implicit((Object)(object)val) || ((Character)val).IsDead() || r.Ticks <= 0) { recoveries.Remove(r); continue; } float num = r.Remaining / (float)r.Ticks; r.Remaining -= num; r.Ticks--; if (!budget.TryGetValue(r.Recipient, out Queue<(double, float)> value)) { value = (budget[r.Recipient] = new Queue<(double, float)>()); } while (value.Count > 0 && Plugin.Now - value.Peek().Item1 >= 6.0) { value.Dequeue(); } num = Mathf.Min(num, Mathf.Max(0f, ((Character)val).GetMaxHealth() * 0.12f - value.Sum<(double, float)>(((double time, float amount) p) => p.amount))); AuthorityProfile val2 = Plugin.Instance.Network.Authority(r.Caster); if (r.Caster == r.Recipient && val2 != null && Plugin.Now < val2.State.BloodDebtUntil && val2.State.BloodDebt > 0.0) { float num2 = Mathf.Min(num, (float)val2.State.BloodDebt); Record state = val2.State; state.BloodDebt -= (double)num2; num -= num2; } if (num > 0f) { value.Enqueue((Plugin.Now, num)); ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { component.InvokeRPC("Heal", new object[2] { num, true }); } } } } internal static void BoostCurrent(float amount) { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return; } foreach (SE_Shield item in ((Character)localPlayer).GetSEMan().GetStatusEffects().OfType<SE_Shield>()) { ApplyBoost(item, amount); } } private static void ApplyBoost(SE_Shield shield, float amount) { Boost orCreateValue = boosted.GetOrCreateValue(shield); if (!orCreateValue.Applied) { orCreateValue.Applied = true; Traverse val = Traverse.Create((object)shield).Field("m_totalAbsorbDamage"); if (orCreateValue.Baseline <= 0f) { orCreateValue.Baseline = val.GetValue<float>(); } val.SetValue((object)(orCreateValue.Baseline * (1f + Mathf.Clamp(amount, 0f, 0.08f)))); } } } internal sealed class CastContext { internal long Id; internal Player Owner; internal ItemData Weapon; internal bool Secondary; internal int Combo; internal double Started; internal string School = ""; internal float PenaltyBonus; internal float StaminaCost; internal float DurabilityBefore; internal bool Settled; internal readonly HashSet<int> Targets = new HashSet<int>(); internal readonly HashSet<string> Events = new HashSet<string>(); internal bool Once(string key) { return Events.Add(key); } } public sealed class SkillProjectile : MonoBehaviour { internal CastContext Context; } internal static class CastTracking { private sealed class Scope { internal CastContext Previous; internal CastContext Context; internal bool Finish; } [HarmonyPatch] private static class AttackScope { private static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[5] { "OnAttackTrigger", "ProjectileAttackTriggered", "DoMeleeAttack", "DoAreaAttack", "FireProjectileBurst" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.Method(typeof(Attack), text, (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } } } private static void Prefix(Attack __instance, MethodBase __originalMethod, out Scope __state) { __state = new Scope { Previous = Current }; Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Active && !((Object)(object)Traverse.Create((object)__instance).Field("m_character").GetValue<Humanoid>() != (Object)(object)Player.m_localPlayer)) { if (__originalMethod.Name == "OnAttackTrigger" && Current == null) { attacks.Remove(__instance); attacks.Add(__instance, Create(__instance)); } CastContext castContext = Current ?? attacks.GetValue(__instance, Create); __state.Context = castContext; __state.Finish = Current == null; Current = castContext; } } private static Exception Finalizer(Scope __state, Exception __exception) { if (__state.Context != null && __state.Finish && __exception == null) { AdvancedCombat.Finish(__state.Context); } Current = __state.Previous; return __exception; } } [HarmonyPatch(typeof(Attack), "ModifyDamage")] private static class Stamp { private static void Postfix(HitData __0) { if (Current != null && __0 != null) { hits.Remove(__0); hits.Add(__0, Current); } } } [HarmonyPatch(typeof(HitData), "Clone")] private static class Clone { private static void Postfix(HitData __instance, HitData __result) { if (__result != null) { CastContext castContext = For(__instance); if (castContext != null) { hits.Remove(__result); hits.Add(__result, castContext); } } } } [HarmonyPatch] private static class ProjectileSetup { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Projectile), "Setup", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Aoe), "Setup", (Type[])null, (Type[])null); } private static void Postfix(Component __instance, Character owner, HitData hitData) { if (!((Object)(object)owner != (Object)(object)Player.m_localPlayer)) { CastContext castContext = For(hitData); if (castContext != null) { (__instance.GetComponent<SkillProjectile>() ?? __instance.gameObject.AddComponent<SkillProjectile>()).Context = castContext; } } } } [HarmonyPatch] private static class ProjectileScope { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Projectile), "OnHit", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Projectile), "DoAOE", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Aoe), "OnHit", (Type[])null, (Type[])null); } private static void Prefix(Component __instance, out CastContext __state) { __state = Current; SkillProjectile component = __instance.GetComponent<SkillProjectile>(); if (Object.op_Implicit((Object)(object)component) && component.Context != null) { Current = component.Context; } } private static Exception Finalizer(CastContext __state, Exception __exception) { Current = __state; return __exception; } } [ThreadStatic] internal static CastContext Current; internal static bool ProcessingDot; private static long sequence; private static readonly ConditionalWeakTable<Attack, CastContext> attacks = new ConditionalWeakTable<Attack, CastContext>(); private static readonly ConditionalWeakTable<HitData, CastContext> hits = new ConditionalWeakTable<HitData, CastContext>(); internal static CastContext For(HitData hit) { if (hit == null || !hits.TryGetValue(hit, out var value)) { return Current; } return value; } private static CastContext Create(Attack attack) { Humanoid value = Traverse.Create((object)attack).Field("m_character").GetValue<Humanoid>(); Player val = (Player)(object)((value is Player) ? value : null); return new CastContext { Id = ++sequence, Owner = val, Weapon = attack.GetWeapon(), Secondary = (Object.op_Implicit((Object)(object)val) && Traverse.Create((object)val).Field("m_currentAttackIsSecondary").GetValue<bool>()), Combo = Traverse.Create((object)attack).Field("m_currentAttackCainLevel").GetValue<int>(), Started = Plugin.Now, Settled = (ProfessionHooks.StationarySeconds >= 1.0), StaminaCost = Traverse.Create((object)attack).Field("m_attackStamina").GetValue<float>(), DurabilityBefore = (attack.GetWeapon()?.m_durability ?? 0f), School = MagicSchools.School(attack.GetWeapon()) }; } } internal static class CombatEvents { [HarmonyPatch(typeof(Character), "OnDeath")] private static class AuthorityKill { private static void Prefix(Character __instance) { //IL_011b: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown Plugin instance = Plugin.Instance; if (!Object.op_Implicit((Object)(object)instance) || !instance.Network.IsAuthority || !instance.Network.Connected || __instance.IsPlayer() || __instance.IsTamed()) { return; } HitData value = Traverse.Create((object)__instance).Field("m_lastHit").GetValue<HitData>(); Character val = ((value != null) ? value.GetAttacker() : null); Player val2 = (Player)(object)((val is Player) ? val : null); long num = ((val2 != null) ? val2.GetPlayerID() : ((val == null) ? ((long?)null) : ((Component)val).GetComponent<FamiliarLife>()?.Owner).GetValueOrDefault()); if (num != 0L) { string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); AuthorityProfile val3 = instance.Network.Authority(num); if (val3 != null && (prefabName == "Abomination" || prefabName == "Bjorn")) { val3.State.Discoveries.Add("defeated:" + prefabName); instance.Network.Store(val3); } instance.Network.NotifyPlayer(num, new Envelope { Op = "kill", Tree = instance.TreeFor(value.m_skill), Choice = prefabName, Safe = (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<BaseAI>()) && !((Component)__instance).GetComponent<BaseAI>().IsAlerted()) }); } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class ActualDamage { private static void Prefix(Character __instance, out float __state) { __state = __instance.GetHealth(); } private static void Postfix(Character __instance, float __state) { Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(__instance.GetHealth() >= __state)) { instance.LastDamage = Plugin.Now; instance.LastCombat = Plugin.Now; instance.Network.ObserveCombat(Player.m_localPlayer.GetPlayerID()); PerkState.Clear("axe_rhythm"); if (instance.Has("run", "break_contact") && instance.Data.Trigger("break_contact", Plugin.Now, 15.0)) { PerkState.Grant("run_speed", 3.0, 0.05f); } if (__instance.GetHealthPercentage() < 0.3f && instance.Has("run", "survivors_pace") && instance.Data.Trigger("survivors_pace", Plugin.Now, 30.0)) { PerkState.Grant("run_speed", 4.0, 0.1f); PerkState.Grant("survivor_cost", 4.0, 0.15f); } if (instance.Has("crossbows", "return_fire") && instance.Data.Trigger("return_fire", Plugin.Now, 10.0)) { PerkState.Grant("return_fire", 5.0, 0.2f); } if (instance.Has("bows", "close_escape") && instance.Data.Trigger("close_escape", Plugin.Now, 10.0)) { PerkState.Grant("bow_escape", 4.0, 0.25f); } } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] private static class Blocked { private static void Postfix(Humanoid __instance, HitData hit, bool __result) { Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Active && __result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { if (instance.Has("blocking", "recover_formation")) { PerkState.Grant("stagger_guard", 2.0, 0.1f); } if (instance.Has("swords", "guard_to_edge")) { PerkState.Grant("sword_guard", 3.0, 0.08f); } if (instance.Has("spears", "guarded_thrust")) { PerkState.Grant("spear_guard", 3.0, 0.1f); } if (instance.Has("polearms", "answered_charge")) { PerkState.Grant("polearm_counter", 3.0, 0.2f); } } } } } internal static class CompanionNetwork { [HarmonyPatch(typeof(Character), "Start")] private static class Register { private static void Postfix(Character __instance) { if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Tameable>())) { return; } ZNetView view = ((Component)__instance).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { return; } view.Register<long, string>("VikingMastery.Companion", (Action<long, long, string>)delegate(long sender, long keeper, string action) { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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) long num = (ZNet.instance.IsServer() ? ZNet.GetUID() : (ZNet.instance.GetServerPeer()?.m_uid ?? 0)); if (sender == num && view.IsOwner() && __instance.IsTamed() && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<FamiliarLife>())) { Record val = Plugin.Instance.Network.Build(keeper); if (!(action != "release") || (val != null && val.Rank("animal_husbandry", "chosen_companion") != 0)) { long num2 = view.GetZDO().GetLong("vs_keeper", 0L); if (num2 == 0L || num2 == keeper) { if (action == "release") { view.GetZDO().Set("vs_keeper", 0L); } else { Player val2 = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == keeper)); if (Object.op_Implicit((Object)(object)val2)) { if (action == "bond" && Vector3.Distance(((Component)val2).transform.position, ((Component)__instance).transform.position) <= 6f) { view.GetZDO().Set("vs_keeper", keeper); } if (action == "recall" && num2 == keeper && val.Rank("animal_husbandry", "familiar_voice") > 0 && Vector3.Distance(((Component)val2).transform.position, ((Component)__instance).transform.position) <= 40f) { MonsterAI component = ((Component)__instance).GetComponent<MonsterAI>(); if (Object.op_Implicit((Object)(object)component)) { component.SetFollowTarget(((Component)val2).gameObject); } } } } } } } }); if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CompanionLife>())) { ((Component)__instance).gameObject.AddComponent<CompanionLife>(); } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class Guard { private static void Prefix(Character __instance, HitData hit) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Instance.Network.Connected || hit == null) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner()) { return; } long keeper = component.GetZDO().GetLong("vs_keeper", 0L); if (keeper == 0L) { return; } component.GetZDO().Set("vs_companion_combat", (long)(Plugin.Now + 10.0)); Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == keeper)); Record val2 = Plugin.Instance.Network.Build(keeper); if (Object.op_Implicit((Object)(object)val) && val2 != null && !(Vector3.Distance(((Component)val).transform.position, ((Component)__instance).transform.position) > 12f)) { float num = ((val2.Rank("animal_husbandry", "steadfast_bond") > 0) ? 0.08f : 0f); if (val2.Rank("animal_husbandry", "trusted_companion") > 0 && __instance.GetHealthPercentage() < 0.3f && Plugin.Now >= (double)component.GetZDO().GetLong("vs_companion_guard_ready", 0L)) { component.GetZDO().Set("vs_companion_guard_ready", (long)(Plugin.Now + 90.0)); component.GetZDO().Set("vs_companion_guard_until", (long)(Plugin.Now + 5.0)); } if (Plugin.Now < (double)component.GetZDO().GetLong("vs_companion_guard_until", 0L)) { num = Mathf.Max(num, 0.15f); } ((DamageTypes)(ref hit.m_damage)).Modify(1f - num); } } } internal static void Request(string action, Character animal = null) { //IL_002a: 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_002f: 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_003f: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00c2: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { Vector3 val = (Object.op_Implicit((Object)(object)animal) ? ((Component)animal).transform.position : ((Component)localPlayer).transform.position); Multiplayer network = Plugin.Instance.Network; Envelope val2 = new Envelope { Op = "support", Choice = "companion_" + action }; object perk; if (!Object.op_Implicit((Object)(object)animal)) { perk = ""; } else { ZNetView component = ((Component)animal).GetComponent<ZNetView>(); perk = ((component == null) ? null : ((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO()?.m_uid)/*cast due to .constrained prefix*/).ToString()); } val2.Perk = (string)perk; val2.X = val.x; val2.Y = val.y; val2.Z = val.z; network.Support(val2); } } internal static void Handle(AuthorityProfile profile, Envelope m) { if (m.Choice != "companion_bond" && m.Choice != "companion_recall") { return; } Player player = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && p.GetPlayerID() == profile.Player)); if (!Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead()) { return; } bool flag = m.Choice == "companion_bond"; if (profile.State.Rank("animal_husbandry", flag ? "chosen_companion" : "familiar_voice") == 0 || !profile.State.Trigger("companion_command", Plugin.Now, 1.0)) { return; } Character[] source = Character.GetAllCharacters().Where(delegate(Character c) { if (Object.op_Implicit((Object)(object)c) && c.IsTamed() && !c.IsDead() && !Object.op_Implicit((Object)(object)((Component)c).GetComponent<FamiliarLife>()) && Object.op_Implicit((Object)(object)((Component)c).GetComponent<Tameable>())) { ZNetView component = ((Component)c).GetComponent<ZNetView>(); if (component == null) { return false; } return component.IsValid(); } return false; }).ToArray(); if (flag) { Character candidate = ((IEnumerable<Character>)source).FirstOrDefault((Func<Character, bool>)((Character c) => ((object)Unsafe.As<ZDOID, ZDOID>(ref ((Component)c).GetComponent<ZNetView>().GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString() == m.Perk && Vector3.Distance(((Component)c).transform.position, ((Component)player).transform.position) <= 6f)); if (!Object.op_Implicit((Object)(object)candidate)) { return; } long num = ((Component)candidate).GetComponent<ZNetView>().GetZDO().GetLong("vs_keeper", 0L); if (num != 0L && num != profile.Player) { return; } foreach (Character item in source.Where((Character c) => (Object)(object)c != (Object)(object)candidate && ((Component)c).GetComponent<ZNetView>().GetZDO().GetLong("vs_keeper", 0L) == profile.Player)) { ((Component)item).GetComponent<ZNetView>().InvokeRPC("VikingMastery.Companion", new object[2] { profile.Player, "release" }); } ((Component)candidate).GetComponent<ZNetView>().InvokeRPC("VikingMastery.Companion", new object[2] { profile.Player, "bond" }); return; } foreach (Character item2 in source.Where((Character c) => ((Component)c).GetComponent<ZNetView>().GetZDO().GetLong("vs_keeper", 0L) == profile.Player && Vector3.Distance(((Component)c).transform.position, ((Component)player).transform.position) <= 40f)) { ((Component)item2).GetComponent<ZNetView>().InvokeRPC("VikingMastery.Companion", new object[2] { profile.Player, "recall" }); } } } public sealed class CompanionLife : MonoBehaviour { private double next; private void Update() { if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Instance.Network.Connected || Plugin.Now < next) { return; } next = Plugin.Now + 5.0; ZNetView component = ((Component)this).GetComponent<ZNetView>(); Character component2 = ((Component)this).GetComponent<Character>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner() || !Object.op_Implicit((Object)(object)component2) || component2.IsDead() || Object.op_Implicit((Object)(object)((Component)this).GetComponent<FamiliarLife>())) { return; } long num = component.GetZDO().GetLong("vs_keeper", 0L); if (num == 0L) { return; } Record val = Plugin.Instance.Network.Build(num); if (val == null) { return; } if (val.Rank("animal_husbandry", "chosen_companion") == 0) { component.GetZDO().Set("vs_keeper", 0L); return; } Tameable component3 = ((Component)this).GetComponent<Tameable>(); BaseAI component4 = ((Component)this).GetComponent<BaseAI>(); if (Object.op_Implicit((Object)(object)component4) && component4.IsAlerted()) { component.GetZDO().Set("vs_companion_combat", (long)(Plugin.Now + 10.0)); } else if (val.Rank("animal_husbandry", "quiet_recovery") > 0 && Object.op_Implicit((Object)(object)component3) && !component3.IsHungry() && Plugin.Now >= (double)component.GetZDO().GetLong("vs_companion_combat", 0L)) { component2.Heal(component2.GetMaxHealth() * 0.01f, true); } } } internal static class CostPerks { private static Plugin P => Plugin.Instance; internal static double Attack(ItemData weapon, string tree) { double num = PerkState.Amount("parry_discount"); if (PerkState.On("evade_window") && P.Has("dodge", "ready_weapon")) { num += 0.15; } if (tree == "axes") { num += (double)PerkState.Amount("axe_kill"); } if (tree == "clubs") { num += (double)PerkState.Amount("club_discount"); } if (tree == "knives" && P.Has(tree, "close_rhythm")) { num += (double)PerkState.Count("knife_rhythm") * 0.03; } if (tree == "swords") { if (P.Has(tree, "flowing_steel")) { num += (double)PerkState.Count("sword_flow") * 0.03; } num += (double)PerkState.Amount("sword_parry_cost"); } if (tree == "fists" && P.Has(tree, "slip_and_strike") && PerkState.On("evade_window")) { num += 0.2; } if (Object.op_Implicit((Object)(object)weapon.m_dropPrefab) && ((Object)weapon.m_dropPrefab).name.IndexOf("ServingTray", StringComparison.OrdinalIgnoreCase) >= 0) { num += P.Effect("cooking", "cooking_cost") + (P.Has("cooking", "serving_practice") ? 0.15 : 0.0); } if (Object.op_Implicit((Object)(object)weapon.m_dropPrefab) && ((Object)weapon.m_dropPrefab).name.IndexOf("Scythe", StringComparison.OrdinalIgnoreCase) >= 0) { num += (double)PerkState.Amount("scythe_cost"); } Character val = FacingEnemy(Player.m_localPlayer); if (Object.op_Implicit((Object)(object)val)) { if (tree == "knives" && val.GetHealthPercentage() < 0.3f && P.Has(tree, "finish_the_cut")) { num += 0.2; } if (tree == "spears" && val.IsStaggering() && P.Has(tree, "stay_close")) { num += 0.2; } if (P.Has("sneak", "measured_opening") && Object.op_Implicit((Object)(object)((Component)val).GetComponent<BaseAI>()) && !((Component)val).GetComponent<BaseAI>().IsAlerted()) { num += 0.15; } } if (tree == "spears" && Traverse.Create((object)Player.m_localPlayer).Field("m_currentAttackIsSecondary").GetValue<bool>() && P.Has(tree, "clean_release")) { num += 0.1; } return num; } internal static Character FacingEnemy(Player p) { //IL_0043: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) Character result = null; float num = 25f; foreach (Character allCharacter in Character.GetAllCharacters()) { if (Object.op_Implicit((Object)(object)allCharacter) && !allCharacter.IsDead() && !allCharacter.IsTamed() && !allCharacter.IsPlayer() && Vector3.Distance(((Component)p).transform.position, ((Component)allCharacter).transform.position) < 4f) { float num2 = Vector3.Angle(((Character)p).GetLookDir(), ((Component)allCharacter).transform.position - ((Component)p).transform.position); if (num2 < num) { num = num2; result = allCharacter; } } } return result; } internal static double Jump(Player p) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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) double num = 0.0; if (P.Has("jump", "travel_rhythm") && PerkState.WasRunning && Plugin.Now - PerkState.RunStarted >= 3.0) { num += 0.15; } RaycastHit val = default(RaycastHit); if (P.Has("jump", "hillbound") && Physics.Raycast(((Component)p).transform.position + ((Character)p).GetLookDir() + Vector3.up * 2f, Vector3.down, ref val, 4f, LayerMask.GetMask(new string[3] { "terrain", "piece", "Default" })) && ((RaycastHit)(ref val)).point.y > ((Component)p).transform.position.y + 0.15f) { num += 0.08; } return num; } } internal static class TravelPerks { [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class FallRecovery { private static void Prefix(Character __instance, HitData hit) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 Plugin instance = Plugin.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && (int)hit.m_hitType == 3 && instance.Has("jump", "recover_breath") && instance.Data.Trigger("recover_breath", Plugin.Now, 10.0)) { PerkState.Grant("travel_recovery", 4.0, 0.1f); } } } private static bool grounded = true; private static Vector3 takeoff; private static double undetected; internal static void Tick(Player p) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: 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_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; bool num = ((Character)p).IsOnGround(); if (!num && grounded) { takeoff = ((Component)p).transform.position; } if (num && !grounded) { PerkState.Grant("landed", 2.0); if (instance.Has("jump", "settled_landing")) { PerkState.Grant("stagger_guard", 2.0, 0.08f); } if (instance.Has("jump", "mountain_stride") && ((Component)p).transform.position.y > takeoff.y + 0.25f && instance.Data.Trigger("mountain_stride", Plugin.Now, 8.0)) { PerkState.Grant("travel_speed", 4.0, 0.08f); } if (instance.Has("jump", "vaulting_legs")) { PerkState.Grant("landing_momentum", 0.5, 0.15f); } } grounded = num; if (((Character)p).IsSneaking() && !p.IsSensed()) { if (undetected == 0.0) { undetected = Plugin.Now; } if (instance.Has("sneak", "ghost_trail") && Plugin.Now - undetected >= 10.0) { PerkState.Grant("ghost_trail", 0.2); } } else { undetected = 0.0; } if (!((Character)p).IsSwimming() || !instance.Has("swim", "find_the_bank")) { return; } bool flag = false; RaycastHit val = default(RaycastHit); for (int i = 0; i < 8; i++) { if (flag) { break; } float num2 = (float)i * MathF.PI / 4f; if (Physics.Raycast(((Component)p).transform.position + new Vector3(Mathf.Sin(num2) * 6f, 3f, Mathf.Cos(num2) * 6f), Vector3.down, ref val, 4f, LayerMask.GetMask(new string[3] { "terrain", "piece", "Default" })) && ((RaycastHit)(ref val)).point.y >= ((Component)p).transform.position.y - 0.5f) { flag = true; } } if (flag) { PerkState.Grant("shore_speed", 0.2, 0.06f); } } } internal static class CraftHooks { [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] private static class Duration { private static void Prefix(InventoryGui __instance, out float __state) { __state = __instance.m_craftDuration; if (!Object.op_Implicit((Object)(object)P) || !P.Active) { return; } Recipe value = Traverse.Create((object)__instance).Field("m_craftRecipe").GetValue<Recipe>(); if (!Object.op_Implicit((Object)(object)value) || !Object.op_Implicit((Object)(object)value.m_item)) { return; } ItemData itemData = value.m_item.m_itemData; string obj = (Object.op_Implicit((Object)(object)itemData.m_dropPrefab) ? ((Object)itemData.m_dropPrefab).name : ""); double num = (obj.StartsWith("MeadBase", StringComparison.Ordinal) ? P.Effect("alchemy", "alchemy_craft") : ((itemData.m_shared.m_food > 0f) ? P.Effect("cooking", "food_craft_time") : P.Effect("crafting", "craft_time"))); if (obj.StartsWith("MeadBase", StringComparison.Ordinal)) { if (P.Has("alchemy", "clean_workspace") && PerkState.On("craft_chain_alchemy")) { num += 0.15; } } else if (itemData.m_shared.m_food > 0f) { if (P.Has("cooking", "busy_kitchen") && PerkState.On("craft_chain_food")) { num += 0.1; } num += (double)PerkState.Amount("hearth_craft"); } else if (P.Has("crafting", "workshop_rhythm") && PerkState.On("craft_chain_equipment")) { num += 0.1; } __instance.m_craftDuration *= 1f - (float)Balance.Reduction(num); } private static Exception Finalizer(InventoryGui __instance, float __state, Exception __exception) { __instance.m_craftDuration = __state; return __exception; } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] private static class Crafted { private static void Prefix(InventoryGui __instance, Player player, out string[] __state) { __state = null; if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } Recipe value = Traverse.Create((object)__instance).Field("m_craftRecipe").GetValue<Recipe>(); if (Object.op_Implicit((Object)(object)value) && Object.op_Implicit((Object)(object)value.m_item)) { ItemData itemData = value.m_item.m_itemData; if ((Object.op_Implicit((Object)(object)itemData.m_dropPrefab) ? ((Object)itemData.m_dropPrefab).name : "").StartsWith("MeadBase", StringComparison.Ordinal)) { __state = new string[2] { itemData.m_shared.m_name, ((Humanoid)player).GetInventory().CountItems(itemData.m_shared.m_name, -1, true).ToString() }; } } } private static void Postfix(Player player, string[] __state) { if (__state != null && ((Humanoid)player).GetInventory().CountItems(__state[0], -1, true) > int.Parse(__state[1])) { P.Award("alchemy", 0.5f); } } } [HarmonyPatch(typeof(Player), "EatFood")] private static class LastingMeal { private static void Postfix(Player __instance, ItemData item, bool __result) { if (__result && Object.op_Implicit((Object)(object)P) && P.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && P.Has("cooking", "lasting_meal")) { Food val = ((IEnumerable<Food>)__instance.GetFoods()).FirstOrDefault((Func<Food, bool>)((Food f) => f.m_name == item.m_shared.m_name)); if (val != null) { val.m_time *= 1.05f; } } } } [HarmonyPatch(typeof(Fermenter), "AddItem")] private static class Fermented { private static void Postfix(Fermenter __instance, Humanoid user, bool __result) { if (__result && Object.op_Implicit((Object)(object)P) && P.Active && !((Object)(object)user != (Object)(object)Player.m_localPlayer)) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner()) { component.GetZDO().Set("vs_ferment_multiplier", P.Has("alchemy", "careful_cellaring") ? 0.92f : 1f); component.GetZDO().Set("vs_producer", Player.m_localPlayer.GetPlayerID()); } } } } [HarmonyPatch(typeof(Fermenter), "SlowUpdate")] private static class FermentTime { private static void Prefix(Fermenter __instance, out float __state) { __state = __instance.m_fermentationDuration; ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)P) && P.Active && Object.op_Implicit((Object)(object)component) && component.IsValid()) { __instance.m_fermentationDuration *= Mathf.Clamp(component.GetZDO().GetFloat("vs_ferment_multiplier", 1f), 0.5f, 1f); } } private static Exception Finalizer(Fermenter __instance, float __state, Exception __exception) { __instance.m_fermentationDuration = __state; return __exception; } } private static Plugin P => Plugin.Instance; } internal static class DefenceAndHandling { [HarmonyPatch(typeof(Humanoid), "BlockAttack")] private static class Block { private static void Prefix(Humanoid __instance, out bool __state) { Traverse val = Traverse.Create((object)__instance); __state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && val.Field("m_blockTimer").GetValue<float>() <= val.Field("m_perfectBlockInterval").GetValue<float>(); } private static void Postfix(Humanoid __instance, HitData hit, bool __result, bool __state) { if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (!__result) { if (((Character)__instance).IsStaggering() && P.Has("blocking", "last_rampart") && P.Data.Trigger("last_rampart", Plugin.Now, 30.0)) { ((DamageTypes)(ref hit.m_damage)).Modify(0.85f); Traverse obj = Traverse.Create((object)__instance).Field("m_staggerDamage"); obj.SetValue((object)(obj.GetValue<float>() * 0.8f)); } return; } if (P.Has("blocking", "planted_feet")) { hit.m_pushForce *= 1f - (float)P.Effect("blocking", "block_push"); } if (!__state) { if (P.Has("blocking", "weather_the_blows")) { PerkState.Chain("block_wall", 2, 3.0, 0L); } return; } PerkState.Grant("parry_window", 3.0); PerkState.Grant("parry_attack", 3.0); if (P.Has("blocking", "measured_answer")) { PerkState.Grant("parry_discount", 3.0, 0.15f); } if (P.Has("blocking", "light_on_the_shield") && P.Data.Trigger("light_on_the_shield", Plugin.Now, 4.0)) { ((Character)__instance).AddStamina(5f); } if (P.Has("swords", "answered_blow")) { PerkState.Grant("sword_parry_cost", 3.0, 0.2f); } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class Incoming { private static void Prefix(Character __instance, HitData hit) { if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || hit == null) { return; } Character attacker = hit.GetAttacker(); if (Object.op_Implicit((Object)(object)attacker) && BaseAI.IsEnemy(attacker, __instance) && hit.m_dodgeable && __instance.IsDodgeInvincible() && P.Data.Trigger("evasion_event", Plugin.Now, 0.2)) { PerkState.Grant("evade_window", 3.0); if (P.Has("dodge", "break_away")) { PerkState.Grant("travel_speed", 2.0, 0.08f); } if (P.Has("dodge", "low_profile")) { PerkState.Grant("stagger_guard", 2.0, 0.1f); } if (P.Has("dodge", "second_wind") && P.Data.Trigger("second_wind", Plugin.Now, 8.0)) { __instance.AddStamina(4f); } if (P.Has("dodge", "untouched") && PerkState.Chain("evasions", 2, 8.0, 0L) >= 2 && P.Data.Trigger("untouched", Plugin.Now, 15.0)) { PerkState.Grant("untouched", 4.0, 0.15f); } if (P.Has("dodge", "clean_getaway") && __instance.GetHealthPercentage() < 0.3f && P.Data.Trigger("clean_getaway", Plugin.Now, 30.0)) { PerkState.Grant("travel_speed", 4.0, 0.15f); } } ((DamageTypes)(ref hit.m_damage)).Modify(1f - Mathf.Min(0.2f, PerkState.Amount("blood_guard") + PerkState.Amount("winter_guard"))); } } [HarmonyPatch(typeof(ItemData), "GetBlockPower", new Type[] { typeof(int), typeof(float) })] private static class BlockArmor { private static void Postfix(ItemData __instance, ref float __result) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)P) && P.Active && Traverse.Create((object)Player.m_localPlayer).Field("m_currentBlocker").GetValue<ItemData>() == __instance) { double num = 0.0; if (P.Has("blocking", "braced_shield") && ((Character)Player.m_localPlayer).IsBlocking() && Traverse.Create((object)Player.m_localPlayer).Field("m_blockTimer").GetValue<float>() >= 1f) { num += 0.08; } if (P.Has("blocking", "weather_the_blows")) { num += (double)PerkState.Count("block_wall") * 0.05; } if ((int)__instance.m_shared.m_skillType == 11 && P.Has("fists", "guarded_hands")) { num += 0.08; } __result *= 1f + (float)num; } } } [HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")] private static class BowDrain { private static void Postfix(ItemData __instance, ref float __result) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)P) && P.Active && __instance == ((Humanoid)Player.m_localPlayer).GetCurrentWeapon() && (int)__instance.m_shared.m_skillType == 8) { double num = P.Effect("bows", "attack_cost") + (double)PerkState.Amount("bow_follow") + (double)PerkState.Amount("bow_escape"); float value = Traverse.Create((object)Player.m_localPlayer).Field("m_attackDrawTime").GetValue<float>(); if (P.Has("bows", "patient_release") && value >= __instance.m_shared.m_attack.m_drawDurationMin + 1f) { num += 0.2; } __result *= 1f - (float)Balance.Reduction(num); } } } [HarmonyPatch(typeof(ItemData), "GetWeaponLoadingTime")] private static class Reload { private static void Postfix(ItemData __instance, ref float __result) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)P) && P.Active && __instance == ((Humanoid)Player.m_localPlayer).GetCurrentWeapon() && (int)__instance.m_shared.m_skillType == 14) { __result *= 1f - PerkState.Amount("reload_speed"); } } } [HarmonyPatch(typeof(Player), "UpdateWeaponLoading")] private static class ReloadCost { private static void Prefix(Player __instance, ItemData __0, out (Attack attack, float cost) __state) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 __state = (attack: null, cost: 0f); if (Object.op_Implicit((Object)(object)P) && P.Active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && __0 != null && (int)__0.m_shared.m_skillType == 14) { Attack attack = __0.m_shared.m_attack; __state = (attack: attack, cost: attack.m_reloadStaminaDrain); attack.m_reloadStaminaDrain *= 1f - (float)Balance.Reduction(P.Effect("crossbows", "reload_cost") + (double)PerkState.Amount("return_fire")); } } private static Exception Finalizer((Attack attack, float cost) __state, Exception __exception) { if (__state.attack != null) { __state.attack.m_reloadStaminaDrain = __state.cost; } return __exception; } } [HarmonyPatch(typeof(Player), "IsWeaponLoaded")] private static class Loaded { private static bool before; private static void Postfix(Player __instance, bool __result) { if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (__result && !before) { if (P.Has("crossbows", "keep_it_ready")) { PerkState.Grant("travel_speed", 3.0, 0.05f); } if (PerkState.Consume("reload_speed")) { PerkState.Chain("fast_reloads", 2, 30.0, 0L); } else { PerkState.Clear("fast_reloads"); } } before = __result; } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] private static class MultiHit { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { List<CodeInstruction> code = new List<CodeInstruction>(source); for (int i = 0; i < code.Count; i++) { yield return code[i]; if (i >= 1 && i + 1 < code.Count && code[i].opcode == OpCodes.Mul && code[i - 1].opcode == OpCodes.Ldc_R4 && code[i - 1].operand is float num && Math.Abs(num - 0.75f) < 0.001f && code[i + 1].opcode == OpCodes.Div) { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DefenceAndHandling), "MultiDenominator", (Type[])null, (Type[])null)); } } } } private static Plugin P => Plugin.Instance; internal static float MultiDenominator(float denominator) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) Plugin p = P; CastContext current = CastTracking.Current; if (!Object.op_Implicit((Object)(object)p) || !p.Active || current?.Weapon == null || denominator <= 1f) { return denominator; } string text = p.TreeFor(current.Weapon.m_shared.m_skillType); float num = 0f; if ((text == "axes" && p.Has(text, "wide_hew")) || (text == "clubs" && p.Has(text, "broad_impact")) || (text == "polearms" && p.Has(text, "sweeping_steel")) || (text == "pickaxes" && p.Has(text, "broad_fracture"))) { num = 0.2f; } if (text == "swords" && p.Has(text, "clean_arc")) { num = 0.15f; } if (num == 0f) { return denominator; } float num2 = 1f / ((1f - num) / denominator + num); num2 = Mathf.Max(num2, denominator / 1.3f); current.PenaltyBonus = denominator / num2 - 1f; return num2; } } internal static class DruidItems { internal const string Renewal = "VikingMastery_StaffRenewal"; internal const string Wildbound = "VikingMastery_StaffWildbound"; private static bool registered; internal static void Register() { ItemManager.OnVanillaItemsAvailable += Create; } private static void Create() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00da: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown if (registered) { return; } try { ItemConfig val = new ItemConfig(); val.Name = "Staff of Renewal"; val.Description = "A living bough, bound with roots. Restore an ally with primary attack; plant a healing grove with secondary attack."; val.CraftingStation = "piece_workbench"; val.MinStationLevel = 3; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig("ElderBark", 20, 0, true), new RequirementConfig("AncientSeed", 3, 0, true), new RequirementConfig("SurtlingCore", 2, 0, true), new RequirementConfig("Iron", 5, 0, true) }; CustomItem val2 = new CustomItem("VikingMastery_StaffRenewal", "StaffShield", val); val2.ItemDrop.m_itemData.m_shared.m_skillType = Plugin.Instance.Types["druid"]; ItemManager.Instance.AddItem(val2); val = new ItemConfig(); val.Name = "Staff of the Wildbound"; val.Description = "Call a guardian of the wild. Select a familiar in VikingMastery; primary attack conjures, secondary recalls."; val.CraftingStation = "piece_workbench"; val.MinStationLevel = 3; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig("ElderBark", 25, 0, true), new RequirementConfig("AncientSeed", 5, 0, true), new RequirementConfig("Root", 4, 0, true), new RequirementConfig("Iron", 5, 0, true) }; CustomItem val3 = new CustomItem("VikingMastery_StaffWildbound", "StaffSkeleton", val); val3.ItemDrop.m_itemData.m_shared.m_skillType = Plugin.Instance.Types["druid"]; ItemManager.Instance.AddItem(val3); val = new ItemConfig(); val.Name = "Root Infusion"; val.Description = "Bitter roots steeped with golden mushrooms. A little strength for the old arts."; val.CraftingStation = "piece_cauldron"; val.MinStationLevel = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("MushroomYellow", 3, 0, true), new RequirementConfig("Thistle", 2, 0, true), new RequirementConfig("Honey", 2, 0, true) }; CustomItem val4 = new CustomItem("VikingMastery_RootInfusion", "MushroomYellow", val); SharedData shared = val4.ItemDrop.m_itemData.m_shared; shared.m_food = 15f; shared.m_foodStamina = 15f; shared.m_foodEitr = 35f; shared.m_foodBurnTime = 1200f; shared.m_foodRegen = 1f; ItemManager.Instance.AddItem(val4); registered = true; } catch (Exception ex) { Plugin.Instance.Notice = "Druid equipment registration failed; see BepInEx log."; Logger.LogError((object)ex); } } } internal sealed class Grove { internal Vector3 Position; internal double Until; internal GameObject Visual; } internal sealed class Mend { internal Character Target; internal float Remaining; internal int Ticks; } internal static class DruidRuntime { [HarmonyPatch(typeof(Humanoid), "StartAttack")] private static class StaffActions { private static bool Prefix(Humanoid __instance, bool secondaryAttack, ref bool __result) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)P) || !P.Active || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData currentWeapon = __instance.GetCurrentWeapon(); string text = (Object.op_Implicit((Object)(object)currentWeapon?.m_dropPrefab) ? ((Object)currentWeapon.m_dropPrefab).name : ""); if (text != "VikingMastery_StaffRenewal" && text != "VikingMastery_StaffWildbound") { return true; } Player val = (Player)__instance; if (((Character)val).IsDead() || ((Character)val).InDodge() || ((Character)val).InAttack() || ((Character)val).IsStaggering()) { __result = false; return false; } Cast(val, secondaryAttack, text); __result = false; return false; } } [HarmonyPatch(typeof(Character), "OnDeath")] private static class Death { private static void Prefix(Character __instance) { if (!Object.op_Implicit((Object)(object)P) || !P.Active || Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<FamiliarLife>()) || !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<BaseAI>())) { return; } string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); HitData value = Traverse.Create((object)__instance).Field("m_lastHit").GetValue<HitData>(); if (!P.Network.Connected) { AdvancedCombat.Killed(__instance, value); } if ((!(prefabName == "Abomination") && !(prefabName == "Bjorn")) || value == null) { return; } if (!((Object)(object)value.GetAttacker() == (Object)(object)Player.m_localPlayer)) { Character attacker = value.GetAttacker(); if (((attacker == null) ? ((long?)null) : ((Component)attacker).GetComponent<FamiliarLife>()?.Owner) != Player.m_localPlayer.GetPlayerID()) { return; } } P.Data.Discoveries.Add("defeated:" + prefabName); } } private static readonly List<FamiliarLife> familiars = new List<FamiliarLife>(); private static readonly List<Mend> mends = new List<Mend>(); private static Grove grove; private static double nextTick; private static readonly Dictionary<long, double> groveEntered = new Dictionary<long, double>(); private static readonly Dictionary<long, double> elderUntil = new Dictionary<long, double>(); private static Plugin P => Plugin.Instance; internal static bool InGrove(Player p) { //IL_002a: 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_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_0070: Unknown result type (might be due to invalid IL or missing references) if (!PerkState.On("grove_stagger")) { if (grove != null && Plugin.Now < grove.Until && Vector3.Distance(((Component)p).transform.position, grove.Position) <= 4f + (float)P.Effect("druid", "grove_radius")) { return Visible(grove.Position + Vector3.up, ((Character)p).GetCenterPoint()); } return false; } return true; } internal static bool ElderActive(Player p) { if (!PerkState.On("elder_grove")) { if (elderUntil.TryGetValue(p.GetPlayerID(), out var value)) { return Plugin.Now < value; } return false; } return true; } internal static void Tick(Player p) { if (Plugin.Now < nextTick) { return; } nextTick = Plugin.Now + 1.0; if (((Character)p).IsDead()) { Dismiss(); return; } Mend[] array = mends.ToArray(); foreach (Mend mend in array) { if (!Object.op_Implicit((Object)(object)mend.Target) || mend.Target.IsDead() || mend.Ticks <= 0) { mends.Remove(mend); continue; } float num = mend.Remaining / (float)mend.Ticks; mend.Remaining -= num; mend.Ticks--; Heal(p, mend.Target, num); if (mend.Ticks == 0) { mends.Remove(mend); } } if (grove != null) { if (Plugin.Now >= grove.Until) { if (Object.op_Implicit((Object)(object)grove.Visual)) { Object.Destroy((Object)(object)grove.Visual); } grove = null; } else { float radius = 4f + (float)P.Effect("druid", "grove_radius"); List<Player> list = (from t in Player.GetAllPlayers() where Object.op_Implicit((Object)(object)t) && !((Character)t).IsDead() && !((Character)t).IsPVPEnabled() && ((Character)t).GetHealth() < ((Character)t).GetMaxHealth() && Vector3.Distance(((Component)t).transform.position, grove.Position) <= radius && Visible(grove.Position + Vector3.up, ((Character)t).GetCenterPoint()) select t).ToList(); foreach (Player allPlayer in Player.GetAllPlayers()) { long playerID = allPlayer.GetPlayerID(); if (InGrove(allPlayer)) { if (!groveEntered.ContainsKey(playerID)) { groveEntered[playerID] = Plugin.Now; } if (P.Has("druid", "elder_of_renewal") && Plugin.Now - groveEntered[playerID] >= 3.0) { elderUntil[playerID] = Plugin.Now + 2.0; } } else { groveEntered.Remove(playerID); } } float amount = (float)Balance.HealingShare(3.0, list.Count); foreach (Player item in list) { Heal(p, (Character)(object)item, amount); } } } familiars.RemoveAll((FamiliarLife x) => !Object.op_Implicit((Object)(object)x)); } private static void Heal(Player caster, Character target, float amount) { if (!target.IsDead() && !(amount <= 0f)) { float health = target.GetHealth(); double num = P.Effect("druid", "druid_heal"); if (target.GetHealthPercentage() < 0.4f) { num += P.Effect("druid", "druid_low_heal"); } Player val = (Player)(object)((target is Player) ? target : null); if (val != null && ElderActive(val)) { num += 0.15; } target.Heal(amount * (1f + (float)num), true); float num2 = Mathf.Max(0f, target.GetHealth() - health); if (num2 > 0f && P.Data.Trigger("druid_heal_xp", Plugin.Now, 2.0)) { P.Award("druid", Mathf.Min(num2, 5f) * 0.05f); } } } internal static bool Visible(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return !Physics.Linecast(from, to, LayerMask.GetMask(new string[4] { "Default", "static_solid", "piece", "terrain" })); } private static Character Target(Player p, float range) { //IL_001b: 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) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 origin = ((Character)p).GetEyePoint(); Vector3 dir = ((Character)p).GetLookDir(); return (Character)(((object)(from c in Character.GetAllCharacters().Where(delegate(Character c) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00b8: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)c) && (Object)(object)c != (Object)(object)p && !c.IsDead()) { Player val = (Player)(object)((c is Player) ? c : null); if (((val != null && !((Character)val).IsPVPEnabled()) || (P.Has("druid", "kindred_bond") && ((Component)c).GetComponent<FamiliarLife>()?.Owner == p.GetPlayerID())) && Vector3.Distance(origin, c.GetCenterPoint()) < range) { Vector3 val2 = dir; Vector3 val3 = c.GetCenterPoint() - origin; if (Vector3.Dot(val2, ((Vector3)(ref val3)).normalized) > 0.94f) { return Visible(origin, c.GetCenterPoint()); } } } return false; }) orderby Vector3.Angle(dir, c.GetCenterPoint() - origin) select c).FirstOrDefault()) ?? ((object)p)); } private static bool Spend(Player p, string key, float eitr, double seconds) { if (!P.Data.Ready(key, Plugin.Now)) { P.Notice = "The staff is recovering."; return false; } float num = eitr * (1f - (float)Balance.Reduction(P.Effect("druid", "eitr_cost"))); if (!((Character)p).HaveEitr(num)) { P.Notice = "Not enough eitr."; return false; } ((Character)p).UseEitr(num); ItemData currentWeapon = ((Humanoid)p).GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_useDurability) { currentWeapon.m_durability = Mathf.Max(0f, currentWeapon.m_durability - (1f - (float)P.Effect("druid", "durability"))); } ZSyncAnimation value = Traverse.Create((object)p).Field("m_zanim").GetValue<ZSyncAnimation>(); if (Object.op_Implicit((Object)(object)value)) { value.SetTrigger("staff_shield"); } P.Data.Trigger(key, Plugin.Now, seconds); P.Save(); return true; } internal static void PlayCast(Player p) { ItemData currentWeapon = ((Humanoid)p).GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_useDurability) { currentWeapon.m_durability = Mathf.Max(0f, currentWeapon.m_durability - (1f - (float)P.Effect("druid", "durability"))); } ZSyncAnimation value = Traverse.Create((object)p).Field("m_zanim").GetValue<ZSyncAnimation>(); if (Object.op_Implicit((Object)(object)value)) { value.SetTrigger("staff_shield"); } } internal static void Cast(Player p, bool secondary, string staff) { //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_018c: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) if (P.Network != null && P.Network.Connected)