using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using MelonLoader;
using SilkSong;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SilkSong")]
[assembly: AssemblyDescription("A MelonLoader mod for Hollow Knight: Silksong")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SilkSongMod")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("12345678-1234-1234-1234-123456789012")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: MelonInfo(typeof(SilkSongMod), "SilkSongMod", "1.0.0", "YourName", null)]
[assembly: MelonGame("Team Cherry", "Hollow Knight Silksong")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SilkSong;
public class SilkSongMod : MelonMod
{
private Component heroController;
[Obsolete]
public override void OnApplicationStart()
{
MelonLogger.Msg("Silksong Health Mod v1.0 - Ready!");
MelonLogger.Msg("Controls: F1=Add Health, F2=Max Out Mask Shards, F3=Refill Health, F4=One Hit Kill Mode, F5=Add 1000 Money, F6=Add 1000 Shards, F8=Unlock All Crests, F9=Unlock All Tools, F10=Unlock All Items, F11=Max All Collectables");
}
public override void OnInitializeMelon()
{
((MelonBase)this).OnInitializeMelon();
MelonLogger.Msg("Health mod initialized!");
}
public override void OnUpdate()
{
if ((Object)(object)heroController == (Object)null)
{
GameObject val = GameObject.Find("Hero_Hornet(Clone)");
if ((Object)(object)val != (Object)null)
{
heroController = val.GetComponent("HeroController");
if ((Object)(object)heroController != (Object)null)
{
MelonLogger.Msg("Hero found! Health controls active.");
}
}
}
if ((Object)(object)heroController != (Object)null)
{
if (Input.GetKeyDown((KeyCode)282))
{
AddHealth(1);
}
if (Input.GetKeyDown((KeyCode)283))
{
AddMaxHealth(6);
}
if (Input.GetKeyDown((KeyCode)284))
{
RefillHealth();
}
if (Input.GetKeyDown((KeyCode)285))
{
EnableOneHitKill();
}
if (Input.GetKeyDown((KeyCode)286))
{
AddMoney(1000);
}
if (Input.GetKeyDown((KeyCode)287))
{
AddShards(1000);
}
if (Input.GetKeyDown((KeyCode)289))
{
UnlockAllCrests();
}
if (Input.GetKeyDown((KeyCode)290))
{
UnlockAllTools();
}
if (Input.GetKeyDown((KeyCode)291))
{
UnlockAllItems();
}
if (Input.GetKeyDown((KeyCode)292))
{
MaxAllCollectables();
}
}
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
MelonLogger.Msg("Scene: " + sceneName);
heroController = null;
}
private void AddHealth(int amount)
{
try
{
MethodInfo method = ((object)heroController).GetType().GetMethod("AddHealth");
if (method != null)
{
method.Invoke(heroController, new object[1] { amount });
MelonLogger.Msg($"Added {amount} health");
}
else
{
MelonLogger.Msg("AddHealth method not found");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error adding health: " + ex.Message);
}
}
private void AddMaxHealth(int amount)
{
try
{
MethodInfo method = ((object)heroController).GetType().GetMethod("AddToMaxHealth");
if (method != null)
{
method.Invoke(heroController, new object[1] { amount });
MelonLogger.Msg($"Added {amount} max health - Save to main menu and re-enter to see UI update");
}
else
{
MelonLogger.Msg("AddToMaxHealth method not found");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error adding max health: " + ex.Message);
}
}
private void RefillHealth()
{
try
{
MethodInfo method = ((object)heroController).GetType().GetMethod("RefillHealthToMax");
if (method != null)
{
method.Invoke(heroController, null);
MelonLogger.Msg("Health refilled to max");
}
else
{
MelonLogger.Msg("RefillHealthToMax method not found");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error refilling health: " + ex.Message);
}
}
private void AddMoney(int amount)
{
try
{
if ((Object)(object)heroController != (Object)null)
{
Type type = ((object)heroController).GetType();
Type type2 = type.Assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "CurrencyType");
if (type2 != null)
{
object obj = Enum.Parse(type2, "Money");
MethodInfo method = type.GetMethod("AddCurrency", BindingFlags.Instance | BindingFlags.Public, null, new Type[3]
{
typeof(int),
type2,
typeof(bool)
}, null);
if (method != null)
{
method.Invoke(heroController, new object[3] { amount, obj, false });
MelonLogger.Msg($"Added {amount} money");
}
else
{
MelonLogger.Msg("HeroController.AddCurrency method not found");
}
}
else
{
MelonLogger.Msg("CurrencyType enum not found");
}
}
else
{
MelonLogger.Msg("Hero controller not found");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error adding money: " + ex.Message);
}
}
private void AddShards(int amount)
{
try
{
if ((Object)(object)heroController != (Object)null)
{
Type type = ((object)heroController).GetType();
Type type2 = type.Assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "CurrencyType");
if (type2 != null)
{
object obj = Enum.Parse(type2, "Shard");
MethodInfo method = type.GetMethod("AddCurrency", BindingFlags.Instance | BindingFlags.Public, null, new Type[3]
{
typeof(int),
type2,
typeof(bool)
}, null);
if (method != null)
{
method.Invoke(heroController, new object[3] { amount, obj, false });
MelonLogger.Msg($"Added {amount} shards");
}
else
{
MelonLogger.Msg("HeroController.AddCurrency method not found");
}
}
else
{
MelonLogger.Msg("CurrencyType enum not found");
}
}
else
{
MelonLogger.Msg("Hero controller not found");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error adding shards: " + ex.Message);
}
}
private void UnlockAllCrests()
{
try
{
MelonLogger.Msg("=== F8: CALLING MASTER CREST UNLOCK ===");
Object[] array = Resources.FindObjectsOfTypeAll(typeof(ToolCrestList));
MelonLogger.Msg($"Found {array.Length} ToolCrestList objects");
Object[] array2 = array;
foreach (Object val in array2)
{
if (val == (Object)null)
{
continue;
}
Type type = ((object)val).GetType();
if (type.Name == "ToolCrestList")
{
MethodInfo method = type.GetMethod("UnlockAll");
if (method != null)
{
method.Invoke(val, null);
MelonLogger.Msg("Called ToolCrestList.UnlockAll() on " + val.name + " - All crests unlocked!");
return;
}
MelonLogger.Msg("ToolCrestList found but UnlockAll method not found");
}
}
MelonLogger.Msg("ToolCrestList component not found");
}
catch (Exception ex)
{
MelonLogger.Msg("Error calling master crest unlock: " + ex.Message);
}
}
private void UnlockAllTools()
{
try
{
MelonLogger.Msg("=== F9: UNLOCKING ALL TOOLS ===");
Object[] array = Resources.FindObjectsOfTypeAll(typeof(ToolItemSkill));
MelonLogger.Msg($"Found {array.Length} ToolItemSkill objects");
int num = 0;
Object[] array2 = array;
foreach (Object val in array2)
{
if (!(((object)val).GetType().Name == "ToolItemSkill"))
{
continue;
}
try
{
Type type = ((object)val).GetType();
MethodInfo method = type.GetMethod("Unlock");
if (method != null)
{
Type type2 = null;
Type[] nestedTypes = type.GetNestedTypes();
foreach (Type type3 in nestedTypes)
{
if (type3.Name.Contains("PopupFlags"))
{
type2 = type3;
break;
}
}
if (type2 != null)
{
object obj = Enum.Parse(type2, "ItemGet");
method.Invoke(val, new object[2] { null, obj });
}
else
{
method.Invoke(val, new object[2]);
}
MelonLogger.Msg("Unlocked tool: " + val.name);
num++;
}
else
{
MelonLogger.Msg("No Unlock method found on " + val.name);
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error unlocking " + val.name + ": " + ex.Message);
}
}
MelonLogger.Msg($"Tool Unlock: Unlocked {num} tools");
}
catch (Exception ex2)
{
MelonLogger.Msg("Error unlocking tools: " + ex2.Message);
}
}
private void UnlockAllItems()
{
try
{
MelonLogger.Msg("=== F10: UNLOCKING ALL ITEMS ===");
Object[] array = Resources.FindObjectsOfTypeAll(typeof(ToolItemBasic));
MelonLogger.Msg($"Found {array.Length} ToolItemBasic objects");
int num = 0;
Object[] array2 = array;
foreach (Object val in array2)
{
if (!(((object)val).GetType().Name == "ToolItemBasic"))
{
continue;
}
try
{
Type type = ((object)val).GetType();
MethodInfo method = type.GetMethod("Unlock");
if (method != null)
{
Type type2 = null;
Type[] nestedTypes = type.GetNestedTypes();
foreach (Type type3 in nestedTypes)
{
if (type3.Name.Contains("PopupFlags"))
{
type2 = type3;
break;
}
}
if (type2 != null)
{
object obj = Enum.Parse(type2, "ItemGet");
method.Invoke(val, new object[2] { null, obj });
}
else
{
method.Invoke(val, new object[2]);
}
MelonLogger.Msg("Unlocked item: " + val.name);
num++;
}
else
{
MelonLogger.Msg("No Unlock method found on " + val.name);
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error unlocking " + val.name + ": " + ex.Message);
}
}
MelonLogger.Msg($"Item Unlock: Unlocked {num} items");
}
catch (Exception ex2)
{
MelonLogger.Msg("Error unlocking items: " + ex2.Message);
}
}
private void MaxAllCollectables()
{
try
{
MelonLogger.Msg("=== F11: MAXING ALL COLLECTABLES ===");
Object[] array = Resources.FindObjectsOfTypeAll(typeof(CollectableItem));
MelonLogger.Msg($"Found {array.Length} CollectableItem objects");
int num = 0;
Object[] array2 = array;
foreach (Object val in array2)
{
if (val == (Object)null)
{
continue;
}
try
{
Type type = ((object)val).GetType();
MethodInfo method = type.GetMethod("AddAmount", BindingFlags.Instance | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, new object[1] { 99 });
MelonLogger.Msg("Added 99x " + val.name);
num++;
}
else
{
MelonLogger.Msg("No AddAmount method found on " + val.name + " (type: " + type.Name + ")");
}
}
catch (Exception ex)
{
MelonLogger.Msg("Error maxing " + val.name + ": " + ex.Message);
}
}
MelonLogger.Msg($"Collectable Max: Added 99x to {num} collectables");
}
catch (Exception ex2)
{
MelonLogger.Msg("Error maxing collectables: " + ex2.Message);
}
}
private void EnableOneHitKill()
{
try
{
MelonLogger.Msg("=== F4: TARGETING ENEMY DAMAGE ONLY ===");
int num = 0;
MonoBehaviour[] array = Object.FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Type type = ((object)val).GetType();
string text = type.Name.ToLower();
if (text.Contains("tool"))
{
MelonLogger.Msg("TypeName: " + text);
}
if (!text.Contains("damageenemies"))
{
continue;
}
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
string text2 = fieldInfo.Name.ToLower();
if ((!text2.Contains("damage") && !text2.Contains("multiplier")) || (!(fieldInfo.FieldType == typeof(float)) && !(fieldInfo.FieldType == typeof(int))))
{
continue;
}
try
{
if (fieldInfo.FieldType == typeof(float))
{
fieldInfo.SetValue(val, 100f);
MelonLogger.Msg("Set " + type.Name + "." + fieldInfo.Name + " = 100.0f");
num++;
}
else if (fieldInfo.FieldType == typeof(int))
{
fieldInfo.SetValue(val, 100);
MelonLogger.Msg("Set " + type.Name + "." + fieldInfo.Name + " = 100");
num++;
}
}
catch (Exception)
{
}
}
}
MelonLogger.Msg($"Enemy Damage Boost: Modified {num} DamageEnemies values only");
}
catch (Exception ex2)
{
MelonLogger.Msg("Error targeting enemy damage: " + ex2.Message);
}
}
}