Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MyriadJewels v0.1.4
MyriadJewels.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jewelcrafting; using Microsoft.CodeAnalysis; using MyriadJewels.Effects.Bloodstone; using MyriadJewels.Effects.Carnelian; using MyriadJewels.Effects.Hematite; using MyriadJewels.Effects.Howlite; using MyriadJewels.Effects.MossAgate; using MyriadJewels.Effects.Pyrite; using MyriadJewels.Effects.Synergies; using MyriadJewels.Effects.Tourmaline; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MyriadJewels")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b8c3d3c1b9840dfa998919a01d628943223572f0")] [assembly: AssemblyProduct("MyriadJewels")] [assembly: AssemblyTitle("MyriadJewels")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace MyriadJewels { internal static class EffectRegistration { internal static void Register() { API.AddGemEffect<SpiritWolf.Config>("Spirit Wolf", "Summons a wolf cub that scales with your kit.", "Spirit wolf familiar; gem quality $1%."); API.AddGemEffect<CombatCrow.Config>("Combat Crow", "Summons a crow nestling that scales with your kit.", "Combat crow familiar; gem quality $1%."); API.AddGemEffect<SummonPotency.Config>("Summon Potency", "Familiar HP and damage up.", "Familiar power increased by $1%."); API.AddGemEffect<TrophyHunter.Config>("Trophy Hunter", "Trophy drops come easier.", "$1% trophy drop chance; $2% trophy weight reduction."); API.AddGemEffect<SecondWind.Config>("Second Wind", "Stamina recovers sooner after use.", "Stamina regen delay reduced by $1%."); API.AddGemEffect<CombatBreath.Config>("Combat Breath", "Attack and block cost less stamina.", "Attack and block stamina cost reduced by $1%."); API.AddGemEffect<EitrReservoir.Config>("Eitr Reservoir", "Increases maximum eitr.", "Maximum eitr increased by $1."); API.AddGemEffect<ClearHead.Config>("Clear Head", "Eitr returns faster after casting.", "Eitr regen delay reduced by $1%."); API.AddGemEffect<ManicCycle.Config>("Manic Cycle", "Faster adrenaline gain and decay.", "Adrenaline gain/decay rate +$1%."); API.AddGemEffect<SurgeDetonate.Config>("Surge Detonate", "Surge spends adrenaline for burst.", "On Surge, convert adrenaline into $1% burst."); API.AddGemEffect<OverchargeLean.Config>("Overcharge Lean", "Lean into Overcharge risk/reward.", "Overcharge effects amplified by $1%."); API.AddGemEffect<HighWaterAnchor.Config>("High-Water Anchor", "Resist decay while adrenaline is high.", "While high, adrenaline decay reduced by $1%."); API.AddGemEffect<CrestAmp.Config>("Crest Amp", "Power while adrenaline is high.", "While adrenaline ≥ threshold: +$1% combat power."); API.AddGemEffect<TrinketResonance.Config>("Trinket Resonance", "Battle Flow trinkets scale harder while high.", "BF trinket scaling +$1% while high."); API.AddGemEffect<LightningProc.Config>("Lightning Proc", "Chance on hit for lightning burst.", "$2% chance to deal $1% lightning damage."); API.AddGemEffect<SpiritHex.Config>("Spirit Hex", "Chance on hit for spirit damage.", "$2% chance to deal $1% spirit damage."); API.AddGemEffect<PhysicalBurst.Config>("Physical Burst", "Chance on hit for physical burst.", "$2% chance to deal $1% physical burst."); API.AddGemEffect<StaminaSiphon.Config>("Stamina Siphon", "Chance to restore stamina on block/hit.", "$2% chance to restore $1 stamina."); API.AddGemEffect<EitrSiphon.Config>("Eitr Siphon", "Chance to restore eitr on hit.", "$2% chance to restore $1 eitr."); API.AddGemEffect<AdrenalSpike.Config>("Adrenal Spike", "Chance on hit for adrenaline.", "$2% chance to gain $1 adrenaline."); API.AddGemEffect<AddSlash.Config>("Add Slash", "Chance to add slash damage.", "$2% chance to add $1% slash."); API.AddGemEffect<AddBlunt.Config>("Add Blunt", "Chance to add blunt damage.", "$2% chance to add $1% blunt."); API.AddGemEffect<AddPierce.Config>("Add Pierce", "Chance to add pierce damage.", "$2% chance to add $1% pierce."); API.AddGemEffect<AddLightning.Config>("Add Lightning", "Chance to add lightning damage.", "$2% chance to add $1% lightning."); API.AddGemEffect<AddSpirit.Config>("Add Spirit", "Chance to add spirit damage.", "$2% chance to add $1% spirit."); API.AddGemEffect<AddChopPick.Config>("Add Chop Pick", "Chance to add chop/pickaxe damage.", "$2% chance to add $1% tool damage."); API.AddGemEffect<ResistSlash.Config>("Resist Slash", "Reduces slash damage taken.", "Slash damage taken reduced by $1%."); API.AddGemEffect<ResistBlunt.Config>("Resist Blunt", "Reduces blunt damage taken.", "Blunt damage taken reduced by $1%."); API.AddGemEffect<ResistPierce.Config>("Resist Pierce", "Reduces pierce damage taken.", "Pierce damage taken reduced by $1%."); API.AddGemEffect<ResistFire.Config>("Resist Fire", "Reduces fire damage taken.", "Fire damage taken reduced by $1%."); API.AddGemEffect<ResistFrost.Config>("Resist Frost", "Reduces frost damage taken.", "Frost damage taken reduced by $1%."); API.AddGemEffect<ResistLightning.Config>("Resist Lightning", "Reduces lightning damage taken.", "Lightning damage taken reduced by $1%."); API.AddGemEffect<ResistPoison.Config>("Resist Poison", "Reduces poison damage taken.", "Poison damage taken reduced by $1%."); API.AddGemEffect<ResistSpirit.Config>("Resist Spirit", "Reduces spirit damage taken.", "Spirit damage taken reduced by $1%."); API.AddGemEffect<TwinBladeAptitude.Config>("Twin Blade Aptitude", "DualWield skill up.", "DualWield skill +$1%."); API.AddGemEffect<OffHandCatchUp.Config>("Off-Hand Catch-Up", "Softer off-hand penalty while dual.", "Off-hand penalty eased by $1%."); API.AddGemEffect<PairedRhythm.Config>("Paired Rhythm", "After dual hits, short attack speed.", "After dual hits: +$1% attack speed briefly."); API.AddGemEffect<ClawRake.Config>("Claw Rake", "Fist secondary assist.", "Fist secondary power +$1%."); API.AddGemEffect<KickThunder.Config>("Kick Thunder", "2H axe kick stagger.", "Kick stagger / blunt +$1%."); API.AddGemEffect<SledgeQuake.Config>("Sledge Quake", "Sledge special AOE/stagger.", "Sledge special power +$1%."); API.AddGemEffect<GreatWeaponPoise.Config>("Great Weapon Poise", "While 2H: stagger threshold up.", "2H stagger threshold +$1%."); API.AddGemEffect<GreatWeaponEconomy.Config>("Great Weapon Economy", "While 2H: attack stam cost down.", "2H attack stamina cost -$1%."); API.AddGemEffect<GreatWeaponSpecial.Config>("Great Weapon Special", "While 2H: secondary power up.", "2H secondary power +$1%."); API.AddGemEffect<GreatWeaponCommit.Config>("Great Weapon Commit", "While 2H: damage after heavy lands.", "After 2H secondary: +$1% damage briefly."); API.AddGemEffect<WellFedGrace.Config>("Well Fed Grace", "Bonus while Nature Well Fed.", "While Well Fed: +$1% to homestead bonuses."); API.AddGemEffect<Fieldcraft.Config>("Fieldcraft", "Farming, mining, lumber, foraging.", "Profession skills +$1%."); API.AddGemEffect<Outrider.Config>("Outrider", "Ranching, sailing, packhorse.", "Travel/ranch skills +$1%."); API.AddGemEffect<Craftmaster.Config>("Craftmaster", "Blacksmithing and building.", "Craft skills +$1%."); API.AddGemEffect<ExpertRuneforger.Config>("Expert Runeforger", "Runeforging skill.", "Runeforging +$1%."); API.AddGemEffect<ExpertAtgeir.Config>("Expert Atgeir", "Polearm skill.", "Polearms +$1%."); API.AddGemEffect<ExpertUnarmed.Config>("Expert Unarmed", "Fists skill.", "Unarmed +$1%."); API.AddGemEffect<ExpertSledge.Config>("Expert Sledge", "Sledge / 2H blunt skill.", "Clubs +$1%."); API.AddGemEffect<FamiliarBond.Config>("Familiar Bond", "Familiar duration and potency.", "Familiar duration/potency +$1%."); API.AddGemEffect<MoonHunt.Config>("Moon Hunt", "Night trophy hunt.", "At night: trophy chance +$1%."); API.AddGemEffect<ManicEngine.Config>("Manic Engine", "Overdrive Surge amp.", "Surge / detonate power +$1%."); API.AddGemEffect<CrestSovereign.Config>("Crest Sovereign", "Edge crest amp.", "Crest threshold/power +$1%."); API.AddGemEffect<FusedPulse.Config>("Fused Pulse", "High adren eitr return.", "While high adren: eitr return +$1%."); API.AddGemEffect<OpposedHearts.Config>("Opposed Hearts", "Surge AS / low DR.", "On Surge: AS +$1%; when low: DR +$2%."); API.AddGemEffect<TwinTempest.Config>("Twin Tempest", "DualWield cadence amp.", "Off-hand / rhythm ease +$1%."); API.AddGemEffect<GreatOath.Config>("Great Oath", "2H commit amp.", "2H special / commit +$1%."); API.AddGemEffect<Warpath.Config>("Warpath", "Stance hits feed adrenaline.", "Stance hits grant +$1 adrenaline."); API.AddGemEffect<SecondLung.Config>("Second Lung", "Economy sockets amp.", "Second Wind / Combat Breath +$1%."); API.AddGemEffect<OrangeReservoir.Config>("Orange Reservoir", "Eitr reservoir play.", "Eitr Reservoir / Clear Head +$1%."); API.AddGemEffect<Cascade.Config>("Cascade", "Pyrite proc chance up.", "Pyrite proc chances +$1%."); API.AddGemEffect<IronLattice.Config>("Iron Lattice", "Hematite resists amp.", "Hematite resists +$1%."); API.AddGemEffect<RootedCraft.Config>("Rooted Craft", "Profession sockets amp.", "Fieldcraft / Outrider / Craftmaster +$1%."); API.AddGemEffect<GreenThumb.Config>("Green Thumb", "Well Fed + green.", "Well Fed Grace +$1%."); API.AddGemEffect<FullLarder.Config>("Full Larder", "Food drain while Well Fed.", "Food drain -$1% while Well Fed."); API.AddGemEffect<RuneGrove.Config>("Rune Grove", "Runeforge gain.", "Runeforging gain +$1%."); API.AddGemEffect<PackAndPulse.Config>("Pack & Pulse", "Surge echoes to familiars.", "On Surge: familiars gain +$1% power briefly."); } } internal static class Gems { internal static void Register() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_010e: Unknown result type (might be due to invalid IL or missing references) API.AddGems("Howlite", "howlite", new Color(0.92f, 0.93f, 0.9f, 1f)); API.AddGems("Carnelian", "carnelian", new Color(0.82f, 0.28f, 0.14f, 1f)); API.AddGems("Bloodstone", "bloodstone", new Color(0.35f, 0.12f, 0.14f, 1f)); API.AddGems("Pyrite", "pyrite", new Color(0.85f, 0.72f, 0.22f, 1f)); API.AddGems("Hematite", "hematite", new Color(0.35f, 0.36f, 0.4f, 1f)); API.AddGems("Tourmaline", "tourmaline", new Color(0.72f, 0.18f, 0.42f, 1f)); API.AddGems("Moss Agate", "mossagate", new Color(0.35f, 0.55f, 0.28f, 1f)); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class HerbPlantableFix { private readonly struct HerbDef { public readonly string PickableName; public readonly string ItemName; public readonly string PieceName; public readonly string PieceDescription; public HerbDef(string pickableName, string itemName, string pieceName, string pieceDescription) { PickableName = pickableName; ItemName = itemName; PieceName = pieceName; PieceDescription = pieceDescription; } } private static readonly HerbDef[] Herbs = new HerbDef[2] { new HerbDef("Pickable_Sage_bal", "Sage_bal", "Sage", "Plant sage to grow more pickable sage."), new HerbDef("Pickable_Mint_bal", "Mint_bal", "Mint", "Plant mint to grow more pickable mint.") }; [HarmonyPriority(0)] private static void Postfix(ZNetScene __instance) { ((MonoBehaviour)__instance).StartCoroutine(CoFix()); } private static IEnumerator CoFix() { for (int i = 0; i < 180; i++) { if (TryFix()) { yield break; } yield return null; } Plugin.Log.LogWarning((object)"MyriadJewels: could not rebind sage/mint cultivator pickables."); } private static bool TryFix() { ZNetScene instance = ZNetScene.instance; ObjectDB instance2 = ObjectDB.instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance2)) { return false; } List<PieceTable> cultivatorTables = GetCultivatorTables(instance2, instance); if (cultivatorTables.Count == 0) { return false; } bool result = true; HerbDef[] herbs = Herbs; foreach (HerbDef herb in herbs) { if (!FixHerb(instance, instance2, cultivatorTables, herb)) { result = false; } } return result; } private static bool FixHerb(ZNetScene zns, ObjectDB odb, List<PieceTable> tables, HerbDef herb) { GameObject itemPrefab = odb.GetItemPrefab(herb.ItemName); GameObject val = FindPickablePrefab(zns, herb.PickableName, itemPrefab); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)itemPrefab)) { return false; } Pickable component = val.GetComponent<Pickable>(); if (!Object.op_Implicit((Object)(object)component.m_itemPrefab)) { component.m_itemPrefab = itemPrefab; } EnsureInZNetScene(zns, val); if (!Object.op_Implicit((Object)(object)val.GetComponent<Piece>())) { EnsurePiece(val, itemPrefab, zns, herb); } foreach (PieceTable table in tables) { SwapCultivatorPrefab(table, herb.ItemName, val); } return true; } private static GameObject? FindPickablePrefab(ZNetScene zns, string pickableName, GameObject item) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = zns.GetPrefab(pickableName); if (IsWorldPickable(prefab, item)) { return prefab; } GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if (!Object.op_Implicit((Object)(object)val) || ((Object)val).name != pickableName) { continue; } Scene scene = val.scene; if (((Scene)(ref scene)).IsValid()) { scene = val.scene; if (!string.IsNullOrEmpty(((Scene)(ref scene)).name)) { continue; } } if (IsWorldPickable(val, item)) { return val; } } return null; } private static bool IsWorldPickable(GameObject go, GameObject item) { if (!Object.op_Implicit((Object)(object)go) || (Object)(object)go == (Object)(object)item) { return false; } if (!Object.op_Implicit((Object)(object)go.GetComponent<Pickable>())) { return false; } return !Object.op_Implicit((Object)(object)go.GetComponent<ItemDrop>()); } private static void EnsureInZNetScene(ZNetScene zns, GameObject pickable) { int key = StableHash(((Object)pickable).name); if (!zns.m_namedPrefabs.TryGetValue(key, out var value) || !((Object)(object)value == (Object)(object)pickable)) { zns.m_namedPrefabs[key] = pickable; if (!zns.m_prefabs.Contains(pickable)) { zns.m_prefabs.Add(pickable); } } } private static void EnsurePiece(GameObject pickable, GameObject item, ZNetScene zns, HerbDef herb) { //IL_0031: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown ItemDrop component = item.GetComponent<ItemDrop>(); if (Object.op_Implicit((Object)(object)component)) { Piece val = pickable.AddComponent<Piece>(); val.m_name = herb.PieceName; val.m_description = herb.PieceDescription; val.m_category = (PieceCategory)0; val.m_cultivatedGroundOnly = false; val.m_groundOnly = true; val.m_groundPiece = true; val.m_canBeRemoved = true; val.m_targetNonPlayerBuilt = false; val.m_icon = component.m_itemData.GetIcon(); val.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = component, m_amount = 1, m_recover = false } }; GameObject prefab = zns.GetPrefab("RaspberryBush"); Piece val2 = ((prefab != null) ? prefab.GetComponent<Piece>() : null); if (Object.op_Implicit((Object)(object)val2)) { val.m_placeEffect = val2.m_placeEffect; } } } private static void SwapCultivatorPrefab(PieceTable table, string itemName, GameObject pickable) { string name = ((Object)pickable).name; bool flag = false; for (int num = table.m_pieces.Count - 1; num >= 0; num--) { GameObject val = table.m_pieces[num]; if (Object.op_Implicit((Object)(object)val)) { string text = ((Object)val).name.Replace("(Clone)", "").Trim(); if (text == itemName || (Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>()) && !Object.op_Implicit((Object)(object)val.GetComponent<Pickable>()) && (text == itemName || text == name))) { if (flag) { table.m_pieces.RemoveAt(num); } else { table.m_pieces[num] = pickable; flag = true; Plugin.Log.LogInfo((object)("MyriadJewels: cultivator " + itemName + " rebound to " + name)); } } else if (text == name) { if (flag) { table.m_pieces.RemoveAt(num); } else { table.m_pieces[num] = pickable; flag = true; } } } } if (!flag) { table.m_pieces.Add(pickable); } } private static List<PieceTable> GetCultivatorTables(ObjectDB odb, ZNetScene zns) { List<PieceTable> list = new List<PieceTable>(); string[] array = new string[2] { "Cultivator", "BlackMetalCultivator_bal" }; foreach (string text in array) { GameObject obj = odb.GetItemPrefab(text) ?? zns.GetPrefab(text); PieceTable val = ((obj == null) ? null : obj.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if (Object.op_Implicit((Object)(object)val) && !list.Contains(val)) { list.Add(val); } } return list; } private static int StableHash(string str) { int num = 5381; int num2 = 5381; for (int i = 0; i < str.Length; i++) { if ((i & 1) == 0) { num = ((num << 5) + num) ^ str[i]; } else { num2 = ((num2 << 5) + num2) ^ str[i]; } } return num + num2 * 1566083941; } } [BepInPlugin("com.myriad.jewels", "MyriadJewels", "0.1.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.myriad.jewels"; public const string PluginName = "MyriadJewels"; public const string PluginVersion = "0.1.4"; internal static ManualLogSource Log; internal static Harmony Harmony; private void Awake() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; if (!API.IsLoaded()) { Log.LogError((object)"Jewelcrafting API not loaded; MyriadJewels aborted."); return; } EffectRegistration.Register(); Gems.Register(); API.AddGemConfig(LoadEmbeddedYaml()); Harmony = new Harmony("com.myriad.jewels"); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { try { Harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogError((object)("Harmony patch failed for " + type.FullName + ": " + ex.Message)); } } FamiliarController.HookRecalc(); Log.LogInfo((object)("MyriadJewels 0.1.4 loaded (7 stones). SoftMods: " + SoftMods.DumpAsmHint())); } private static string LoadEmbeddedYaml() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("MyriadJewels.yaml", StringComparison.OrdinalIgnoreCase)); if (text == null) { throw new InvalidOperationException("Embedded MyriadJewels.yaml not found."); } using Stream stream = executingAssembly.GetManifestResourceStream(text); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } internal static class SoftMods { private static Assembly? _battleFlow; private static Assembly? _dualMastery; private static bool _bfTried; private static bool _dmTried; internal static Assembly? BattleFlow { get { if (_bfTried) { return _battleFlow; } _bfTried = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "BalrondBattleFlow") { _battleFlow = assembly; break; } } return _battleFlow; } } internal static Assembly? DualMastery { get { if (_dmTried) { return _dualMastery; } _dmTried = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "BalrondDualMastery") { _dualMastery = assembly; break; } } return _dualMastery; } } internal static float GetAdrenaline(Player player) { try { Assembly battleFlow = BattleFlow; if (battleFlow == null) { return 0f; } MethodInfo methodInfo = battleFlow.GetType("BalrondBattleFlow.AdrenalineRuntime")?.GetMethod("GetCurrentAdrenaline", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null) { return 0f; } return (methodInfo.Invoke(null, new object[1] { player }) is float num) ? num : 0f; } catch { return 0f; } } internal static void AddAdrenaline(Player player, float amount) { try { Assembly battleFlow = BattleFlow; if (!(battleFlow == null)) { (battleFlow.GetType("BalrondBattleFlow.AdrenalineRuntime")?.GetMethod("AddAdrenaline", BindingFlags.Static | BindingFlags.Public) ?? battleFlow.GetType("BalrondBattleFlow.AdrenalineRuntime")?.GetMethod("ModifyAdrenaline", BindingFlags.Static | BindingFlags.Public))?.Invoke(null, new object[2] { player, amount }); } } catch { } } internal static bool IsDualWielding(Player player) { try { Assembly dualMastery = DualMastery; if (dualMastery == null) { return false; } MethodInfo methodInfo = dualMastery.GetType("BalrondDualWield.DualWieldMath")?.GetMethod("IsDualWieldingOneHandedWeapons", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null) { return false; } object obj = methodInfo.Invoke(null, new object[1] { player }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } internal static bool IsTwoHandedNoShield(Player player) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 ItemData rightItem = ((Humanoid)player).GetRightItem(); if (rightItem == null) { return false; } if (((Humanoid)player).GetLeftItem() != null) { return false; } return (int)rightItem.m_shared.m_itemType == 14; } internal static string DumpAsmHint() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("BF=").Append(BattleFlow != null).Append(" DM=") .Append(DualMastery != null); return stringBuilder.ToString(); } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class TamedCombatIsEnemy { [HarmonyPriority(0)] private static void Postfix(Character a, Character b, ref bool __result) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)a) || !Object.op_Implicit((Object)(object)b) || (Object)(object)a == (Object)(object)b) { return; } bool flag = a.IsTamed(); bool flag2 = b.IsTamed(); if (flag == flag2) { return; } Character val = (flag ? b : a); if (val is Player) { __result = false; return; } Faction faction = val.GetFaction(); if (((int)faction == 0 || (int)faction == 11) ? true : false) { __result = false; } else { __result = true; } } } } namespace MyriadJewels.Effects.Tourmaline { public static class TwinBladeAptitude { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class OffHandCatchUp { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class PairedRhythm { [PublicAPI] public struct Config { [AdditivePower] public float Power; } internal static int HitCount; internal static float Until; } public static class ClawRake { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class KickThunder { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class SledgeQuake { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class GreatWeaponPoise { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class GreatWeaponEconomy { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class GreatWeaponSpecial { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class GreatWeaponCommit { [PublicAPI] public struct Config { [AdditivePower] public float Power; } internal static float Until; } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] internal static class TourmalineStamina { private static void Postfix(Attack __instance, ref float __result) { Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null && SoftMods.IsTwoHandedNoShield(val)) { float power = API.GetEffectPower<GreatWeaponEconomy.Config>(val, "Great Weapon Economy").Power; if (!(power <= 0f)) { __result *= 100f / (100f + power); } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class TourmalineDamage { [HarmonyPriority(0)] private static void Prefix(HitData hit) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Invalid comparison between Unknown and I4 //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Invalid comparison between Unknown and I4 //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Invalid comparison between Unknown and I4 Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val == null) { return; } float num = 1f; if (SoftMods.IsDualWielding(val)) { PairedRhythm.HitCount++; float num2 = API.GetEffectPower<PairedRhythm.Config>(val, "Paired Rhythm").Power + API.GetEffectPower<TwinTempest.Config>(val, "Twin Tempest").Power; if (num2 > 0f && PairedRhythm.HitCount >= 4) { PairedRhythm.HitCount = 0; PairedRhythm.Until = Time.time + 3f; } if (Time.time < PairedRhythm.Until) { num += num2 / 100f; } float num3 = API.GetEffectPower<OffHandCatchUp.Config>(val, "Off-Hand Catch-Up").Power + API.GetEffectPower<TwinTempest.Config>(val, "Twin Tempest").Power; if (num3 > 0f) { num += num3 / 200f; } } if (SoftMods.IsTwoHandedNoShield(val)) { float power = API.GetEffectPower<GreatOath.Config>(val, "Great Oath").Power; float num4 = API.GetEffectPower<GreatWeaponSpecial.Config>(val, "Great Weapon Special").Power + power; float num5 = API.GetEffectPower<GreatWeaponCommit.Config>(val, "Great Weapon Commit").Power + power; if ((int)hit.m_skill == 7) { num += API.GetEffectPower<KickThunder.Config>(val, "Kick Thunder").Power / 100f; } if ((int)hit.m_skill == 3) { num += API.GetEffectPower<SledgeQuake.Config>(val, "Sledge Quake").Power / 100f; } if ((int)hit.m_skill == 11) { num += API.GetEffectPower<ClawRake.Config>(val, "Claw Rake").Power / 100f; } if (num4 > 0f) { num += num4 / 200f; } if (Time.time < GreatWeaponCommit.Until) { num += num5 / 100f; } else if (num5 > 0f && hit.m_staggerMultiplier > 1f) { GreatWeaponCommit.Until = Time.time + 2.5f; } } if (num != 1f) { hit.ApplyModifier(num); } } } [HarmonyPatch(typeof(Character), "GetStaggerTreshold")] internal static class TourmalinePoise { private static void Postfix(Character __instance, ref float __result) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && SoftMods.IsTwoHandedNoShield(val)) { float power = API.GetEffectPower<GreatWeaponPoise.Config>(val, "Great Weapon Poise").Power; if (!(power <= 0f)) { __result *= 1f + power / 100f; } } } } [HarmonyPatch(typeof(Skills), "GetSkillFactor")] internal static class TourmalineDualSkill { private static void Postfix(Skills __instance, SkillType skillType, ref float __result) { Player player = __instance.m_player; if (!((Object)(object)player == (Object)null)) { float power = API.GetEffectPower<TwinBladeAptitude.Config>(player, "Twin Blade Aptitude").Power; if (power > 0f && SoftMods.DualMastery != null && SoftMods.IsDualWielding(player)) { __result += power / 100f; } } } } } namespace MyriadJewels.Effects.Synergies { public static class FamiliarBond { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class MoonHunt { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class ManicEngine { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class CrestSovereign { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class FusedPulse { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class OpposedHearts { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class TwinTempest { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class GreatOath { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class Warpath { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class SecondLung { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class OrangeReservoir { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class Cascade { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class IronLattice { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class RootedCraft { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class GreenThumb { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class FullLarder { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class RuneGrove { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class PackAndPulse { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } } namespace MyriadJewels.Effects.Pyrite { public static class LightningProc { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class SpiritHex { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class PhysicalBurst { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class StaminaSiphon { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class EitrSiphon { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AdrenalSpike { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } [HarmonyPatch(typeof(Character), "Damage")] internal static class PyriteProcs { [HarmonyPriority(300)] private static void Prefix(HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { float power = API.GetEffectPower<Cascade.Config>(val, "Cascade").Power; float totalDamage = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage(); float value = Random.value; LightningProc.Config effectPower = API.GetEffectPower<LightningProc.Config>(val, "Lightning Proc"); if (effectPower.Power > 0f && value <= (effectPower.Chance + power) / 100f) { hit.m_damage.m_lightning += totalDamage * effectPower.Power / 100f; } SpiritHex.Config effectPower2 = API.GetEffectPower<SpiritHex.Config>(val, "Spirit Hex"); if (effectPower2.Power > 0f && Random.value <= (effectPower2.Chance + power) / 100f) { hit.m_damage.m_spirit += totalDamage * effectPower2.Power / 100f; } PhysicalBurst.Config effectPower3 = API.GetEffectPower<PhysicalBurst.Config>(val, "Physical Burst"); if (effectPower3.Power > 0f && Random.value <= (effectPower3.Chance + power) / 100f) { float num = totalDamage * effectPower3.Power / 100f; hit.m_damage.m_slash += num * 0.34f; hit.m_damage.m_blunt += num * 0.33f; hit.m_damage.m_pierce += num * 0.33f; } EitrSiphon.Config effectPower4 = API.GetEffectPower<EitrSiphon.Config>(val, "Eitr Siphon"); if (effectPower4.Power > 0f && Random.value <= (effectPower4.Chance + power) / 100f) { ((Character)val).AddEitr(effectPower4.Power); } AdrenalSpike.Config effectPower5 = API.GetEffectPower<AdrenalSpike.Config>(val, "Adrenal Spike"); if (effectPower5.Power > 0f && Random.value <= (effectPower5.Chance + power) / 100f) { SoftMods.AddAdrenaline(val, effectPower5.Power); } Warpath.Config effectPower6 = API.GetEffectPower<Warpath.Config>(val, "Warpath"); if (effectPower6.Power > 0f && (SoftMods.IsDualWielding(val) || SoftMods.IsTwoHandedNoShield(val))) { SoftMods.AddAdrenaline(val, effectPower6.Power); } } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] internal static class PyriteStaminaSiphon { private static void Postfix(Humanoid __instance, bool __result) { if (!__result) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { StaminaSiphon.Config effectPower = API.GetEffectPower<StaminaSiphon.Config>(val, "Stamina Siphon"); float power = API.GetEffectPower<Cascade.Config>(val, "Cascade").Power; if (!(effectPower.Power <= 0f) && !(Random.value > (effectPower.Chance + power) / 100f)) { ((Character)val).AddStamina(effectPower.Power); } } } } } namespace MyriadJewels.Effects.MossAgate { public static class WellFedGrace { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class Fieldcraft { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class Outrider { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class Craftmaster { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ExpertRuneforger { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ExpertAtgeir { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ExpertUnarmed { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ExpertSledge { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } [HarmonyPatch(typeof(Skills), "GetSkillFactor")] internal static class MossSkillBoosts { private static void Postfix(Skills __instance, SkillType skillType, ref float __result) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Invalid comparison between Unknown and I4 //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 Player player = __instance.m_player; if ((Object)(object)player == (Object)null) { return; } float power = API.GetEffectPower<RootedCraft.Config>(player, "Rooted Craft").Power; float num = 0f; if (IsWellFed(player)) { num = API.GetEffectPower<WellFedGrace.Config>(player, "Well Fed Grace").Power + API.GetEffectPower<GreenThumb.Config>(player, "Green Thumb").Power; } float num2 = 0f; if ((int)skillType <= 11) { if ((int)skillType != 3) { if ((int)skillType != 4) { if ((int)skillType == 11) { num2 += API.GetEffectPower<ExpertUnarmed.Config>(player, "Expert Unarmed").Power; } } else { num2 += API.GetEffectPower<ExpertAtgeir.Config>(player, "Expert Atgeir").Power; } } else { num2 += API.GetEffectPower<ExpertSledge.Config>(player, "Expert Sledge").Power; } } else if (skillType - 12 > 1) { if ((int)skillType == 103 || (int)skillType == 110) { num2 += API.GetEffectPower<Outrider.Config>(player, "Outrider").Power + power; } } else { num2 += API.GetEffectPower<Fieldcraft.Config>(player, "Fieldcraft").Power + power; } num2 += API.GetEffectPower<Craftmaster.Config>(player, "Craftmaster").Power * 0.25f + power * 0.25f; num2 += API.GetEffectPower<ExpertRuneforger.Config>(player, "Expert Runeforger").Power * 0.25f + API.GetEffectPower<RuneGrove.Config>(player, "Rune Grove").Power * 0.25f; num2 += num * 0.25f; if (num2 > 0f) { __result += num2 / 100f; } } internal static bool IsWellFed(Player player) { foreach (Food food in player.m_foods) { if (food.m_item != null) { return true; } } return false; } } [HarmonyPatch(typeof(Player), "UpdateFood")] internal static class FullLarderFoodDrain { private static void Prefix(Player __instance) { float power = API.GetEffectPower<FullLarder.Config>(__instance, "Full Larder").Power; if (power <= 0f || !MossSkillBoosts.IsWellFed(__instance)) { return; } foreach (Food food in __instance.m_foods) { food.m_time = Mathf.Min(food.m_item.m_shared.m_foodBurnTime, food.m_time + power * 0.02f * Time.fixedDeltaTime); } } } } namespace MyriadJewels.Effects.Howlite { public static class SpiritWolf { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class CombatCrow { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class SummonPotency { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class TrophyHunter { [PublicAPI] public struct Config { [AdditivePower] public float Power; [InverseMultiplicativePercentagePower] public float Chance; } } internal enum FamiliarKind { Wolf, Crow } internal sealed class MyriadFamiliar : MonoBehaviour { internal FamiliarKind Kind; internal long OwnerId; internal float TargetDamage; } internal static class FamiliarController { private const float WolfCooldownBase = 90f; private const float CrowCooldownBase = 75f; private const float MinCooldown = 20f; private const string ZdoFamiliarKey = "Myriad.Familiar"; private const string ZdoOwnerKey = "Myriad.FamiliarOwner"; private const string ZdoDamageKey = "Myriad.FamiliarDamage"; private const string ZdoScaleKey = "Myriad.FamiliarScale"; private const string WolfPrefab = "Wolf_cub"; private const string WolfPrefabFallback = "Wolf"; private const string CrowPrefab = "CrowNestling_bal"; private const string CrowPrefabFallback = "GiantCrow_bal"; private static GameObject? _wolf; private static GameObject? _crow; private static float _wolfCooldownUntil; private static float _crowCooldownUntil; private static float _pulseUntil; private static float _nextSweep; internal static float PulseMul { get { if (!(Time.time < _pulseUntil)) { return 1f; } return 1.25f; } } internal static void HookRecalc() { API.OnEffectRecalc += delegate { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Ensure(localPlayer); } }; } internal static void Ensure(Player player) { float power = API.GetEffectPower<SpiritWolf.Config>(player, "Spirit Wolf").Power; float power2 = API.GetEffectPower<CombatCrow.Config>(player, "Combat Crow").Power; float potency = API.GetEffectPower<SummonPotency.Config>(player, "Summon Potency").Power + API.GetEffectPower<FamiliarBond.Config>(player, "Familiar Bond").Power; if (power > 0f) { _wolf = Maintain(player, _wolf, FamiliarKind.Wolf, power, potency, ref _wolfCooldownUntil); } else { _wolf = Despawn(_wolf, applyCooldown: false); DestroyOwnedKind(player.GetPlayerID(), FamiliarKind.Wolf, null); } if (power2 > 0f) { _crow = Maintain(player, _crow, FamiliarKind.Crow, power2, potency, ref _crowCooldownUntil); return; } _crow = Despawn(_crow, applyCooldown: false); DestroyOwnedKind(player.GetPlayerID(), FamiliarKind.Crow, null); } internal static void DespawnAll(Player player) { if ((Object)(object)_wolf != (Object)null) { LoseFamiliar(FamiliarKind.Wolf, player, applyCooldown: true); _wolf = Despawn(_wolf, applyCooldown: false); } if ((Object)(object)_crow != (Object)null) { LoseFamiliar(FamiliarKind.Crow, player, applyCooldown: true); _crow = Despawn(_crow, applyCooldown: false); } DestroyOwnedKind(player.GetPlayerID(), FamiliarKind.Wolf, null); DestroyOwnedKind(player.GetPlayerID(), FamiliarKind.Crow, null); } internal static void OnFamiliarDeath(Character familiar) { if (!TryGetFamiliar(familiar, out var kind, out var ownerId)) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).IsOwner() && (ownerId == 0L || ownerId == localPlayer.GetPlayerID()) && (ownerId != 0L || (kind == FamiliarKind.Wolf && Object.op_Implicit((Object)(object)_wolf) && (Object)(object)((Component)familiar).gameObject == (Object)(object)_wolf) || (kind == FamiliarKind.Crow && Object.op_Implicit((Object)(object)_crow) && (Object)(object)((Component)familiar).gameObject == (Object)(object)_crow))) { LoseFamiliar(kind, localPlayer, applyCooldown: true); if (kind == FamiliarKind.Wolf) { _wolf = null; } else { _crow = null; } } } private static void LoseFamiliar(FamiliarKind kind, Player player, bool applyCooldown) { if (applyCooldown) { float num = RespawnCooldown(player, (kind == FamiliarKind.Wolf) ? 90f : 75f); if (kind == FamiliarKind.Wolf) { _wolfCooldownUntil = Time.time + num; } else { _crowCooldownUntil = Time.time + num; } } } private static float RespawnCooldown(Player player, float baseSeconds) { float num = API.GetEffectPower<SummonPotency.Config>(player, "Summon Potency").Power + API.GetEffectPower<FamiliarBond.Config>(player, "Familiar Bond").Power; return Mathf.Max(20f, baseSeconds * 100f / (100f + num)); } internal static bool IsFamiliar(Character character) { FamiliarKind kind; long ownerId; return TryGetFamiliar(character, out kind, out ownerId); } internal static bool TryGetFamiliar(Character character, out FamiliarKind kind, out long ownerId) { kind = FamiliarKind.Wolf; ownerId = 0L; if (!Object.op_Implicit((Object)(object)character)) { return false; } bool flag = false; ZNetView nview = character.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { ZDO zDO = nview.GetZDO(); int num = zDO.GetInt("Myriad.Familiar", 0); if (num > 0) { kind = ((num == 2) ? FamiliarKind.Crow : FamiliarKind.Wolf); ownerId = zDO.GetLong("Myriad.FamiliarOwner", 0L); flag = true; } } MyriadFamiliar myriadFamiliar = default(MyriadFamiliar); if (((Component)character).TryGetComponent<MyriadFamiliar>(ref myriadFamiliar)) { if (flag) { myriadFamiliar.Kind = kind; if (ownerId != 0L) { myriadFamiliar.OwnerId = ownerId; } } else { kind = myriadFamiliar.Kind; ownerId = myriadFamiliar.OwnerId; } return true; } return flag; } internal static void TryBind(Character character) { if (Object.op_Implicit((Object)(object)character) && TryGetFamiliar(character, out var kind, out var ownerId)) { Dress(character, kind, ownerId); } } internal static void Pulse(float seconds, float _) { _pulseUntil = Time.time + seconds; } internal static void TickFollow(Player player) { TickFollowOne(player, ref _wolf, FamiliarKind.Wolf, 2f, 0f); TickFollowOne(player, ref _crow, FamiliarKind.Crow, 3f, 1.5f); if (!(Time.time < _nextSweep)) { _nextSweep = Time.time + 2f; SweepOrphans(); RetuneAlive(player); } } private static void TickFollowOne(Player player, ref GameObject? familiar, FamiliarKind kind, float radius, float height) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)familiar)) { familiar = null; return; } Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * (0f - radius) + Vector3.up * height; Character component = familiar.GetComponent<Character>(); if ((Object)(object)component == (Object)null) { familiar.transform.position = Vector3.Lerp(familiar.transform.position, val, Time.deltaTime * 2f); return; } Dress(component, kind, player.GetPlayerID()); MonsterAI component2 = ((Component)component).GetComponent<MonsterAI>(); if (component2 != null) { if ((Object)(object)component2.GetFollowTarget() != (Object)(object)((Component)player).gameObject) { component2.SetFollowTarget(((Component)player).gameObject); } ((BaseAI)component2).m_alerted = true; } if (Vector3.Distance(((Component)component).transform.position, ((Component)player).transform.position) > 40f) { TeleportFamiliar(component, val); } } private static void TeleportFamiliar(Character ch, Vector3 target) { //IL_0006: 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) ((Component)ch).transform.position = target; if ((Object)(object)ch.m_nview != (Object)null && ch.m_nview.IsValid() && ch.m_nview.IsOwner()) { ch.m_nview.GetZDO().SetPosition(target); } } private static GameObject? Maintain(Player player, GameObject? existing, FamiliarKind kind, float power, float potency, ref float cooldownUntil) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_013f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)existing != (Object)null && !Object.op_Implicit((Object)(object)existing)) { existing = null; } if ((Object)(object)existing != (Object)null) { ApplyStats(existing, player, kind, power, potency, fillHealth: false); return existing; } if (Time.time < cooldownUntil) { return null; } if (player.GetPlayerID() == 0L || (Object)(object)ZNetScene.instance == (Object)null) { return null; } DestroyOwnedKind(player.GetPlayerID(), kind, null); string text = ((kind == FamiliarKind.Crow) ? "CrowNestling_bal" : "Wolf_cub"); string text2 = ((kind == FamiliarKind.Crow) ? "GiantCrow_bal" : "Wolf"); ZNetScene instance = ZNetScene.instance; object obj = ((instance != null) ? instance.GetPrefab(text) : null); if (obj == null) { ZNetScene instance2 = ZNetScene.instance; obj = ((instance2 != null) ? instance2.GetPrefab(text2) : null); } GameObject val = (GameObject)obj; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("MyriadJewels: familiar prefab '" + text + "' / '" + text2 + "' missing.")); return null; } ComputeStats(player, kind, power, potency, out var hp, out var damage, out var visualScale); Vector3 val2 = ((Component)player).transform.position + ((Component)player).transform.forward * 2f + Vector3.up * ((kind == FamiliarKind.Crow) ? 1.2f : 0f); GameObject val3 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity); StripRanchBehaviors(val3); long playerID = player.GetPlayerID(); if (!MarkZdo(val3, kind, playerID, damage, visualScale)) { Plugin.Log.LogWarning((object)("MyriadJewels: aborting " + ((Object)val).name + " spawn, ZDO mark failed.")); DestroyNetworked(val3); return null; } ApplyStats(val3, player, kind, power, potency, fillHealth: true); MonsterAI component = val3.GetComponent<MonsterAI>(); if (component != null) { component.SetFollowTarget(((Component)player).gameObject); ((BaseAI)component).m_alerted = true; } DropOnDestroyed[] componentsInChildren = val3.GetComponentsInChildren<DropOnDestroyed>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Plugin.Log.LogInfo((object)$"Spawned familiar {((Object)val).name} hp={hp:0} dmg={damage:0.0} scale={visualScale:0.00} kit={KitPower(player):0} gem={power} pot={potency}."); return val3; } private static void RetuneAlive(Player player) { float power = API.GetEffectPower<SpiritWolf.Config>(player, "Spirit Wolf").Power; float power2 = API.GetEffectPower<CombatCrow.Config>(player, "Combat Crow").Power; float potency = API.GetEffectPower<SummonPotency.Config>(player, "Summon Potency").Power + API.GetEffectPower<FamiliarBond.Config>(player, "Familiar Bond").Power; if (power > 0f && Object.op_Implicit((Object)(object)_wolf)) { ApplyStats(_wolf, player, FamiliarKind.Wolf, power, potency, fillHealth: false); } if (power2 > 0f && Object.op_Implicit((Object)(object)_crow)) { ApplyStats(_crow, player, FamiliarKind.Crow, power2, potency, fillHealth: false); } } private static void ApplyStats(GameObject go, Player player, FamiliarKind kind, float power, float potency, bool fillHealth) { if (!Object.op_Implicit((Object)(object)go)) { return; } ComputeStats(player, kind, power, potency, out var hp, out var damage, out var visualScale); if (!MarkZdo(go, kind, player.GetPlayerID(), damage, visualScale)) { return; } Character component = go.GetComponent<Character>(); if (component != null) { float maxHealth = component.GetMaxHealth(); float health = component.GetHealth(); component.SetMaxHealth(hp); if (fillHealth) { component.SetHealth(hp); } else if (hp > maxHealth) { component.SetHealth(health + (hp - maxHealth)); } else { component.SetHealth(Mathf.Min(health, hp)); } Dress(component, kind, player.GetPlayerID()); } } private static float KitPower(Player player) { float bodyArmor = ((Character)player).GetBodyArmor(); float maxEitr = ((Character)player).GetMaxEitr(); return Mathf.Max(bodyArmor, maxEitr * 0.5f); } private static void ComputeStats(Player player, FamiliarKind kind, float power, float potency, out float hp, out float damage, out float visualScale) { float num = KitPower(player); float num2 = ((num <= 100f) ? (num / 100f) : ((100f + Mathf.Min((num - 100f) * 0.25f, 20f)) / 100f)); float num3 = Mathf.Clamp(0.85f + (power - 15f) / 25f * 0.35f, 0.8f, 1.25f); float num4 = 1f + potency / 200f; float num5 = num3 * num4; hp = (26f + 74f * num2) * num5; damage = (8f + 34f * num2) * num5; visualScale = 0.72f + 0.4f * num2 + (num3 - 1f) * 0.15f; if (kind == FamiliarKind.Crow) { hp *= 0.85f; damage *= 0.85f; visualScale *= 0.9f; } hp = Mathf.Clamp(hp, 16f, 125f); damage = Mathf.Clamp(damage, 5f, 50f); visualScale = Mathf.Clamp(visualScale, 0.65f, 1.18f); } private static void StripRanchBehaviors(GameObject go) { Growup[] componentsInChildren = go.GetComponentsInChildren<Growup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Procreation[] componentsInChildren2 = go.GetComponentsInChildren<Procreation>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } CharacterTimedDestruction[] componentsInChildren3 = go.GetComponentsInChildren<CharacterTimedDestruction>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } } private static bool MarkZdo(GameObject go, FamiliarKind kind, long ownerId, float damage, float visualScale) { //IL_00a3: 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) ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } if (!component.IsOwner()) { component.ClaimOwnership(); } if (!component.IsOwner()) { return false; } ZDO zDO = component.GetZDO(); zDO.Persistent = false; component.m_persistent = false; component.m_syncInitialScale = true; zDO.Set("Myriad.Familiar", (kind != FamiliarKind.Crow) ? 1 : 2); zDO.Set("Myriad.FamiliarOwner", ownerId); zDO.Set("Myriad.FamiliarDamage", damage); zDO.Set("Myriad.FamiliarScale", visualScale); zDO.Set(ZDOVars.s_scaleScalarHash, visualScale); zDO.Set(ZDOVars.s_tamed, true); go.transform.localScale = Vector3.one * visualScale; return true; } internal static void ScaleOutgoingHit(HitData hit) { if (hit == null) { return; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null) { return; } TryBind(attacker); MyriadFamiliar myriadFamiliar = default(MyriadFamiliar); if (!((Component)attacker).TryGetComponent<MyriadFamiliar>(ref myriadFamiliar)) { if (IsFamiliar(attacker)) { hit.ApplyModifier(0.25f); } return; } float totalDamage = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage(); if (totalDamage <= 0.01f) { return; } if (myriadFamiliar.TargetDamage <= 0f) { hit.ApplyModifier(0.25f); return; } float num = myriadFamiliar.TargetDamage; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && myriadFamiliar.OwnerId == localPlayer.GetPlayerID()) { num *= PulseMul; } float num2 = num / totalDamage; hit.ApplyModifier(num2); hit.m_pushForce *= Mathf.Clamp(num2, 0.25f, 1f); hit.m_staggerMultiplier *= Mathf.Clamp(num2, 0.35f, 1f); } private static void Dress(Character ch, FamiliarKind kind, long ownerId) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) MyriadFamiliar myriadFamiliar = default(MyriadFamiliar); if (!((Component)ch).TryGetComponent<MyriadFamiliar>(ref myriadFamiliar)) { myriadFamiliar = ((Component)ch).gameObject.AddComponent<MyriadFamiliar>(); } myriadFamiliar.Kind = kind; myriadFamiliar.OwnerId = ownerId; ZNetView nview = ch.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { ZDO zDO = nview.GetZDO(); float num = zDO.GetFloat("Myriad.FamiliarDamage", myriadFamiliar.TargetDamage); if (num > 0f) { myriadFamiliar.TargetDamage = num; } float num2 = zDO.GetFloat("Myriad.FamiliarScale", 0f); if (num2 > 0.1f) { ((Component)ch).transform.localScale = Vector3.one * num2; } } ch.m_faction = (Faction)0; ch.m_tamed = true; if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner()) { nview.GetZDO().Set(ZDOVars.s_tamed, true); if (!ch.IsTamed()) { ch.SetTamed(true); } } CharacterDrop component = ((Component)ch).GetComponent<CharacterDrop>(); if (component != null) { component.m_dropsEnabled = false; } Player val = FindOwner(ownerId); if ((Object)(object)val != (Object)null) { MonsterAI component2 = ((Component)ch).GetComponent<MonsterAI>(); if (component2 != null && (Object)(object)component2.GetFollowTarget() != (Object)(object)((Component)val).gameObject) { component2.SetFollowTarget(((Component)val).gameObject); } } } private static Player? FindOwner(long ownerId) { if (ownerId == 0L) { return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && localPlayer.GetPlayerID() == ownerId) { return localPlayer; } foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == ownerId) { return allPlayer; } } return null; } private static GameObject? Despawn(GameObject? go, bool applyCooldown) { if ((Object)(object)go != (Object)null) { if (applyCooldown) { Player localPlayer = Player.m_localPlayer; MyriadFamiliar myriadFamiliar = default(MyriadFamiliar); if (localPlayer != null && go.TryGetComponent<MyriadFamiliar>(ref myriadFamiliar)) { LoseFamiliar(myriadFamiliar.Kind, localPlayer, applyCooldown: true); } } DestroyNetworked(go); } return null; } private static void DestroyOwnedKind(long ownerId, FamiliarKind kind, GameObject? except) { if (ownerId == 0L) { return; } List<GameObject> list = new List<GameObject>(); foreach (Character allCharacter in Character.GetAllCharacters()) { if (Object.op_Implicit((Object)(object)allCharacter) && !((Object)(object)((Component)allCharacter).gameObject == (Object)(object)except) && TryGetFamiliar(allCharacter, out var kind2, out var ownerId2) && kind2 == kind && ownerId2 == ownerId) { list.Add(((Component)allCharacter).gameObject); } } foreach (GameObject item in list) { DestroyNetworked(item); } } private static void SweepOrphans() { List<GameObject> list = new List<GameObject>(); foreach (Character allCharacter in Character.GetAllCharacters()) { if (!Object.op_Implicit((Object)(object)allCharacter)) { continue; } TryBind(allCharacter); if (TryGetFamiliar(allCharacter, out var _, out var ownerId) && ownerId != 0L && !((Object)(object)FindOwner(ownerId) != (Object)null)) { ZNetView nview = allCharacter.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { list.Add(((Component)allCharacter).gameObject); } } } foreach (GameObject item in list) { DestroyNetworked(item); } } private static void DestroyNetworked(GameObject go) { if (!Object.op_Implicit((Object)(object)go)) { return; } try { ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Persistent = false; component.m_persistent = false; if (!component.IsOwner()) { component.ClaimOwnership(); } if (component.IsOwner() && (Object)(object)ZNetScene.instance != (Object)null) { component.Destroy(); return; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("MyriadJewels: familiar despawn failed: " + ex.Message)); } Object.Destroy((Object)(object)go); } } [HarmonyPatch(typeof(Character), "Awake")] internal static class FamiliarBindOnSpawn { private static void Postfix(Character __instance) { FamiliarController.TryBind(__instance); } } [HarmonyPatch(typeof(Character), "Damage")] internal static class FamiliarOutgoingDamage { private static void Prefix(HitData hit) { FamiliarController.ScaleOutgoingHit(hit); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class FamiliarBootstrap { private static void Postfix(Player __instance) { if (((Character)__instance).IsOwner()) { FamiliarController.Ensure(__instance); } } } [HarmonyPatch(typeof(Humanoid), "EquipItem", new Type[] { typeof(ItemData), typeof(bool) })] internal static class FamiliarOnEquip { private static void Postfix(Humanoid __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ((Character)val).IsOwner()) { FamiliarController.Ensure(val); } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[] { typeof(ItemData), typeof(bool) })] internal static class FamiliarOnUnequip { private static void Postfix(Humanoid __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ((Character)val).IsOwner()) { FamiliarController.Ensure(val); } } } [HarmonyPatch(typeof(Player), "OnDestroy")] internal static class FamiliarOnPlayerDestroy { private static void Prefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { FamiliarController.DespawnAll(__instance); } } } [HarmonyPatch(typeof(Game), "Update")] internal static class FamiliarFollowTick { private static void Postfix() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).IsOwner()) { FamiliarController.TickFollow(localPlayer); } } } [HarmonyPatch(typeof(Character), "OnDeath")] internal static class FamiliarOnDeath { private static void Prefix(Character __instance) { if (FamiliarController.IsFamiliar(__instance)) { CharacterDrop component = ((Component)__instance).GetComponent<CharacterDrop>(); if (component != null) { component.m_dropsEnabled = false; } FamiliarController.OnFamiliarDeath(__instance); } } } [HarmonyPatch(typeof(DropOnDestroyed), "OnDestroyed")] internal static class FamiliarNoDropOnDestroyed { private static bool Prefix(DropOnDestroyed __instance) { Character componentInParent = ((Component)__instance).GetComponentInParent<Character>(); if (!((Object)(object)componentInParent == (Object)null)) { return !FamiliarController.IsFamiliar(componentInParent); } return true; } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] internal static class FamiliarNoCharacterDrop { private static bool Prefix(CharacterDrop __instance) { Character component = ((Component)__instance).GetComponent<Character>(); if (!((Object)(object)component == (Object)null)) { return !FamiliarController.IsFamiliar(component); } return true; } } [HarmonyPatch(typeof(Character), "OnDeath")] internal static class TrophyHunterOnKill { private static void Prefix(Character __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ((Character)val).IsOwner()) { FamiliarController.DespawnAll(val); } else { if (FamiliarController.IsFamiliar(__instance)) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { TrophyHunter.Config effectPower = API.GetEffectPower<TrophyHunter.Config>(localPlayer, "Trophy Hunter"); float power = API.GetEffectPower<MoonHunt.Config>(localPlayer, "Moon Hunt").Power; float num = effectPower.Power + (EnvMan.IsNight() ? power : 0f); if (!(num <= 0f) && !(Random.value > num / 100f)) { ((Character)localPlayer).AddStamina(Mathf.Clamp(num * 0.25f, 1f, 10f)); } } } } } [HarmonyPatch(typeof(ItemData), "GetWeight")] internal static class TrophyWeightReduce { private static void Postfix(ItemData __instance, ref float __result) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float chance = API.GetEffectPower<TrophyHunter.Config>(localPlayer, "Trophy Hunter").Chance; if (!(chance <= 0f) && (int)__instance.m_shared.m_itemType == 1 && !(__instance.m_shared.m_weight < 5f)) { __result *= (100f - Mathf.Clamp(chance, 0f, 50f)) / 100f; } } } } } namespace MyriadJewels.Effects.Hematite { public static class AddSlash { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AddBlunt { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AddPierce { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AddLightning { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AddSpirit { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class AddChopPick { [PublicAPI] public struct Config { [AdditivePower] public float Power; [AdditivePower] public float Chance; } } public static class ResistSlash { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistBlunt { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistPierce { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistFire { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistFrost { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistLightning { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistPoison { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class ResistSpirit { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } [HarmonyPatch(typeof(Character), "Damage")] internal static class HematiteTypedDamage { private static void Prefix(HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { float power = API.GetEffectPower<Cascade.Config>(val, "Cascade").Power; float totalDamage = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage(); float value = Random.value; float value2 = Random.value; AddSlash.Config effectPower = API.GetEffectPower<AddSlash.Config>(val, "Add Slash"); if (effectPower.Power > 0f && value <= (effectPower.Chance + power) / 100f) { hit.m_damage.m_slash += totalDamage * effectPower.Power / 100f; } AddBlunt.Config effectPower2 = API.GetEffectPower<AddBlunt.Config>(val, "Add Blunt"); if (effectPower2.Power > 0f && value <= (effectPower2.Chance + power) / 100f) { hit.m_damage.m_blunt += totalDamage * effectPower2.Power / 100f; } AddPierce.Config effectPower3 = API.GetEffectPower<AddPierce.Config>(val, "Add Pierce"); if (effectPower3.Power > 0f && value <= (effectPower3.Chance + power) / 100f) { hit.m_damage.m_pierce += totalDamage * effectPower3.Power / 100f; } AddLightning.Config effectPower4 = API.GetEffectPower<AddLightning.Config>(val, "Add Lightning"); if (effectPower4.Power > 0f && value2 <= (effectPower4.Chance + power) / 100f) { hit.m_damage.m_lightning += totalDamage * effectPower4.Power / 100f; } AddSpirit.Config effectPower5 = API.GetEffectPower<AddSpirit.Config>(val, "Add Spirit"); if (effectPower5.Power > 0f && value2 <= (effectPower5.Chance + power) / 100f) { hit.m_damage.m_spirit += totalDamage * effectPower5.Power / 100f; } AddChopPick.Config effectPower6 = API.GetEffectPower<AddChopPick.Config>(val, "Add Chop Pick"); if (effectPower6.Power > 0f && value <= (effectPower6.Chance + power) / 100f) { float num = totalDamage * effectPower6.Power / 100f; hit.m_damage.m_chop += num; hit.m_damage.m_pickaxe += num; } } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class HematiteResists { private static void Prefix(Character __instance, HitData hit) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { Character attacker = hit.GetAttacker(); if (attacker != null && !((Object)(object)attacker == (Object)(object)__instance)) { float power = API.GetEffectPower<IronLattice.Config>(val, "Iron Lattice").Power; Scale(ref hit.m_damage.m_slash, API.GetEffectPower<ResistSlash.Config>(val, "Resist Slash").Power + power); Scale(ref hit.m_damage.m_blunt, API.GetEffectPower<ResistBlunt.Config>(val, "Resist Blunt").Power + power); Scale(ref hit.m_damage.m_pierce, API.GetEffectPower<ResistPierce.Config>(val, "Resist Pierce").Power + power); Scale(ref hit.m_damage.m_fire, API.GetEffectPower<ResistFire.Config>(val, "Resist Fire").Power + power); Scale(ref hit.m_damage.m_frost, API.GetEffectPower<ResistFrost.Config>(val, "Resist Frost").Power + power); Scale(ref hit.m_damage.m_lightning, API.GetEffectPower<ResistLightning.Config>(val, "Resist Lightning").Power + power); Scale(ref hit.m_damage.m_poison, API.GetEffectPower<ResistPoison.Config>(val, "Resist Poison").Power + power); Scale(ref hit.m_damage.m_spirit, API.GetEffectPower<ResistSpirit.Config>(val, "Resist Spirit").Power + power); } } } private static void Scale(ref float value, float resistPower) { if (!(value <= 0f) && !(resistPower <= 0f)) { value *= (100f - Mathf.Clamp(resistPower, 0f, 90f)) / 100f; } } } } namespace MyriadJewels.Effects.Carnelian { public static class SecondWind { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class CombatBreath { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] private static class ReduceAttackStamina { private static void Postfix(Attack __instance, ref float __result) { Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { float num = API.GetEffectPower<Config>(val, "Combat Breath").Power + API.GetEffectPower<SecondLung.Config>(val, "Second Lung").Power; if (!(num <= 0f)) { __result *= 100f / (100f + num); } } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] private static class ReduceBlockStamina { private static void Prefix(Humanoid __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { float num = API.GetEffectPower<Config>(val, "Combat Breath").Power + API.GetEffectPower<SecondLung.Config>(val, "Second Lung").Power; if (!(num <= 0f)) { __instance.m_blockStaminaDrain *= 100f / (100f + num); } } } } } public static class EitrReservoir { [PublicAPI] public struct Config { [AdditivePower] public float Power; } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] private static class IncreaseMaxEitr { private static void Postfix(Player __instance, ref float eitr) { float power = API.GetEffectPower<Config>(__instance, "Eitr Reservoir").Power; float power2 = API.GetEffectPower<OrangeReservoir.Config>(__instance, "Orange Reservoir").Power; eitr += power + power2; } } } public static class ClearHead { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { })] internal static class CarnelianUpdateStats { private static void Prefix(Player __instance) { float num = API.GetEffectPower<SecondWind.Config>(__instance, "Second Wind").Power + API.GetEffectPower<SecondLung.Config>(__instance, "Second Lung").Power; if (num > 0f) { __instance.m_staminaRegenDelay = Mathf.Max(0.1f, __instance.m_staminaRegenDelay * (100f - num) / 100f); } float num2 = API.GetEffectPower<ClearHead.Config>(__instance, "Clear Head").Power + API.GetEffectPower<OrangeReservoir.Config>(__instance, "Orange Reservoir").Power; if (num2 > 0f) { __instance.m_eitrRegenDelay = Mathf.Max(0.1f, __instance.m_eitrRegenDelay * (100f - num2) / 100f); } } } } namespace MyriadJewels.Effects.Bloodstone { public static class ManicCycle { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class SurgeDetonate { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class OverchargeLean { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class HighWaterAnchor { [PublicAPI] public struct Config { [InverseMultiplicativePercentagePower] public float Power; } } public static class CrestAmp { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } public static class TrinketResonance { [PublicAPI] public struct Config { [AdditivePower] public float Power; } } [HarmonyPatch(typeof(Character), "Damage")] internal static class BloodstoneCombat { [HarmonyPriority(100)] private static void Prefix(HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { float adrenaline = SoftMods.GetAdrenaline(val); float num = 1f; float num2 = API.GetEffectPower<ManicCycle.Config>(val, "Manic Cycle").Power + API.GetEffectPower<ManicEngine.Config>(val, "Manic Engine").Power; if (num2 > 0f) { SoftMods.AddAdrenaline(val, num2 * 0.05f); } float num3 = API.GetEffectPower<CrestAmp.Config>(val, "Crest Amp").Power + API.GetEffectPower<CrestSovereign.Config>(val, "Crest Sovereign").Power; float num4 = 60f; if (API.GetEffectPower<CrestSovereign.Config>(val, "Crest Sovereign").Power > 0f) { num4 = 45f; } if (num3 > 0f && adrenaline >= num4) { num += num3 / 100f; } float power = API.GetEffectPower<TrinketResonance.Config>(val, "Trinket Resonance").Power; if (power > 0f && adrenaline >= num4) { num += power / 200f; } float power2 = API.GetEffectPower<OverchargeLean.Config>(val, "Overcharge Lean").Power; if (power2 > 0f && adrenaline >= 90f) { num += power2 / 100f; } float num5 = API.GetEffectPower<SurgeDetonate.Config>(val, "Surge Detonate").Power + API.GetEffectPower<ManicEngine.Config>(val, "Manic Engine").Power; if (num5 > 0f && adrenaline >= 95f) { num += num5 / 100f; SoftMods.AddAdrenaline(val, 0f - Mathf.Min(adrenaline, 25f)); } OpposedHearts.Config effectPower = API.GetEffectPower<OpposedHearts.Config>(val, "Opposed Hearts"); if (effectPower.Power > 0f && adrenaline >= 90f) { num += effectPower.Power / 100f; } if (num != 1f) { hit.ApplyModifier(num); } } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class BloodstoneEdgeDefense { [HarmonyPriority(200)] private static void Prefix(Character __instance, HitData hit) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { float adrenaline = SoftMods.GetAdrenaline(val); OpposedHearts.Config effectPower = API.GetEffectPower<OpposedHearts.Config>(val, "Opposed Hearts"); if (effectPower.Power > 0f && adrenaline < 30f) { float num = (100f - Mathf.Clamp(effectPower.Power * 0.5f, 0f, 20f)) / 100f; hit.ApplyModifier(num); } float num2 = API.GetEffectPower<HighWaterAnchor.Config>(val, "High-Water Anchor").Power + API.GetEffectPower<CrestSovereign.Config>(val, "Crest Sovereign").Power; if (num2 > 0f && adrenaline >= 70f) { hit.ApplyModifier((100f - Mathf.Clamp(num2 * 0.25f, 0f, 20f)) / 100f); } } } } [HarmonyPatch(typeof(Player), "FixedUpdate")] internal static class BloodstonePulseWatcher { private static float _lastAdren; private static bool _surged; private static void Postfix(Player __instance) { if (((Character)__instance).IsOwner()) { float adrenaline = SoftMods.GetAdrenaline(__instance); float power = API.GetEffectPower<FusedPulse.Config>(__instance, "Fused Pulse").Power; if (power > 0f && adrenaline >= 70f) { __instance.m_eitrRegenDelay = Mathf.Max(0.1f, __instance.m_eitrRegenDelay * (100f - power) / 100f); } PackAndPulse.Config effectPower = API.GetEffectPower<PackAndPulse.Config>(__instance, "Pack & Pulse"); if (effectPower.Power > 0f && adrenaline >= 90f && _lastAdren < 90f && !_surged) { _surged = true; FamiliarController.Pulse(6f, effectPower.Power); FamiliarController.Ensure(__instance); } if (adrenaline < 50f) { _surged = false; } _lastAdren = adrenaline; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }