#archived-modding-development
1 messages · Page 514 of 1
do you mean changing one item in the list after it has been initialized? gotCharms[1] don't new List every time you want to change one item
i just want 1 of the items to change from true to false without touching the first 3rd or 4th one
During initialization or after? That's the part that's confusing here, bub.
public List<bool> gotCharms = new List<bool>() { true, true, true, true };
//later
gotCharms[1] = false;
no?
If during, do what I said. If after, do what nes said.
bool gotCharms[1] = true gives me 3 errors
it seems to me you wanted to do this: (don't do this)
public List<bool> gotCharms = new List<bool>() { true, true, true, true };
public List<bool> gotCharms = new List<bool>() { true, false, true, true };
don't put bool you already defined the list
You don't need bool in there. Just a statement like gotCharms[1] = false.
gotCharms doesn't exist (in current context)
i did
public List<bool> gotCharms = new List<bool>() { true, true, true, true };
...
//later
gotCharms[1] = false
can you post the code that has both of those lines (like including where they are like in methods or classes)
I don't know in what places you put these two lines
public class CHESaveSettings : ModSettings
{
///public bool charm1new = true;
// Better charms, insert default values here
public List<bool> gotCharms = new List<bool>() { true, true, true, true };
public List<bool> newCharms = new List<bool>() { false, false, false, false };
public List<bool> equippedCharms = new List<bool>() { false, false, false, false };
public List<int> charmCosts = new List<int>() { 4, 2, 1, 1 };
}
...
public override void Initialize()
{
ModHooks.Instance.AfterSavegameLoadHook += initSaveSettings;
}
...
private void initSaveSettings(SaveGameData data)
{
// Charms
Settings.gotCharms = Settings.gotCharms;
Settings.newCharms = Settings.newCharms;
Settings.equippedCharms = Settings.equippedCharms;
Settings.charmCosts = Settings.charmCosts;
gotCharms[1] = false;
}
i dont understand much of the code already there :(
settings.gotCharms
Also I suggest reading this https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/
You're referring to a variable in the Settings object, so it makes sense you need to reference the object in order to access the variable.
Also, the first four lines of initSaveSettings do literally nothing.
so, Settings.gotCharms[1] = false;?
^ yes
it seems to work
Got that from grenade I think
SFG's code lol
Well okie-dokie then ¯_(ツ)_/¯
i copied that from back when it wasn't a single thing, but a property that built on savesetting.getX/setX
hmm i only turned it true here:
private void uumuu()
{
if (PlayerData.instance.GetBool(nameof(PlayerData.killedMegaJellyfish)) == true && uuwuugone == false)
{
Settings.gotCharms[1] = true;
uuwuugone = true;
Log("uumuugone? " + uuwuugone + ".");
}
}
``` but for some reason when i start a save its already there
though it should only be gotten when uumuu is killed
i made sure the code to detect uumuu is dead works
in theory yes, but it will break once you save+exit 100%
is uuwuugone a field of the mod
because if so then it will not reset between saves
can only reset on being loaded for the first time
sfg i saw that
no
but still i should not have it at the start of a save right?
depends on how the flag is initialized
if you have loaded any other save with uumuu killed on that game launch then it will definitely still be true
but if you are a normal human being, yes, it should not have it at the start
i haven't
but why do i have it at the start of a new save?
idk, how are you initialising the flag
public class CHESaveSettings : ModSettings
{
///public bool charm1new = true;
// Better charms, insert default values here
public List<bool> gotCharms = new List<bool>() { true, false, true, true };
public List<bool> newCharms = new List<bool>() { false, false, false, false };
public List<bool> equippedCharms = new List<bool>() { false, false, false, false };
public List<int> charmCosts = new List<int>() { 4, 2, 1, 1 };
}
...
public override void Initialize()
{
Settings.gotCharms[1] = false;
}
...
private void initSaveSettings(SaveGameData data)
{
// Charms
Settings.gotCharms = Settings.gotCharms;
Settings.newCharms = Settings.newCharms;
Settings.equippedCharms = Settings.equippedCharms;
Settings.charmCosts = Settings.charmCosts;
}
...
private void uumuu()
{
if (PlayerData.instance.GetBool(nameof(PlayerData.killedMegaJellyfish)) == true && uuwuugone == false)
{
Settings.gotCharms[1] = true;
uuwuugone = true;
Log("uumuugone? " + uuwuugone + ".");
}
}
```this is all i have about the gotCharms
the only thing missing is the declaration of uuwuugone
because the charm stuff probably works
public class CharmHelperExample : Mod<CHESaveSettings, CHEGlobalSettings>
{
bool uuwuugone = false;
}
...
(in initialize)
if (uuwuugone == false)
{
ModHooks.Instance.HeroUpdateHook += uumuu;
}
if (uuwuugone == true)
{
ModHooks.Instance.HeroUpdateHook -= uumuu;
uuwuugone = true;
}
...
private void uumuu()
{
if (PlayerData.instance.GetBool(nameof(PlayerData.killedMegaJellyfish)) == true && uuwuugone == false)
{
Settings.gotCharms[1] = true;
uuwuugone = true;
Log("uumuugone? " + uuwuugone + ".");
}
}
this?
the uumuu shit should work
yeah it works
why does it look like CharmHelperExample closes immediately after you declare uuwuugone
it may not be very efficient
hmm yeah it doesn't
but it may not be smart to send the whole class here
if you want i ofc can
idk how much work it would be, but you could try reconstructing it
No if in initialize (as uuwuugone will definetly be false)
Hook into modhooks setbool (call InternalBoolSet, and if the target string is "killedMegaJellyfish" [i'm not sure about the name], set Settings.gotCharms[1] = true)
should be way better for the computing side
this
don't read the bool on every frame, just see when the bool is set and set yours at that point
but will my version break the gotCharm or smth?
not sure but you may also have to hook game load? don't think loading the game triggers setplayerbool
holy shit i was pepega with the setbool thing, doesn't return anything
save gets loaded, overrides savesettings
no you just call InternalBoolSet if the target bool isn't "killedMegaJellyfish"
just do a
private void SetPlayerBool(string target, bool val) {
switch (target)
{
case "killedMegaJellyFish":
uuwuugone = value;
// Do not break here, continue to default:
default:
InternalBoolSet(target, val)
}
}
SetBoolInternal?
I can't remember if the docs are wrong
whichever one of those is in Modding 
i just wanna know, what part of my code breaks it (so i know what i did wrong)
yes
so, no idea?
i mean i don't know your code
you can add more logging and see exactly where it breaks
if the script just stops working its probably throwing an exception
putting if statements in public override void Initialize doesnt work iirc
it does work it's just useless
uh huh
i mean init is called immediately after the field is initialised with value false 
these is a large difference between the statements "called after field initialization" and "if statements don't work"
i agree
I wanted to point that out but thought someone else had them fix it
What type are fsm variables?
Not their values
The variables themselves
As in, what would be the type of the thing marked here
FsmFloat i think
Thanks, both of you
Why are there so many acid detectors in the collector's room? (Ruins2_11)
every single jar that falls from the ceiling during the fight has one such detector
w
why
to detect acid
i don't even know if they are used, haven't checked that
because i was wrong, those are not the jars that fall, but only jar pieces from idk where
Hmm, maybe they just copied and pasted from jars in rooms with acid? It's still kinda funny
this doesn't make it any clearer
.

slightly off topic but how does someone start getting into modding a game from scratch
like how did hollow knight mods start out
ty
not at all off topic btw
[ERROR]:[UNITY] - NullReferenceException: Object reference not set to an instance of an object
[ERROR]:[UNITY] - ActionButtonIconBase.GetButtonIcon (HeroActionButton actionButton)
[ERROR]:[UNITY] - ActionButtonIconBase.RefreshButtonIcon ()
[ERROR]:[UNITY] - ActionButtonIconBase.OnEnable ()
[ERROR]:[UNITY] - ActionButtonIcon.OnEnable ()
[ERROR]:[UNITY] - UnityEngine.GameObject:SetActive(Boolean)
[ERROR]:[UNITY] - GameCameras:StartScene()
[ERROR]:[UNITY] - GameCameras:SceneInit()
[ERROR]:[UNITY] - GameManager:BeginScene()
[ERROR]:[UNITY] - <BeginSceneTransitionRoutine>c__AnonStorey13:<>m__3()
[ERROR]:[UNITY] - <BeginRoutine>c__Iterator0:MoveNext()
[ERROR]:[UNITY] - UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
[ERROR]:[UNITY] -
```what is this
an nre
ikr we're so helpful
buttons crashed
it says something about button but i have nothing in my mod that has to do with a button
maybe you crashed initialize so hard that other stuff crashed
it happens when i open inv, and i try to go up to the charms that are equiped
or the set/getbool stuff
aren't you adding charms, which would have buttons to equip them?
on that moment i lose all control of the inventory and con only leave it
hmm maybe
could be that whatever you're doing on charm update is crashing or something
i can see if it still does it when i remove the charm part
considering it crashes at GetButtonIcon, are your sprites present?
yes?
that sounds confident
very confident
update: the typereference does work (only 1 stage up though, so basically useless as well), but the resolved typedefinition is null (because the type doesn't exist without the assembly loaded)
this should not have worked (testing changes for the 1.5 mapi)
@jolly oriole @copper nacelle just wondering: how severely will 1.5 break mods?
depends on what you mean by break
Will most mods still work or will they all have to be updated?
i assume all mods will need to be recompiled targeting 4.7.2 at the very least?
4.0
should be doing netstandard
oh yea, netstandard 2 was it sadly
mfw sadly
4.x would've been way better
but i wouldn't have had to make a custom json.net
or does the netstandard one work?
the issue is unrelated to net standard itself, just a unity change
btw, why is the mapi framework 472 if the game is netstandard?
i have an unpushed change already
sadge
I realized it was the tech after someone had issues building the api
because the standard mscorlib wasn't being ref'd by dotnet build for some reason
but really we should've been using netstandard anyways
and that worked
their example is newtonsoft
wtf we have async now
just out of curiosity: why does the api even sort the assemblies by library & mod?
it's not like anybody would try to execute code when the library is loaded
idk ask serena
probably some good reaosn
i think you can specify assembly load order in the attribute but i might be remembering wrong
Oh yeah
This is what you can load with Resources.Load
there's some shaders and materials
not much else
some language data ig
@rain cedar
Oh yeah and something of note
Resources.FindObjectsOfType finds more than what's in resources
for some reason
so you can avoid some preloading with it
LoadAll fills it up a bunch though
despite it only loading garbage from resources
*FindObjectsOfTypeAll
chad
that's also the only way to get all monobehaviours in a scene when some are deactivated (though it does also get more than just the ones in the scene)
in unity 2017*
i think it's possible to resolve assemblies into a loadorder
my code for that:
foreach (string modPath in Directory.GetFiles(path, "*.dll"))
{
using AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(modPath);
Logger.Log($"MainModule: '{asmDef.MainModule}'");
Logger.Log($"\t\tAssemblyReferences:");
foreach (var item in asmDef.MainModule.AssemblyReferences)
{
Logger.Log($"\t\t\tName: '{item.Name}'");
Logger.Log($"\t\t\tFullName: '{item.FullName}'");
}
Logger.Log("");
}
IDK what you're trying to do, but afaik unless you define your own load context and manually load assemblies into it in a specific order then guaranteeing a load order is difficult
the modding api already loads assemblies manually
Correct, but that isn't the same as a full load-order control for all assemblies.
Dependencies get auto-loaded, down the tree
ok yea, maybe not for loadorder, but type resolving instead, as mono.cecil doesn't resolve basetypes in another assembly.
so, when tot.dll's main class inherits sfcore.dll's generic mod class.
Yeah, you can mess with type resolution a little more easily
Most libs that support .netstandard 2.0 will support framework 4.7.2 (like newtonsoft and what-not). Otherwise you might end up with limited APIs due to standard2.0
4.7.2 works
yeah 472

@jolly oriole did you ever try this https://github.com/jilleJr/Newtonsoft.Json-for-Unity
Newtonsoft.Json (Json.NET) 10.0.3, 11.0.2, 12.0.3, & 13.0.1 for Unity IL2CPP builds, available via Unity Package Manager - jilleJr/Newtonsoft.Json-for-Unity
of course not
it's for il2cpp so it shouldn't depend on enit
it's a unity package
ok and
it's not directly a dll i can download and infect my pc with
are unitypackages for specific unity versions or can i just plonk it in any version?
apparently it just works
nvm i think i downloaded the wrong thing
where should i find the newtonsoft dll then?
maybe doesn't work with unity 2017
I'll try it in a bit
yep, apparently requires unity 2018+? testing with 2020
... after it decides to finally start
works with 2020
works ingame
Nice
Sick
ModdingApi using this now?
not yet
How do I run an extension for the Debug Mod?
I've been writing some code for my project and ended up working with some of the Debug Mod's API, and I want to run the small part I have so far so that I can make sure it works before I move on
Wdym, how is it currently coded
Is there a class inheriting the mod class(or a abstract class inheriting the mod class)
How big of an undertaking is it to add in a couple charms to the game?
I'm interested in making a couple nail related charms
the mapi is netstandard 2.1 though (so ig i'm not updating to that currently)
I reverted it idk if I pushed
yeah master is still on 2.1
suicide

so i'll take a wild guess and say you didn't push
I pushed
just saw 👍
Not much for the adding charms part thanks to sfgrenade. They made a page in the apidocs about charms and other things. I suggest reading the entirety of the api docs https://radiance.host/apidocs/
Well reply didn’t work
Look at the messages above
thoughts on sha256 for 1.5
sounds like a good idea
sounds good, gives me even more time to make my shit available on 1.5
For what part?
probably to replace the sha1
the modinstaller
Thanks. Hopefully this won't be too hard
Is there any way to detect a parry?
HeroController::NailParry
yeah
How would I go about replacing the sprites for the circled items?
(Solved)
Hello,
First of all thanks for all the modding tools, I've been playing with the API for a few days and it's really pleasant to use 🙂
I have a question though: can you add a dependency to something that's not a mod ? If so where would you put the additional dll that your mod needs ? (Sorry if this is a dumb question, I'm used to developing but neither in C# nor on Windows)
you can put misc dlls in the mods folder
or use ILmerge to merge them into your mod's dll if you wish
Really ? I tried and got an error at startup in Hollow Knight. I must have missed something, I'll try again then
Thanks for the ILmerge idea, I didn't know this thing existed
You can put them in the Managed folder and outright avoid the modloader from trying to load them.
Don't use ILMerge basically ever unless you're REALLY intent on having a single assembly.
I am bias, ILMerge makes me irrationally upset
I mean, isn't it nicer to have a single DLL to install ? What's the problem with this tool ?
the assembly that isn't a mod will "fail to load" because there is no mod, but it still loads
Oh ok thanks
its just a frustratingly long string at the top of the screen 
It has benefits and drawbacks. Drawbacks include mangling assembly resolution since you're literally merging the types of another assembly into your own. I suggest against it since including another DLL is not a deal-breaker. (for most, I suppose)
Makes sense, thanks 🙂
To give an example, something I'm working on references an external DLL. I put this in the Managed folder. That DLL references newtonsoft which is ILMerged into ModdingApi for 1.4. This breaks my mod since I need to reference newtonsoft and NOT the Assembly-CSharp DLL. (I'm now* developing it for 1.5 beta due to this)
Hmm ok I see
If I put the dll in the mods folder I loose all the modding infos at the top left of the screen, that doesn't seem good
What dll does your mod rely on?
It would rely on the Razer Chroma API (just got a new keyboard and thought it would be fun to light the RGB LEDs according to events in the game), you can find it here for example https://github.com/razerofficial/CSharp_SampleApp
Wait I might be dumb
I see, that shouldn't affect the modloader but I'm unsure as to why nothing else appears in the top left. The modding api is clearly running. Do you have any mods for it to show?
Yes I have a few things usually (Custom Knight, Grass mod, some tests of mine, etc.)
maybe check modlog.txt in case its just modconsole that's crashed?
Fyremoth 
Good call but it's the same thing in here. But I'm starting to think I didn't get the right DLL (Razer's doc is clearly not as good as radiance.host unfortunately)
Check your unity logs then, there might be an exception in there that doesn't appear in the modlogs
Considering the razer sdk has native dlls, it could be possible unity shat the bed somehow.
If modlog is the ModLog.txt in my save folder, then it just has
[INFO]:[ModManager] - Initializing
[INFO]:[ModManager] - Initialized
[INFO]:[API] - Loading ModdingApi Global Settings.
[INFO]:[API] - Main menu loading
[INFO]:[API] - Preloaded reflection in 96ms
[INFO]:[API] - Trying to load mods
[INFO]:[API] - Attempting to determine type of mod assemblies (library/mod/addon)
[INFO]:[API] - Saving Global Settings
You ever isntalled DRPC? 👀
What is this thing ?
Oh just a mod that breaks everything
If you never installed it then thats not the problem
Where are unity logs ? Is it output_log.txt ? I got some errors here but I'm not sure it's the errors I'm looking for
Good to know
Well then I have that, which doesn't look too good
BadImageFormatException: Format of the executable (.exe) or library (.dll) is invalid.
at Mono.Cecil.PE.ImageReader.ReadOptionalHeaders (System.UInt16& subsystem, System.UInt16& dll_characteristics) [0x00000] in <filename unknown>:0
at Mono.Cecil.PE.ImageReader.ReadImage () [0x00000] in <filename unknown>:0
at Mono.Cecil.PE.ImageReader.ReadImage (Disposable`1 stream, System.String file_name) [0x00000] in <filename unknown>:0
at Mono.Cecil.ModuleDefinition.ReadModule (Disposable`1 stream, System.String fileName, Mono.Cecil.ReaderParameters parameters) [0x00000] in <filename unknown>:0
at Mono.Cecil.ModuleDefinition.ReadModule (System.String fileName, Mono.Cecil.ReaderParameters parameters) [0x00000] in <filename unknown>:0
UnityEngine.MonoBehaviour:StartCoroutine_Auto_Internal(IEnumerator)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
OnScreenDebugInfo:Awake()
Yeah, I think, because your modlog is so short, that something in unity is breaking and the modloader dies before it loads any mods
There it is
That's the native DLL being loaded as an assembly or being loaded on a system of different bitness than it expected
.NET has DLLs referred to as assemblies or 'managed code'. These are not the same as native dlls such as those compiled from C/C++/Go/whatever
Regarding the bitness of the system it should be right if the DLL works with Razer's C# sample app ?
idk, I don't integrate native dlls ¯_(ツ)_/¯
Wise choice
It could simply be unity trying to load it as an assembly and failing because it might expect native dlls to go into the /plugins folder or something stupid
Well anyway thanks a lot for your help and your quick answers everyone
I can neither confirm nor deny that
But how did you know?
Guess or recent stream
Yeah. I just realised that the name of the cloak was in the shot
The name of ddark
Ah. Yeah.
(For anyone interested in my Razer DLL problem, everything actually works if I put my DLL in a folder that's accessible in my PATH, but I guess asking the users of a mod to modify their PATH is not really nice)
it should be possible to dynamically add that to the path if it isn't already there, but i've never done anything like that
Yes it should be doable somehow, I'll look into that, thanks
It's possible, but dll resolution in .NET should follow the same principles as assembly resolution iirc. Putting it in the same folder as the EXE should work too
You could put it in the mods folder and just let modloader fail to load it, oh well no big deal
Well yeah but as we saw that crashes Unity
I'd advise against permanently editing a user's PATH unless otherwise specifically noted.
In the Managed folder, I thought. My hypothesis was that Unity itself was attempting to load it, not necessarily the modding API
Sorry if it wasn't clear : putting the DLL in Managed results in [ERROR]:[API] - Error: System.DllNotFoundException: CChromaEditorLibrary in ModLog, and putting it in Managed/Mods results in a crash in output_log (the one I pasted earlier)
That error in the modlog is acceptable, is it somehow blocking your mod from working? If the modding api fails to load a DLL it just moves on
And you dont NEED the modding api to load that dll, just your mod specifically to find it
I could be misunderstanding what's happening, i suppose
Well the error is not acceptable because it's triggered when my mod tries to intialize Razer's SDK and it completely crashes
I don't get the subsequent logs / keyboard colors that I should get
It's not triggered by the modding API, it's just triggered by my mod trying to load the DLL
(I think)
That may be the deal, sounds possible I suppose. The discord rich presence mod also uses native dlls, for discord's api, I think. I don't remember who made it in order to point you at someone to ask Qs to
Someone else here will probably remember though 
Dont download it
No problem, thanks for all your help. I'll look into temporarily modifying the PATH, that may simply be easier
.
Well, seems like
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";hollow_knight_Data\\Managed\\Mods\\MyCoolMod");
simply works
Almost too easy
Yeah, but that's not necessarily temporary
And it would be additive unless you check the PATH each time for what you want to be in it
Well I don't see it in my PATH after closing the game so I'd say that it is temporary
Well yes, it is, but the constructor of my mod is guaranteed to be called exactly once right ?
Is that your user PATH or machine PATH? Did you check both?
Yes, I suppose. Although you should likely put that in Initialize() which I believe is called once
I put that as early as I could but I guess it makes more sense in Intialize, you're right
I don't see it either in my control panel PATH or in a userland powershell ($env:PATH), is there somewhere else I should check ?
I just checked the SetEnvironmentVariable method docs and it mentions it's for the current process.
So you may actually be okay there
Env variables are always process localized unless you change the defaults
Which I assume would be some win32 dllimport shit
That's what I would have guessed too, but I'm not too familiar with Windows env var (only Linux ones), so thanks for the confirmation
Can anyone explain the logistics of this?
arrays
I may be using the word logistics wrong
But yeah
If anyone can explain whatever this is meant to do it'll be nice
indices correspond
Specifically, all the "tracking" stuff
event ATTACK has a 40% chance of happenening, but only 2 times max in a row (tracked with 'Attack Count') and can only not happen 3 times max in a row (tracked with 'Ms Attack')
eventMax is the max times something can happen in a row iirc?
Ah
Thanks
So it all tracks how many times things happened/ hadn't happened in a row?
yes
Epic, thanks
how can i get the type of a private struct inside a class
getnestedtype
it's a nested type bro
Oh
you just typeof(Outer).GetNestedType("inner", binding flags that I can't be bothered writing on mobile)
is it also possible to get the classtype for casting reasons?
casting apparently doesn't work with the selfmade type
for specifics: HealthManager.HPScaleGG is a private struct
just made custom reflection stuff to directly get the values of normal types inside hpScale
Sorry, what's your Q or did you figure it out?
figured it out
resulted in a very short line of code
int level2 = (int) typeof(HealthManager).GetNestedType("HPScaleGG", BindingFlags.NonPublic).GetField("level2").GetValue(typeof(HealthManager).GetField("hpScale", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(self));
That's a mouthful
i mean, this works and i only need it twice per enemy spawned
I suggest caching the FieldInfo objects if you're doing this often (in other words: more than once ever)
meh
Just to avoid repetitive reflection lookups... Although I think reflection has a cache in .NET I'm not sure
the only time it could lag is with bosses that spawn enemies or the colosseum
otherwise it's just loading screen
No it doesn't have a cache
If you don't cache your field lookups you are wrong
and you should feel wrong
poggy woggy
Speaking about reflection, is there any difference between
InputHandler input = ReflectionHelper.GetAttr<HeroController, InputHandler>(HeroController.instance, "inputHandler");
and
InputHandler input = GameManager.instance.inputHandler;
``` ?
The difference is that the former is based around emitting methods at runtime to have fast private field access
Afaik it just gets the private HeroController.instance.inputHandler
Utility wise though no
Yeah, found it. I'd say yes, about the same.
Is there any reason to use one over the other? (And just to check, they are the same object?)
idk inputHandler's visibility, but if it's public there's no need for the first option
Remove ReflectionHelper just add https://github.com/albahari/uncapsulator 😛
in this exact scenario
In this case, the former is getting from HeroController and the second is from GameManager
oh, missed that
dynamic doesn't exist on net 3.5
if it compiles to calling the interface stuff then it might work if you include the intrinsic
Port DLR to .net 3.5, problem solved
But, yeah, I don't expect dramatic change. Mostly just being a twerp. Although uncapsulator might work well in 1.5
they do the same thing anyways just without the nicer api
except that one won't work on 1.5
and mine will 😤
because reflection emit is not supported there
fwoggy woggy
Would it be possible to add it in to the managed folder, similar to Newtonsoft? I did find this some time ago and has a version for dot net standard 2.0. https://www.nuget.org/packages/System.Reflection.Emit/
Provides classes that allow a compiler or tool to emit metadata and optionally generate a PE file on disk. The primary clients of these classes are script engines and compilers.
Commonly Used Types:
System.Reflection.Emit.AssemblyBuilder
System.Reflection.Emit.FieldBuilder
System.Reflection.Emit.TypeBuilder
System.Reflection.Emit.MethodBuilder
...
Pretty sure I tried that but it was reffing mscorlib for emit stuff
I can give it another shot though
Is the AfterTakeDamageHook sometimes not called?
shouldn't
My code:
ModHooks.Instance.AfterTakeDamageHook += DisableDamage;
private static int DisableDamage(int hazardType, int damageAmount)
{
return 0;
}
Doesn't work on the second dunk
that's because iframes lol

OK so it's a bug in the modding API basically?
yes
alternative, use the OnTakeDamage hook
i have no clue
OK
apparently
Well it said the latest commit was Jul 2020, but VS refuses to acknowledge ModHooks.Instance.OnTakeDamage
yea, it's not part of the 1432 mapi i think
(maybe because it's internal?)
Spaghetti alert
On.HeroController.TakeDamage += poo;
private static void poo(On.HeroController.orig_TakeDamage orig, HeroController self, GameObject go, CollisionSide damageSide, int damageAmount, int hazardType)
{
self.cState.invulnerable = false;
orig(self, go, damageSide, damageAmount, hazardType);
}
That "fixed" the issue...
Side question why is hazardType an int rather than using the GlobalEnums.HazardType?
🍝
Cherries in spaghetti sounds awful
I see, I suppose I should have expected as much
Hi, sorry to bother you again, but is there any way to get a hook on crystal dash and/or bench events ? I don't see any in the docs, but maybe they are specifics cases of other hooks ? I thought about SavegameSaveHook for benching but it's probably called a lot more that just when I bench right ?
when you save?
theres no thing for just when you bench sadly
i've searched for it before
Ok thanks
TakeDamageHook @steady comet
is it in 1432?
just because it's not on the api docs lol
I should use TakeDamageHook rather than TakeDamage? Or just instead of both?
whats this:
[ERROR]:[API] - at System.Collections.Generic.Dictionary`2[System.String,UnityEngine.Sprite].get_Item (System.String key) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at TransHK.CharmHelperExample+TextureStrings.Get (System.String key) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at TransHK.CharmHelperExample.Initialize () [0x00000] in <filename unknown>:0
[ERROR]:[API] - at Modding.Mod.Initialize (System.Collections.Generic.Dictionary`2 preloadedObjects) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at Modding.ModLoader.LoadMod (IMod mod, Boolean updateModText, Boolean changeSettings, System.Collections.Generic.Dictionary`2 preloadedObjects) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at Modding.ModLoader+<LoadMods>d__9.MoveNext () [0x00000] in <filename unknown>:0```
smth about a key??
looks like a keynotfoundexception
when a dictionary doesn't have the key you request
Well if I try
ModHooks.Instance.TakeDamageHook += DisableDamage;
private static int DisableDamage(ref int hazardType, int damage)
{
return 0;
}
it doesn't do the hazard respawn thing
I think TakeDamageHook is too early
yes
Fair enough, the spaghetti is good enough for me if I have to use 1432
If you're interested I found a way using SetPlayerBoolHook :
ModHooks.Instance.SetPlayerBoolHook += OnSetPlayerBool ;
// ...
private void OnSetPlayerBool(string target, bool val)
{
if (target == "atBench" && val)
{
// ...
}
}
Although for some reason it's fired multiple times very fast when you bench, so you should implement some cooldown mechanism to have your processing executed only once
have you tried reading the channel description
my mistake
toxic
DynamicHeapAllocator allocation probe 1 failed - Could not get memory for large allocation 536870912.
DynamicHeapAllocator allocation probe 2 failed - Could not get memory for large allocation 536870912.
DynamicHeapAllocator allocation probe 3 failed - Could not get memory for large allocation 536870912.
DynamicHeapAllocator allocation probe 4 failed - Could not get memory for large allocation 536870912.
Anyone encountered this before?
It happends when assigning a custom texture loaded from an asset bundle to pure vessel
then your assetbundle is too big
who even has a exactly 512 MB assetbundle
What is the max size it can be?
Oops. I am sorry that I pinged you.
I guess your name is correct
on 1432 that depends how many and which other mods exist (also preloads, as those also take up memory)
test of teamwork has 10 MB of assetbundles (their filesize, don't know how much unity would use for it)
I don’t think it’s the asset bundle. I moved sprites to an assetbundle to stop this from happening on some other bosses
hm
shouldn't be an issue
1 alternative i could think of is having those sprites in their own assetbundle, so if that loads the rest of the assetbundle isn't loaded (and i hope you don't load all assets from the assetbundle after loading the assetbundle)
I only load sprites when they are needed.
I’ll try moving the PV sprite to it’s own asset bundle
Could it also be the compression on the asset bundle?
compression shouldn't be an issue, but you can try it
i use the editor script from https://docs.unity3d.com/ScriptReference/BuildPipeline.BuildAssetBundles.html to build assetbundles
though slightly different
- different output folder
- made it 2 buttons for testing, 1 compressed, 1 uncompressed
I might try it. We are using assetbundles browser
im getting this again:
[ERROR]:[UNITY] - KeyNotFoundException: The given key was not present in the dictionary.
[ERROR]:[UNITY] - System.Collections.Generic.Dictionary`2[System.String,System.String].get_Item (System.String key)
[ERROR]:[UNITY] - TransHK.TransMod+<SetSprite>d__15.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] -
my code is:
Dictionary<string, string> Bossscene = new Dictionary<string, string>() { { "Room_Final_Boss_Core", "Hollow Knight Boss" } };
//...
public Dictionary<string, Texture> EnemyTextures = new Dictionary<string, Texture>();
//...
USceneManager.activeSceneChanged += SceneChanged;
//...
foreach (string res in asm.GetManifestResourceNames())
{
Log("GetManifestRescourceNames");
using (Stream s = asm.GetManifestResourceStream(res))
{
if (s == null) continue;
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, buffer.Length);
_tex = new Texture2D(2, 2);
_tex.LoadImage(buffer, true);
if (res.Contains("Lifeblood THK.png"))
{
EnemyTextures.Add("Hollow Knight Boss", _tex);
}
else if (res.Contains("Big_Buzzboi.png"))
{
EnemyTextures.Add("", _tex);
}
else if (res.Contains("yet another png name for an enemy"))
{
EnemyTextures.Add("another enemy name", _tex);
}
}
Log("aftergetmanifestrescourcenames");
}
//...
private void SceneChanged(Scene arg0, Scene arg1)
{
Log("Scene had changed");
GameManager.instance.StartCoroutine(SetSprite(arg1));
}
//...
private IEnumerator SetSprite(Scene arg1)
{
Log("Setting sprites");
var boss = arg1.Find(Bossscene[arg1.name]);
boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = EnemyTextures[boss.name];
yield return null;
Log("Setting sprites End");
}
```anyone have an idea whats wrong?
i have all the png's
directly using EnemyTextures[boss.name] will always try to find the key in the dictionary for every boss
so if you do not initialise every single boss then it will error at that point
you could use .TryGetValue(string key, out Texture Value) and test for if it returns false
or test if the dictionary contains the key before attempting to find it
boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = EnemyTextures[boss.TryGetValue(string key, out string Value)];?
cus that gives me 4 errors
no, out string Value sets the variable you put in to the value
TryGetValue returns a bool
i'd just test for containskey first honestly
and trygetvalue is also a method on the dictionary, not on boss
i dont understand it lol
i have no idea where to put .TryGetValue(string key, out Texture Value)
oo
Hi, today I don't even have any question / problem ! 🙂
Just wanted to say that I managed to implement the lighting effects for most of the events that I wanted, so I pushed a first working version of my Razer Chroma mod here : https://github.com/Webcretaire/HollowKnight.RainbowKnight
I also made a small preview here : https://youtu.be/FNZI_AMrrO0
If anyone has a Razer keyboard and wants to test it feel free to do so and tell me what you think (the lighting effects can certainly be improved, I'm not a very good designer)
And also obviously thank you for your help for the past few days, Hollow Knight people really are a nice community
hi , where i can find some info or documentation about hk modding?
a lot of it is written at https://radiance.host/apidocs/Getting-Started.html and the official unity documentation
oh thanks
It is incredible that there is no way to turn them off.
Is it not possible to change the functionality of the getters and/or setters of properties using the ON namespace?
It is in theory
In reality it is a gambling game
Small methods are often inlined by the JIT
I've created a custom enemy in a custom scene, setup the AI and everything. It can attack and damage enemy but knight can not hit the enemy for a reason that I dont know. Is there something extra that should do?
Is there a static HealthManager that I should add to the scene like SceneManager?
Does it have a colider?
It needs a healthmanager (the normal one), be on layer 9, and if it then still doesn't work also a rigidbody
The last thing also allows it to be hittable by all players in multiplayer
It does have a collider yeap when the kinght hits it, knight gets damage. enemy is layer 11 and its attack is on 22
what is layer 9 for
i think layer 9 was enemies, could be wrong though
enemy also has a rigidbody2d
HealthManagerOnTakeDamage is not being called
I wonder is there something that I should do about On.HealthManager
I also have this method and it is being called successfully
may i ask what name the enemy gameobject has?
Witch
the only way that doesn't work then is your naildamage is 0
Is it possible though
it should fully work unless:
- your nailDamage is 0
- your HealthManager is dead
- your HealthManager has iframes from the last attack
what does the last one means?
when an enemy gets hit, it has iframes for 0.15/0.2 seconds
it does never gets hit so I assume not the last option
what is the diff between the On.HealthManager and the healthmanager instance on the object?
Is the first one something different
the first one is just for hooks, so you get notified and can execute code when a method of the latter one gets called
Were all the On.??? hooks generated automatically by the monomod?
in the 1432 version bundled directly into assembly-csharp, in 1.5 it's the mmhooks dll
I mean, as opposed to someone having to manually create all of them (I'm guessing that's the case with the ModHooks?)
then there probably is an exception
That's pretty cool - thanks 🙂
tested it (had to first put a healthmanager on my object as i didn't have that), and
var hmPrefab = Resources.FindObjectsOfTypeAll<HealthManager>()[0];
var hm = this.gameObject.AddComponent<HealthManager>();
Dictionary<string, FieldInfo> fis = new Dictionary<string, FieldInfo>();
foreach (var fi in typeof(HealthManager).GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
fis.Add(fi.Name, fi);
fi.SetValue(hm, fi.GetValue(hmPrefab));
}
fis["boxCollider"].SetValue(hm, null);
fis["recoil"].SetValue(hm, null);
fis["hitEffectReceiver"].SetValue(hm, null);
fis["enemyDeathEffects"].SetValue(hm, null);
fis["animator"].SetValue(hm, null);
fis["sprite"].SetValue(hm, null);
fis["damageHero"].SetValue(hm, null);
fis["audioPlayerPrefab"].SetValue(hm, null);
fis["regularInvincibleAudio"].SetValue(hm, null);
fis["enemyType"].SetValue(hm, 0);
fis["effectOrigin"].SetValue(hm, Vector3.zero);
fis["ignoreKillAll"].SetValue(hm, true);
fis["invincible"].SetValue(hm, false);
fis["invincibleFromDirection"].SetValue(hm, -1);
fis["preventInvincibleEffect"].SetValue(hm, true);
fis["hasAlternateInvincibleSound"].SetValue(hm, false);
fis["alternateInvincibleSound"].SetValue(hm, null);
fis["deathAudioSnapshot"].SetValue(hm, null);
fis["semiPersistent"].SetValue(hm, false);
fis["stunControlFSM"].SetValue(hm, null);
hm.hp = 99999;
made the hook trigger
made it work with your code. The HealthManager I've preloaded might be the problem.Thank you very much, altough your code made me wonder two things
- How did you select the HealthManager values that you set after foreach loop?
- Is using Resources.FindObjectOfType an alternative to preloading?
- null or default values (for ignoreKillAll i just thought they may be fitting, and invincibleFromDirection 0 is invincible from all directions, so -1 was the choice)
- no, it only finds loaded things, so contents from not loaded scenes can't be found this way
if you make an actual enemy you probably don't need anything after the for loop
again thank you very much for help
i'm trying to load a scene in HoG. I first tried what benchwarp does and it gave me a black screen. Then i tried using debug mod's save state and this happens.
is there any way to stop the player from moving or a better way to load the scene. I did HeroController.instance.RelinquishControl(); to try to stop movement but it didn't seem to work
im looking for dialogues stored in dnspy, does someone know where i can find them
not in dnspy
do you know where?
because i see i can get them with the getlanguage hook, but i don't know which key corresponds to what text, if that makes sense
you can log the sheet and key w/ the result in there
i saw that note on the radiance.host site as well, but how would i do that
thanks for your vid btw
private string OnLangGet(string key, string sheetTitle) {
string res = Language.Language.GetInternal(key, sheetTitle);
Log($"{sheetTitle}-{key}: {res}");
return res;
}
glad the video helped
if you want any particular sheet i have them all too, though you can just use AssetStudio pretty easily
thank you!
you forgot a $
that's true
Are there resources for learning how to mod? I have programming experience and a bit of Unity experience, and I'm not looking to do anything too ambitious
https://radiance.host/apidocs/Getting-Started.html seems to be a good place to start
heyo, anybody here know how to make HK mods?
the message right above yours......
yeah, the apidocs for modding it specifically state that it can't be modded
it is a joke
oh
yeah well you see I lack this thing called a brain
um so, I would prefer not to make the mod myself because I'm already trying to learn like 6 other things rn
but I can provide assets for the mod if someone can do the actual modding
what do you want to make? If it's a tiso mod, it's already being worked on
but I guess there's always room for more tiso
the real problem is finding an active modder that doesn't already have 6 other projects they are working on
that is what I want to do, yes
could you point me in the direction of some of those mods
I feel called out
I know of two possible sources, 1. jngo(not been here for a while) 2. private mod that I will not disclose
but everyone has thought of a tiso boss at some point, so there's prob more
well then
I suppose the question becomes "anyone here working on or know who's working on a Tiso boss mod"
Do you know c#?
You should probably learn it first
I would like to learn it, for several reasons
one of which is Terraria and also just because it seems like a really versatile language
Ah yeah, terraria modding is fun
I sprite for a bunch of terraria mods but I've never coded any
the most programming I've done was a HTML game in Javascript
it was for a course
byeah I should just do c#
You should also probably learn a bit of how to work with unity(ex: basic knowledge of how to use monobehaviors and gameobjects)
I wanted to make a mod where we actually witness Tiso's death, but that's probably not what you meant
no, I was thinking about adding a Tiso boss fight
probably accessed by dream nailing his corpse
i want to load a scene in HoG when i press a button. I'm currently doing: ```cs
if (Input.GetKeyDown(KeyCode.B))
{
GameManager.instance.BeginSceneTransition(new GameManager.SceneLoadInfo
{
IsFirstLevelForPlayer = false,
SceneName = "GG_Hollow_Knight",
HeroLeaveDirection = GlobalEnums.GatePosition.unknown,
EntryGateName = "door_dreamEnter",
PreventCameraFadeOut = false,
WaitForSceneTransitionCameraFade = true,
Visualization = GameManager.SceneLoadVisualizations.GodsAndGlory,
AlwaysUnloadUnusedAssets = false
});
}```
But when i press the key, i only see a black screen but i can hear the boss and i can take damage
hello can I talk about skin development in this chat
most skin development talk happens in #modding-discussion
copying what the inspect elements in hog do would also be an option, idk what they exactly do
how would i copy the inspect elements
you could preload them, but doing what the statues do is probably better:
1. send "DREAM ENTER" event to some object
2. set dreamReturnScene pd string
3. send "BOX DOWN DREAM" event to all (broadcastall)
4. send "CONVO CANCEL" event to all (broadcastall)
5. if you want to be fancy, spawn a gg_battle_transitions gameobject
6. send "GG TRANSITION OUT" event to above spawned object
7. call HeroController.instance.ClearMPSendEvents()
8. image
how do i spawn gg_battle_transitions
and for 3 and 4 its just EventRegister.SendEvent("BOX DOWN DREAM");?
may be a globally accessible gameobject (or preload an Inspect gameobject and pull it out of the fsm)
PlayMakerFSM.BroadcastEvent("eventname")
btw, the 2nd to last part of the image isn't needed
Why does PlayMakerFSM.BroadcastEvent not work?
oh, then i haven't found it
the false is only to also send it to itself lol
Oh I see lmao
i just found that because SendMessageByName used that
In the 1.5 mapi do you have to broadcast an FsmEvent rather than a string fsmEventName?
i have no idea
OK, I guess I'll investigate when I get the 1.5 mapi (which I'm far too lazy to get before I'm forced to lmao)
Awesome thanks 
like this ?EasierPantheonPractice.PreloadedObjects["Inspect"].FindGameObjectInChildren("gg_battle_transitions");
and this is the thing i preloaded ("GG_Workshop","Inspect")
actually no, it's not part of the structure, but only referenced in the fsm, so something like
EasierPantheonPractice.PreloadedObjects["Inspect"].LocateMyFsm("GG Boss UI").GetAction<CreateObject>("Transition", 0).gameObject
("GG_Workshop", "GG_Statue_Hornet/Inspect")
so if i wanna do for all bosses I'll have to preload each one?
no, because the thing you're getting from <#archived-modding-development message> is a prefab, just need to instantiate/spawn it whenever you need (spawnpoint should be the knight i think)
how do i send an event to that? the lightblub told me its a HutongGames.PlayMaker.FsmGameObject and that doesnt have a method for send event
foreach (var item in go.GetComponentsInChildren<PlayMakerFSM>())
item.SendEvent("lol");
with go being the thing you have + .Value
ez, not a single thing of this was tested 😎
Hey so I was trying to use the mod installer yesterday, and I ran into an issue where hk stopped recognizing my controller, and some guy said "oh yeah, that happens, just use a gamepad->keyboard translator." I would rather not do this for various reasons, so I thought I'd ask about
- how exactly the mod api interacts with the game controller api (like, where in the modding api code we interact with controller related things)?
- why this is done?
I ask because, not really knowing about how the modding api works, i would think it would be preferable to not interact with the controller in the first place.
FYI, I've been a software engineer for like 10 years (although not a game dev), and I know tons of programming languages, although not really C# particularly. So you can explain stuff in technical terms, not just abstractly
Change some guy to Someone to be more accurate
like, i tried searching for stuff like controller (but mvc, lulz) or input in https://github.com/HollowKnight-Modding/HollowKnight.Modding, but i'm not sure i found the right places to look, and anyway I gather that's not even the correct repo
I did try a bunch of big picture-related things & plugging in controller either before or after starting hk, although not any external programs like joy2key or whatever it was
anyway, this wasn't a request for support
I was asking about what was actually going on in the code, since maybe we could just solve this once for everyone
The only time i used joy2key was when i connected my wii controller and all hell broke loose
yeah, see, maybe there's a way to avoid that
but i'd need to know for sure whether the repo ref'd above was the correct, canonical, up-to-date repo, and also where to find whatever code affects controller input
b/c i probably don't have time to just figure it all out myself from the ground up
If Someone said it was not the roght one then it was not the right one
But i dont really know if its the right one
I wasn't 100% sure I understood what he meant here: #archived-modding-help message
It seems to be the right one
But this is for the 1.5 beta
Ah
Hollow knight 1.5 is a beta release
1432-60 is the current active version on the installer
does that mean a beta of hk or a beta of the mod api?
so there's a beta of hk, and work on the mod api to support the beta, got it
so i could dl & run the hk 1.5 rc if i flipped some flag on steam?
cool, that all makes sense
so does anyone know where in the mod api code we interact with the controller or input?
is it InputHandler.cs?
I guess?
GitHub's code search is atrocious, otherwise I'd be with you. You use Unity's input modules to handle input, just as if the game would.
y the embed tho
There may be helper code in the modding api, but IDK man, that's where searching will come in handy just don't expect much from github's searchbox
too many clicks to type brackets
yeah, i know how to use github & its codesearch (& that it sucks & you probably have to just clone & search the fs)
there might be a simple solution to the problem, but it's going to be a hidden one. it's probably a byproduct of the API hijacking the game's launch. It's not going to be a cut and dry solution of "inputmethod=xinput"
sure, but does anyone know exactly where we hijack the input, and more importantly why?
i think 56 would know
tmk.... nowhere
56 would be the one to ask tho
that's why I'm saying.... I don't think there's any method in this code that directly takes over input handling. However, the API may have a side effect with the game/steam/etc by virtue of an omission or something that's causing only limited inputs to be accepted
i'm pretty sure you're right
If the what is causing it, why its causing it and how to fix it was known then the bug wouldn't exist
I'm sure it's fixable, but figuring out why the interaction is happening like it is.... will take a ton of debugging
no i don't mean why it's causing it, i mean why do we hijack input in the first place
because that would help me figure out what's going on & what solutions wouldn't break whatever it is we're trying to accomplish in the first place
the assembly file is the main launching file of the game
Its a side effect of something its just not known of what
so by nature of replacing it....
^
that's why I'm saying, I don't see a method in this code that would be hijacking input handling directly. but some other hand-off might be broken
you mean, nobody is trying to hijack input to e.g. make the menu work or make some class of mods possible, just somebody did something that's doing it & it wasn't intentional?
i think it's more like xinput is in the assembly for mac/linux but the modded one doesn't contain that, or something similar, idk
btw, so i didn't mention this earlier, but i checked the player log both with & without the mod api installed:
original:
Game controller set to Generic Controller.
modded:
Game controller set to Unknown Device.
which is why i think Mickely is right
using inputs != input types.
the API allows only XInput when it's installed iirc
but without the API, steam input handling works fine
so some handoff of input method is broken
that's what I mean about hijacking input handling
i think sfgrenade may be on to something tho
there is no method in the API that defines input handling. but yes, inputs are used for UIs, etc
so the unity/steam/etc input methods are being broken
do you have any reason to believe that while the modded assembly doesn't have xinput, it would have the libs for other devices like for a switch pro controller or whatever?
i have no clue about that, just heard something like that once
the controller i usually use is an 8bitdo sn30 pro, which steam treats as an xbox 360 controller (& would thus use xinput i think)
but i also have the sn30 pro+, which can be configured to use xinput, or some other nintendo-specific thing, or some android-related thing (idk, i stopped reading the manual at some point)
anyway, the point is that:
- if the issue is the modded asm missing xinput
- if the modded asm is known to NOT be missing xinput-but-for-nintendo-switch
then it would work if i used the pro+ in switch controller mode
i don't actually want to use the pro+ since i like the other controller better, but it would let us identify & solve the problem
maybe
i mean this isn't just about allowing me to play the game with mod api & some controller, but about reducing the number of people who come here and ask why their controller doesn't work
also, my original objective here was to install debug mod so I could learn the speedrun skips, and having to use my less-good controller kind of clashes with that goal
(for some reason i want to say that "xinput-but-for-nintendo-switch" is actually called "dinput", but idk, that might have been the android one, or just what 8bitdo calls it, or some other thing)
Is there a way to add a mod option in the pause menu? I’m not seeing anything in the docs
You should look at how other mods do it. The ModdingApi itself does not add a way to do this
Alright, thanks
So I just tested it & in fact he pro+ controller in switch-input mode DOES work with the mod api installed. Sort of.
Basically, I may have it configured wrong, but vanilla hollow knight doesn't actually recognize the switch controller in game (i.e. from menu > options > controller), and also it's pretty much unusable in that the d-pad doesn't work, i have to use the left stick to navigate the menus & move the knight, and the only button that works is the a button, and that only works in the menu. But it does work the same with & without the mod api installed. Maybe this is relevant to the theory that the modded asm is missing xinput on some platforms (I'm on linux).
Note that I'm blacklisting the hid_nintendo driver so that steam uses it's built-in hidraw-based pro controller driver. If that's relevant to anything
As I said before, I really don't want to use the pro+ controller, since it's not as good as the other controller, and the only reason I got the mod installer in the first place was to install debug mod to learn the speedrun skips, so if I have to use a suboptimal controller to learn them that kind of defeats the purpose. I'm just noting stuff that may be useful to understand however whatever is happening to people's controllers happens.
looking at debug output with good controller, I see the following:
orig:
Steam stats received.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
WARNING: Shader Unsupported: 'Sprites/Lit' - Pass '' has no vertex shader
mods:
Steam stats received.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
[InControl] Joystick 1: "dev:xb360:Xbox 360 Controller"
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
WARNING: Shader Unsupported: 'Sprites/Lit' - Pass '' has no vertex shader
so the mod api adds that InControl bit, whatever it is
later we see from both orig & mods:
Game controller set to None.
InControl is standard
it's what hk uses for input as a whole
one of the issues with controllers is xinput
varies between platforms
then, the working version does:
Unloading 64 unused Assets to reduce memory usage. Loaded Objects now: 44936.
Total: 126.858000 ms (FindLiveObjects: 2.264000 ms CreateObjectMapping: 1.367000 ms MarkObjects: 122.829000 ms DeleteObjects: 0.398000 ms)
Game controller set to Generic Controller.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Controller Support Not Yet Verified
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Unable to match controller of known type (Generic Controller), will attempt default mapping set.
so i guess that match succeeds.
but with mods
Unloading 73 unused Assets to reduce memory usage. Loaded Objects now: 45044.
Total: 151.753000 ms (FindLiveObjects: 5.953000 ms CreateObjectMapping: 2.183000 ms MarkObjects: 143.253000 ms DeleteObjects: 0.363000 ms)
Game controller set to Unknown Device.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Controller Support Not Yet Verified
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Unable to match controller of known type (Unknown Device), will attempt default mapping set.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Subscribing to controller detection.
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Fallback handler could not load library /home/dmr/.local/share/Steam/steamapps/common/Hollow Knight/hollow_knight_Data/Mono/x86_64/InControlNative
Fallback handler could not load library /home/dmr/.local/share/Steam/steamapps/common/Hollow Knight/hollow_knight_Data/Mono/x86_64/libInControlNative.so
Fallback handler could not load library /home/dmr/.local/share/Steam/steamapps/common/Hollow Knight/hollow_knight_Data/Mono/x86_64/./InControlNative
...(snip)...
Unsubscribing from controller detection.
I guess it's a missing library then
@copper nacelle earlier sfgrenade suggested that on some platforms, we patch the asm without adding xinput for some platforms
On Linux and mac the universal binary is built against the windows assembly yes
which prompted me to try using my replica switch pro controller in actual-switch mode, which kinda worked
Which means native functions aren't tied in
Controllers are still fucked on windows anyways though
you mean the universal binary for hk or for the mod installer or what?
the api labeled universal is just built against windows because for the most part everything is the same
so presumably, InControl is statically linked to the mac/linux binaries, and running the mod installer is wiping them out somehow?
not running mod installer, using the ModdingApi
InControl has pinvokes
maybe I'm confused: my mental model of what's going on is that running the mod installer patches the hollow knight binaries to add the modding api, so that mod packages can hook into the modding api
just replacing the assembly with the modded one
Can't trust the average user to have .net core let alone msbuild
can't trust the average user to know what clicking install on a mod does
that's true
It's just a matter of building against the other vanilla folder
Pretty sure I have it already
so i could fix this by building HollowKnight.Modding myself against my own vanilla hk dir, assuming I knew how to apply the result?
maybe, but this
presumably i would want to git co 1.4.3.2-60 first
for steps 3-4, is it just msbuild -p:Configuration=Debug or what?
ok; i assumed that was only for step 8 for whatever reason
presumably i'm missing some core ms libs:
/usr/lib/mono/msbuild/15.0/bin/Microsoft.CSharp.CurrentVersion.targets(331,5): error MSB4019: The imported project "/usr/lib/mono/msbuild/15.0/bin/Roslyn/Microsoft.CSharp.Core.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.```
if you'd like I can just build against the Linux binaries in like 20m
Otherwise yeah
that might be better; it turns out i didn't even have the dotnet-sdk installed, and downloading that will take a while, and then who knows whether that's everything
Cool
i'm actually installing dotnet-sdk anyway, but i sorta doubt that'll solve everything
anyone know why .NET 3.5 isn't in the target framework list for Visual Studio? I have 3.5 enabled in control panel as well as added as an additional component in the Visual Studio installer
did you get the targeting pack
probably not
I couldn't find a developer pack- there was only a runtime in the .net downloads page
can't find it, do you have a file or link?
it does? ok then
3.5 is a pain
there's also .net 3.5 dev tools in the vs installer but you said you already did that
fwiw if you've selected .net core on a new project then versions of .net framework won't show up and you have to either edit the csproj or remake the project in vs
(3.5 being a .net framework version)
inner peace
56 really is shifu
@copper nacelle so that build actually worked. Although it actually didn't work the first time I started hollow knight & appeared to produce the exact same error in Player.log. Just to be sure I deleted Player.log & restarted hk & the controller worked.
I mean, I presume it doesn't actually use Player.log as a cache of config autodiscovery it's tried (it fucking better not anyway)
i definitely didn't change anything between the 1st 2 runs other than deleting Player.log
unfortunately, if i now try to run the mod installer it overwrites the fixed version i just manually installed with the broken one it auto-downloads; presumably I can still use the mod installer to install debug mod & then re-overwrite the assembly dll
yeah that's annoying
i could maybe fix that later
but yeah you can install and just overwrite again
so i appear to have gotten both debug mod & controller working properly, so that's nice
presumably also relevant for macos people who have controller issues
yeah
clearly I'm doing something wrong because 3.5 is still missing
I'm going through create project -> c# class library -> name and shit, and then I only have the wrong options
.net 2.0, .net 2.1, .net core 2.1, .net core 3.1, and .net 5.0
that is the wrong type
you aren't making a framework lib
also idk when this happened for c# because one of my addons was breaking it but it's nice
easiest way to fix this is prob just opening the .csproj in an editor and changing netcoreapp3.1 or whatever to net35
but 35 because you're presumably using 1.4.3.2
there are different class library options for .net core and framework
CallMethodProper sux, doesn't want to store fsm variables for me
got the inv page working better, idk how the journal doesn't break
I found out a while ago how it doesn’t break but since I don’t need to again I won’t
yo, with your journalHelper, you have it made using instances, but everything else is basically static, why not change it all to static?
Do FSMs get reset? like if I want to change one, do I need to do it only when the game is first loaded or every time a scene is loaded?
latter
some fsms have a template, so you need to make it first think that it doesn't, then make changes
First off, you will want to include the following HutongGames.PlayMaker, HutongGames.PlayMaker.Actions, and ModCommon.Util.
what does this mean/how do I do it?
reference them in your project and then have
using {}
at the top of a .cs file (one using for each namespace)
Good idea, will do
Making a big update to frog core anyways
how would I get the game object for the Shade? to change its fsm
probably OnEnemyEnable hook or something like that and check if it's name is a shade name. then modify the fsm
SceneManager has a HollowShadeObject
what's causing this error? The other error is "Cannot resolve symbol 'GameObject'". Am I missing a dependency?
sorry for being clueless 
Right click on it and let it generate a function for you
doesn't help
the problem is it doesn't recognize GameObject so it thinks it has the wrong signature
Did you write GameObject or gameObject
@runic wind you need using UnityEngine; - do you have that?
yeah, but it says it's not being used
probably not
As a side note, if you want to mess with FSMs, the way rando does it is to use the On.PlayMakerFSM.OnEnable hook - https://github.com/homothetyhk/HollowKnight.RandomizerMod/blob/master/RandomizerMod3.0/RandomizerMod.cs#L518
Well there has to be a reference to UnityEngine.dll (I think that's the one?) in the csproj
Yeah, UnityEngine.dll
I think you can just add references through Visual Studio (if that's the ide you're using?)
using rider because visual studio did not like .NET 3.5
Oh - I assume you can also in rider but I don't know how to
yeah I know how
I believe I referenced UnityEngine.dll but I'm trying to find the .csproj to make sure
yeah UnityEngine.dll is referenced
Does it not recognise the GameObject keyword? What happens if you right click it?
Huh
in VS if I don't have using UnityEngine it just tells me to add it
Perhaps someone more experienced than me will have to help :/
try UnityEngine.GameObject
I still get "Cannot resolve symbol 'GameObject'"
add refeerence to UnityEngine.CoreModule
also, you could try this to make VS work https://windowsreport.com/net-framework-3-5-missing-windows-10/
I'll stick with Rider for now, but thanks
I'll take a look if I'm still doing modding stuff when the rider trial runs out
So I know nothing about modding or coding in general, but I really want to get into HK modding. I have no idea what I need or how to even start and I was hoping maybe someone could help me.
#archived-modding-development you should probably learn the c# language first
The apidocs are really helpful
https://radiance.host/apidocs/
This is modding-dev lol
xD
Yeah I thought it would be better to ask here
One of the questions I have is what you use to make the mods and dlls.
An IDE, such as visual studio in which to code
That IDE also makes a dll
Also watch the modding tutorial by 56
ok thanks
c# is pretty easy to pick up, its very similar to java
seems pretty intuitive as far as coding languages come
If I ever finish some kind of mod where do you post it?
Either pr the modlinks.xml yourself, ask me or someone else to do it or ask for more explanation
ok I'll come to that when I get there then
You know what github is?
Alright I'll just save the page then
would there be any downside to just referencing all of the unity.dll s?
The .csproj file is bigger
true
would the .dll be bigger?
iirc resharper has a tool to remove all unused references once you're done
but that costs money so 
not if you're a student afaik
when implementing ITogglableMod what do i put inside the Unload method
Generally you want to unhook what you hooked in Initialize and if you created stuff destroy that
got it, thanks
C sharp question, is there a good way to swap two variables? Like
a, b = b, a
in python.
Just tested
(b, a) = (a, b);
and it works
New-ish tuple syntax lets us do fun stuff in C# too
Why is vengefly speed fps dependent?
Looking at the fsm, I'm guessing it's something in ChaseObject
is acceleration done every frame instead of every physics frame or something?
Relatedly, how do I find the code in dnSpy for the methods in fsms?
@runic wind from what I know, playmaker doesn’t use Time.DeltaTime which means that everything scales eitht he amount of frames
if i were at home, i could check exactly that
You can look in playmaker.dll and assembly C sharp.dll in the HutongGames.Playmaker.Actions namespace and some actions are just in the global namespace
(in fact if you're feeling lazy like me you can find the action just by using DNSPY's in-built search feature to search for the name of the action)
when changing things in PlayerData can i just use PlayerData.instance.(variable)=(whatever i want)?
You can, but it's considered polite to do it using the SetBool (or SetInt, or whatever it is) method so it goes through the hook for other mods to use
what is the correct way to do so?
If it's a bool, then
PlayerData.instance.SetBool(nameof(PlayerData.???), ???)
thank you very much!
The nameof(PlayerData.???) is just a compiler thing that means you're less likely to have a typo
thank you so much for this, i've been trying to figure this out for like the past 24 hours
mostly because im dumb lmao
That’s what I do
is there a hook for when the player receives a charm notch?
There's a hook for everything
is it included in the charmupdate hook?
You can use SetBool or SetInt hooks
can search through the "On.xxxx" hooks
gonna say this just in case, but the list of hooks in the apidocs document is not exhaustive
so i could just use the setint hook for PlayerData.charmSlots?
try it
uh oh
that went poorly
game just crashed, think it's because of the way in which i tried to test if it works
What’s your code
/*private void OnSetPlayerIntHook(string intName, int value)
{
//Ensures the player can only have a maximum of 3 slots even when aquiring a charm notch
PlayerData.instance.SetInt(nameof(PlayerData.charmSlots), 3);
}*/
thank you
do not call setint in a setinthook
you can also do cs ater `
```cs
message
```
for colours
Color is cool
what is the diff between SetIntInternal and SetInt?
SetInt calls the hooks SetIntInternal doesn’t tmk
So the only place you should really use SetIntInternal is the hook
ok
The example mod given on the apidocs is hellmod, is that what I should be using? Seems like it isn't
using as what
an example probably
An example to learn what the heck i'm supposed to do/so I can work off of it instead of spending a while creating all the files in the right places
It's a decent example yeah
Alright
have you watched the video provided?
i'd start with that and then go from there using hellmod as an example

