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 HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("XpScaling")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+74c389aeb2245b0882a42d9ce0cdde966aad63e9")]
[assembly: AssemblyProduct("XpScaling")]
[assembly: AssemblyTitle("XpScaling")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 XpScaling
{
internal static class GearGrid
{
public static int LargestEmptyRegion(GearData data)
{
GearInfo info = data.Gear.Info;
if (!info.HasUpgradeGrid)
{
return 0;
}
int width = default(int);
int height = default(int);
info.GetUpgradeGridSize(ref width, ref height, false);
return HexGrid.LargestEmptyRegion(FindOccupiedCells(data, width, height), width, height);
}
public static bool[] FindOccupiedCells(GearData data, int width, int height)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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_0039: Unknown result type (might be due to invalid IL or missing references)
IUpgradable gear = data.Gear;
bool[] array = new bool[width * height];
List<UpgradeEquipData> equippedUpgrades = data.equippedUpgrades;
for (int i = 0; i < (equippedUpgrades?.Count ?? 0); i++)
{
UpgradeEquipData val = equippedUpgrades[i];
UpgradeInstance upgrade = ((UpgradeEquipData)(ref val)).GetUpgrade();
if (upgrade == null)
{
continue;
}
EquippedCellsEnumerator equippedCells = upgrade.GetEquippedCells(gear);
try
{
while (((EquippedCellsEnumerator)(ref equippedCells)).MoveNext())
{
if (((EquippedCellsEnumerator)(ref equippedCells)).X >= 0 && ((EquippedCellsEnumerator)(ref equippedCells)).X < width && ((EquippedCellsEnumerator)(ref equippedCells)).Y >= 0 && ((EquippedCellsEnumerator)(ref equippedCells)).Y < height)
{
array[((EquippedCellsEnumerator)(ref equippedCells)).Y * width + ((EquippedCellsEnumerator)(ref equippedCells)).X] = true;
}
}
}
finally
{
((EquippedCellsEnumerator)(ref equippedCells)).Dispose();
}
}
return array;
}
}
internal static class HexGrid
{
private static readonly (int X, int Y)[] EvenColumnNeighbors = new(int, int)[6]
{
(0, -1),
(0, 1),
(-1, 0),
(1, 0),
(-1, -1),
(1, -1)
};
private static readonly (int X, int Y)[] OddColumnNeighbors = new(int, int)[6]
{
(0, -1),
(0, 1),
(-1, 0),
(1, 0),
(-1, 1),
(1, 1)
};
public static int LargestEmptyRegion(bool[] occupied, int width, int height)
{
bool[] seen = (bool[])occupied.Clone();
int num = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
num = Math.Max(num, Fill(seen, j, i, width, height));
}
}
return num;
}
private static int Fill(bool[] seen, int x, int y, int width, int height)
{
if (x < 0 || x >= width || y < 0 || y >= height || seen[y * width + x])
{
return 0;
}
seen[y * width + x] = true;
int num = 1;
(int, int)[] array = ((x % 2 == 0) ? EvenColumnNeighbors : OddColumnNeighbors);
for (int i = 0; i < array.Length; i++)
{
(int, int) tuple = array[i];
int item = tuple.Item1;
int item2 = tuple.Item2;
num += Fill(seen, x + item, y + item2, width, height);
}
return num;
}
}
[MycoMod(/*Could not decode attribute arguments.*/)]
[BepInPlugin("xpscaling", "XPScaling", "0.2.1")]
[BepInProcess("Mycopunk.exe")]
public class Plugin : BaseUnityPlugin
{
private sealed class ItemRecord
{
public int? LastRunEmptyRegion;
public int XpGranted;
}
[HarmonyPatch(typeof(GearData), "AddXP")]
private static class AddXpPatch
{
private static void Prefix(GearData __instance, ref int xp)
{
if (xp > 0)
{
xp = ScaledXp(__instance, xp);
}
}
private static void Postfix(GearData __instance, int xp)
{
RecordFor(__instance).XpGranted += xp;
}
}
[HarmonyPatch(typeof(ModuleEquipSlots), "OnEquippedOrUnequipped")]
private static class GridEditedPatch
{
private static void Postfix(ModuleEquipSlots __instance)
{
Guarded("could not count an edited grid", delegate
{
if (!__instance.skins && __instance.target != null && IsRunInProgress())
{
RememberGrid(PlayerData.GetGearData(__instance.target.Info));
}
});
}
}
[HarmonyPatch(typeof(MissionManager), "OnNetworkSpawn")]
private static class MissionStartedPatch
{
private static void Postfix()
{
items.Clear();
}
}
[HarmonyPatch(typeof(MissionRewardsWindow), "SetRewards")]
private static class RewardsPatch
{
private static void Prefix(List<RewardInfo> rewards)
{
Guarded("left rewards unscaled", delegate
{
//IL_000b: 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_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < rewards.Count; i++)
{
RewardInfo val = rewards[i];
object reward = val.reward;
IUpgradable val2 = (IUpgradable)((reward is IUpgradable) ? reward : null);
if (val2 != null && items.TryGetValue(PlayerData.GetGearData(val2.Info), out var value))
{
val.amount = value.XpGranted;
rewards[i] = val;
}
}
});
}
private static void Postfix()
{
items.Clear();
}
}
private const float StarterCellCount = 25f;
private const float MaxScalar = 99f;
private static ManualLogSource Log;
private static ConfigEntry<float> bonusXpScalar;
private static ConfigEntry<float> globalXpScalar;
private static readonly Dictionary<GearData, ItemRecord> items = new Dictionary<GearData, ItemRecord>();
private void Awake()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
bonusXpScalar = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BonusXpScalar", 1f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 99f), Array.Empty<object>()));
globalXpScalar = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GlobalXpScalar", 1f, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 99f), Array.Empty<object>()));
UpgradeLookupIndex.Bind(((BaseUnityPlugin)this).Config, Log);
new Harmony("xpscaling").PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)$"loaded, BonusXpScalar={bonusXpScalar.Value}, GlobalXpScalar={globalXpScalar.Value}");
}
private static int ScaleXp(int xp, int emptyRegion, float bonusScalar, float globalScalar)
{
return Mathf.RoundToInt((float)xp * globalScalar * (1f + (float)emptyRegion / 25f * bonusScalar));
}
private static void Guarded(string failure, Action action)
{
try
{
action();
}
catch (Exception arg)
{
Log.LogError((object)$"{failure}: {arg}");
}
}
private static ItemRecord RecordFor(GearData data)
{
if (!items.TryGetValue(data, out var value))
{
value = new ItemRecord();
items[data] = value;
}
return value;
}
private static bool IsRunInProgress()
{
MissionManager instance = MissionManager.Instance;
if ((Object)(object)instance != (Object)null && instance.IsMissionActive)
{
return !instance.HasMissionEnded;
}
return false;
}
private static void RememberGrid(GearData data)
{
RecordFor(data).LastRunEmptyRegion = GearGrid.LargestEmptyRegion(data);
}
private static int ScaledXp(GearData data, int xp)
{
try
{
if (IsRunInProgress())
{
RememberGrid(data);
}
int emptyRegion = RecordFor(data).LastRunEmptyRegion ?? GearGrid.LargestEmptyRegion(data);
return ScaleXp(xp, emptyRegion, bonusXpScalar.Value, globalXpScalar.Value);
}
catch (Exception arg)
{
Log.LogError((object)$"left XP unscaled: {arg}");
return xp;
}
}
}
internal static class UpgradeLookupIndex
{
private readonly struct Slot
{
public readonly UpgradeInstance Instance;
public readonly int Key;
public readonly int InfoIndex;
public readonly int InstanceIndex;
public Slot(UpgradeInstance instance, int key, int infoIndex, int instanceIndex)
{
Instance = instance;
Key = key;
InfoIndex = infoIndex;
InstanceIndex = instanceIndex;
}
}
[HarmonyPatch(typeof(PlayerData), "GetUpgradeInstanceFromID", new Type[] { typeof(int) })]
private static class LookupPatch
{
private static bool Prefix(int id, ref UpgradeInstance __result)
{
if (!Active)
{
return true;
}
try
{
__result = Find(id);
}
catch (Exception e)
{
Fault(e);
}
return __result == null;
}
private static void Postfix(int id, UpgradeInstance __result)
{
if (!Active || __result == null || searchOnlyIds.Contains(id))
{
return;
}
try
{
if (Find(id) == null)
{
Rebuild();
if (!slots.ContainsKey(id))
{
searchOnlyIds.Add(id);
}
}
}
catch (Exception e)
{
Fault(e);
}
}
}
private const string Section = "UpgradeLookupIndex";
private static ManualLogSource log;
private static ConfigEntry<bool> useIndex;
private static readonly Dictionary<int, Slot> slots = new Dictionary<int, Slot>();
private static readonly HashSet<int> searchOnlyIds = new HashSet<int>();
private static bool faulted;
private static bool Active
{
get
{
if (useIndex.Value)
{
return !faulted;
}
return false;
}
}
internal static void Bind(ConfigFile config, ManualLogSource logger)
{
log = logger;
useIndex = config.Bind<bool>("UpgradeLookupIndex", "Enabled", true, "Use the index for upgrade lookups.");
}
private static UpgradeInstance Find(int id)
{
Dictionary<int, List<UpgradeInfo>> dictionary = PlayerData.Instance?.data;
if (dictionary == null || !slots.TryGetValue(id, out var value) || !dictionary.TryGetValue(value.Key, out var value2) || value.InfoIndex >= value2.Count)
{
return null;
}
List<UpgradeInstance> instances = value2[value.InfoIndex].Instances;
if (instances == null || value.InstanceIndex >= instances.Count)
{
return null;
}
UpgradeInstance val = instances[value.InstanceIndex];
if (val != value.Instance || val.InstanceID != id)
{
return null;
}
return val;
}
private static void Rebuild()
{
slots.Clear();
foreach (KeyValuePair<int, List<UpgradeInfo>> datum in PlayerData.Instance.data)
{
for (int i = 0; i < datum.Value.Count; i++)
{
List<UpgradeInstance> instances = datum.Value[i].Instances;
if (instances != null)
{
for (int j = 0; j < instances.Count; j++)
{
Add(instances[j], datum.Key, i, j);
}
}
}
}
}
private static void Add(UpgradeInstance instance, int key, int infoIndex, int instanceIndex)
{
int instanceID = instance.InstanceID;
if (!searchOnlyIds.Contains(instanceID))
{
if (slots.Remove(instanceID))
{
searchOnlyIds.Add(instanceID);
}
else
{
slots[instanceID] = new Slot(instance, key, infoIndex, instanceIndex);
}
}
}
private static void Fault(Exception e)
{
faulted = true;
log.LogError((object)$"upgrade lookup index turned off: {e}");
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}