#archived-modding-development
1 messages · Page 507 of 1
ehm
shit
im stoopid
[INFO]:[Thing] - SceneIsValid
[ERROR]:[UNITY] - NullReferenceException: Object reference not set to an instance of an object
[ERROR]:[UNITY] - TransHK.Rareclass.Find (Scene scene, System.String name)
[ERROR]:[UNITY] - TransHK.TransMod+<SetSprite>d__5.MoveNext ()
[ERROR]:[UNITY] - UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress)
[ERROR]:[UNITY] - UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
[ERROR]:[UNITY] - TransHK.TransMod:SceneChanged(Scene, Scene)
[ERROR]:[UNITY] - UnityEngine.SceneManagement.SceneManager:UnloadScene(String)
[ERROR]:[UNITY] - <BeginSceneTransitionRoutine>c__AnonStorey13:<>m__2()
[ERROR]:[UNITY] - <BeginRoutine>c__Iterator0:MoveNext()
[ERROR]:[UNITY] - UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
[ERROR]:[UNITY] -
[INFO]:[TransMod] - Scenechanged
Well
it starts right at
Log("SceneIsValid");
GameObject retGo;
foreach (var go in scene.GetRootGameObjects())
{
if (go.name == name)
{
Log("if (go.name == name)");
return go;
}
retGo = go.transform.Find(name).gameObject;
if (retGo != null)
{
Log("if retGo != null");
return retGo;
}
}
Ohhh I think I see the problem
Let me rewrite something for you
public static class Rareclass
{
public static void Log(string s)
{
Modding.Logger.Log($"[Thing] - {s}");
}
public static GameObject Find(this Scene scene, string name)
{
Log("NewMethodCalled");
if (scene.IsValid())
{
Log("SceneIsValid");
Transform retGo;
foreach (var go in scene.GetRootGameObjects())
{
if (go.name == name)
{
Log("if (go.name == name)");
return go;
}
retGo = go.transform.Find(name);
if (retGo != null)
{
Log("if retGo != null");
return retGo.gameObject;
}
}
}
return null;
}
}
uhm, i may forgot unity 2017 quircks
as retGo = go.transform.Find(name); can give null
@jolly oriole fix that when you're home
so if i want to change sprites of bosses, i have to:
1 . change if (arg1.name != "Room_Final_Boss_Core") return; to the correct scene
2. change var boss = arg1.Find("Hollow Knight Boss"); to the right name
Right?
Nah frogcore
Oh you mean replacing sprites?
Maybe
Anyways time to update frogcore on the installer since it’s been broken for a while now
Also gonna add some ez tk2d sprite replacement stuff
imma make it so the scene and boss arent hardcoded
Where did I leave the frogcore source
idk
nice
Jk frogcore is tiny compared to other core mods
What’s wrong with frog?
it has to be capital
F
bruh whats wrong withstring selectedBoss = "Hollow Knight Boss";
nvm
Nah it was a reply to the sentence as a whole
Time to make people fear me
With the power
Of frog
why is it when i click in the middle of the line when i type it replaces stuff that is already there
when the insert key was pressed, the cursor slightly changes and the typing is change to replace the text at the current position
@cedar hemlock
it's easy, just requires this nonsense
private void SceneChanged(Scene arg0, Scene arg1)
{
if (arg1.name != "Room_Final_Boss_Core") return;
GameManager.instance.StartCoroutine(SetSprite());
// Change audio
var sm = arg1.Find("_SceneManager").GetComponent<SceneManager>();
var mc = sm.GetAttr<SceneManager, MusicCue>("musicCue");
var ci = mc.GetAttr<MusicCue, MusicCue.MusicChannelInfo[]>("channelInfos");
// ToDo replace null with custom audioclip
ci[MusicChannels.Main].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
// ToDo replace null with custom audioclip
ci[MusicChannels.MainAlt].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
// ToDo replace null with custom audioclip
ci[MusicChannels.Action].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
// ToDo replace null with custom audioclip
ci[MusicChannels.Sub].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
// ToDo replace null with custom audioclip
ci[MusicChannels.Tension].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
// ToDo replace null with custom audioclip
ci[MusicChannels.Extra].SetAttr<MusicCue.MusicChannelInfo, AudioClip>("clip", null);
mc.SetAttr<MusicCue, MusicCue.MusicChannelInfo[]>("channelInfos", ci);
sm.SetAttr<SceneManager, MusicCue>("musicCue", mc);
}
with the first 4 lines (and the last one) already existing
poggers
lemme change some things
14 a lil better
8...
Error CS1069 The type name 'AudioClip' could not be found in the namespace 'UnityEngine'. This type has been forwarded to assembly 'UnityEngine.AudioModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' Consider adding a reference to that assembly.
a bunch of times
so i just add the reference for this right?
2 now..
2 times this:
do you know what reference i need to add?
Visual studio has helpful hints if it detects the reference you're looking for. Look for the lighbulb at the left of the line.
either modcommon, sfcore or maybe vasi (honestly don't know about this one)
but le me check if theres a no dependency workaround for that
There's a small chance VS figured it out, but if the assembly isn't there in the first place then yeah
i dont see an lightbulb
Then maybe it doesn't know. Was just a thought. I'm just trying to throw out tips since you seem new to VS and C#.
yeah i can a bit java so i know a bit c#
Well, you know the syntax well enough. There are enough fundamental differences that it probably feels a little tough I imagine. A weird difference here or there
but at this point i'd suggest referencing modcommon to do that, makes a lot of things easier
yeah i was helping someone so i am a bit busy :)
hmm
modcommon doesnt work
vasi then
still nothing
Modding.ReflectionHelper.SetAttr(theObjectToChange, "nameOfTheField", valueYouWantSet, true);
hm
do i place that in scenechanged?
and what do i want to change, whats the field, whats the value
1 sec
it your code so you prob know :)
private void SceneChanged(Scene arg0, Scene arg1)
{
if (arg1.name != "Room_Final_Boss_Core") return;
GameManager.instance.StartCoroutine(SetSprite());
// Change audio
var sm = arg1.Find("_SceneManager").GetComponent<SceneManager>();
var mc = Modding.ReflectionHelper.GetAttr<SceneManager, MusicCue>(sm, "musicCue");
var ci = Modding.ReflectionHelper.GetAttr<MusicCue, MusicCue.MusicChannelInfo[]>(mc, "channelInfos");
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.Main], "clip", null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.MainAlt], "clip", null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.Action], "clip", null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.Sub], "clip", null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.Tension], "clip", null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[MusicChannels.Extra], "clip", null);
Modding.ReflectionHelper.SetAttr(mc, "channelInfos", ci);
Modding.ReflectionHelper.SetAttr(sm, "musicCue", mc);
}
and:
Error CS0411 The type arguments for method 'ReflectionHelper.SetAttr<TObject, TField>(TObject, string, TField)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
oh yea, but hovering should give you an option to put a cast there, you can do that
yea, let me quickly change those 6 lines
the 6 lines
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.Main], "clip", (AudioClip) null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.MainAlt], "clip", (AudioClip) null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.Action], "clip", (AudioClip) null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.Sub], "clip", (AudioClip) null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.Tension], "clip", (AudioClip) null);
// ToDo replace null with custom audioclip
Modding.ReflectionHelper.SetAttr(ci[(int) MusicChannels.Extra], "clip", (AudioClip) null);
fixed the code a bit above, should have everything
why did this not work
did i do something wrong?
vs being vs, idk
so do i place an audio file in mods or will there be an folder
you can load an audioclip in any way, shape or form unity provides and pass it as one (or multiple) of the null parameters
I suggest assetbundling
assetbundling for a single audioclip sux ass
wait
good point
although for thk it would be 6-7, at which point it could be good again
can i just place the audio file in mods or can i do it in a folder or do i need to do smth to the wav
how are you loading it?
well how are you loading the audio file in the dll
oh do i need to do the same as the image
nah
but I suggest doing that since you don't have to give out anything more than a dll
ok but if i want do do it only for myself can i just place the wav in mods?
yes
okay
but you need to load the file from there
unlike loading from the resources like the image
so how do i tell it the wav is in ... ?
well I closed visual studio so I'll type from memory
nice
Path.WithoutExtention(Path.WithoutExtention(Assembly.GetExecutingAssembly().Name.FullName)))I think
or Assembly.GetExecutingAssembly().Name.FullName + @"\..\..\"
in the scene changed?
where you load the file, it's the path you put in
nonono
no
fine, I'll open visual studio again
lol
File.ReadAllBytes(Assembly.GetExecutingAssembly().Location + @"\..\filename");
at ..\ i place the path
this will return a byte array that you can put in one of WavUtility's methods
no
place the file name
currently it gets the path to the mods folder by getting the path to the dll file(contains the dll file's name)
File.ReadAllBytes(Assembly.GetExecutingAssembly().Location + @"\PathHere?\filename duh");
no
Assembly.GetExecutingAssembly().Location + @"\..\" gets you to the mods folder
Assembly.GetExecutingAssembly().Location + @"\..\hereifiwanttodoitinanotherfolder\Filename"
right?
yes
do you have WavUtilityyet
nope
you need to put the bytes from this into one of it's methods
which one?```
var sm = arg1.Find("_SceneManager").GetComponent<SceneManager>();
var mc = Modding.ReflectionHelper.GetAttr<SceneManager, MusicCue>(sm, "musicCue");
var ci = Modding.ReflectionHelper.GetAttr<MusicCue, MusicCue.MusicChannelInfo[]>(mc, "channelInfos");
add this class to your project
https://github.com/deadlyfingers/UnityWav/blob/master/WavUtility.cs
that's btw broken for anything loaded from memory, untiy paths and multichannel
oh
cool
now I know why it didn't work before
it's probably better I switched to assetbundling anyways since it was a lot of audio clips
?
all 400 lines lol
unless you want to erase anything not used by the method I described or the methods used by that and so on
welcome to code
65 errors 
that needed for sfgrenades to so i already have it
speed
Yes
Those are the kinds of things visual studio can fill in for you
lol
Always look at the lightbulb
Well, you can do things the hard way or use the IDE
Well that’s 1/2 my life at this point
only the craziest
Write code in discord
I knew a guy that wrote ASP classic in notepad to make a web game... It scared me.
I require no proof of your black magic
lol
I was writing in notepad on my school pc for unity for a while
That almost sounds like you had no choice, since school pcs can be locked down. But still, though, way too much effort for me. The most basic I've gone is vscode. I'm a poser. 
I got vscode eventually tho. Slightly better
only slightly? basic notepad is a nightmare
how do i add the Wavutil or whatever
You copy everything in the GitHub file and paste it in a .cs file in visual studio
Getting a audio clip from it?
how do i get the bites into the things that need it
Aka this
or does it go automaticly using wavutils
Just do AudioClip myclip = WavUtility.ToAudioClip(path);
Grenade said the bytes way doesn’t work
https://raw.githubusercontent.com/SFGrenade/CustomBgm/master/WavUtility.cs this one has everything working afaik
Yay
Yes, also the assembly stuff since that’s part of the path
Np
Oh and btw if i want to change sprites of multiple enemies can that be done in one cs or do i need to make multiple
I meant that can you define that you want img 1 fir this and img 2 for that etc
When i write the line
public class ClassName : Mod, ITogglableMod
It gives me this error:
error CS0535: 'ClassName' does not implement interface member 'ITogglableMod.Unload()'
Can someone help me with this
You need to implement the "Unload" method if you want it to be an ITogglableMod - an example of what this would look like is e.g. here https://github.com/homothetyhk/HollowKnight.InfiniteNotches/blob/master/InfiniteNotches/InfiniteNotches.cs
So in that method I only do -= the function I want to run?
Basically, in Unload you reverse everything you do in Initialize
So if there's only one function you want your mod to run while it's loaded, then you should just -= that function in the unload
Thank you
?
Can be done in one cs
okay
Show your code that checks what the scene name is
USceneManager.activeSceneChanged += SceneChanged;
private void SceneChanged(Scene arg0, Scene arg1)
{
if (arg1.name != Bossscene) return;
{
GameManager.instance.StartCoroutine(SetSprite(arg1));
i think thats everything
oh and string Bossscene = "Room_Final_Boss_Core";
Ok
oh and have no idea if it works
Let me rewrite a little for ya
i havent tested it since here
ok thk still works
the music doesn't
Replace csharp string Bossscene = "Room_Final_Boss_Core";
With
Dictionary<string, string> Bossscenes = new Dictionary<string, string>() { "Room_Final_Boss_Core", " Hollow Knight Boss" }; ```
Error CS0246 The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?)
Replace scene changed with
private void SceneChanged(Scene arg0, Scene arg1)
{
if (Bossscenes.Contains(arg1.name)
{
GameManager.instance.StartCoroutine(SetSprite(arg1));
the music part is totaly broken lol
Again refer to the lightbulb
What music plays
lightbulb say fix formatting but it doesn't work
Then you need to use sfg’s ver of WavUtility
Error CS7036 There is no argument given that corresponds to the required formal parameter 'value' of 'Dictionary<string, string>.Add(string, string)'```
I think you need to add using System.Collections or using System.Collections.Generic
i did that
Oh let me quickly fix that
sfg version doesn't use WavUtitlity or smth
(its in my code)
nvm fixed it
oh and my Bossscene does not work
Back, had to do something
Yeah leme fix that
Replace csharp string Bossscene = "Room_Final_Boss_Core";
With
Dictionary<string, string> Bossscenes = new Dictionary<string, string>() { { "Room_Final_Boss_Core", " Hollow Knight Boss" } }; ```
can someone help me use uuwuu
this is modding development
oh
how does foreach (var item in defaultItemList) throw an NRE when initialized with defaultItemList = new List<Item>();???
seems impossible if that's the only code
either the list isn't actually being initialized before or it is and it has a null item that's being used
or it's being set to null somewhere inbetween
i mean
are you sure it's the foreach
yes
sure it's not the list in the component that's null?
the function got to the '8' log before stopping
put a log before the add
oh yea, should've tried those
trying now
ofc it's the add
i never initialized that list
no need to test
gaming
well, works now
if this is 1.5 you can setup a pdb and not have to log spam
very nice qol improvement
I'm sorry for your loss
making it work on 1432 first, who knows which century 1.5 will release
the entire inventory is fucked pog
Nice
i'm somewhat close to done now, somehow completely missed an entire go with fsms on it
CallMethodProper error on Enemy List -> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IndexOutOfRangeException: Array index is out of range.
nice
poggers, menu screen broke
that's dynamic optional mod dependency
idk, for testing
NullReferenceException: Object reference not set to an instance of an object
at SFCore.Utils.FsmUtil.ChangeTransition
sadge
Cool, my favorite null reference, fsm utils
this is PC right
...yes? Mods only work on pc. Also this is modding-development
Does anyone know where i can find the source code of royal dreamer
hey everyone, it was suggested to me that this would be the place to ask if a HK mod could be added to the ModInstaller? I really love that mod but because it changes the same file as the API's, I can't use it in my game if I want all the other cool mods available in the installer
The installer itself just adds .dll files, and installs the moddingAPI. Is this a mod you made that you're trying to get something integrated to the API, or is this a mod that you like that just uses a different method of modding?
it's not my mod, but i'm not sure how to answer the second question, i'm not very knowledgeable in that subject. when you dl the mod, you get the Assembly_Sharp.dll file and that's it
oh btw it's the "no cost for wayward compass & gathering swarm" mod
easy mod?
free utility mod?
cus thats on the installer
so your code makes it so != cant be used in if (arg1.name != Bossscene) anyone have a fix?
the lightbulb doesn't help
I'm so sorry I'm very confused. English isn't my native language so I'm not sure what you're saying. Is there a mod that does this already in the installer, is that what you're saying?
but if I enable easy mod, will it make everything else easier? or can i just toggle whatever part of easy mod i want to use?
sorry, in modding discussion they said to come here. so there's no way to add another mod to the installer? since i don't want the game to be easier
no in modding help they said you to come here and you can pr the modlinks
i don't understand you, i'm sorry. i'm not frustrated by you, just not understanding anything pr or modlinks. it's ok i can give up on this, it's not very important and i suppose if there was an easy way someone would have told already. thanks for giving answers, ruttie.
ok
bruh
the textures completely broke
ok nvm
fixed the textures
idk why it was if (arg1.name != Bossscene) so i made it if (arg1.name == Bossscene)
btw the music is totally broken without errors in modlog
I have once uploaded a file called "freeutility.dll" to this discord, just search for uploaded files by me
He wants to add it to the modinstaller
Oh and is it okay if i just copy everything from custombgm into the mod im making or should i do,it in another
I mean, i don't know why you'd want 2 mods for your single use case
hey, yes a member linked me your file and I was able to use it. thank you for making it!
np
I already gave you stuff to replace
Hmm maybe i missed it or smth
Let me find it
This
Ok ill see if it works
Error CS1929 'Dictionary<string, string>' does not contain a definition for 'Contains' and the best extension method overload 'PlayMakerUtilsDotNetExtensions.Contains(VariableType[], VariableType)' requires a receiver of type 'VariableType[]'
Change Contains to ContainsKey
bruh
it worked
private IEnumerator SetSprite(Scene arg1)
{
Log("Setting sprites");
var boss = arg1.Find(selectedBoss);
boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = _tex;
yield return null;
}
readonly string selectedBoss = "Hollow Knight Boss";
apparently i managed to make the fsm just stop working upon reaching this action and i don't know how.
as in: it literally just stops, no further logs, no exception, nothing
private IEnumerator SetSprite(Scene arg1)
{
Log("Setting sprites");
var boss = arg1.Find(Bossscenes[arg1.name]);
boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = _tex;
yield return null;
}
yes
Just need to do some stuff with the texture stuff to make it work with multiple scenes/bosses
update: try using Bossscene instead of Bossscenes as that easier
arg1.Find(Bossscenes[arg1.name]) needs to be arg1.Find(Bossscene[arg1.name])
yeah i can change it later
its easier if i change Bossscenes to Bossscene then changing everything else :)
Ok
btw sfgrenade why is your music you provided for bgm so loud lol
i need to set the music so low lol
because it's poggers
lol
from github
and yes
Nice
i managed to break blue hk again
nice
Nice
... the items have descriptions in the base game
lol
oohh im stupid
Remove hunter’s notes time
i always forget that
Or will they be a part of item helper
maybe i'll put the amount for things like rancid eggs there
easiest solution to that problem as well
after that i only need to fix the lazy fsm not working anymore when opening the inventory on that screen
What does the normal inventory look like?
Are you going to leave the space there blank, or do something like space out the stuff on the left?
Ok
also your code might have broken the custom texture
idk modlogs doesn't give errors and thk just doesn't change
Is Qol installed and enabled?
yes
Hmmm
do i need to reference?
Dictionary<string, string> Bossscene = new Dictionary<string, string>() { { "Room_Final_Boss_Core", " Hollow Knight Boss" } };
Hmm
how does the texture part know what selectedboss is?
it isn't there
i thought it was in your code as you added " Hollow Knight Boss" } };
private void SceneChanged(Scene arg0, Scene arg1)
{
if (Bossscene.ContainsKey(arg1.name))
{
GameManager.instance.StartCoroutine(SetSprite(arg1));
Looks right
ok i changed some things let me try again
Did you make sure you built the mod
yes
bruh fixed it
What changed
i changed " Hollow Knight Boss" to "Hollow Knight Boss"
Did I seriously leave a space
yes lol
bye
Goodbye
how does this look?
i liked it when there was a line
btw, idk if anybody else had a similar problem of an fsm just not continueing to function, stopping dead without an exception
i had an issue where fsms would point to the wrong tab, then crash
i figured it out, apparently completely misread the state name
and even then the stopping was because i didn't change back a number (when i changed it for testing)
ah, i was talking about the in game fsm, but resolved
oh
i also had some weird interactions with the viewer
is there a fix to arrays starting at 1 for some reason
i never had an array start at one, or do you mean this kinda thing?
yes i know its just displaying wrong
oh
its putting the 0th element at position 1 in the array
apparently not
the avalonia version shows that the first 'index' indicates the array
i love a thorough modlog
I have rookie numbers
i only bloated my modlog so i see everything about this pfsm
👍
sadge, closing and reopening works now though
Nice also not nice
ah yes my favourite item, d̵͂͊f̸̒͝e̶͑̽w̸̓̕ȑ̶̒f̷̅̽r̵̂̀d̵̅̊s̶͐͠ẗ̷̰́ǧ̷̳f̷͋̽w̵̛͝r̵̈́̈́y̷̖̔h̴͂̇a̷̎̆w̶͈̋t̸̓̀
Same
inventory overhaul?
For item helper(thing that allows adding of more items to the equipment menu)
I made one, but it was really bad, so sfg is making a much better one
basically, i'm copying the journal and make it work with items/equipment
I tried making a new panel at one point but it all died
more progress now, the cursor doesn't disappear when closing the inventory for no reason
It was centered at the lower left portion of the screen, and moving the cursor causes millions of null references
gaming
thanks!
@vocal spire customknight thing (idk if you still work on it): kingsoul/voidheart shows with the original texture instead of the skin one
Ok
I thought there was already a fix made
For now it only edits the knight though(will add more in the future, might make it use sprite collection names to replace stuff)
So i decided to look into custom charms, but there's one problem...
if i equip a charm and leave the equipment menu it doesn't stay equiped or smth
i seems equiped and its there but i can just equip it again
and again and again
Your equipment bools are messed up. Did you make sure to include everything from the example grenade made for charms?
nice
rip
Confusion
test for the item limit with random sprites from the game
result: it just works nicely
ah ok
the random sprites might just be sometimes a bit bigger than the inventory items (e.g. the black blanker or whatever that is)
Heyo, Quick question: Would it be possible to mod a Character creator into the game? My Idea was to have all the knight assets be redone as a blank masked one and then stack 5 Layers on top of each other like so.
Eyes
Horns 1
Horns 2
Cloak colour
Blank mask
Also if this works, the sprite combination would has to have a saved designation I presume, so this could be applied onto the multiplayer mod 🤔 chose the code corespondent to your combination you want to have and ad it into a config or better yet in game
Check the source code of decorationmaster
@fair rampart unity can load shaders directly from assets files if they are referenced by a scene
so I just make a blank scene and then reference the assets files
but all assets from the assets files are loaded when referenced in editor so I strip out all other assets other than shaders
and yes available in scene view
I've tried that
not sure what you're trying but the actual setup is a bit complicated
Hello hello hello everyone
A few questions
Why is it necessary to search for FindObjectsOfType<HealthManager>() and not just look directly for the name of whatever it is?
because in a scene there can be
Crystal Flyer
Crystal Flyer (1)
Crystal Flyer (2)
...
and GameObject.Find() requires a specific name
no sources just guessing
umm
can you send me what you have
I can explain better with an example
So, there isn't any sort of FindObjectsWithNameContainingSpecificString?
Hm
What about just returning all things in scene?
you'd need to write your own method for that
Welp 
Would that be the only way to reskin non-enemy objects or is there something I missed?
Please be something I missed
you could search for SpriteRenderers, as most non enemy things aren't animated
And static objects like breakable environment?
idk, would probably be dependent on each object
Damnit
We'll get there when we get there, I suppose
What about particle effects?
Wait those are particle effects
So they have stuff special to them
Hm
Alright what about things like the background/foreground/etc.?
just a little more detail about that:
I would manually create a blank scene and blank shader .assets file and copy the needed shader bytes to your shader .assets file rather than copying whole game files
you can create a blank assets file with the scene creator here https://github.com/nesrak1/HKWorldEdit2/blob/master/Assets/Editor/Bundler/BundleCreator.cs#L12
I think as long as it's a valid assets file renamed with .unity extension it should load it as a scene.
to reference it, just create a blank gameobject, create a blank material, then attach the material to the gameobject.
details on creating a blank asset and filling it here: https://github.com/nesrak1/AssetsTools.NET#create-new-asset-from-scratch
so the main issue why you can't just include the shader into the scene is because unity has bugs and apparently putting a shader into a scene crashes the editor
so instead it goes in another assets file (which has to be outside the editor Assets folder otherwise the editor crashes due to an assertion)
you can reference the other assets file by changing the assets file's dependencies array. the index of the dependency into the array starts at 1 not 0.
you can create a dependency like this: https://github.com/nesrak1/HKWorldEdit2/blob/master/Assets/Editor/Bundler/Loader.cs#L211
so if you only have one reference and it's to that assets file that holds the shader, you want to point it towards fileid 1 and pathid whatever path it is in that file.
so basically you point the material's shader pointer towards the shader and save and you should be good to go.
@fair rampart
it would probably be better for me to write some generic code, that way there's no confusion
btw kein what're you making?
Hey sooo
I have this absolute crazy idea to replace every enemy with primal aspids and do it with gatling aspids
How would i do that?(To replace every enemy with the primal aspids)
yep raw shader bytes
just copy the asset data directly
there's not really a good built in way so just get a binaryreader, set its position at assetInfo.absoluteFilePos and then read assetInfo.curFileSize bytes
there is no such thing as an asset file
there are assets files and then assets
yeah ok whatever I make mistakes too
asset is the raw bytes for a thing like shader or texture or gameobject
assets file is the file that holds assets
if your project is in raw mode instead of text mode, project assets files are the same format as compiled game assets files
except I think type tree, but that's it, that's just so that when you upgrade it knows which fields are what
Hey @dark wigeon, do you know if it's possible to change what assemblies are referenced in an asset bundle? When I look at the data inside of the built asset bundle for InfernoKingGrimm, it's looking for the IKG scripts under "Assembly-CSharp.dll". But the scripts are actually under InfernoKingGrimm.dll when I go to load the mod in HK. Would there be any way of changing this so that it references the correct assembly? I'm unable to use asmdefs to change the assemblies because of how my project is structured.
you can just do that in uabe
export dump the MonoScript that references Assembly-CSharp.dll, change it in the text file and reimport it
this isn't a new beta hk bundle right
oh I guess you probably want that to happen automatically after bundle build?
but if you really do want to postprocess the bundle you can script it, it just takes a bit of setup
Yeah, I was trying to see if I can get my mod updated to the latest HK Beta, wasn't sure if using UABE was possible in that version yet. I had a working (but jank) system working that did the assembly change, but that's bricked in the beta.
cool
is it also something I can use through C# or through command line to automate the process?
nothing on command line but you can use the library in c#
ok, I'll take a look at it later
Read and write unity assets/bundle files, based on https://github.com/DerPopo/UABE/ - nesrak1/AssetsTools.NET
I make unity reference my assembly by having 2 assemblies, one with just monobehaviours that i put in the project and one with everything that i put out on the modinstaller
(the one with just monobehaviours i also removed all function bodies and references to the modded assembly-csharp)
Someone is actually using this for a mod!!! I'm so happy!!
Oh I thought they made it themselves
so i fixed it, but where do i add the custom decriptions, names and effects?
no, im not an artist :)
You don't need to be an artist to make textures 
eh its less work lol
Language get hook, next to the bool hook
ok
hello hi everyone
would you know where i can find good tutorials/documentation on how to start creating hk mods ?
so do i just copy
if (key.StartsWith("CHARM_NAME_"))
{
int charmNum = int.Parse(key.Split('_')[2]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return "CHARM NAME";
}
}
and paste it again, then change "CHARM_NAME_" to "CHARM_NAME_X" X being thenumber?
or do i change the number elsewhere?
you are so cool, thank you :)
Gimme a minute or two (or 5) to get on my pc, i cant give detailed code help with shitcord mobile
take your time :)
so
if (key.StartsWith("CHARM_NAME_"))
{
int charmNum = int.Parse(key.Split('_')[2]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return "CHARM NAME";
}
}
is written the same way the bool handling is.
if you only add a single charm, you could write
if (key.Equals($"CHARM_NAME_{charmHelper.charmIDs[0]}")) return "My Custom Charm Name";
if you have multiple on the other hand, it could be
// possible to have this somewhere in the class
private string[] charmNames = { "Name 1", "Name 2", ... };
...
// In the language get hook
if (key.StartsWith("CHARM_NAME_"))
{
// get the charm id of the charm name convo key
int charmNum = int.Parse(key.Split('_')[2]);
// check if charm id is one of our own
if (charmHelper.charmIDs.Contains(charmNum))
{
// return custom name set above
return charmNames[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
let me quickly add comments
so in (charmNum)) i type the number of the charm to change?
no, as that is supplied by the request of a string
No problem and thanks :D
so, then at (key.Split('charmnumhere??')[2]);
No
im stupid
the only thing to change would either be
- the
"My Custom Charm Name"in
if (key.Equals($"CHARM_NAME_{charmHelper.charmIDs[0]}")) return "My Custom Charm Name";
or
2. the private string[] charmNames = { "Name 1", "Name 2", ... }; in
// possible to have this somewhere in the class
private string[] charmNames = { "Name 1", "Name 2", ... };
...
// In the language get hook
if (key.StartsWith("CHARM_NAME_"))
{
// get the charm id of the charm name convo key
int charmNum = int.Parse(key.Split('_')[2]);
// check if charm id is one of our own
if (charmHelper.charmIDs.Contains(charmNum))
{
// return custom name set above
return charmNames[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
In private string[] charmNames
oh okay i get it now
i messed smth up lol
oh wait
i might know the issue
hmm
that just reversed it
well, it does look like it actually loaded the name though
yes
i'll just reset the OnLanguageGethook
hmm
the code you gave me is different from the example
possible
when i use the code from the example the name no longer works
yours:
if (key.StartsWith("CHARM_NAME_"))
{
// get the charm id of the charm name convo key
int charmNum = int.Parse(key.Split('_')[2]);
// check if charm id is one of our own
if (charmHelper.charmIDs.Contains(charmNum))
{
// return custom name set above
return charmNames[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
the example:
if (key.StartsWith("CHARM_NAME_"))
{
int charmNum = int.Parse(key.Split('_')[2]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return "CHARM NAME";
}
}
the only difference being that i replaced the return value with something that can be customized per charm
yea
it's interresting bc the example code is also made for multiple charms, but then gives code that is only used to change all the names to one thing
yea, i could update it rn, which i think i'll do rn
ok so i got the names and desc's working, now the effects
i never tried something with effects, but you may want to activate/deactivate the effects in the charmupdatehook https://radiance.host/apidocs/Hooks.html#charmupdatehook
and where do i put the effects?
that has to be managed by each mod on it's own, i don't have helpers for that
ok and how do i do that?
good question
is it in the docs or somewhere else..?
that's never a good sign
on the docs i see if (PlayerData.instance.GetBool("equippedCharm_27")), so is the number of the charms equippedCharm_41, equippedCharm_42, equippedCharm_43 and equippedCharm_44?
well, that depends on the loaded mods
so ig a method similar to the language hook would be good
but something like
if (PlayerData.instance.GetBool($"equippedCharm_{charmHelper.charmIDs[0]}"))
{
// code here for one charm
}
if (PlayerData.instance.GetBool($"equippedCharm_{charmHelper.charmIDs[1]}"))
{
// code here for one charm
}
if (PlayerData.instance.GetBool($"equippedCharm_{charmHelper.charmIDs[2]}"))
{
// code here for one charm
}
if (PlayerData.instance.GetBool($"equippedCharm_{charmHelper.charmIDs[3]}"))
{
// code here for one charm
}
for 4 charms would be ideal
Btw ruttie did you finish the blue hollow knight reskin thing?
especially if the effects severely differ from one another
you mean if he is blue now?
if yes, yes
Cool
Do you have screenshot or not right now
As in, do you happen to have a screenshot, or not yet
lol
it's cause of the particles
thats a rly bad picture for the drive to take lol
to change the particles will take some time
what kind of hook should i use? one similar to ModHooks.Instance.GetPlayerBoolHook?
i do have an better pic tho
that code is specifically for inside the charmupdate hook similar to the joni's blessing code that is found in the api docs
oh okay
it works! thx
is there an doc somewhere with all the charm effects?
(the code for them ofc)
no, they're scattered throught the game
sad
some in HeroController.CharmUpdate (or gamemanager, idk), some in fsms, some only in attack methods
in the game files, you can use software like https://github.com/nesrak1/HollowKnightFSMView/releases/latest to look at those
ok then how do i give the charms textures
when doing
charmHelper.customSprites = new Sprite[] { new Sprite(), new Sprite(), new Sprite(), new Sprite() };
supply loaded sprites instead of the new Sprite() x4
load the sprites the same way you loaded the thk spritesheet
yeah so...
Yooo that's cool
does
var boss = arg1.Find(Bossscene[arg1.name]);
boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = _tex;
yield return null;
``` also support multiple textures??
whats the easiest thing i can create in order to get the hand of it
try making things cost geo
wdym
i also started with that and miserably failed
if you dash you lose 5 geo or smth
if you need help i have the code for it
i mean, if you do it multiple times after another then yes
wdym
if i re-use this code for the charms will the charms not become like thk?
i mean how do i tell the code to use one texture for this and the other texture for that etc
personally i do something like https://github.com/SFGrenade/MoreHealing/blob/master/Consts/TextureStrings.cs to load my images as sprites and supply them to the charmhelper like https://github.com/SFGrenade/MoreHealing/blob/master/MoreHealing.cs#L54
soo in tmpTextures.Add(QuickerFocusKey, QuickerFocusFile); QuickerFocusFile is the name of the image?
How do I make a settings file for my mod (Like Qol.GlobalSettings)?
oh no nvm
Thanks, i missed that part 🙃
np
I'm probably missing something here, but is there a reason why all the assets are showing up as null when I attempt to iterate through them? The bundle seems to show up just fine in UABE.
the assstsFiles list is actually now only for backend stuff and doesn't get set anywhere by the library
just use LoadAllAssetsFromBundle
can you send me the bundle? I'll just write it for you
ok, in a second
I was just wondering how would I be able to read the base field information on the assets. When I tried calling that method, I couldn't find a "table" property on them
nick, idk if you've read this, but could be an alternative to the fix after building you're doing rn: <#archived-modding-development message>
he said "I'm unable to use asmdefs to change the assemblies because of how my project is structured."
not sure exactly what he meant but I assumed he was saying that wasn't an option
Does anyone know whats happening with the new multiplayer mod
Oh sorry
oh
That is one of the first things I tried, but it comes at a cost. Basically I also have an assembly called HollowKnight.dll in my project, that contains a bunch of things that are from HK's Assembly-CSharp (IMod, NonBouncer, the TMPRO library, etc). When the asset bundle gets built, I want to reference "Assembly-CSharp.dll" instead of "HollowKnight.dll", so any scripts from that assembly get loaded properly when I go to launch the game. The problem is that I cannot rename "HollowKnight.dll" to "Assembly-CSharp.dll" in the project, because it's not possible to add a reference to "Assembly-CSharp" in the editor, thus disallowing me from using anything in that assembly in WeaverCore.dll or InfernoKingGrimm.dll in the project
yeah, the way i do it is to have 2 seperate projects, one specifically for unity where i remove everything relating to the modded assembly and only leave normal unity/c# in (not even function bodies), but unity doesn't care if the types aren't exactly the same (like 2 different enums), though the thing with tmpro is probably bad, maybe possible to just put the .cs files generated by something like utinyripper somewhere into the assets folder, as those are then referenced to assembly-csharp
so i get funny looking classes like
I was trying to make a Global Settings file and I'm getting an error
Code in the new Settings.cs filecs public class GlobalModSettings : ModSettings { public int health = PlayerData.instance.GetInt("maxHealth"); public int blue_hearts = 0; public int soul = 0; }
Code in the main.cs file cs public GlobalModSettings Settings = new GlobalModSettings(); public override ModSettings GlobalSettings { get => Settings; set => Settings = (GlobalModSettings) value; }
In the docs it says to do Settings.health but that gives me an error
yeah just warning in advance
The name 'Settings.health' does not exist in the current context.
instance method?
I'm not following
can you rename Settings to _globalSettings?
where are you doing this
as Settings is reserved for save settings afaik
it do be
in an internal class in the function private void Start()
internal class 
that is an instance member you can't just say Settings.health wherever you want
@charred topaz
I tested with ModifyBundle infernogrimmmod_bundle InfernoKingGrimm.dll
so how do i check the health value from the settings file in my code?
have a static member or pass the settings to your class
Awesome! I do have some irl stuff I need to do, so I can try it out later
Suppose I have multiple enemies I want to reskin
ok
Can I go over all things with a HealthManager and then just do ifs for every name?
is probably the most memory efficient and performant option
Wonderful
Thanks
So should taking off the Where but keeping the Select do it?
Eh who cares let's just try
i'd remove the where
If you're done mind telling me how you did it?
Thanks
doing that worked Thank you

Any idea why two references just disappeared?
Microsoft.CSharp and System.Net.Http
Went poof all of a sudden
I didn't touch them

So, any ideas, or just panic?
no idea
And why the, ah, panic?
because it went poof
1432 yes
Hm
Damnit
So apparently the first one of the two is not meant to exist in 3.5 or something
Still can't figure out the second
And the poofing part was me misunderstanding an error, it was more of "adhgs help why are these here please make them poof"
will 1.5 also updat the net framework?
Yes, to 4.0 I think
not really but still kinda
Yes, but actually no
More like no, but actually yes
then i will probably be back here why my shit aint working
well hk 1.5 won't change that much, but a lot of the mapi will change with the 1.5 release
Depending on how complicated it is, it can be as simple as updating references
nice
Btw what did you want to see earlier ruttie?
All my mods will require SFCore since I can’t be bothered to do global settings the new way
The new way?
generic mods get yeeted out of mapi
You can do the “new” way currently if you want to get used to it
how to reskin multiple enemy's 
Remember the code I gave you that was based off a dictionary
So add more stuff to the dictionary’s initializer, and do some stuff with more textures
ok
Alright problem solved, all I needed to do was violently remove the references
Clearly
Anyone knows what GameObject.DestroyAll() does?
Couldn't find anything about it
Also Destroy doesn't work for me

it's the only thing it elts me do
When I write destroy
it's an extension
I also tried Destroy(x)
idk which mod adds that though
GameObject.Destroy(instance) is the normal way objects are destroyed
oh yea, destroy is a static method
GameObject.Destroy(go) or UnityEngine.Object.Destroy(go)
GameObject.Destroy(UnityEngine.Object instance)
bro don't go talking too complicated with me lol
(im not very good at unity and coding)
Why's it tiny?
Or, more to the point, how do I fix this?
Should I just get a better sprite?
one of the sprite.create parameters is pixelperunit, set that to 66 (or 200/3 to be exact)
because for no reason the in game sprites are somehow 1.5 times as large as custom ones (while showing in uabe as normal)
i have no clue why you'd use a spritesheet for a single image
Oh no
I meant
If I load the spritesheets together with this
What do i do?
How would I differentiate between them?
i have no clue how to do that
Are you asking how to load multiple or something else?
i mean, if the spritesheets are for things like enemies it is perfectly fine to do the same
Oh, k
as the texture itself doesn't get altered, just how big the texture is displayed on a sprite
For what spritesheets will this not work?
Wdym
one would have to test
Ah 
Aren't sprite sheets made by Unity itself?
So if I ever see anything at x1.5 scale, I'll know what caused it
No?
Oh, I must be thinking of something else then.
you can make spritesheets in unity, but TC has both single sprites in images and spritesheets created using an extension called toolkit2d, which afaik is different from unitys one
Oh, me too
Oh, we all do, sometimes
nah
Oh, nice
iirc Unity does have the ability to make sprite sheets? I swear I've read that before.
oh god I'm snail

Oh, Shal, it seems you're worthy of the snail role. But to be fair, seeing as how late am I to your message, so am I.
yes unity actually makes better packed spritesheets than tk2d
when the update comes how fast will the api be updated?
is it a big task or are there only minor differences
Are you talking about the beta?
I think they would rather wait for it to fully release
when 1.5 is released
cause i'll be .net 4.6+ and unity will be 2020(.2 i think?) so there will be lots to change
mhm
I remember when they just released the beta
There were a lot of changes and discussion about that here
Even after 1.5 is fully released, it'll be a while before it's supported like it is now
yeah probably
so i tried that and horribly failed
i managed to break the charms in not only 1 but 2 ways
pretty fast, though i did just remember i had another change for the mapi i'd like to put in there before 1.5 releases
oh ok
so i have this:
public const string Charm1 = "Lifeblood Crystal";
private const string Charm1File = "Lifeblood.Resources.Charm1.png";
...
Assembly asm = Assembly.GetExecutingAssembly();
dict = new Dictionary<string, Sprite>();
Dictionary<string, string> tmpTextures = new Dictionary<string, string>();
tmpTextures.Add(Charm1, Charm1File);
...
charmHelper.customSprites = new Sprite[] { ts.Get(TextureStrings.Charm1), ts.Get(TextureStrings.QuickestFocusKey), ts.Get(TextureStrings.DeeperFocusKey), ts.Get(TextureStrings.DeepestFocusKey) };
and i named the file with the texture Lifeblood.Resources.Charm1.png
and made it an embedded recource
im missing something
depending on the project structure you may have another path instead of "Lifeblood.Resources.Charm1.png" (possibly "Lifeblood.Charm1.png", but generally "Project.OptionalFolder1.OptionalFolder2.Filename.extension")
ooohhh
im stupid
i thought Lifeblood.Resources.Charm1.png needed to be the name of the image
lol
lol
oh well then
What's mapi?
moddingapi
What is the Modding reference?
I opened up some old projects and a lot of them are missing the Modding namespace and I don't know what is it referencing
its so you dont have to type modding.modhooks and you can just use modhooks
you type at the top using modding;
That's the one that's missing
Where can I find it?
It does nothing other than group code. It depends on your style, I personally hate them with a deep passion.
i mean it's missing
you need to reference the assembly.csharp
add assembly-csharp.dll as a reference
wait what? but it was already referenced
and add a reference to asembly.csharp
make sure that the one you're referencing is the modding api
you might have referenced the vanilla one
ye
ohh, yea that was the issue, thanks
sfgrenade used them in his morehealing mod and i just copied them over and was confused lol
someone help?
i used PlayerData.instance.healthBlue = 2; to add 2 lifeblood masks when a scene is changed. When the scene loads, the life blood masks do get added (i can see the lifeblood hit animation and my white masks dont decrease when i get hit) but the lifeblood masks doesn't show up in the HUD. How can i fix that?
afaik they only get added to the ui when the scene changed
w/ ADD BLUE HEALTH you mean PlayerData.instance.healthBlue = 2;
?
it adds blue health
ohh
you literally
do addblue health
what
does "ADD BLUE HEALTH" give you health?
no right?
but where do you put the amount
Thank you
alternatively you can try setting it
and then doing EventRegister.SendEvent("UPDATE BLUE HEALTH")
but i think i had some issue with that
maybe i'm misremembering though
so is this a bit good:
private bool dash()
{
EventRegister.SendEvent("ADD BLUE HEALTH");
bluehealth++;
if (bluehealth != 2)
{
dash();
}
throw new NotImplementedException();
}
hmm no
sry lemme change it
so thats better?
what
is that good
no
or am i stupid
why are you doing this recursively
why is there still a throw
and why is it called dash
ModHooks.Instance.DashPressedHook += dash; :P
code?
yeah
public override void Initialize()
{
ModHooks.Instance.DashPressedHook += dash;
}
int bluehealth = 1;
private bool dash()
{
EventRegister.SendEvent("ADD BLUE HEALTH");
bluehealth++;
if (bluehealth != 2)
{
dash();
}
return true;
}
you call dash in dash
oh
and bluehealth is an instance field
lol
You don’t have the got charm bools right this time
yes
private void initCallbacks()
{
/// Hooks
ModHooks.Instance.GetPlayerBoolHook += OnGetPlayerBoolHook;
ModHooks.Instance.SetPlayerBoolHook += OnSetPlayerBoolHook;
ModHooks.Instance.GetPlayerIntHook += OnGetPlayerIntHook;
ModHooks.Instance.SetPlayerIntHook += OnSetPlayerIntHook;
ModHooks.Instance.AfterSavegameLoadHook += initSaveSettings;
ModHooks.Instance.ApplicationQuitHook += SaveCHEGlobalSettings;
ModHooks.Instance.LanguageGetHook += OnLanguageGetHook;
ModHooks.Instance.CharmUpdateHook += OnCharmUpdate;
}
No, I meant the OnGet(and set)PlayerBoolHook(s)
ohso
private bool OnGetPlayerBoolHook(string target)
{
if (Settings.BoolValues.ContainsKey(target))
{
return Settings.BoolValues[target];
}
#region Custom Charms
if (target.StartsWith("gotCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return Settings.gotCharms[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
if (target.StartsWith("newCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return Settings.newCharms[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
if (target.StartsWith("equippedCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
return Settings.equippedCharms[charmHelper.charmIDs.IndexOf(charmNum)];
}
}
#endregion
return PlayerData.instance.GetBoolInternal(target);
}
and
private void OnSetPlayerBoolHook(string target, bool val)
{
if (Settings.BoolValues.ContainsKey(target))
{
Settings.BoolValues[target] = val;
return;
}
#region Custom Charms
if (target.StartsWith("gotCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
Settings.gotCharms[charmHelper.charmIDs.IndexOf(charmNum)] = val;
return;
}
}
if (target.StartsWith("newCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
Settings.newCharms[charmHelper.charmIDs.IndexOf(charmNum)] = val;
return;
}
}
if (target.StartsWith("equippedCharm_"))
{
int charmNum = int.Parse(target.Split('_')[1]);
if (charmHelper.charmIDs.Contains(charmNum))
{
Settings.equippedCharms[charmHelper.charmIDs.IndexOf(charmNum)] = val;
return;
}
}
#endregion
PlayerData.instance.SetBoolInternal(target, val);
}
Show the settings class you have
this one?
private void initSaveSettings(SaveGameData data)
{
// Charms
Settings.gotCharms = Settings.gotCharms;
Settings.newCharms = Settings.newCharms;
Settings.equippedCharms = Settings.equippedCharms;
Settings.charmCosts = Settings.charmCosts;
}
initglobalsettings?
No
oh that
The class
{
SaveGlobalSettings();
}
ohh
Class

