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 AdagasCruzadas v0.3.0
plugins\AdagasCruzadas\AdagasCruzadas.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using AdagasCruzadas.Combat.StatusEffects; using AdagasCruzadas.Items; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Mayhem")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Adagas duplas (uma em cada mao) para cada adaga do Valheim.")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+fa1f3fbf230f2cc540ea136e6c16526c1dd6cb5f")] [assembly: AssemblyProduct("AdagasCruzadas")] [assembly: AssemblyTitle("AdagasCruzadas")] [assembly: AssemblyVersion("0.2.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 AdagasCruzadas { [BepInPlugin("com.mayhem.adagascruzadas", "AdagasCruzadas", "0.3.0")] internal class AdagasCruzadasPlugin : BaseUnityPlugin { public const string PluginGUID = "com.mayhem.adagascruzadas"; public const string PluginName = "AdagasCruzadas"; public const string PluginVersion = "0.3.0"; internal static ManualLogSource Log; private readonly Harmony _harmony = new Harmony("com.mayhem.adagascruzadas"); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _harmony.PatchAll(); Log.LogInfo((object)"AdagasCruzadas 0.3.0 carregado."); } private void OnDestroy() { _harmony.UnpatchSelf(); } } } namespace AdagasCruzadas.Network { [HarmonyPatch(typeof(ZNet))] internal static class VersionCheckPatch { private const string RpcName = "AdagasCruzadas_Version"; private const int ErrorVersion = 3; private static readonly HashSet<ZRpc> VerifiedPeers = new HashSet<ZRpc>(); private static bool _serverVerified; private static readonly FieldInfo ConnectionStatusField = AccessTools.Field(typeof(ZNet), "m_connectionStatus"); [HarmonyPostfix] [HarmonyPatch("OnNewConnection")] private static void OnNewConnectionPostfix(ZNet __instance, ZNetPeer peer) { VerifiedPeers.RemoveWhere((ZRpc rpc) => rpc == null || !rpc.IsConnected()); peer.m_rpc.Register<string>("AdagasCruzadas_Version", (Action<ZRpc, string>)OnVersionRpc); if (!__instance.IsServer()) { _serverVerified = false; peer.m_rpc.Invoke("AdagasCruzadas_Version", new object[1] { "0.3.0" }); } } private static void OnVersionRpc(ZRpc rpc, string remoteVersion) { string text = "0.3.0"; bool flag = remoteVersion == text; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { if (flag) { VerifiedPeers.Add(rpc); rpc.Invoke("AdagasCruzadas_Version", new object[1] { text }); return; } AdagasCruzadasPlugin.Log.LogWarning((object)("Cliente recusado: AdagasCruzadas " + remoteVersion + " (servidor: " + text + ").")); rpc.Invoke("Error", new object[1] { 3 }); } else if (flag) { _serverVerified = true; } else { AdagasCruzadasPlugin.Log.LogWarning((object)("Servidor com AdagasCruzadas " + remoteVersion + ", este cliente tem " + text + ". Desconectando.")); SetClientError(); } } [HarmonyPrefix] [HarmonyPatch("RPC_PeerInfo")] private static bool PeerInfoPrefix(ZNet __instance, ZRpc rpc) { if (__instance.IsServer()) { if (VerifiedPeers.Contains(rpc)) { return true; } AdagasCruzadasPlugin.Log.LogWarning((object)"Cliente sem AdagasCruzadas tentou conectar; recusado."); rpc.Invoke("Error", new object[1] { 3 }); return false; } if (_serverVerified) { return true; } AdagasCruzadasPlugin.Log.LogWarning((object)"Servidor sem AdagasCruzadas (não respondeu à checagem de versão). Desconectando."); SetClientError(); return false; } private static void SetClientError() { ConnectionStatusField.SetValue(null, (object)(ConnectionStatus)3); } } } namespace AdagasCruzadas.Localization { [HarmonyPatch(typeof(Localization), "SetupLanguage")] internal static class DualDaggerLocalization { private const string PortugueseBrazilian = "Portuguese_Brazilian"; private static void Postfix(Localization __instance, string language) { bool flag = language == "Portuguese_Brazilian"; DualDaggerDefinition[] all = DualDaggerDefinition.All; foreach (DualDaggerDefinition dualDaggerDefinition in all) { LocalizationHelper.Add(__instance, dualDaggerDefinition.NameKey, flag ? dualDaggerDefinition.NamePt : dualDaggerDefinition.NameEn); LocalizationHelper.Add(__instance, dualDaggerDefinition.DescriptionKey, flag ? dualDaggerDefinition.DescriptionPt : dualDaggerDefinition.DescriptionEn); } } } [HarmonyPatch(typeof(Localization), "SetupLanguage")] internal static class InfusionLocalization { private const string PortugueseBrazilian = "Portuguese_Brazilian"; private static void Postfix(Localization __instance, string language) { bool flag = language == "Portuguese_Brazilian"; InfusionDefinition[] all = InfusionDefinition.All; foreach (InfusionDefinition infusionDefinition in all) { LocalizationHelper.Add(__instance, infusionDefinition.NameKey, flag ? infusionDefinition.NamePt : infusionDefinition.NameEn); LocalizationHelper.Add(__instance, infusionDefinition.DescriptionKey, flag ? infusionDefinition.DescriptionPt : infusionDefinition.DescriptionEn); } LocalizationHelper.Add(__instance, "adagascruzadas_infusion_needweapon", flag ? "É preciso estar com uma adaga, espada, lança, machado, arco ou besta de uma mão equipada." : "You need a one-handed knife, sword, spear, axe, bow or crossbow equipped."); LocalizationHelper.Add(__instance, "adagascruzadas_infusion_conflict", flag ? "Esta arma já causa esse efeito por conta própria" : "This weapon already deals that effect on its own"); } } internal static class LocalizationHelper { private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null); public static void Add(Localization loc, string key, string text) { AddWord.Invoke(loc, new object[2] { key, text }); } } } namespace AdagasCruzadas.Items { internal static class CraftingStationLookup { public static CraftingStation Find(string prefabName) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefabName) : null); if ((Object)(object)val != (Object)null) { CraftingStation component = val.GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null) { return component; } } return ((IEnumerable<CraftingStation>)Resources.FindObjectsOfTypeAll<CraftingStation>()).FirstOrDefault((Func<CraftingStation, bool>)((CraftingStation c) => ((Object)((Component)c).gameObject).name == prefabName)); } } internal class RequirementDef { public string Item; public int Amount; public int AmountPerLevel; public RequirementDef(string item, int amount, int amountPerLevel = 0) { Item = item; Amount = amount; AmountPerLevel = amountPerLevel; } } internal class DualDaggerDefinition { public string BasePrefabName; public string DualPrefabName; public string NamePt; public string NameEn; public string DescriptionPt; public string DescriptionEn; public string CraftingStation; public int MinStationLevel; public RequirementDef[] Requirements; public bool KeepBaseAnimationState; public static readonly DualDaggerDefinition[] All = new DualDaggerDefinition[8] { new DualDaggerDefinition { BasePrefabName = "KnifeFlint", DualPrefabName = "AdagasCruzadas_KnifeFlint_Dual", NamePt = "Adagas Cruzadas de Sílex", NameEn = "Flint Crossed Daggers", DescriptionPt = "Um par de facas de sílex lascado, uma para cada mão. O primeiro passo de quem aprende o ofício das Adagas Cruzadas.", DescriptionEn = "A pair of knapped flint knives, one for each hand. The first step of anyone learning the craft of the Crossed Daggers.", CraftingStation = "piece_workbench", MinStationLevel = 1, Requirements = new RequirementDef[3] { new RequirementDef("Wood", 4), new RequirementDef("Flint", 8, 4), new RequirementDef("LeatherScraps", 4) }, KeepBaseAnimationState = true }, new DualDaggerDefinition { BasePrefabName = "KnifeCopper", DualPrefabName = "AdagasCruzadas_KnifeCopper_Dual", NamePt = "Adagas Cruzadas de Cobre", NameEn = "Copper Crossed Daggers", DescriptionPt = "Duas lâminas de cobre gêmeas. Leves, rápidas e feitas para golpear em par.", DescriptionEn = "Twin copper blades. Light, quick, and made to strike as a pair.", CraftingStation = "forge", MinStationLevel = 1, Requirements = new RequirementDef[3] { new RequirementDef("Wood", 4), new RequirementDef("Copper", 16, 8), new RequirementDef("GreydwarfEye", 0, 16) }, KeepBaseAnimationState = true }, new DualDaggerDefinition { BasePrefabName = "KnifeChitin", DualPrefabName = "AdagasCruzadas_KnifeChitin_Dual", NamePt = "Adagas Cruzadas Abissais", NameEn = "Abyssal Crossed Daggers", DescriptionPt = "Duas navalhas arrancadas das profundezas. Cortam como se ainda lembrassem do mar.", DescriptionEn = "Two razors torn from the depths. They cut as if they still remembered the sea.", CraftingStation = "piece_workbench", MinStationLevel = 2, Requirements = new RequirementDef[3] { new RequirementDef("FineWood", 8), new RequirementDef("Chitin", 40, 20), new RequirementDef("LeatherScraps", 4) } }, new DualDaggerDefinition { BasePrefabName = "KnifeSilver", DualPrefabName = "AdagasCruzadas_KnifeSilver_Dual", NamePt = "Adagas Cruzadas de Prata", NameEn = "Silver Crossed Daggers", DescriptionPt = "Um par de adagas de prata. O que uma não termina, a outra termina — e o que é da noite, ambas afastam.", DescriptionEn = "A pair of silver daggers. What one does not finish, the other does — and what belongs to the night, both drive away.", CraftingStation = "forge", MinStationLevel = 3, Requirements = new RequirementDef[4] { new RequirementDef("Wood", 4, 2), new RequirementDef("Silver", 20, 10), new RequirementDef("LeatherScraps", 6, 2), new RequirementDef("Iron", 4, 2) } }, new DualDaggerDefinition { BasePrefabName = "KnifeBlackMetal", DualPrefabName = "AdagasCruzadas_KnifeBlackMetal_Dual", NamePt = "Adagas Cruzadas de Metal Negro", NameEn = "Black Metal Crossed Daggers", DescriptionPt = "Duas lâminas de metal negro, afiadas até o silêncio. A marca de um assassino das Adagas Cruzadas.", DescriptionEn = "Two black metal blades, sharpened into silence. The mark of a Crossed Daggers assassin.", CraftingStation = "forge", MinStationLevel = 4, Requirements = new RequirementDef[3] { new RequirementDef("FineWood", 8), new RequirementDef("BlackMetal", 20, 8), new RequirementDef("LinenThread", 10, 10) } }, new DualDaggerDefinition { BasePrefabName = "KnifeGold", DualPrefabName = "AdagasCruzadas_KnifeGold_Dual", NamePt = "Adagas Cruzadas Nórdicas", NameEn = "Nord Crossed Daggers", DescriptionPt = "Um par de adagas nórdicas fundidas em ouro das Terras de Cinza. Pesam pouco na mão e muito na consciência de quem as enfrenta.", DescriptionEn = "A pair of Nord daggers cast from Ashlands gold. Light in the hand, heavy on the conscience of those who face them.", CraftingStation = "blackforge", MinStationLevel = 4, Requirements = new RequirementDef[4] { new RequirementDef("Gold", 40, 20), new RequirementDef("MoldKnife", 1), new RequirementDef("Frostwood", 20, 10), new RequirementDef("Upgrader7Weapon", 1) } }, new DualDaggerDefinition { BasePrefabName = "KnifeGold_BloodLightning", DualPrefabName = "AdagasCruzadas_KnifeGold_BloodLightning_Dual", NamePt = "Adagas Cruzadas de Trovossangue", NameEn = "Thunderblood Crossed Daggers", DescriptionPt = "Duas adagas nórdicas banhadas em trovossangue. Cada corte deixa o ar cheirando a tempestade.", DescriptionEn = "Two Nord daggers steeped in thunderblood. Every cut leaves the air smelling of storm.", CraftingStation = "blackforge", MinStationLevel = 4, Requirements = new RequirementDef[4] { new RequirementDef("KnifeGold", 2), new RequirementDef("Gold", 40, 20), new RequirementDef("OrbThunderBlood", 2, 2), new RequirementDef("Upgrader7Weapon", 1) } }, new DualDaggerDefinition { BasePrefabName = "KnifeGold_FrostFire", DualPrefabName = "AdagasCruzadas_KnifeGold_FrostFire_Dual", NamePt = "Adagas Cruzadas de Fogogelo", NameEn = "Frostfire Crossed Daggers", DescriptionPt = "Duas adagas nórdicas temperadas em fogogelo. Uma lâmina queima, a outra congela; nenhuma perdoa.", DescriptionEn = "Two Nord daggers tempered in frostfire. One blade burns, the other freezes; neither forgives.", CraftingStation = "blackforge", MinStationLevel = 4, Requirements = new RequirementDef[4] { new RequirementDef("KnifeGold", 2), new RequirementDef("Gold", 40, 20), new RequirementDef("OrbFrostFire", 2, 2), new RequirementDef("Upgrader7Weapon", 1) } } }; public string NameKey => "adagascruzadas_" + BasePrefabName.ToLowerInvariant() + "_dual"; public string DescriptionKey => NameKey + "_desc"; public string NameToken => "$" + NameKey; public string DescriptionToken => "$" + DescriptionKey; } internal static class DualDaggerFactory { private const float WeightMultiplier = 2f; private const float StaminaMultiplier = 1.5f; private const float TimedBlockBonus = 6f; internal const string OffhandGroupName = "offhand"; private static GameObject _container; private static readonly Dictionary<string, GameObject> Clones = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>(); private static readonly MethodInfo UpdateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null); private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs"); private static readonly Vector3 OffhandLocalOffset = new Vector3(0.06f, -0.02f, 0f); private static readonly Vector3 OffhandLocalEuler = new Vector3(0f, 25f, 0f); private static readonly MethodInfo MemberwiseCloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); public static void EnsureRegistered(ObjectDB db) { if ((Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("KnifeSkollAndHati") == (Object)null) { return; } EnsureClones(db); bool flag = false; foreach (GameObject value2 in Clones.Values) { if (!db.m_items.Contains(value2)) { db.m_items.Add(value2); flag = true; } } DualDaggerDefinition[] all = DualDaggerDefinition.All; foreach (DualDaggerDefinition dualDaggerDefinition in all) { if (!Recipes.TryGetValue(dualDaggerDefinition.DualPrefabName, out var value)) { value = BuildRecipe(dualDaggerDefinition, db); if ((Object)(object)value == (Object)null) { continue; } Recipes[dualDaggerDefinition.DualPrefabName] = value; } if (!db.m_recipes.Contains(value)) { db.m_recipes.Add(value); flag = true; } } if (flag) { UpdateRegisters.Invoke(db, null); } if ((Object)(object)ZNetScene.instance != (Object)null) { EnsureRegisteredInScene(ZNetScene.instance); } } public static void EnsureRegisteredInScene(ZNetScene scene) { if ((Object)(object)scene == (Object)null || Clones.Count == 0) { return; } Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)NamedPrefabs.GetValue(scene); foreach (GameObject value in Clones.Values) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)value).name); if (!dictionary.ContainsKey(stableHashCode)) { dictionary[stableHashCode] = value; if (!scene.m_prefabs.Contains(value)) { scene.m_prefabs.Add(value); } } } } private static void EnsureClones(ObjectDB db) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (Clones.Count == DualDaggerDefinition.All.Length) { return; } if ((Object)(object)_container == (Object)null) { _container = new GameObject("AdagasCruzadas_Prefabs"); _container.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_container); } SharedData shared = db.GetItemPrefab("KnifeSkollAndHati").GetComponent<ItemDrop>().m_itemData.m_shared; DualDaggerDefinition[] all = DualDaggerDefinition.All; foreach (DualDaggerDefinition dualDaggerDefinition in all) { if (!Clones.ContainsKey(dualDaggerDefinition.DualPrefabName)) { GameObject itemPrefab = db.GetItemPrefab(dualDaggerDefinition.BasePrefabName); if ((Object)(object)itemPrefab == (Object)null) { AdagasCruzadasPlugin.Log.LogError((object)("Prefab base '" + dualDaggerDefinition.BasePrefabName + "' não encontrado, pulando '" + dualDaggerDefinition.DualPrefabName + "'.")); } else { GameObject val = Object.Instantiate<GameObject>(itemPrefab, _container.transform); ((Object)val).name = dualDaggerDefinition.DualPrefabName; Configure(val, dualDaggerDefinition, shared); Clones[dualDaggerDefinition.DualPrefabName] = val; AdagasCruzadasPlugin.Log.LogInfo((object)("Item criado: " + dualDaggerDefinition.DualPrefabName)); } } } } private static void Configure(GameObject clone, DualDaggerDefinition def, SharedData skollShared) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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) ItemDrop component = clone.GetComponent<ItemDrop>(); SharedData shared = component.m_itemData.m_shared; component.m_itemData.m_dropPrefab = clone; float attackStamina = shared.m_attack.m_attackStamina; Attack val = CloneAttack(skollShared.m_attack); val.m_attackStamina = attackStamina * 1.5f; shared.m_attack = val; shared.m_name = def.NameToken; shared.m_description = def.DescriptionToken; shared.m_weight *= 2f; shared.m_timedBlockBonus = 6f; shared.m_itemType = skollShared.m_itemType; if (!def.KeepBaseAnimationState) { shared.m_animationState = skollShared.m_animationState; } BuildOffhandGroup(clone, def.DualPrefabName); } private static Recipe BuildRecipe(DualDaggerDefinition def, ObjectDB db) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown if (!Clones.TryGetValue(def.DualPrefabName, out var value)) { return null; } CraftingStation val = CraftingStationLookup.Find(def.CraftingStation); if ((Object)(object)val == (Object)null) { AdagasCruzadasPlugin.Log.LogWarning((object)("Estação '" + def.CraftingStation + "' não encontrada ainda para '" + def.DualPrefabName + "'; tentando de novo no próximo registro.")); return null; } List<Requirement> list = new List<Requirement>(); RequirementDef[] requirements = def.Requirements; foreach (RequirementDef requirementDef in requirements) { GameObject itemPrefab = db.GetItemPrefab(requirementDef.Item); if ((Object)(object)itemPrefab == (Object)null) { AdagasCruzadasPlugin.Log.LogError((object)("Recurso '" + requirementDef.Item + "' da receita de '" + def.DualPrefabName + "' não encontrado.")); return null; } list.Add(new Requirement { m_resItem = itemPrefab.GetComponent<ItemDrop>(), m_amount = requirementDef.Amount, m_amountPerLevel = requirementDef.AmountPerLevel, m_recover = true }); } Recipe obj = ScriptableObject.CreateInstance<Recipe>(); ((Object)obj).name = "Recipe_" + def.DualPrefabName; obj.m_item = value.GetComponent<ItemDrop>(); obj.m_amount = 1; obj.m_enabled = true; obj.m_craftingStation = val; obj.m_repairStation = val; obj.m_minStationLevel = def.MinStationLevel; obj.m_resources = list.ToArray(); return obj; } private static void BuildOffhandGroup(GameObject clone, string dualPrefabName) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0110: 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_0125: 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_017a: 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_019d: Unknown result type (might be due to invalid IL or missing references) Transform val = clone.transform.Find("attach"); if ((Object)(object)val == (Object)null) { AdagasCruzadasPlugin.Log.LogWarning((object)("'" + dualPrefabName + "': sem filho 'attach', não foi possível criar a segunda lâmina.")); return; } List<Transform> list = new List<Transform>(); foreach (Transform item in val) { Transform val2 = item; if (!(((Object)val2).name == "equiped") && !(((Object)val2).name == "collider") && !(((Object)val2).name == "offhand")) { list.Add(val2); } } if (!list.Any((Transform t) => (Object)(object)((Component)t).GetComponent<MeshRenderer>() != (Object)null)) { AdagasCruzadasPlugin.Log.LogWarning((object)("'" + dualPrefabName + "': não encontrei a malha da lâmina em 'attach'.")); return; } GameObject val3 = new GameObject("offhand"); val3.transform.SetParent(val, false); val3.transform.localPosition = OffhandLocalOffset; val3.transform.localRotation = Quaternion.Euler(OffhandLocalEuler); val3.transform.localScale = Vector3.one; foreach (Transform item2 in list) { GameObject obj = Object.Instantiate<GameObject>(((Component)item2).gameObject, val3.transform, false); ((Object)obj).name = ((Object)item2).name; obj.transform.localPosition = item2.localPosition; obj.transform.localRotation = item2.localRotation; obj.transform.localScale = item2.localScale; } } private static Attack CloneAttack(Attack source) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return (Attack)MemberwiseCloneMethod.Invoke(source, null); } } internal enum InfusionId { Fire, Frost, Lightning, Spirit, Poison, Vampirism, Slow, Bleed } internal enum InfusionFamily { DirectDamage, Status, Vampirism } internal enum ElementalDamageType { Fire, Frost, Lightning, Spirit, Poison } internal class InfusionDefinition { public const float DurationSeconds = 300f; public InfusionId Id; public string SourcePrefabName; public string NamePt; public string NameEn; public string DescriptionPt; public string DescriptionEn; public RequirementDef[] Requirements; public InfusionFamily Family; public ElementalDamageType DamageType; public float BaseDamage = 10f; public string TargetStatusEffectName; public float Chance = 0.5f; public float HealPercent = 0.15f; public float SlowPercent = 0.3f; public const string CraftingStation = "piece_workbench"; public const int MinStationLevel = 2; public static readonly InfusionDefinition[] All = new InfusionDefinition[8] { new InfusionDefinition { Id = InfusionId.Fire, SourcePrefabName = "BarleyWine", NamePt = "Resina Incendiária", NameEn = "Blazing Resin", DescriptionPt = "Um óleo espesso que guarda fogo represado em cada gota. Os seguidores do mago Nocthar o destilavam em fogueiras que nunca se apagavam — oferenda e arma a um só tempo.", DescriptionEn = "A thick oil that holds fire trapped in every drop. Followers of the mage Nocthar distilled it over bonfires that never died out — offering and weapon at once.", Requirements = new RequirementDef[2] { new RequirementDef("Resin", 3), new RequirementDef("SurtlingCore", 1) }, Family = InfusionFamily.DirectDamage, DamageType = ElementalDamageType.Fire }, new InfusionDefinition { Id = InfusionId.Frost, SourcePrefabName = "MeadFrostResist", NamePt = "Resina Congelante", NameEn = "Freezing Resin", DescriptionPt = "Um óleo que nunca aquece, nem sob o sol mais cruel. Os povos da montanha o passavam nas lâminas para que suas presas parassem de fugir — e, por fim, de sentir.", DescriptionEn = "An oil that never warms, not even under the cruelest sun. Mountain folk coated their blades with it so their prey would stop fleeing — and, at last, stop feeling.", Requirements = new RequirementDef[2] { new RequirementDef("Resin", 3), new RequirementDef("FreezeGland", 2) }, Family = InfusionFamily.DirectDamage, DamageType = ElementalDamageType.Frost }, new InfusionDefinition { Id = InfusionId.Lightning, SourcePrefabName = "MeadLightfoot", NamePt = "Resina Fulminante", NameEn = "Fulminating Resin", DescriptionPt = "Presa no vidro, uma tempestade que nunca se cansa de estourar. Tarkir, o Corta-Relâmpagos, jurou a Tyr que nenhum inimigo ficaria de pé diante dela.", DescriptionEn = "Trapped in glass, a storm that never tires of breaking. Tarkir, the Lightning-Cutter, swore to Tyr that no enemy would remain standing before it.", Requirements = new RequirementDef[2] { new RequirementDef("Resin", 3), new RequirementDef("Thunderstone", 1) }, Family = InfusionFamily.DirectDamage, DamageType = ElementalDamageType.Lightning }, new InfusionDefinition { Id = InfusionId.Spirit, SourcePrefabName = "MeadEitrLingering", NamePt = "Resina do Banimento", NameEn = "Banishment Resin", DescriptionPt = "Forjada para subjugar o que não deveria caminhar entre os vivos. Fórmula tão antiga quanto os primeiros homens, usada para banir o mal que espreita nas noites sem fim.", DescriptionEn = "Forged to subdue what should not walk among the living. A formula as old as the first men, used to banish the evil that lurks in the endless nights.", Requirements = new RequirementDef[3] { new RequirementDef("Resin", 3), new RequirementDef("BoneFragments", 5), new RequirementDef("Ectoplasm", 2) }, Family = InfusionFamily.DirectDamage, DamageType = ElementalDamageType.Spirit }, new InfusionDefinition { Id = InfusionId.Poison, SourcePrefabName = "MeadPoisonResist", NamePt = "Resina Pestilenta", NameEn = "Pestilent Resin", DescriptionPt = "Um extrato nauseante, colhido onde nada cresce limpo. O povo de Brak o untava nas lâminas para que a morte chegasse muito antes do grito.", DescriptionEn = "A nauseating extract, gathered where nothing grows clean. The people of Brak smeared it on their blades so death would arrive long before the scream.", Requirements = new RequirementDef[3] { new RequirementDef("Resin", 3), new RequirementDef("Guck", 2), new RequirementDef("Ooze", 2) }, Family = InfusionFamily.DirectDamage, DamageType = ElementalDamageType.Poison }, new InfusionDefinition { Id = InfusionId.Vampirism, SourcePrefabName = "MeadBzerker", NamePt = "Resina do Pacto Sanguíneo", NameEn = "Blood Pact Resin", DescriptionPt = "Selada com sangue ainda quente, firma um laço breve e cruel entre lâmina e vítima. Ravok, vampiro da linhagem de Azatoth, jamais soube compartilhar — só tomar.", DescriptionEn = "Sealed with still-warm blood, it forges a brief and cruel bond between blade and victim. Ravok, vampire of Azatoth's bloodline, never learned to share — only to take.", Requirements = new RequirementDef[3] { new RequirementDef("Resin", 3), new RequirementDef("Bloodbag", 1), new RequirementDef("Ectoplasm", 2) }, Family = InfusionFamily.Vampirism }, new InfusionDefinition { Id = InfusionId.Slow, SourcePrefabName = "MeadTrollPheromones", NamePt = "Resina do Arruinado", NameEn = "Ruined One's Resin", DescriptionPt = "Um extrato espesso que entorpece os músculos do alvo. Técnica do Arruinado, caçador que perdeu tudo perseguindo as harpias da névoa — menos a paciência de esperar a presa cair.", DescriptionEn = "A thick extract that numbs the target's muscles. A technique of the Ruined One, a hunter who lost everything chasing the mist harpies — except the patience to wait for prey to fall.", Requirements = new RequirementDef[3] { new RequirementDef("Resin", 3), new RequirementDef("Tar", 2), new RequirementDef("Root", 2) }, Family = InfusionFamily.Status, TargetStatusEffectName = "AC_SE_Slowed" }, new InfusionDefinition { Id = InfusionId.Bleed, SourcePrefabName = "MeadHealthMedium", NamePt = "Resina Corta Sangue", NameEn = "Bloodcut Resin", DescriptionPt = "Um óleo avermelhado que impede feridas de fechar. Diz a lenda que suas primeiras gotas caíram sobre um dente-de-leão, num campo ainda quente de sangue — e, desde então, nunca mais estancaram.", DescriptionEn = "A reddish oil that keeps wounds from closing. Legend says its first drops fell on a dandelion, in a field still warm with blood — and, ever since, they never stopped flowing.", Requirements = new RequirementDef[3] { new RequirementDef("Resin", 3), new RequirementDef("Bloodbag", 1), new RequirementDef("Dandelion", 3) }, Family = InfusionFamily.Status, TargetStatusEffectName = "AC_SE_Bleed" } }; public string NameKey => "adagascruzadas_infusion_" + Id.ToString().ToLowerInvariant(); public string DescriptionKey => NameKey + "_desc"; public string NameToken => "$" + NameKey; public string DescriptionToken => "$" + DescriptionKey; public string ClonePrefabName => "AdagasCruzadas_Infusion" + Id; } internal static class InfusionFactory { private static GameObject _container; private static readonly Dictionary<string, GameObject> Clones = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>(); private static readonly MethodInfo UpdateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null); private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs"); public static void EnsureRegistered(ObjectDB db) { if ((Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("Resin") == (Object)null) { return; } EnsureClones(db); bool flag = false; foreach (GameObject value2 in Clones.Values) { if (!db.m_items.Contains(value2)) { db.m_items.Add(value2); flag = true; } } InfusionDefinition[] all = InfusionDefinition.All; foreach (InfusionDefinition infusionDefinition in all) { if (!Recipes.TryGetValue(infusionDefinition.ClonePrefabName, out var value)) { value = BuildRecipe(infusionDefinition, db); if ((Object)(object)value == (Object)null) { continue; } Recipes[infusionDefinition.ClonePrefabName] = value; } if (!db.m_recipes.Contains(value)) { db.m_recipes.Add(value); flag = true; } } if (flag) { UpdateRegisters.Invoke(db, null); } if ((Object)(object)ZNetScene.instance != (Object)null) { EnsureRegisteredInScene(ZNetScene.instance); } } public static GameObject GetClone(string clonePrefabName) { if (!Clones.TryGetValue(clonePrefabName, out var value)) { return null; } return value; } public static void EnsureRegisteredInScene(ZNetScene scene) { if ((Object)(object)scene == (Object)null || Clones.Count == 0) { return; } Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)NamedPrefabs.GetValue(scene); foreach (GameObject value in Clones.Values) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)value).name); if (!dictionary.ContainsKey(stableHashCode)) { dictionary[stableHashCode] = value; if (!scene.m_prefabs.Contains(value)) { scene.m_prefabs.Add(value); } } } } private static void EnsureClones(ObjectDB db) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (Clones.Count == InfusionDefinition.All.Length) { return; } if ((Object)(object)_container == (Object)null) { _container = new GameObject("AdagasCruzadas_InfusionPrefabs"); _container.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_container); } InfusionDefinition[] all = InfusionDefinition.All; foreach (InfusionDefinition infusionDefinition in all) { if (!Clones.ContainsKey(infusionDefinition.ClonePrefabName)) { GameObject itemPrefab = db.GetItemPrefab(infusionDefinition.SourcePrefabName); if ((Object)(object)itemPrefab == (Object)null) { AdagasCruzadasPlugin.Log.LogError((object)("Prefab base '" + infusionDefinition.SourcePrefabName + "' não encontrado, pulando '" + infusionDefinition.ClonePrefabName + "'.")); } else { GameObject val = Object.Instantiate<GameObject>(itemPrefab, _container.transform); ((Object)val).name = infusionDefinition.ClonePrefabName; Configure(val, infusionDefinition, db); Clones[infusionDefinition.ClonePrefabName] = val; AdagasCruzadasPlugin.Log.LogInfo((object)("Item criado: " + infusionDefinition.ClonePrefabName)); } } } } private static void Configure(GameObject clone, InfusionDefinition def, ObjectDB db) { ItemDrop component = clone.GetComponent<ItemDrop>(); SharedData shared = component.m_itemData.m_shared; component.m_itemData.m_dropPrefab = clone; shared.m_name = def.NameToken; shared.m_description = def.DescriptionToken; Sprite val = InfusionIconFactory.Get(db, def.Id); if ((Object)(object)val != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; } else { AdagasCruzadasPlugin.Log.LogWarning((object)("Ícone colorido de '" + def.ClonePrefabName + "' não pôde ser gerado; mantendo o do frasco.")); } shared.m_food = 0f; shared.m_foodStamina = 0f; shared.m_foodEitr = 0f; shared.m_foodBurnTime = 0f; shared.m_foodRegen = 0f; shared.m_consumeStatusEffect = null; } private static Recipe BuildRecipe(InfusionDefinition def, ObjectDB db) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown if (!Clones.TryGetValue(def.ClonePrefabName, out var value)) { return null; } CraftingStation val = CraftingStationLookup.Find("piece_workbench"); if ((Object)(object)val == (Object)null) { AdagasCruzadasPlugin.Log.LogWarning((object)("Estação 'piece_workbench' não encontrada ainda para '" + def.ClonePrefabName + "'; tentando de novo no próximo registro.")); return null; } List<Requirement> list = new List<Requirement>(); RequirementDef[] requirements = def.Requirements; foreach (RequirementDef requirementDef in requirements) { GameObject itemPrefab = db.GetItemPrefab(requirementDef.Item); if ((Object)(object)itemPrefab == (Object)null) { AdagasCruzadasPlugin.Log.LogError((object)("Recurso '" + requirementDef.Item + "' da receita de '" + def.ClonePrefabName + "' não encontrado.")); return null; } list.Add(new Requirement { m_resItem = itemPrefab.GetComponent<ItemDrop>(), m_amount = requirementDef.Amount, m_amountPerLevel = requirementDef.AmountPerLevel, m_recover = true }); } Recipe obj = ScriptableObject.CreateInstance<Recipe>(); ((Object)obj).name = "Recipe_" + def.ClonePrefabName; obj.m_item = value.GetComponent<ItemDrop>(); obj.m_amount = 1; obj.m_enabled = true; obj.m_craftingStation = val; obj.m_repairStation = val; obj.m_minStationLevel = 2; obj.m_resources = list.ToArray(); return obj; } } internal static class InfusionHudEffectFactory { private static readonly Dictionary<InfusionId, StatusEffect> HudEffects = new Dictionary<InfusionId, StatusEffect>(); public static void EnsureRegistered(ObjectDB db) { if ((Object)(object)db == (Object)null) { return; } InfusionDefinition[] all = InfusionDefinition.All; foreach (InfusionDefinition infusionDefinition in all) { if (!HudEffects.ContainsKey(infusionDefinition.Id)) { GameObject clone = InfusionFactory.GetClone(infusionDefinition.ClonePrefabName); if (!((Object)(object)clone == (Object)null)) { StatusEffect val = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)val).name = "AC_SE_Hud_" + infusionDefinition.Id; val.m_name = infusionDefinition.NameToken; val.m_icon = clone.GetComponent<ItemDrop>().m_itemData.GetIcon(); val.m_ttl = 300f; HudEffects[infusionDefinition.Id] = val; } } } foreach (StatusEffect value in HudEffects.Values) { if (!db.m_StatusEffects.Contains(value)) { db.m_StatusEffects.Add(value); } } } public static StatusEffect Get(InfusionId id) { if (!HudEffects.TryGetValue(id, out var value)) { return null; } return value; } public static void Sync(SEMan seMan, InfusionId? active, float remainingSeconds) { if (seMan == null) { return; } foreach (KeyValuePair<InfusionId, StatusEffect> hudEffect in HudEffects) { StatusEffect value = hudEffect.Value; bool flag = active.HasValue && hudEffect.Key == active.Value && remainingSeconds > 0f; bool flag2 = seMan.HaveStatusEffect(value.NameHash()); if (flag && !flag2) { value.m_ttl = remainingSeconds; seMan.AddStatusEffect(value, true, 0, 0f, (short)(-1)); } else if (!flag && flag2) { seMan.RemoveStatusEffect(value, true); } } } } internal static class InfusionIconFactory { private const string SourceItem = "Resin"; private const float LuminanceGain = 1.15f; private static readonly Dictionary<InfusionId, Sprite> Cache = new Dictionary<InfusionId, Sprite>(); public static Sprite Get(ObjectDB db, InfusionId id) { //IL_0040: 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_0079: Unknown result type (might be due to invalid IL or missing references) if (Cache.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { return value; } Sprite sourceIcon = GetSourceIcon(db); if ((Object)(object)sourceIcon == (Object)null) { return null; } Texture2D val = ReadableCopy(sourceIcon); if ((Object)(object)val == (Object)null) { return null; } Texture2D val2 = Tint(val, ColorFor(id)); Object.Destroy((Object)(object)val); Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), sourceIcon.pixelsPerUnit); ((Object)val3).name = "AC_Icon_" + id; ((Object)val3).hideFlags = (HideFlags)61; Cache[id] = val3; return val3; } private static Sprite GetSourceIcon(ObjectDB db) { GameObject val = (((Object)(object)db != (Object)null) ? db.GetItemPrefab("Resin") : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.m_itemData.GetIcon(); } private static Texture2D ReadableCopy(Sprite sprite) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0084: Expected O, but got Unknown Texture2D texture = sprite.texture; if ((Object)(object)texture == (Object)null) { return null; } RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); RenderTexture active = RenderTexture.active; Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; Rect val = (sprite.packed ? sprite.textureRect : sprite.rect); Texture2D val2 = new Texture2D((int)((Rect)(ref val)).width, (int)((Rect)(ref val)).height, (TextureFormat)4, false); val2.ReadPixels(val, 0, 0); val2.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); return val2; } private static Texture2D Tint(Texture2D src, Color color) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_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_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_00a2: Expected O, but got Unknown Color[] pixels = src.GetPixels(); for (int i = 0; i < pixels.Length; i++) { Color val = pixels[i]; float num = Mathf.Clamp01((val.r * 0.299f + val.g * 0.587f + val.b * 0.114f) * 1.15f); pixels[i] = new Color(num * color.r, num * color.g, num * color.b, val.a); } Texture2D val2 = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false); val2.SetPixels(pixels); val2.Apply(); ((Object)val2).hideFlags = (HideFlags)61; return val2; } private static Color ColorFor(InfusionId id) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) return (Color)(id switch { InfusionId.Fire => new Color(1f, 0.45f, 0.05f), InfusionId.Frost => new Color(0.45f, 0.85f, 1f), InfusionId.Lightning => new Color(0.35f, 0.45f, 1f), InfusionId.Spirit => new Color(0.75f, 0.45f, 1f), InfusionId.Poison => new Color(0.35f, 1f, 0.25f), InfusionId.Vampirism => new Color(0.55f, 0f, 0.15f), InfusionId.Slow => new Color(0.45f, 0.3f, 0.15f), InfusionId.Bleed => new Color(1f, 0.15f, 0.1f), _ => Color.white, }); } } [HarmonyPatch(typeof(ObjectDB))] internal static class ObjectDbRegistrationPatch { [HarmonyPostfix] [HarmonyPatch("Awake")] private static void AwakePostfix(ObjectDB __instance) { DualDaggerFactory.EnsureRegistered(__instance); InfusionFactory.EnsureRegistered(__instance); InfusionHudEffectFactory.EnsureRegistered(__instance); InfusionStatusEffectFactory.EnsureRegistered(__instance); } [HarmonyPostfix] [HarmonyPatch("CopyOtherDB")] private static void CopyOtherDbPostfix(ObjectDB __instance) { DualDaggerFactory.EnsureRegistered(__instance); InfusionFactory.EnsureRegistered(__instance); InfusionHudEffectFactory.EnsureRegistered(__instance); InfusionStatusEffectFactory.EnsureRegistered(__instance); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneRegistrationPatch { private static void Postfix(ZNetScene __instance) { DualDaggerFactory.EnsureRegisteredInScene(__instance); InfusionFactory.EnsureRegisteredInScene(__instance); } } } namespace AdagasCruzadas.Combat { [HarmonyPatch(typeof(Attack), "ModifyDamage")] internal static class DualDaggerComboDamagePatch { private static readonly float[] ChainMultipliers = new float[3] { 1.3f, 2f, 1.5f }; private static void Postfix(HitData hitData, int ___m_currentAttackCainLevel, ItemData ___m_weapon) { if (DualDaggerRegistry.IsDualDagger(___m_weapon)) { int num = Mathf.Clamp(___m_currentAttackCainLevel, 0, ChainMultipliers.Length - 1); ((DamageTypes)(ref hitData.m_damage)).Modify(ChainMultipliers[num]); } } } [HarmonyPatch(typeof(VisEquipment), "SetRightHandEquipped")] internal static class DualDaggerOffhandVisualPatch { private class OffhandHolder : MonoBehaviour { public GameObject Offhand; private void OnDestroy() { if ((Object)(object)Offhand != (Object)null) { Object.Destroy((Object)(object)Offhand); } } } private static readonly Vector3 LeftHandEulerOffset = Vector3.zero; private static readonly Vector3 LeftHandPositionOffset = Vector3.zero; private static void Postfix(VisEquipment __instance, bool __result, int hash, GameObject ___m_rightItemInstance) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) if (!__result) { return; } OffhandHolder offhandHolder = ((Component)__instance).GetComponent<OffhandHolder>(); if ((Object)(object)offhandHolder != (Object)null && (Object)(object)offhandHolder.Offhand != (Object)null) { Object.Destroy((Object)(object)offhandHolder.Offhand); offhandHolder.Offhand = null; } if ((Object)(object)___m_rightItemInstance == (Object)null || (Object)(object)__instance.m_leftHand == (Object)null || !DualDaggerRegistry.IsDualDaggerHash(hash)) { return; } Transform val = ___m_rightItemInstance.transform.Find("offhand"); if (!((Object)(object)val == (Object)null)) { val.SetParent(__instance.m_leftHand, false); val.localPosition = LeftHandPositionOffset; val.localRotation = Quaternion.Euler(LeftHandEulerOffset); val.localScale = Vector3.one; if ((Object)(object)offhandHolder == (Object)null) { offhandHolder = ((Component)__instance).gameObject.AddComponent<OffhandHolder>(); } offhandHolder.Offhand = ((Component)val).gameObject; } } } internal static class DualDaggerRegistry { private static readonly HashSet<string> DualPrefabNames = new HashSet<string>(DualDaggerDefinition.All.Select((DualDaggerDefinition d) => d.DualPrefabName)); private static readonly HashSet<int> DualPrefabHashes = new HashSet<int>(DualDaggerDefinition.All.Select((DualDaggerDefinition d) => StringExtensionMethods.GetStableHashCode(d.DualPrefabName))); public static bool IsDualDagger(ItemData weapon) { string text = (((Object)(object)weapon?.m_dropPrefab != (Object)null) ? ((Object)weapon.m_dropPrefab).name : null); if (text != null) { return DualPrefabNames.Contains(text); } return false; } public static bool IsDualDaggerHash(int prefabHash) { return DualPrefabHashes.Contains(prefabHash); } } internal static class InfusableWeapons { private static readonly HashSet<SkillType> AllowedSkills = new HashSet<SkillType> { (SkillType)2, (SkillType)1, (SkillType)5, (SkillType)7, (SkillType)8, (SkillType)14 }; private static readonly HashSet<AnimationState> TwoHandedPoses = new HashSet<AnimationState> { (AnimationState)13, (AnimationState)8, (AnimationState)2, (AnimationState)7 }; private static readonly FieldInfo HiddenRightItemField = AccessTools.Field(typeof(Humanoid), "m_hiddenRightItem"); private static readonly FieldInfo HiddenLeftItemField = AccessTools.Field(typeof(Humanoid), "m_hiddenLeftItem"); public static bool IsInfusable(ItemData weapon) { //IL_0018: 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) SharedData val = weapon?.m_shared; if (val == null) { return false; } if (AllowedSkills.Contains(val.m_skillType)) { return !TwoHandedPoses.Contains(val.m_animationState); } return false; } public static bool IsInfusableHash(int prefabHash) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabHash) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { return IsInfusable(val2.m_itemData); } return false; } public static ItemData GetEquipped(Humanoid humanoid, bool includeSheathed) { if ((Object)(object)humanoid == (Object)null) { return null; } if (IsInfusable(humanoid.RightItem)) { return humanoid.RightItem; } if (IsInfusable(humanoid.LeftItem)) { return humanoid.LeftItem; } if (!includeSheathed) { return null; } object? obj = HiddenRightItemField?.GetValue(humanoid); ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (IsInfusable(val)) { return val; } object? obj2 = HiddenLeftItemField?.GetValue(humanoid); ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null); if (!IsInfusable(val2)) { return null; } return val2; } } internal class InfusionAuraPulse : MonoBehaviour { private const float PeriodSeconds = 1.8f; private const float MinDensity = 0.3f; private const float MinAlpha = 0.45f; private const float MinBrightness = 0.5f; private ParticleSystem[] _systems; private float[] _baseRate; private Color[] _baseColor; private void Awake() { //IL_0046: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0070: 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) _systems = ((Component)this).GetComponentsInChildren<ParticleSystem>(true); _baseRate = new float[_systems.Length]; _baseColor = (Color[])(object)new Color[_systems.Length]; for (int i = 0; i < _systems.Length; i++) { float[] baseRate = _baseRate; int num = i; EmissionModule emission = _systems[i].emission; baseRate[num] = ((EmissionModule)(ref emission)).rateOverTimeMultiplier; Color[] baseColor = _baseColor; int num2 = i; MainModule main = _systems[i].main; MinMaxGradient startColor = ((MainModule)(ref main)).startColor; baseColor[num2] = ((MinMaxGradient)(ref startColor)).color; } AdagasCruzadasPlugin.Log.LogInfo((object)string.Format("[Infusao Visual] pulso ligado em {0} sistema(s), taxas base: {1}.", _systems.Length, string.Join(", ", Array.ConvertAll(_baseRate, (float r) => r.ToString("0.##"))))); } private void Update() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00aa: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (_systems == null) { return; } float num = (Mathf.Sin(Time.time * (float)Math.PI * 2f / 1.8f) + 1f) * 0.5f; float num2 = Mathf.Lerp(0.3f, 1f, num); float num3 = Mathf.Lerp(0.45f, 1f, num); float num4 = Mathf.Lerp(0.5f, 1f, num); for (int i = 0; i < _systems.Length; i++) { ParticleSystem val = _systems[i]; if (!((Object)(object)val == (Object)null)) { EmissionModule emission = val.emission; ((EmissionModule)(ref emission)).rateOverTimeMultiplier = _baseRate[i] * num2; Color val2 = _baseColor[i]; MainModule main = val.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(val2.r * num4, val2.g * num4, val2.b * num4, val2.a * num3)); } } } } internal static class InfusionConflict { public static string Find(ItemData weapon, InfusionDefinition def) { if (weapon?.m_shared == null || def == null) { return null; } switch (def.Family) { case InfusionFamily.DirectDamage: return FindElemental(weapon, def); case InfusionFamily.Status: if (!((Object)(object)weapon.m_shared.m_attackStatusEffect != (Object)null)) { return null; } return weapon.m_shared.m_attackStatusEffect.m_name; case InfusionFamily.Vampirism: { Attack attack = weapon.m_shared.m_attack; if (attack == null || !(attack.m_attackHealthReturnHit > 0f)) { return null; } return "$item_healthhitreturn"; } default: return null; } } private static string FindElemental(ItemData weapon, InfusionDefinition def) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_003f: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) DamageTypes damage = weapon.GetDamage(); switch (def.DamageType) { case ElementalDamageType.Fire: if (!(damage.m_fire > 0f)) { return null; } return "$inventory_fire"; case ElementalDamageType.Frost: if (!(damage.m_frost > 0f)) { return null; } return "$inventory_frost"; case ElementalDamageType.Lightning: if (!(damage.m_lightning > 0f)) { return null; } return "$inventory_lightning"; case ElementalDamageType.Spirit: if (!(damage.m_spirit > 0f)) { return null; } return "$inventory_spirit"; case ElementalDamageType.Poison: if (!(damage.m_poison > 0f)) { return null; } return "$inventory_poison"; default: return null; } } } [HarmonyPatch(typeof(Player), "Update")] internal static class InfusionHudSyncPatch { private const float Interval = 0.5f; private static float _timer; private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { _timer -= Time.deltaTime; if (!(_timer > 0f)) { _timer = 0.5f; ActiveInfusion active = WeaponInfusionState.GetActive(InfusableWeapons.GetEquipped((Humanoid)(object)__instance, includeSheathed: false)); InfusionHudEffectFactory.Sync(((Character)__instance).GetSEMan(), active?.Definition.Id, (active != null) ? WeaponInfusionState.GetRemainingSeconds(active) : 0f); } } } } internal static class InfusionParticleFactory { private const string SourceItem = "BowDraugrFang"; private const string SourceChildPath = "attach/DraugrFangBow"; private const float SurfaceOffset = 0.01f; private const float MeshSpawnSpeed = 1.5f; public static GameObject Create(InfusionId id, Renderer bladeRenderer) { //IL_0076: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bladeRenderer == (Object)null) { return null; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("BowDraugrFang") : null); Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("attach/DraugrFangBow") : null); if ((Object)(object)val2 == (Object)null) { return null; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)bladeRenderer).transform); ((Object)val3).name = "AC_InfusionFx"; val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one; MeshFilter[] componentsInChildren = val3.GetComponentsInChildren<MeshFilter>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } MeshRenderer[] componentsInChildren2 = val3.GetComponentsInChildren<MeshRenderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.Destroy((Object)(object)componentsInChildren2[i]); } Collider[] componentsInChildren3 = val3.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.Destroy((Object)(object)componentsInChildren3[i]); } Light[] componentsInChildren4 = val3.GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.Destroy((Object)(object)((Component)componentsInChildren4[i]).gameObject); } Color color = ColorFor(id); ParticleSystem[] componentsInChildren5 = val3.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem ps in componentsInChildren5) { EmitFromBlade(ps, bladeRenderer); Recolor(ps, color); } val3.AddComponent<InfusionAuraPulse>(); return val3; } private static void EmitFromBlade(ParticleSystem ps, Renderer bladeRenderer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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) MainModule main = ps.main; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)1; ShapeModule shape = ps.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)14; SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((bladeRenderer is SkinnedMeshRenderer) ? bladeRenderer : null); if (val != null) { ((ShapeModule)(ref shape)).skinnedMeshRenderer = val; } else { ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)13; ((ShapeModule)(ref shape)).meshRenderer = (MeshRenderer)(object)((bladeRenderer is MeshRenderer) ? bladeRenderer : null); } ((ShapeModule)(ref shape)).meshShapeType = (ParticleSystemMeshShapeType)2; ((ShapeModule)(ref shape)).normalOffset = 0.01f; ((ShapeModule)(ref shape)).meshSpawnMode = (ParticleSystemShapeMultiModeValue)1; ((ShapeModule)(ref shape)).meshSpawnSpeed = MinMaxCurve.op_Implicit(1.5f); ((ShapeModule)(ref shape)).meshSpawnSpread = 0f; ((ShapeModule)(ref shape)).scale = Vector3.one; ((ShapeModule)(ref shape)).position = Vector3.zero; ((ShapeModule)(ref shape)).rotation = Vector3.zero; } private static void Recolor(ParticleSystem ps, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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) //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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) MainModule main = ps.main; MinMaxGradient startColor = ((MainModule)(ref main)).startColor; ((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(color.r, color.g, color.b, ((MinMaxGradient)(ref startColor)).color.a)); Color val = Color.Lerp(color, Color.white, 0.5f); Gradient val2 = new Gradient(); val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[3] { new GradientColorKey(val, 0f), new GradientColorKey(color, 0.4f), new GradientColorKey(color, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 0.6f), new GradientAlphaKey(0f, 1f) }); ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime; ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true; ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2); } private static Color ColorFor(InfusionId id) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) return (Color)(id switch { InfusionId.Fire => new Color(1f, 0.4f, 0.1f), InfusionId.Frost => new Color(0.5f, 0.85f, 1f), InfusionId.Lightning => new Color(0.6f, 0.7f, 1f), InfusionId.Spirit => new Color(0.75f, 0.6f, 1f), InfusionId.Poison => new Color(0.4f, 1f, 0.3f), InfusionId.Vampirism => new Color(0.8f, 0f, 0.1f), InfusionId.Slow => new Color(0.5f, 0.35f, 0.2f), InfusionId.Bleed => new Color(0.7f, 0f, 0f), _ => Color.white, }); } } internal static class InfusionRegistry { private static readonly Dictionary<string, InfusionDefinition> ByPrefabName = InfusionDefinition.All.ToDictionary((InfusionDefinition d) => d.ClonePrefabName); public static InfusionDefinition Find(ItemData item) { string text = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : null); if (text == null) { return null; } if (!ByPrefabName.TryGetValue(text, out var value)) { return null; } return value; } } internal static class InfusionSoundFactory { private class SoundCleanup : MonoBehaviour { private const float StartGrace = 0.75f; private const float MaxLifetime = 5f; private AudioSource[] _sources; private float _age; private bool _started; private void Awake() { _sources = ((Component)this).GetComponentsInChildren<AudioSource>(true); } private void Update() { _age += Time.deltaTime; if (_age >= 5f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } AudioSource[] sources = _sources; foreach (AudioSource val in sources) { if ((Object)(object)val != (Object)null && val.isPlaying) { _started = true; return; } } if (_started || !(_age < 0.75f)) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } public static void PlayApplySound(InfusionDefinition definition, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!TryPlayNamed(definition, position) && !TryPlay(GetElementalStatusSfx(definition), position)) { TryPlay(GetSourceMeadSfx(definition), position); } } private static string GetNamedSound(InfusionDefinition definition) { if (definition.Id == InfusionId.Spirit) { return "sfx_staffspiritcaller_summon"; } return null; } private static EffectList GetElementalStatusSfx(InfusionDefinition definition) { int num; switch (definition.Id) { case InfusionId.Fire: num = SEMan.s_statusEffectBurning; break; case InfusionId.Frost: num = SEMan.s_statusEffectFrost; break; case InfusionId.Lightning: num = SEMan.s_statusEffectLightning; break; case InfusionId.Poison: num = SEMan.s_statusEffectPoison; break; case InfusionId.Slow: num = SEMan.s_statusEffectPoison; break; default: return null; } StatusEffect val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetStatusEffect(num) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_startEffects; } private static EffectList GetSourceMeadSfx(InfusionDefinition definition) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(definition.SourcePrefabName) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); StatusEffect val3 = (((Object)(object)val2 != (Object)null) ? val2.m_itemData.m_shared.m_consumeStatusEffect : null); if (!((Object)(object)val3 != (Object)null)) { return null; } return val3.m_startEffects; } private static bool TryPlayNamed(InfusionDefinition definition, Vector3 position) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) string namedSound = GetNamedSound(definition); if (namedSound == null || (Object)(object)ZNetScene.instance == (Object)null) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(namedSound); if ((Object)(object)prefab == (Object)null || !HasAudio(prefab)) { return false; } SpawnAudioOnly(prefab, position); return true; } private static bool TryPlay(EffectList list, Vector3 position) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (list?.m_effectPrefabs == null) { return false; } EffectData[] effectPrefabs = list.m_effectPrefabs; foreach (EffectData val in effectPrefabs) { if (!((Object)(object)val?.m_prefab == (Object)null) && val.m_enabled && HasAudio(val.m_prefab)) { SpawnAudioOnly(val.m_prefab, position); return true; } } return false; } private static bool HasAudio(GameObject prefab) { if (!((Object)(object)prefab.GetComponentInChildren<ZSFX>(true) != (Object)null)) { return (Object)(object)prefab.GetComponentInChildren<AudioSource>(true) != (Object)null; } return true; } private static void SpawnAudioOnly(GameObject prefab, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.Destroy((Object)(object)componentsInChildren2[i]); } Light[] componentsInChildren3 = val.GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { ((Behaviour)componentsInChildren3[i]).enabled = false; } MonoBehaviour[] componentsInChildren4 = val.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val2 in componentsInChildren4) { string name = ((object)val2).GetType().Name; if (name == "LightLod" || name == "LightFlicker") { ((Behaviour)val2).enabled = false; } } AudioSource[] componentsInChildren5 = val.GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren5.Length; i++) { componentsInChildren5[i].loop = false; } val.AddComponent<SoundCleanup>(); } } internal class InfusionVisualController : MonoBehaviour { private const float TickInterval = 1f; private ZNetView _nview; private Humanoid _humanoid; private Renderer[] _blades; private GameObject[] _particles; private int _currentShownId = -1; public void Bind(ZNetView nview, Humanoid humanoid, Renderer[] blades) { _nview = nview; _humanoid = humanoid; _blades = blades; ((MonoBehaviour)this).CancelInvoke("Tick"); ((MonoBehaviour)this).InvokeRepeating("Tick", 0f, 1f); } private void Tick() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { ClearParticles(); return; } ZDO zDO = _nview.GetZDO(); if (zDO == null) { ClearParticles(); return; } ActiveInfusion activeInfusion = null; if (_nview.IsOwner() && (Object)(object)_humanoid != (Object)null) { int num = (int)(WeaponInfusionState.GetActive(InfusableWeapons.GetEquipped(_humanoid, includeSheathed: true))?.Definition.Id ?? ((InfusionId)(-1))); zDO.Set("ac_infusion_r", num); } int num2 = zDO.GetInt("ac_infusion_r", -1); if (num2 != _currentShownId) { _currentShownId = num2; ApplyVisual(num2); } } private void ApplyVisual(int id) { ClearParticles(); if (id < 0 || _blades == null) { return; } InfusionDefinition infusionDefinition = InfusionDefinition.All.FirstOrDefault((InfusionDefinition d) => d.Id == (InfusionId)id); if (infusionDefinition != null) { _particles = (GameObject[])(object)new GameObject[_blades.Length]; for (int num = 0; num < _blades.Length; num++) { _particles[num] = InfusionParticleFactory.Create(infusionDefinition.Id, _blades[num]); } AdagasCruzadasPlugin.Log.LogInfo((object)$"[Infusao Visual] efeito de {infusionDefinition.Id} em {_blades.Length} lamina(s) de {((Object)this).name}."); } } private void ClearParticles() { if (_particles == null) { return; } GameObject[] particles = _particles; foreach (GameObject val in particles) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _particles = null; } private void OnDestroy() { ClearParticles(); } } internal static class KnifeSkillBonus { private const float PerLevel = 0.0045f; public static float Multiplier(SkillType weaponSkill, float skillLevel) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)weaponSkill != 2) { return 1f; } return 1f + skillLevel * 0.0045f; } public static float Multiplier(float knifeSkillLevel) { return 1f + knifeSkillLevel * 0.0045f; } } [HarmonyPatch(typeof(Player), "ConsumeItem")] internal static class WeaponInfusionApplyPatch { private static bool Prefix(Player __instance, Inventory inventory, ItemData item, ref bool __result) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) InfusionDefinition infusionDefinition = InfusionRegistry.Find(item); if (infusionDefinition == null) { return true; } ItemData equipped = InfusableWeapons.GetEquipped((Humanoid)(object)__instance, includeSheathed: false); if (equipped == null) { ((Character)__instance).Message((MessageType)2, "$adagascruzadas_infusion_needweapon", 0, (Sprite)null, false); __result = false; return false; } string text = InfusionConflict.Find(equipped, infusionDefinition); if (text != null) { Localization instance = Localization.instance; ((Character)__instance).Message((MessageType)2, instance.Localize("$adagascruzadas_infusion_conflict") + " (" + instance.Localize(text) + ")", 0, (Sprite)null, false); __result = false; return false; } ActiveInfusion active = WeaponInfusionState.GetActive(equipped); if (active != null && active.Definition.Id != infusionDefinition.Id) { StatusEffect val = InfusionHudEffectFactory.Get(active.Definition.Id); if ((Object)(object)val != (Object)null) { ((Character)__instance).GetSEMan().RemoveStatusEffect(val, true); } } WeaponInfusionState.Apply(equipped, infusionDefinition); inventory.RemoveOneItem(item); StatusEffect val2 = InfusionHudEffectFactory.Get(infusionDefinition.Id); if ((Object)(object)val2 != (Object)null) { ((Character)__instance).GetSEMan().AddStatusEffect(val2, true, 0, 0f, (short)(-1)); } InfusionSoundFactory.PlayApplySound(infusionDefinition, ((Component)__instance).transform.position); __result = false; return false; } } [HarmonyPatch(typeof(Attack), "ModifyDamage")] internal static class WeaponInfusionDamagePatch { private static readonly float[] ChainMultipliers = new float[3] { 1.3f, 2f, 1.5f }; internal const string ZdoAttackInfusionKey = "ac_infusion_hit"; internal const string ZdoAttackSkillKey = "ac_infusion_hit_skill"; private static void Postfix(HitData hitData, int ___m_currentAttackCainLevel, ItemData ___m_weapon, Humanoid ___m_character) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) ActiveInfusion activeInfusion = (InfusableWeapons.IsInfusable(___m_weapon) ? WeaponInfusionState.GetActive(___m_weapon) : null); PublishAttackingInfusion(___m_character, activeInfusion, ___m_weapon); if (activeInfusion != null) { int num = Mathf.Clamp(___m_currentAttackCainLevel, 0, ChainMultipliers.Length - 1); float skillBonus = KnifeSkillBonus.Multiplier(___m_weapon.m_shared.m_skillType, hitData.m_skillLevel); switch (activeInfusion.Definition.Family) { case InfusionFamily.DirectDamage: ApplyDirectDamage(hitData, activeInfusion.Definition, ChainMultipliers[num], skillBonus); break; case InfusionFamily.Status: ApplyStatus(hitData, activeInfusion.Definition, skillBonus); break; case InfusionFamily.Vampirism: ApplyVampirism(hitData, activeInfusion.Definition, num, ___m_character, skillBonus); break; } } } private static void PublishAttackingInfusion(Humanoid attacker, ActiveInfusion active, ItemData weapon) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attacker == (Object)null) { return; } ZNetView component = ((Component)attacker).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return; } ZDO zDO = component.GetZDO(); if (zDO != null) { int num = (int)(active?.Definition.Id ?? ((InfusionId)(-1))); if (zDO.GetInt("ac_infusion_hit", -1) != num) { zDO.Set("ac_infusion_hit", num); zDO.Set("ac_infusion_hit_skill", (active != null && weapon?.m_shared != null) ? ((int)weapon.m_shared.m_skillType) : 0); } } } private static void ApplyDirectDamage(HitData hitData, InfusionDefinition def, float multiplier, float skillBonus) { if (hitData.m_variant < 0) { hitData.m_variant = 0; } float num = def.BaseDamage * multiplier * skillBonus; switch (def.DamageType) { case ElementalDamageType.Fire: hitData.m_damage.m_fire += num; break; case ElementalDamageType.Frost: hitData.m_damage.m_frost += num; break; case ElementalDamageType.Lightning: hitData.m_damage.m_lightning += num; break; case ElementalDamageType.Spirit: hitData.m_damage.m_spirit += num; break; case ElementalDamageType.Poison: hitData.m_damage.m_poison += num; break; } } private static void ApplyStatus(HitData hitData, InfusionDefinition def, float skillBonus) { if (Random.value >= def.Chance) { return; } ObjectDB instance = ObjectDB.instance; StatusEffect val = ((instance != null) ? instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(def.TargetStatusEffectName)) : null); if (!((Object)(object)val == (Object)null)) { hitData.m_statusEffectHash = val.NameHash(); if (skillBonus <= 1f) { hitData.m_skillLevel = 0f; } } } private static void ApplyVampirism(HitData hitData, InfusionDefinition def, int level, Humanoid attacker, float skillBonus) { if (!((Object)(object)attacker == (Object)null)) { float num = ((DamageTypes)(ref hitData.m_damage)).GetTotalDamage(); if (level == ChainMultipliers.Length - 1) { num *= 2f; } ((Character)attacker).Heal(num * def.HealPercent * skillBonus, true); } } } internal class ActiveInfusion { public InfusionDefinition Definition; public double EndTime; } internal static class WeaponInfusionState { private const string InfusionKey = "ac_infusion"; private const string EndKey = "ac_infusion_end"; public static ActiveInfusion GetActive(ItemData weapon) { if (weapon == null) { return null; } if (!weapon.m_customData.TryGetValue("ac_infusion", out var value)) { return null; } if (!weapon.m_customData.TryGetValue("ac_infusion_end", out var value2)) { return null; } if (!double.TryParse(value2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Clear(weapon); return null; } if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.GetTimeSeconds() >= result) { Clear(weapon); return null; } if (!Enum.TryParse<InfusionId>(value, out var id)) { Clear(weapon); return null; } InfusionDefinition infusionDefinition = InfusionDefinition.All.FirstOrDefault((InfusionDefinition d) => d.Id == id); if (infusionDefinition == null) { Clear(weapon); return null; } return new ActiveInfusion { Definition = infusionDefinition, EndTime = result }; } public static void Apply(ItemData weapon, InfusionDefinition definition) { double num = ZNet.instance.GetTimeSeconds() + 300.0; weapon.m_customData["ac_infusion"] = definition.Id.ToString(); weapon.m_customData["ac_infusion_end"] = num.ToString(CultureInfo.InvariantCulture); } public static void Clear(ItemData weapon) { weapon.m_customData.Remove("ac_infusion"); weapon.m_customData.Remove("ac_infusion_end"); } public static float GetRemainingSeconds(ActiveInfusion active) { if (active == null || (Object)(object)ZNet.instance == (Object)null) { return 0f; } return (float)(active.EndTime - ZNet.instance.GetTimeSeconds()); } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] internal static class WeaponInfusionTooltipPatch { private static void Postfix(ItemData item, ref string __result) { if (InfusableWeapons.IsInfusable(item)) { ActiveInfusion active = WeaponInfusionState.GetActive(item); if (active != null) { float remainingSeconds = WeaponInfusionState.GetRemainingSeconds(active); int num = (int)(remainingSeconds / 60f); int num2 = (int)(remainingSeconds % 60f); string arg = Localization.instance.Localize(active.Definition.NameToken); __result += $"\n<color=orange>Infundida: {arg} ({num:00}:{num2:00})</color>"; } } } } [HarmonyPatch(typeof(VisEquipment), "AttachItem")] internal static class WeaponInfusionVisualPatch { internal const string ZdoInfusionKey = "ac_infusion_r"; private static void Postfix(VisEquipment __instance, GameObject __result, int itemHash, bool backAttach) { if ((Object)(object)__result == (Object)null || !InfusableWeapons.IsInfusableHash(itemHash)) { return; } Renderer[] array = (from r in __result.GetComponentsInChildren<Renderer>(true) where EmitsAlongTheBlade(r, __result.transform) select r).ToArray(); if (array.Length == 0) { AdagasCruzadasPlugin.Log.LogInfo((object)("[Infusao Visual] " + ((Object)__result).name + " nao tem malha propria pra emitir a aura; arma fica sem efeito visual. Renderers: " + DescribeRenderers(__result))); return; } InfusionVisualController infusionVisualController = __result.GetComponent<InfusionVisualController>(); if ((Object)(object)infusionVisualController == (Object)null) { infusionVisualController = __result.AddComponent<InfusionVisualController>(); } infusionVisualController.Bind(((Component)__instance).GetComponent<ZNetView>(), ((Component)__instance).GetComponent<Humanoid>(), array); AdagasCruzadasPlugin.Log.LogInfo((object)$"[Infusao Visual] controller ligado em {((Object)__result).name} (embainhada={backAttach}, laminas={array.Length})."); } private static bool EmitsAlongTheBlade(Renderer renderer, Transform attachRoot) { if (renderer is MeshRenderer) { return true; } SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val == null) { return false; } Transform rootBone = val.rootBone; if (!((Object)(object)rootBone == (Object)null)) { return rootBone.IsChildOf(attachRoot); } return true; } private static string DescribeRenderers(GameObject root) { IEnumerable<string> source = root.GetComponentsInChildren<Renderer>(true).Select(delegate(Renderer r) { SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null); return (val == null) ? (((Object)r).name + ":" + ((object)r).GetType().Name) : (((Object)r).name + ":Skinned(root=" + (((Object)(object)val.rootBone != (Object)null) ? ((Object)val.rootBone).name : "null") + ")"); }); return string.Join(", ", source.ToArray()); } } } namespace AdagasCruzadas.Combat.Ui { internal class EnemyStatusIcons : MonoBehaviour { private const float IconSize = 26f; private const float Spacing = 4f; private const float VerticalOffset = -18f; private const string ZdoStatusKey = "ac_target_status"; private const float SyncInterval = 0.25f; private Character _character; private ZNetView _nview; private RectTransform _row; private readonly List<Image> _pool = new List<Image>(); private readonly List<StatusEffect> _visible = new List<StatusEffect>(); private readonly List<int> _sources = new List<int>(); private float _syncTimer; private string _lastPublished; private static readonly int[] InfusionStatusHashes = new int[5] { SEMan.s_statusEffectBurning, SEMan.s_statusEffectFrost, SEMan.s_statusEffectPoison, SEMan.s_statusEffectSpirit, SEMan.s_statusEffectLightning }; public void Setup(Character character, RectTransform reference) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) _character = character; _nview = (((Object)(object)character != (Object)null) ? ((Component)character).GetComponent<ZNetView>() : null); if (!((Object)(object)_row != (Object)null)) { GameObject val = new GameObject("AC_StatusIcons", new Type[1] { typeof(RectTransform) }); _row = val.GetComponent<RectTransform>(); ((Transform)_row).SetParent(((Component)this).transform, false); if ((Object)(object)reference != (Object)null) { _row.anchorMin = reference.anchorMin; _row.anchorMax = reference.anchorMax; _row.pivot = reference.pivot; _row.anchoredPosition = reference.anchoredPosition + new Vector2(0f, -18f); } else { _row.anchoredPosition = new Vector2(0f, -18f); } _row.sizeDelta = new Vector2(0f, 26f); } } private void LateUpdate() { if (!((Object)(object)_character == (Object)null) && !((Object)(object)_row == (Object)null)) { if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner()) { CollectFromStatusManager(); PublishToZdo(); } else { CollectFromZdo(); } Layout(); } } private void CollectFromStatusManager() { _visible.Clear(); _sources.Clear(); SEMan sEMan = _character.GetSEMan(); if (sEMan == null) { return; } InfusionStatusSource component = ((Component)_character).GetComponent<InfusionStatusSource>(); foreach (StatusEffect statusEffect in sEMan.GetStatusEffects()) { if (!((Object)(object)statusEffect == (Object)null) && !statusEffect.m_hidden) { int num = -1; if ((Object)(object)component != (Object)null && component.TryGet(statusEffect.NameHash(), out var infusion)) { num = (int)infusion; } if (!((Object)(object)ResolveIcon(statusEffect, num) == (Object)null)) { _visible.Add(statusEffect); _sources.Add(num); } } } ForgetExpiredSources(component, sEMan); } private void ForgetExpiredSources(InfusionStatusSource source, SEMan seMan) { if ((Object)(object)source == (Object)null || !source.HasAny) { return; } int[] infusionStatusHashes = InfusionStatusHashes; foreach (int num in infusionStatusHashes) { if (!seMan.HaveStatusEffect(num)) { source.Forget(num); } } } private void PublishToZdo() { _syncTimer -= Time.deltaTime; if (_syncTimer > 0f) { return; } _syncTimer = 0.25f; ZDO zDO = _nview.GetZDO(); if (zDO == null) { return; } string text = string.Empty; if (_visible.Count > 0) { string[] array = new string[_visible.Count]; for (int i = 0; i < _visible.Count; i++) { array[i] = _visible[i].NameHash() + ":" + _sources[i]; } text = string.Join(",", array); } if (!(text == _lastPublished)) { _lastPublished = text; zDO.Set("ac_target_status", text); } } private void CollectFromZdo() { _visible.Clear(); _sources.Clear(); ZDO val = (((Object)(object)_nview != (Object)null && _nview.IsValid()) ? _nview.GetZDO() : null); if (val == null || (Object)(object)ObjectDB.instance == (Object)null) { return; } string text = val.GetString("ac_target_status", string.Empty); if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (int.TryParse(array2[0], out var result)) { int result2 = -1; if (array2.Length > 1) { int.TryParse(array2[1], out result2); } StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(result); if (!((Object)(object)statusEffect == (Object)null) && !statusEffect.m_hidden && !((Object)(object)ResolveIcon(statusEffect, result2) == (Object)null)) { _visible.Add(statusEffect); _sources.Add(result2); } } } } private static Sprite ResolveIcon(StatusEffect se, int infusionId) { if (infusionId < 0) { return se.m_icon; } Sprite val = InfusionIconFactory.Get(ObjectDB.instance, (InfusionId)infusionId); if (!((Object)(object)val != (Object)null)) { return se.m_icon; } return val; } private void Layout() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) EnsurePool(_visible.Count); float num = (0f - ((float)_visible.Count * 26f + (float)Mathf.Max(0, _visible.Count - 1) * 4f)) / 2f + 13f; for (int i = 0; i < _pool.Count; i++) { Image val = _pool[i]; if (i >= _visible.Count) { if (((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } continue; } if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } val.sprite = ResolveIcon(_visible[i], _sources[i]); ((Graphic)val).rectTransform.anchoredPosition = new Vector2(num, 0f); num += 30f; } } private void EnsurePool(int count) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) while (_pool.Count < count) { GameObject val = new GameObject("AC_StatusIcon", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)_row, false); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(26f, 26f); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).raycastTarget = false; _pool.Add(component2); } } } [HarmonyPatch(typeof(EnemyHud), "UpdateHuds")] internal static class EnemyStatusIconsPatch { private static readonly FieldInfo HudsField = AccessTools.Field(typeof(EnemyHud), "m_huds"); private static readonly Type HudDataType = AccessTools.Inner(typeof(EnemyHud), "HudData"); private static readonly FieldInfo GuiField = ((HudDataType != null) ? AccessTools.Field(HudDataType, "m_gui") : null); private static readonly FieldInfo HealthFastField = ((HudDataType != null) ? AccessTools.Field(HudDataType, "m_healthFast") : null); private static void Postfix(EnemyHud __instance) { if (HudsField == null || GuiField == null || !(HudsField.GetValue(__instance) is IDictionary dictionary)) { return; } foreach (DictionaryEntry item in dictionary) { object key = item.Key; Character val = (Character)((key is Character) ? key : null); if (!((Object)(object)val == (Object)null) && item.Value != null) { object? value = GuiField.GetValue(item.Value); GameObject val2 = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.GetComponent<EnemyStatusIcons>() != (Object)null)) { val2.AddComponent<EnemyStatusIcons>().Setup(val, GetHealthBarRect(item.Value)); } } } } private static RectTransform GetHealthBarRect(object hudData) { object? obj = HealthFastField?.GetValue(hudData); GuiBar val = (GuiBar)((obj is GuiBar) ? obj : null); if (!((Object)(object)val != (Object)null)) { return null; } Transform transform = ((Component)val).transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); } } internal class InfusionStatusSource : MonoBehaviour { private readonly Dictionary<int, InfusionId> _byStatusHash = new Dictionary<int, InfusionId>(); public bool HasAny => _byStatusHash.Count > 0; public static InfusionStatusSource GetOrAdd(GameObject target) { InfusionStatusSource component = target.GetComponent<InfusionStatusSource>(); if (!((Object)(object)component != (Object)null)) { return target.AddComponent<InfusionStatusSource>(); } return component; } public void Mark(int statusHash, InfusionId infusion) { _byStatusHash[statusHash] = infusion; } public bool TryGet(int statusHash, out InfusionId infusion) { return _byStatusHash.TryGetValue(statusHash, out infusion); } public void Forget(int statusHash) { _byStatusHash.Remove(statusHash); } } [HarmonyPatch(typeof(Character), "RPC_Damage")] internal static class InfusionStatusSourcePatch { private static readonly Dictionary<InfusionId, int> StatusByInfusion = new Dictionary<InfusionId, int> { { InfusionId.Fire, SEMan.s_statusEffectBurning }, { InfusionId.Frost, SEMan.s_statusEffectFrost }, { InfusionId.Poison, SEMan.s_statusEffectPoison }, { InfusionId.Spirit, SEMan.s_statusEffectSpirit }, { InfusionId.Lightning, SEMan.s_statusEffectLightning } }; private static void Postfix(Character __instance, HitData hit) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between I4 and Unknown if ((Object)(object)__instance == (Object)null || hit == null) { return; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null) { return; } ZNetView component = ((Component)attacker).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO == null) { return; } int num = zDO.GetInt("ac_infusion_hit", -1); if (num >= 0 && zDO.GetInt("ac_infusion_hit_skill", 0) == (int)hit.m_skill && StatusByInfusion.TryGetValue((InfusionId)num, out var value)) { SEMan sEMan = __instance.GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(value)) { InfusionStatusSo