using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
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 UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("NineCustomWandMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NineCustomWandMod")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9d9b6302-6cf7-4da8-b83b-d874bc17eebd")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NineCustomWandMod;
[BepInPlugin("NineCustomWandMod", "(mod)NineCustomWandMod", "1.0.0.0")]
public class NineCustomWandMod : BaseUnityPlugin
{
public static ManualLogSource logger;
public static ConfigEntry<bool> LogDebugEnabled { get; set; }
public static int WandTextTitleID { get; set; }
public static int WandTextDescrptionID { get; set; }
public static ConfigEntry<int> WandConfigID { get; set; }
public static ConfigEntry<int> WandNormalSlots { get; set; }
public static ConfigEntry<string> WandIconId { get; set; }
public static ConfigEntry<int> WandSpecialAbility { get; set; }
public static ConfigEntry<int> WandPriceCoin { get; set; }
public static ConfigEntry<int> WandDropStage { get; set; }
public static ConfigEntry<int> WandPostSlotTriggerType { get; set; }
public static ConfigEntry<float> WandPostSlotTriggerChargeRatio { get; set; }
public static ConfigEntry<float> WandShootInterval { get; set; }
public static ConfigEntry<float> WandCoolDown { get; set; }
public static ConfigEntry<float> WandAngle { get; set; }
public static ConfigEntry<int> WandMaxMP { get; set; }
public static ConfigEntry<int> WandMpRecovery { get; set; }
public static ConfigEntry<int> WandShootCount { get; set; }
public static ConfigEntry<int> WandCostCorrection { get; set; }
public static ConfigEntry<int> WandCriticalChance { get; set; }
public static ConfigEntry<int> WandDamageCorrection { get; set; }
public static ConfigEntry<int> WandInt1 { get; set; }
public static ConfigEntry<int> WandInt2 { get; set; }
public static ConfigEntry<int> WandInt3 { get; set; }
public static ConfigEntry<float> WandFloat1 { get; set; }
public static ConfigEntry<float> WandFloat2 { get; set; }
public static ConfigEntry<float> WandFloat3 { get; set; }
public static ConfigEntry<string> WandSpellIDList { get; set; }
public static ConfigEntry<string> WandNormalSlotIsLock { get; set; }
public static ConfigEntry<int> WandPostSlots { get; set; }
public static ConfigEntry<string> WandPostSlotIsLock { get; set; }
public static bool AlreadyInjectedCustomWand { get; set; }
public void Awake()
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Awake: Plugin NineCustomWandMod start.");
logger = ((BaseUnityPlugin)this).Logger;
LoadSettings();
Harmony.CreateAndPatchAll(typeof(NineCustomWandMod), (string)null);
Log("Awake: Plugin NineCustomWandMod end.");
}
public static void Log(string message)
{
ConfigEntry<bool> logDebugEnabled = LogDebugEnabled;
if (logDebugEnabled == null || logDebugEnabled.Value)
{
logger.LogDebug((object)message);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(TextConfig), "TryGetText")]
private static void Pretfix_TryGetText_Mod(TextConfig __instance, int id, ref string text, bool __result)
{
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Expected O, but got Unknown
Log("Prefix_TryGetText_Mod start.");
Log("Prefix_TryGetText_Mod id: " + id);
Log("Prefix_TryGetText_Mod text: " + text);
if (!TextConfig.dic.ContainsKey(WandTextTitleID))
{
Log("Creating Custom Wand Text Title");
TextConfig val = new TextConfig();
val.id = WandTextTitleID;
val.chineseS = "Nine 的定制魔杖";
val.chineseH = "";
val.chineseT = "Nine 的客製化魔杖";
val.english = "Nine's Custom Wand";
val.japanese = "Nineのカスタムワンド";
val.german = "Nines individueller Zauberstab";
val.korean = "Nine의 커스텀 완드";
val.russian = "Индивидуальная палочка Nine";
val.spanish_spain = "Varita personalizada de Nine";
val.applyAlogia = true;
Log("add Custom Wand Text Title to game");
TextConfig.dic.Add(WandTextTitleID, val);
TextConfig.dic[WandTextTitleID].RegetStr();
Log("Creating Custom Wand Text desc");
TextConfig val2 = new TextConfig();
val2.id = WandTextDescrptionID;
val2.chineseS = "由被称为“Nine”的魔法狂热魔法师创造的魔杖";
val2.chineseH = "";
val2.chineseT = "由被稱為「Nine」的魔法狂熱法師創造的魔杖";
val2.english = "Wand created by the magic fanatic mage know as 'Nine'";
val2.japanese = "「Nine」として知られる魔法狂の魔術師が作った杖";
val2.german = "Zauberstab, hergestellt vom zauberfanatiker „Nine.“";
val2.korean = "'Nine'로 알려진 마법광 마법사가 만든 지팡이";
val2.russian = "Палочка, созданная магом-фанатиком магии, известным как «Nine».";
val2.spanish_spain = "Varita creada por el mago fanático de la magia conocido como 'Nine'";
val2.applyAlogia = true;
Log("add Custom Wand Text Description to game");
TextConfig.dic.Add(WandTextDescrptionID, val2);
TextConfig.dic[WandTextDescrptionID].RegetStr();
Log("Prefix_TryGetText_Mod end.");
}
}
public void LoadSettings()
{
Log("LoadSettings: Plugin NineCustomWandMod start.");
LogDebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogDebugEnabled", false, "Enable mod logging");
WandConfigID = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandConfigID", 9000, "ID of the Wand to add of the pool of game starts at 9000");
WandNormalSlots = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandNormalSlots", 16, "Number of normal slots of the custom Wand");
WandIconId = ((BaseUnityPlugin)this).Config.Bind<string>("WandConfig", "WandIconId", "201", "Id of the icon of the Custom Wand, find it on the games files or just try 1, 11, 12, etc see what works :D");
WandSpecialAbility = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandSpecialAbility", 0, "Enum, what it does? only god knows, the dev used obfuscator the enum name is JOBFEEJALOK...so good luck");
WandPriceCoin = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandPriceCoin", 0, "Price if the Custom Wand would appear in the store....useless for this mod? well this exist so i put in the config");
WandDropStage = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandDropStage", 101, "in what stage this Wand would drop....useless for this mod? well this exist so i put in the config");
WandPostSlotTriggerType = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandPostSlotTriggerType", 0, "enum IOINDHALAIP, this define the type of post slot effect, stand, run, etc, what charges it 1-10 good lock finding out what is what");
WandPostSlotTriggerChargeRatio = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandPostSlotTriggerChargeRatio", 0f, "the value of each charge");
WandShootInterval = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandShootInterval", 0.1f, "Pretty self explanatory, the shot rate, 1/10 of a second default value");
WandCoolDown = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandCoolDown", 0.1f, "Pretty self explanatory, the cool down, 1/10 of a second default value");
WandAngle = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandAngle", 0f, "i guess that this is the called 'spreed' of the wand in game ");
WandMaxMP = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandMaxMP", 200, "Pretty self explanatory, the wand max MP");
WandMpRecovery = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandMpRecovery", 20, "MP that the wand regen per second?");
WandShootCount = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandShootCount", 1, "How many shoots the wand shot at time?");
WandCostCorrection = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandCostCorrection", 100, "no idea what is this o what it do");
WandCriticalChance = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandCriticalChance", 0, "Crit chance?");
WandDamageCorrection = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandDamageCorrection", 100, "no idea what is this o what it do");
WandInt1 = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandInt1", 0, "no idea what is this o what it do");
WandInt2 = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandInt2", 0, "no idea what is this o what it do");
WandInt3 = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandInt3", 0, "no idea what is this o what it do");
WandFloat1 = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandFloat1", 0f, "no idea what is this o what it do");
WandFloat2 = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandFloa2t", 0f, "no idea what is this o what it do");
WandFloat3 = ((BaseUnityPlugin)this).Config.Bind<float>("WandConfig", "WandFloat3", 0f, "no idea what is this o what it do");
WandSpellIDList = ((BaseUnityPlugin)this).Config.Bind<string>("WandConfig", "WandSpellIDList", "10263, 31213, 30113, 30023, 31023", "Array of IDs of spells, you can find the file in the zip of the mod, this can change based on game version");
WandNormalSlotIsLock = ((BaseUnityPlugin)this).Config.Bind<string>("WandConfig", "WandNormalSlotIsLock", "false, false, false, false, false", "'false, false, false, false, false' Array that define if a normal slot is 'locked' to change/place/remove spells");
WandPostSlots = ((BaseUnityPlugin)this).Config.Bind<int>("WandConfig", "WandPostSlots", 0, "Number of 'post' slots of the custom Wand, i never used good luck trying");
WandPostSlotIsLock = ((BaseUnityPlugin)this).Config.Bind<string>("WandConfig", "WandPostSlotIsLock", "", "'false, false, false, false, false' Array that define if a post slot is 'locked' to change/place/remove spells, i never used good luck trying");
string s = "500" + WandConfigID.Value;
WandTextTitleID = int.Parse(s);
string s2 = "510" + WandConfigID.Value;
WandTextDescrptionID = int.Parse(s2);
Log("LoadSettings: Plugin NineCustomWandMod end.");
}
[HarmonyPostfix]
[HarmonyPatch(typeof(LCFIFNPGNGC), "AnnouncedDeath")]
private static void Postfix_AnnouncedDeath_Mod(LCFIFNPGNGC __instance, JDEANGCPOGH BKNFEALPMJH)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
if ((int)__instance.UnitCfg.corpseType == 0 && (int)__instance.UnitCfg.unitType <= 0)
{
Log("Postfix_AnnouncedDeath_Mod start.");
Log("Postfix_AnnouncedDeath_Mod AlreadyInjectedCustomWand: " + AlreadyInjectedCustomWand);
Log("Postfix_AnnouncedDeath_Mod __instance.LJGCDKHJPEM.corpseType: " + ((object)(HDFMKNINMHD)(ref __instance.UnitCfg.corpseType)).ToString());
Log("Postfix_AnnouncedDeath_Mod __instance.LJGCDKHJPEM.unitType " + ((object)(MAMJIKEBPFG)(ref __instance.UnitCfg.unitType)).ToString());
AlreadyInjectedCustomWand = false;
Log("Postfix_AnnouncedDeath_Mod AlreadyInjectedCustomWand: " + AlreadyInjectedCustomWand);
Log("Postfix_AnnouncedDeath_Mod end.");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(DKMCLHAPMDH), "EnterRoom")]
private static void Postfix_EnterRoom_Mod(DKMCLHAPMDH __instance)
{
//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)
Log("Postfix_EnterRoom_Mod start.");
KKOCLKGKHMJ oEKNDCNLCCD = __instance.OEKNDCNLCCD;
Log("__instance.OEKNDCNLCCD: " + ((object)(KKOCLKGKHMJ)(ref oEKNDCNLCCD)).ToString());
Log("Postfix_EnterRoom_Mod end.");
}
public static T[] DeserializeArray<T>(string serializedList, int arraySize = -1)
{
Log("DeserializeArray start.");
List<T> list = new List<T>();
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
string[] array = serializedList.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string text in array)
{
try
{
T item = (T)converter.ConvertFromString(text);
list.Add(item);
}
catch (Exception ex)
{
logger.LogError((object)("Error while converting array from config: " + ex.Message));
}
}
if (arraySize > 0)
{
if (list.Count > arraySize)
{
logger.LogError((object)"Error: Content size is bigger than the specified array size.");
list.RemoveRange(arraySize, list.Count - arraySize);
}
else if (list.Count < arraySize)
{
while (list.Count < arraySize)
{
list.Add(default(T));
}
}
}
Log("DeserializeArray end.");
return list.ToArray();
}
public static WandConfig GetCustomStartWand()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Expected O, but got Unknown
Log("GetCustomStartWand start.");
WandConfig val = new WandConfig();
val.id = WandConfigID.Value;
val.icon = WandIconId.Value;
val.specialAbility = (JOBFEEJALOK)WandSpecialAbility.Value;
val.priceCoin = WandPriceCoin.Value;
val.dropStage = WandDropStage.Value;
val.postSlotTriggerType = (IOINDHALAIP)WandPostSlotTriggerType.Value;
val.PostSlotTriggerChargeRatio = WandPostSlotTriggerChargeRatio.Value;
val.shootInterval = WandShootInterval.Value;
val.coolDown = WandCoolDown.Value;
val.angle = WandAngle.Value;
val.maxMP = WandMaxMP.Value;
val.mpRecovery = WandMpRecovery.Value;
val.shootCount = WandShootCount.Value;
val.costCorrection = WandCostCorrection.Value;
val.criticalChance = WandCriticalChance.Value;
val.damageCorrection = WandDamageCorrection.Value;
val.int1 = WandInt1.Value;
val.int2 = WandInt2.Value;
val.int3 = WandInt3.Value;
val.float1 = WandFloat1.Value;
val.float2 = WandFloat2.Value;
val.float3 = WandFloat3.Value;
val.normalSlots = (SlotData[])(object)new SlotData[WandNormalSlots.Value];
int[] array = DeserializeArray<int>(WandSpellIDList.Value);
if (array.Length > WandNormalSlots.Value)
{
logger.LogError((object)"Spell count bigger than the slots available (normal)");
}
for (int i = 0; i < array.Length; i++)
{
SlotData val2 = new SlotData(array[i]);
int num = val.normalSlots.Length - 1 - i;
val.normalSlots[num] = val2;
}
bool[] normalSlotIsLock = DeserializeArray<bool>(WandNormalSlotIsLock.Value, WandNormalSlots.Value);
val.normalSlotIsLock = normalSlotIsLock;
val.postSlots = (SlotData[])(object)new SlotData[WandPostSlots.Value];
bool[] postSlotIsLock = DeserializeArray<bool>(WandPostSlotIsLock.Value, WandPostSlots.Value);
val.postSlotIsLock = postSlotIsLock;
logger.LogDebug((object)"GetCustomStartWand end.");
return val;
}
public static void AddCustomWandsToWandConfigInstance()
{
Log("AddCustomWandsToWandConfigInstance start.");
if (WandConfig.dic.ContainsKey(WandConfigID.Value))
{
Log("AddCustomWandsToWandConfigInstance Custom Wand already in game memory.");
return;
}
WandConfig customStartWand = GetCustomStartWand();
Log("Postfix_RoomEnter_Mod add new wand.");
WandConfig.dic.Add(customStartWand.id, customStartWand);
Log("AddCustomWandsToWandConfigInstance end.");
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CHBOBCMIHEL), "RoomEnter")]
private static void Postfix_RoomEnter_Mod(CHBOBCMIHEL __instance)
{
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
Log("Postfix_RoomEnter_Mod start.");
if (AlreadyInjectedCustomWand)
{
if (__instance.RoomCfg.id == 101)
{
AlreadyInjectedCustomWand = false;
}
else
{
Log("Postfix_RoomEnter_Mod already set wand.");
}
return;
}
AddCustomWandsToWandConfigInstance();
Log("Postfix_RoomEnter_Mod __instance.FJBLHBBOBGB.name:" + __instance.RoomCfg.name);
Log("Postfix_RoomEnter_Mod __instance.FJBLHBBOBGB.id:" + __instance.RoomCfg.id);
if (__instance.RoomCfg.id != 1011)
{
Log("Postfix_RoomEnter_Mod not first room (1011)");
return;
}
LBJLBHKNCJN inst = LBJLBHKNCJN.Inst;
Log("Postfix_RoomEnter_Mod not LBJLBHKNCJN.MODEPFKJDGA?.EBMOKMDICFD 1." + (object)((inst != null) ? inst.PlayerGO : null));
LBJLBHKNCJN inst2 = LBJLBHKNCJN.Inst;
if ((Object)(object)((inst2 != null) ? inst2.PlayerGO : null) == (Object)null)
{
Log("Postfix_RoomEnter_Mod not initialized GHMHJJPJEAF.");
return;
}
Log("Postfix_RoomEnter_Mod set new wand.");
BBLIFLBPDCJ inst3 = BBLIFLBPDCJ.Inst;
if (inst3 != null)
{
_ = inst3.EHAHIJCLFPL;
if (0 == 0)
{
bool flag = false;
LMFAHPPEPKO.Inst.GetGO("Prefabs/Mixed/Item", BBLIFLBPDCJ.Inst.EHAHIJCLFPL, 0f, (Transform)null).GetComponent<LPAJLGPGANB>().Initialize(__instance, (NJPDLLKBHEE)0, WandConfigID.Value, false, true);
Log("Postfix_RoomEnter_Mod AlreadyInjectedCustomWand: " + AlreadyInjectedCustomWand);
AlreadyInjectedCustomWand = true;
Log("Postfix_RoomEnter_Mod AlreadyInjectedCustomWand: " + AlreadyInjectedCustomWand);
Log("Postfix_RoomEnter_Mod end.");
return;
}
}
Log("Postfix_RoomEnter_Mod BBLIFLBPDCJ.MODEPFKJDGA.EHAHIJCLFPL == null.");
}
}