Decompiled source of VikingMastery v0.1.1

BepInEx/plugins/JustQOL-VikingMastery/VikingMastery.Core.dll

Decompiled a day ago
using 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
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)