using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using RoR2;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Reconsume")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Reconsume")]
[assembly: AssemblyTitle("Reconsume")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 Reconsume
{
public sealed class CommonConfigData
{
public bool RefillOnStage;
public bool CanScrap;
public CommonConfigData(bool RefillOnStage, bool CanScrap)
{
this.RefillOnStage = RefillOnStage;
this.CanScrap = CanScrap;
}
public CommonConfigData(ConfigEntry<bool> RefillOnStageEntry, ConfigEntry<bool> CanScrapEntry)
{
RefillOnStage = RefillOnStageEntry.Value;
CanScrap = CanScrapEntry.Value;
}
}
internal static class Log
{
internal static ManualLogSource _logSource;
internal static void Init(ManualLogSource logSource)
{
_logSource = logSource;
}
internal static void LogDebug(object data)
{
_logSource.LogDebug(data);
}
internal static void LogError(object data)
{
_logSource.LogError(data);
}
internal static void LogFatal(object data)
{
_logSource.LogFatal(data);
}
internal static void LogInfo(object data)
{
_logSource.LogInfo(data);
}
internal static void LogMessage(object data)
{
_logSource.LogMessage(data);
}
internal static void LogWarning(object data)
{
_logSource.LogWarning(data);
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.jiejasonliu.Reconsume", "Reconsume", "1.0.4")]
public class Reconsume : BaseUnityPlugin
{
protected Dictionary<ItemDef, ItemDef> candidateItems;
protected Dictionary<ItemDef, CommonConfigData> candidateItemsConfigData;
protected static ConfigEntry<float> RefillConsumedPercent;
protected static ConfigEntry<bool> RefillPowerElixir;
protected static ConfigEntry<bool> ScrapConsumedPowerElixir;
protected static ConfigEntry<float> HealingStrengthPowerElixir;
protected static ConfigEntry<bool> RefillDelicateWatch;
protected static ConfigEntry<bool> ScrapConsumedDelicateWatch;
protected static ConfigEntry<bool> RefillDiosBestFriend;
protected static ConfigEntry<bool> ScrapConsumedDiosBestFriend;
public void Awake()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: 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_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
Log.Init(((BaseUnityPlugin)this).Logger);
SetupConfiguration();
Run.Start += new hook_Start(Init_CandidateItems);
SceneDirector.PopulateScene += new hook_PopulateScene(StageRestore_CandidateItems);
ScrapperController.BeginScrapping_UniquePickup += new Manipulator(IL_FixItemTier_CandidateItems);
PickupPickerController.SetOptionsFromInteractor += new Manipulator(IL_ScrapperWhiteList_CandidateItems);
HealthComponent.UpdateLastHitTime += new Manipulator(IL_AlterHealStrength_PowerElixir);
Log.LogInfo("Reconsume::Awake() done.");
}
private void SetupConfiguration()
{
RefillConsumedPercent = ((BaseUnityPlugin)this).Config.Bind<float>("_General", "RefillConsumedPercent", 0.33f, "Percentage of consumed items to restore each stage (0.0 - 1.0; 0.33 being 33%)");
RefillPowerElixir = ((BaseUnityPlugin)this).Config.Bind<bool>("PowerElixir", "RefillPowerElixir", true, "Restore power elixir at the beginning of each stage");
ScrapConsumedPowerElixir = ((BaseUnityPlugin)this).Config.Bind<bool>("PowerElixir", "ScrapConsumedPowerElixir", true, "Allow scrapping consumed power elixirs");
HealingStrengthPowerElixir = ((BaseUnityPlugin)this).Config.Bind<float>("PowerElixir", "HealingStrengthPowerElixir", 0.75f, "Healing strength of power elixir (vanilla default is 0.75)");
RefillDelicateWatch = ((BaseUnityPlugin)this).Config.Bind<bool>("DelicateWatch", "RefillDelicateWatch", true, "Restore delicate watch at the beginning of each stage");
ScrapConsumedDelicateWatch = ((BaseUnityPlugin)this).Config.Bind<bool>("DelicateWatch", "ScrapConsumedDelicateWatch", true, "Allow scrapping consumed delicate watches");
RefillDiosBestFriend = ((BaseUnityPlugin)this).Config.Bind<bool>("DiosBestFriend", "RefillDiosBestFriend", false, "Restore dio's best friend at the beginning of each stage");
ScrapConsumedDiosBestFriend = ((BaseUnityPlugin)this).Config.Bind<bool>("DiosBestFriend", "ScrapConsumedDiosBestFriend", false, "Allow scrapping consumed dio's best friend");
}
private void Init_CandidateItems(orig_Start orig, Run self)
{
orig.Invoke(self);
candidateItems = new Dictionary<ItemDef, ItemDef>
{
{
Items.HealingPotionConsumed,
Items.HealingPotion
},
{
Items.FragileDamageBonusConsumed,
Items.FragileDamageBonus
},
{
Items.ExtraLifeConsumed,
Items.ExtraLife
}
};
candidateItemsConfigData = new Dictionary<ItemDef, CommonConfigData>
{
{
Items.HealingPotionConsumed,
new CommonConfigData(RefillPowerElixir, ScrapConsumedPowerElixir)
},
{
Items.FragileDamageBonusConsumed,
new CommonConfigData(RefillDelicateWatch, ScrapConsumedDelicateWatch)
},
{
Items.ExtraLifeConsumed,
new CommonConfigData(RefillDiosBestFriend, ScrapConsumedDiosBestFriend)
}
};
}
private void StageRestore_CandidateItems(orig_PopulateScene orig, SceneDirector self)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
orig.Invoke(self);
float num = Math.Clamp(RefillConsumedPercent.Value, 0f, 1f);
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
Inventory inventory = instance.master.inventory;
foreach (ItemIndex item in new List<ItemIndex>(inventory.itemAcquisitionOrder))
{
ItemDef itemDef = ItemCatalog.GetItemDef(item);
if (candidateItems.TryGetValue(itemDef, out var value) && candidateItemsConfigData[itemDef].RefillOnStage)
{
int itemCountPermanent = inventory.GetItemCountPermanent(itemDef);
int num2 = ((itemCountPermanent >= 1) ? Convert.ToInt32(Math.Ceiling((float)itemCountPermanent * num)) : 0);
inventory.RemoveItemPermanent(itemDef, num2);
inventory.GiveItemPermanent(value, num2);
}
}
}
}
private void IL_FixItemTier_CandidateItems(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
val.GotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchCallvirt(x, typeof(ItemDef), "get_tier"),
(Instruction x) => ILPatternMatchingExt.MatchCall(x, typeof(PickupCatalog), "FindScrapIndexForItemTier")
});
val.Index += 1;
val.Emit(OpCodes.Ldarg_1);
val.EmitDelegate<Func<ItemTier, UniquePickup, ItemTier>>((Func<ItemTier, UniquePickup, ItemTier>)delegate(ItemTier pickupToTakeItemTier, UniquePickup pickupToTake)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
if ((int)pickupToTakeItemTier == 5)
{
PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupToTake.pickupIndex);
ItemIndex val2 = (ItemIndex)((pickupDef == null) ? (-1) : ((int)pickupDef.itemIndex));
foreach (var (val5, val6) in candidateItems)
{
if (val2 == val5.itemIndex)
{
return val6.tier;
}
}
}
return pickupToTakeItemTier;
});
}
private void IL_ScrapperWhiteList_CandidateItems(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_007c: 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)
ILCursor val = new ILCursor(il);
val.GotoNext((MoveType)0, new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchCallvirt(x, "System.Collections.Generic.List`1<RoR2.PickupPickerController/Option>", "ToArray")
});
val.Emit(OpCodes.Ldarg_1);
val.Emit(OpCodes.Ldloc_0);
val.EmitDelegate<Action<Interactor, List<Option>>>((Action<Interactor, List<Option>>)delegate(Interactor activator, List<Option> optionList)
{
//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_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: 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_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_0097: 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_009e: Unknown result type (might be due to invalid IL or missing references)
object obj;
if (activator == null)
{
obj = null;
}
else
{
CharacterBody component = ((Component)activator).GetComponent<CharacterBody>();
obj = ((component != null) ? component.inventory : null);
}
Inventory val2 = (Inventory)obj;
if (!Object.op_Implicit((Object)(object)val2))
{
return;
}
foreach (ItemIndex item in new List<ItemIndex>(val2.itemAcquisitionOrder))
{
ItemDef itemDef = ItemCatalog.GetItemDef(item);
if (candidateItems.TryGetValue(itemDef, out var _) && candidateItemsConfigData[itemDef].CanScrap)
{
PickupIndex val3 = PickupCatalog.FindPickupIndex(item);
optionList.Add(new Option
{
available = true,
pickup = new UniquePickup(val3)
{
decayValue = 0f
}
});
}
}
});
}
private void IL_AlterHealStrength_PowerElixir(ILContext il)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
int num = default(int);
val.GotoNext((MoveType)0, new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 0.75f),
(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchInitobj(x, "RoR2.ProcChainMask")
});
val.Index += 1;
val.Remove();
float value = HealingStrengthPowerElixir.Value;
val.Emit(OpCodes.Ldc_R4, value);
}
}
}