using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using IL.RoR2; using Mono.Cecil.Cil; using MonoMod.Cil; using On.RoR2.Projectile; using R2API; using RoR2; using RoR2.Projectile; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("StackChanges")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ccda5084511894f1e75b3ba350d8409188b9502e")] [assembly: AssemblyProduct("StackChanges")] [assembly: AssemblyTitle("StackChanges")] [assembly: AssemblyVersion("1.0.0.0")] namespace StackChanges; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.Sagittariod.StackChanges", "Pedantic Item Stack Changes", "1.0.2")] public class StackChanges : BaseUnityPlugin { public static ConfigEntry chronicExpansionBaseBuffValue; public static ConfigEntry chronicExpansionAdditiveBuffValue; public static ConfigEntry bolsteringLanternBaseBuffValue; public static ConfigEntry bolsteringLanternAdditiveBuffValue; public static ConfigEntry dynamiteFirstStackDamage; public static ConfigEntry dynamiteAdditionalStackDamage; public static ConfigEntry luminousShotFirstStackDamage; public static ConfigEntry luminousShotAdditionalStackDamage; public static ConfigEntry eclipseLiteBaseBarrier; public static ConfigEntry eclipseLiteStackBarrier; public static ConfigEntry runicLensBaseProcChance; public static ConfigEntry runicLensStackProcChance; public static ConfigEntry warBondsBaseBuffCount; public static ConfigEntry warBondsStackBuffCount; public static StackChanges Instance { get; private set; } public void Awake() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown BindConfigs(); UpdateItemDescriptions(); Harmony val = new Harmony("com.Sagittariod.StackChanges"); val.PatchAll(); ProjectileController.Start += new hook_Start(ProjectileController_Start); RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(RecalculateStatsAPI_GetStatCoefficients); CharacterBody.OnSkillCooldown += new Manipulator(CharacterBody_OnSkillCooldown_IL); GlobalEventManager.ProcessHitEnemy += new Manipulator(GlobalEventManager_ProcessHitEnemy_IL); } private void BindConfigs() { chronicExpansionBaseBuffValue = ((BaseUnityPlugin)this).Config.Bind("Chronic Expansion", "First Stack Buff", 0.035f, "Vanilla = 0.035"); chronicExpansionAdditiveBuffValue = ((BaseUnityPlugin)this).Config.Bind("Chronic Expansion", "Additional Stack Buff", 0.0175f, "Vanilla = 0.01"); bolsteringLanternBaseBuffValue = ((BaseUnityPlugin)this).Config.Bind("Bolstering Lantern", "First Stack Buff", 0.1f, "Vanilla = 0.1"); bolsteringLanternAdditiveBuffValue = ((BaseUnityPlugin)this).Config.Bind("Bolstering Lantern", "Additional Stack Buff", 0.05f, "Vanilla = 0.035"); dynamiteFirstStackDamage = ((BaseUnityPlugin)this).Config.Bind("Box of Dynamite", "Base Damage Coefficient", 2.4f, "Vanilla = 2.4"); dynamiteAdditionalStackDamage = ((BaseUnityPlugin)this).Config.Bind("Box of Dynamite", "Extra Damage Coefficient per Stack", 2.4f, "Vanilla = 0.85"); luminousShotFirstStackDamage = ((BaseUnityPlugin)this).Config.Bind("Luminous Shot", "Base Damage Coefficient", 1.2f, "Vanilla = 1.75"); luminousShotAdditionalStackDamage = ((BaseUnityPlugin)this).Config.Bind("Luminous Shot", "Extra Damage Coefficient per Stack", 0.6f, "Vanilla = 0.5"); eclipseLiteBaseBarrier = ((BaseUnityPlugin)this).Config.Bind("Eclipse Lite", "Base Barrier", 0.008f, "Vanilla = 0.01"); eclipseLiteStackBarrier = ((BaseUnityPlugin)this).Config.Bind("Eclipse Lite", "Extra Barrier per Stack", 0.004f, "Vanilla = 0.0025"); runicLensBaseProcChance = ((BaseUnityPlugin)this).Config.Bind("Runic Lens", "Base Chance Increase per 100% Damage", 3f, "Vanilla = 3.0"); runicLensStackProcChance = ((BaseUnityPlugin)this).Config.Bind("Runic Lens", "Extra Chance Increase per 100% Damage per Stack", 0f, "Vanilla = 3.0"); warBondsBaseBuffCount = ((BaseUnityPlugin)this).Config.Bind("War Bonds", "Base Max Buff Count", 15, "Vanilla = 15"); warBondsStackBuffCount = ((BaseUnityPlugin)this).Config.Bind("War Bonds", "Extra Max Buff Count per Stack", 0, "Vanilla = 5"); } private void UpdateItemDescriptions() { LanguageAPI.Add("ITEM_INCREASEDAMAGEONMULTIKILL_DESC", $"Killing an enemy increases your damage by {chronicExpansionBaseBuffValue.Value * 100f}% (+{chronicExpansionAdditiveBuffValue.Value * 100f}% per stack), up to 10 (+5 per stack), for 7s. Dealing damage refreshes the timer."); LanguageAPI.Add("ITEM_ATTACKSPEEDPERNEARBYALLYORENEMY_DESC", $"Increase your attack speed by {bolsteringLanternBaseBuffValue.Value * 100f}% (+{bolsteringLanternAdditiveBuffValue.Value * 100f}% per stack) for up to 3 (+1 per stack) enemies and allies within 20 meters."); LanguageAPI.Add("ITEM_DRONESDROPDYNAMITE_DESC", $"Gain Lt. Droneboy. While in combat, your drones drop sticks of dynamite that detonate for {dynamiteFirstStackDamage.Value * 100f}% damage (+{dynamiteAdditionalStackDamage.Value * 100f}% per stack), stunning enemies. Recharges after 10 seconds."); LanguageAPI.Add("ITEM_INCREASEPRIMARYDAMAGE_DESC", $"Activating your Secondary skill stores up to 5 charges (+1 per stack). Requires 3 charges for your Primary skill to fire lightning strikes, dealing {luminousShotFirstStackDamage.Value * 100f}% TOTAL damage (+{luminousShotAdditionalStackDamage.Value * 100f}% per stack) each. Reduces Secondary skill cooldown by 20%."); LanguageAPI.Add("ITEM_BARRIERONCOOLDOWN_DESC", $"When a skill comes off cooldown, gain a temporary barrier for {eclipseLiteBaseBarrier.Value * 100f}% (+{eclipseLiteStackBarrier.Value * 100f}% per stack) of your maximum health per second of the skill's base cooldown."); LanguageAPI.Add("ITEM_METEORATTACKONHIGHDAMAGE_DESC", $"3% chance on hit to call down a meteor, dealing 2000% base damage. Every 100% attack damage dealt increases the activation chance by {runicLensBaseProcChance.Value}% (+{runicLensStackProcChance.Value}% per stack) and damage by 150% (+50% per stack)."); LanguageAPI.Add("ITEM_BARRAGEONBOSS_DESC", $"During boss events, 5 missiles bombard the area, dealing 2.5% (+2.5% per stack) of boss' Max Health in damage. Before the boss event, gain additional missiles, up to a maximum of {warBondsBaseBuffCount.Value} (+{warBondsStackBuffCount.Value} per stack), per 50 gold gained. Gold requirement scales over time."); } private void ScaleProjectile(ProjectileController controller, ItemDef item, float vanillaBase, float vanillaStack, float customBase, float customStack) { GameObject owner = controller.owner; CharacterBody val = ((owner != null) ? owner.GetComponent() : null); if ((Object)(object)val == (Object)null) { return; } int itemCountEffective = val.inventory.GetItemCountEffective(item); if (itemCountEffective > 0) { ProjectileDamage component = ((Component)controller).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { float num = vanillaBase + vanillaStack * (float)(itemCountEffective - 1); float num2 = customBase + customStack * (float)(itemCountEffective - 1); component.damage *= num2 / num; } } } private void RecalculateStatsAPI_GetStatCoefficients(CharacterBody sender, StatHookEventArgs args) { int buffCount = sender.GetBuffCount(Buffs.IncreaseDamageBuff); int itemCountEffective = sender.inventory.GetItemCountEffective(Items.IncreaseDamageOnMultiKill); float num = 0.035f + 0.01f * (float)(itemCountEffective - 1); float num2 = chronicExpansionBaseBuffValue.Value + chronicExpansionAdditiveBuffValue.Value * (float)(itemCountEffective - 1); args.damageMultAdd += (num2 - num) * (float)buffCount; int buffCount2 = sender.GetBuffCount(Buffs.AttackSpeedPerNearbyAllyOrEnemyBuff); int itemCountEffective2 = sender.inventory.GetItemCountEffective(Items.AttackSpeedPerNearbyAllyOrEnemy); float num3 = 0.1f + 0.035f * (float)(itemCountEffective2 - 1); float num4 = bolsteringLanternBaseBuffValue.Value + bolsteringLanternAdditiveBuffValue.Value * (float)(itemCountEffective2 - 1); args.attackSpeedMultAdd += (num4 - num3) * (float)buffCount2; } private void ProjectileController_Start(orig_Start orig, ProjectileController self) { orig.Invoke(self); if (((Object)self).name.StartsWith("DynamiteProjectile")) { ScaleProjectile(self, Items.DronesDropDynamite, 2.4f, 0.85f, dynamiteFirstStackDamage.Value, dynamiteAdditionalStackDamage.Value); } if (((Object)self).name.StartsWith("LuminousShotProjectile")) { ScaleProjectile(self, Items.IncreasePrimaryDamage, 1.75f, 0.5f, luminousShotFirstStackDamage.Value, luminousShotAdditionalStackDamage.Value); } } private void CharacterBody_OnSkillCooldown_IL(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (val.TryGotoNext(new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 0.01f) })) { val.Next.Operand = eclipseLiteBaseBarrier.Value; } if (val.TryGotoNext(new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 0.0025f) })) { val.Next.Operand = eclipseLiteStackBarrier.Value; } } private void GlobalEventManager_ProcessHitEnemy_IL(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (val.TryGotoNext(new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Items), "MeteorAttackOnHighDamage") })) { if (val.TryGotoNext(new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 3f) })) { val.Next.Operand = runicLensStackProcChance.Value; } if (val.TryGotoNext(new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 3f) })) { val.Next.Operand = runicLensBaseProcChance.Value; } } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class BarrageOnBossBehaviour_maxBuffCount_Patch { [HarmonyILManipulator] public static void ILManipulator(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0055: 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) ILCursor val = new ILCursor(il); if (val.TryGotoNext((MoveType)2, new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 15) })) { int index = val.Index; val.Index = index - 1; val.Remove(); val.Emit(OpCodes.Ldc_I4, StackChanges.warBondsBaseBuffCount.Value); } val.Index = 0; if (val.TryGotoNext((MoveType)2, new Func[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 5) })) { int index = val.Index; val.Index = index - 1; val.Remove(); val.Emit(OpCodes.Ldc_I4, StackChanges.warBondsStackBuffCount.Value); } } }