using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SkillXpMead")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SkillXpMead")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("49bc217c-e6ea-4b2d-9b60-4089e4610b8d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SkillXpMead;
[BepInPlugin("com.example.skillxpmead", "Skill XP Mead", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class SkillXpMeadPlugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(Skills), "RaiseSkill")]
private static class Skills_RaiseSkill_Patch
{
private static void Prefix(SkillType skillType, ref float factor)
{
Player localPlayer = Player.m_localPlayer;
if (!((Object)(object)localPlayer == (Object)null) && HasBoost(localPlayer))
{
float num = Mathf.Max(0f, CfgMultiplier.Value);
factor *= num;
}
}
}
public const string ModGuid = "com.example.skillxpmead";
public const string ModName = "Skill XP Mead";
public const string ModVersion = "1.1.0";
internal static ManualLogSource Log;
private static ConfigEntry<float> CfgMultiplier;
private static ConfigEntry<float> CfgDurationSeconds;
private static ConfigEntry<string> CfgRecipe;
private static ConfigEntry<int> CfgOutputAmount;
private static ConfigEntry<int> CfgMinStationLevel;
internal const string EffectInternalName = "SE_SkillXpBoost_DG";
internal const string ItemPrefabName = "DG_SkillXpMead";
private static readonly int EffectHash = Animator.StringToHash("SE_SkillXpBoost_DG");
internal static CustomStatusEffect SkillXpEffect;
private Harmony _harmony;
private void Awake()
{
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
CfgMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SkillXpMultiplier", 5f, "XP gain multilpyer. 5 = +400% (x5).");
CfgDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DurationSeconds", 300f, "Effect duration in seconds. 300 = 5 min.");
CfgRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Recipe", "Ingredients", "Honey:10,Thistle:5,Raspberry:10", "Recipe in format: Prefab:Amount,Prefab:Amount,... Example: Honey:10,Thistle:5,Raspberry:10");
CfgOutputAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "OutputAmount", 1, "amount of potions per 1 craft.");
CfgMinStationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "MinStationLevel", 1, "min lvl of StationLevel.");
AddStatusEffect();
PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
_harmony = new Harmony("com.example.skillxpmead");
_harmony.PatchAll();
Log.LogInfo((object)"Skill XP Mead 1.1.0 loaded");
}
private void OnDestroy()
{
PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private void AddStatusEffect()
{
//IL_0051: 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_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
((Object)val).name = "SE_SkillXpBoost_DG";
TrySetNameHash((StatusEffect)(object)val, EffectHash);
((StatusEffect)val).m_name = "Mastery";
((StatusEffect)val).m_tooltip = "Skill XP gain boosted";
((StatusEffect)val).m_ttl = Mathf.Max(1f, CfgDurationSeconds.Value);
((StatusEffect)val).m_startMessageType = (MessageType)1;
((StatusEffect)val).m_startMessage = "You feel ready to learn anything.";
((StatusEffect)val).m_stopMessageType = (MessageType)1;
((StatusEffect)val).m_stopMessage = "The surge of mastery fades.";
SkillXpEffect = new CustomStatusEffect((StatusEffect)(object)val, false);
ItemManager.Instance.AddStatusEffect(SkillXpEffect);
}
private void OnVanillaPrefabsAvailable()
{
try
{
AddPotionItemInCauldron();
}
catch (Exception ex)
{
Log.LogError((object)ex);
}
finally
{
PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
}
}
private void AddPotionItemInCauldron()
{
//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_0079: 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_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Expected O, but got Unknown
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Expected O, but got Unknown
string[] source = new string[3] { "MeadTasty", "MeadHealthMinor", "MeadStaminaMinor" };
string text = source.FirstOrDefault((string p) => (Object)(object)PrefabManager.Instance.GetPrefab(p) != (Object)null);
if (string.IsNullOrEmpty(text))
{
Log.LogError((object)"Can't find vanilla mead prefab to clone (MeadTasty/MeadHealthMinor/MeadStaminaMinor).");
return;
}
ItemConfig val = new ItemConfig
{
Name = "Mead of Mastery",
Description = "Increases skill XP gain.",
CraftingStation = "piece_cauldron",
MinStationLevel = Math.Max(1, CfgMinStationLevel.Value),
Amount = Math.Max(1, CfgOutputAmount.Value)
};
List<(string, int)> list = ParseRecipe(CfgRecipe.Value);
if (list.Count == 0)
{
Log.LogWarning((object)"Recipe config parsed as empty. Falling back to default Honey:10,Thistle:5,Raspberry:10");
list = new List<(string, int)>
{
("Honey", 10),
("Thistle", 5),
("Raspberry", 10)
};
}
foreach (var item in list)
{
val.AddRequirement(item.Item1, item.Item2, 0);
}
CustomItem val2 = new CustomItem("DG_SkillXpMead", text, val);
ItemManager.Instance.AddItem(val2);
val2.ItemDrop.m_itemData.m_shared.m_consumeStatusEffect = SkillXpEffect.StatusEffect;
try
{
Sprite[] icons = val2.ItemDrop.m_itemData.m_shared.m_icons;
if (icons != null && icons.Length != 0 && (Object)(object)icons[0] != (Object)null)
{
SkillXpEffect.StatusEffect.m_icon = icons[0];
}
}
catch
{
}
Log.LogInfo((object)string.Format("Added {0} (cloned from {1}) recipe='{2}' output={3}", "DG_SkillXpMead", text, CfgRecipe.Value, val.Amount));
Log.LogInfo((object)"NOTE: Changing recipe in config usually requires game restart to take effect.");
}
private static List<(string prefab, int amount)> ParseRecipe(string s)
{
List<(string, int)> list = new List<(string, int)>();
if (string.IsNullOrWhiteSpace(s))
{
return list;
}
string[] array = s.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string text in array)
{
string text2 = text.Trim();
if (text2.Length == 0)
{
continue;
}
string[] array2 = (from x in text2.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries)
select x.Trim()).ToArray();
if (array2.Length != 2)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("Bad recipe part '" + text2 + "'. Expected Prefab:Amount"));
}
continue;
}
string item = array2[0];
if (!int.TryParse(array2[1], out var result) || result <= 0)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("Bad amount in recipe part '" + text2 + "'."));
}
}
else
{
list.Add((item, result));
}
}
return list;
}
private static void TrySetNameHash(StatusEffect effect, int hash)
{
try
{
FieldInfo field = ((object)effect).GetType().GetField("m_nameHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.FieldType == typeof(int))
{
field.SetValue(effect, hash);
}
}
catch
{
}
}
internal static bool HasBoost(Player p)
{
if ((Object)(object)p == (Object)null)
{
return false;
}
SEMan sEMan = ((Character)p).GetSEMan();
if (sEMan == null)
{
return false;
}
try
{
if (sEMan.HaveStatusEffect(EffectHash))
{
return true;
}
}
catch
{
}
try
{
return typeof(SEMan).GetField("m_statusEffects", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(sEMan) is List<StatusEffect> source && source.Any((StatusEffect se) => (Object)(object)se != (Object)null && ((Object)se).name == "SE_SkillXpBoost_DG");
}
catch
{
return false;
}
}
}