#archived-modding-development
1 messages Β· Page 501 of 1
does modifying an instantiated transform change the source transform
btw, you don't need to mind my pr rn, fixing a few more thing, then maybe close the pr, reset my fork and doing the changes again
nvm
I am using obs, I think my audio settings were set weird somewhere
looks amazing
@vocal spire is there e repo for lifeblood master?
well it's somewhere. if I'm going to put in effort into finding it is a different question with a similar answer
local man does not comply with gpl
?
gpl? isn't modding api mit?
pretty sure lbm had fsmutil
oh yeah modcommon is a thing
should probably be lgpl or something considering modcommon is mit
π€
dnspy editing time
epic music begin now
also I had copied fsmutil from some other boss mod
you know, the good thing about specifically editing lifeblood master in dnspy is I was too dumb at the time to use GetAction, it's all copying states and changing transitions
bruh
time to sue him
kick him out of pale court
π€
now hold on that's just losing labor
kicking the only other playmaker person out
oh fuck yea, there was something
redfrog pretends he lost the source but in reality lifebloodmaster's dll is malicious and he's desperately trying to hide it
π€ how did u know
it's true
the true malicious thing to do is to somehow make a c/c++ dll do all the work in a mod, that the c# dll only loads the c/c++ one and nothing else
so no one can read what the mod does
just use thinking for the 147th time
program it in playmakerfsm
but change the name of every fsm action to be random garbage
lol
and have one action per line of code
that's the greatest idea ever
anyway when doing that lm fails to load
time to recreate the code I guess
then I can get back to finishing a terraria mod
so I can get back to finishing a among us mod
so I can get back to finishing pale court
why are you recreating it
Β―_(γ)_/Β―
dnspy has a save as solution button you know
nice
but things like const values and bool flags (fuck those honestly) have to be corrected
F
I mean they're not wrong they're just inlined
yea but they look ugly
I probably didn't use any consts
ah yes
i'm still working on my 1st one though
F
my first one was worse than that abomination. it was dream shield coop updated. Scary stuff..... i keep wanting to update it, but just no
also when you upload code to github, does the spacing ever just go weird
huh
would that explain https://github.com/RedFrog6002/LifeFruitCore/blob/main/LifeFruitCore.cs
ctrl+f "\t", replace with " "
This honestly looks like something that would be in the original game. I think you did perfect!
And this is coming from someone who just started playing last week haha
CustomKnight but with music????
wait thats actually amazing
truly magnificent
suggestions on what to add (currently just thinking modlog & output_log)
list of mods in the mods folder
- search bar for mods
- having a way to search mods by a specific person
3. taking more inspiration from t mod loader
me not knowing what tmodloader even looks like
hiiii again. i followed the tutorials on the apidocs and i kind of understand things a little better now. i'm able to make a little custom scene and import it as an assetbundle. how could i make it so that it plays my own bgm when i enter the scene?
sorry this must seem pretty basic π
you can create a gameobject and put an audiosource on it
does it output to the audiomixer by default?
you can just set the volume to use like GameManager's audio level
there's a method
idr the exact name
oh dang the music wasnt playing because i forgot to build the scene π
GameManager.instance.GetImplicitCinematicVolume()
oh wait are you supposed to divide it further
i just took the value directly and played it at that volume π₯΄
maybe you don't have to
it is divided by 10 already in the method
i thought i did
oh well
worked like a charm, thanks!
np
So I've been thinking about slowly learning to mod the game, and I just wanted to double check a couple of things:
-
Are there any "recommended" ways to start learning it?
I already have https://radiance.host/apidocs/Getting-Started.html#creating-mods bookmarked -
There's a few pinned messages about using specific versions of Unity, but they specifically reference various asset things (the most recent one from two years ago, says to use
Unity 2017.4.10f1). Is this specifically for adding assets to the game, or do I need to change to that version before doing anything?
(The version of Unity I currently have installed looks to beUnity 2018.4.12f1; so I want to know if I need to change that before I start looking at existing mods).
π
My current plans are just to edit some existing mods for personal use, to help with learning how it all works. So, the code will mostly be stolen lol.
If I want to edit elements that are on the menus, do I need to mess with "asset bundles"?
And so, if I'm not doing things with asset bundles, does that mean I don't need to use Unity at all? I can just entirely use IntelliJ? (I know the game uses C# scripts, but I just assumed that I'd somehow need to do something more than just code).
if you aren't using assetbundles, no unity is required. if you need assetbundles depends on how you want to go about whatever you're doing. sometimes there's a single way, sometimes there are a bunch.
I don't actually know what asset bundles are. Based on the name, I assume that they're assets, like game objects- and I don't plan on adding anything to the game that isn't already in it.
Yep
Yeah, basically entirely new enemies/objects/etc
Ah. Well that's a huge relief then!
easiest way t add real BGM: use SFCore
- https://github.com/SFGrenade/SFCore/releases/tag/v1.2 sfcoreunity.dll
- put that somewhere into your unity project (so it enables you to use monobehaviours in the dll)
- make GO with a collider2d trigger at the entrance of your scene
- add a
PatchMusicRegionsbehaviour on it (from sfcore) - for better functionality, also add https://raw.githubusercontent.com/SFGrenade/ModdingHelper/master/Unity Scripts/Editor/PatchMusicRegionsEditor.cs to the Editor subfolder in the assets folder
- adjust values as needed
still no license 
added mit to sfcore, happy now?
np
ok so i got most of that right when i tried to use it earlier
im guessing i just didnt set some attribute right cuz id enter the collider and the music would just cut out entirely
glad to know im not a complete idiot
thx for the help, i need to sleep now
gn!
Aight anyone knows why my mod doesn't appear in the topleft
technically, every mod dll that has a class derived by Mod should appear in the top left
do you have a github repo with that mod so i could take a look at it?
It did, when I started development
Then it just disappeared
Uh, nop
nope
I didn't start using github
yet
I mean to
Eventually
im running out of ideas
yea ok, do you have a GetVersion method in the mod class?
for my customknight
oh no, why
Yep, yep
Move onto charms 
does it crash/throw an exception?
can you show the top left corner?
can you give the namespace / name of the mod?
it's possible that your mod isn't displayed if a mod loaded after it has the same namespace
Wdym namespace?
nvm, didn't read
Also I'm back btw ||
||
but can you give your modlog / output_log?
Oh shit you're right
I ahven't checked that in ages
And after that it only prints out language keys/strings cuz I hadn't turned that off and I probably should
then probably in output log
Should I just send the file?
how come increasing the scenewidth on the cameracontroller doesnt fix the camera from not following you
cameracontroller has scenewidth?
GameCameras.instance.cameraController.sceneWidth
i just change GameManager.tilemap.width and GameManager.sceneWidth
that makes more sense
and FindObjectOfType<GameMap>().SetManualTilemap(0, 0, width, height);
and all that in a On.GameManager.RefreshTilemapInfo
hmm the camera still won't follow past the same spot
oh wait
yea
the camera still stops following at 160,40ish
private void GameManagerOnRefreshTilemapInfo(On.GameManager.orig_RefreshTilemapInfo orig, GameManager self, string targetscene)
{
if (targetscene == DryyaScene)
{
Log($"wid {GameManager.instance.sceneWidth} and heigh {GameManager.instance.sceneHeight}");
self.sceneWidth = 500;
self.sceneHeight = 500;
Log($"Tiled wid {self.tilemap.width} height {self.tilemap.height}");
self.tilemap.width = 500;
self.tilemap.height = 500;
FindObjectOfType<GameMap>().SetManualTilemap(0, 0, 500, 500);
}
orig(self, targetscene);
}
huh so orig doesnt use the value in gamemanager?
alright thanks
np
is there any reason the unityexplorer ui won't show up on start?
do you have all 3 of the dlls
I do
it was working before, it stopped showing up while I was toying around with the main menu
Are there any good examples of how Source codes of mods should be uploaded to git hub?
There really isnβt a good example since all of them are basically the same
Fair enough
idk why Create Game is cut off but here's some progress
dreading implementing the mitm server
what exactly changed in newest moddingAPI that appears to have broken everything? and is it worth rolling back the version on installer 
Time to go look at GitHub!
and is it worth rolling back the version on installer :vesselsip:
Probably, for now
how exactly is it broken
this is so non descriptive
it works for me, with just debug mod installed
yeah but certain mods like hollow twitch refuse to load
Got a modlog?
the thing with decomaster: it initializes its own json thing, with its own settings and still somehow fails
Huh
https://github.com/a2659802/HollowKnight.Decoration/blob/master/DecorationMaster.cs#L39 calls https://github.com/a2659802/HollowKnight.Decoration/blob/master/Util/SerializeHelper.cs#L80 which uses a simple JsonConvert.DeserializeObject at https://github.com/a2659802/HollowKnight.Decoration/blob/master/Util/SerializeHelper.cs#L98
π€
imma test every commit from the globalsettings one onwards to check which one decomaster can't handle
don't worry, i know what i'm doing
uh huh
https://github.com/seresharp/HollowKnight.Modding/commit/cfc33db275611be1bf7f5d99831a9760ff78f9ec apparently breaks deco master
why'd you even move the actual add component
because decomaster somehow crashes with the dictionary it preloaded
and this <#archived-modding-development message>
all my homies do not need to hook gamemanager.awake
but gamemanager also doesn't do shit until main menu is loaded
as it doesn't exist at that point
are there under 255 gameplay scenes in the game
there are nearly 500 total ones, so i doubt it would be under 255 gameplay ones, especially with mods
but the decomaster error is really weird, as it's a KeyNotFoundException:
[INFO]:[DecorationMaster] - Loaded Json
[ERROR]:[API] - Error: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
[ERROR]:[API] - at System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.Dictionary`2[System.String,UnityEngine.GameObject]].get_Item (System.String key) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at DecorationMaster.ObjectLoader.Load (System.Collections.Generic.Dictionary`2 preloadedObjects) [0x00000] in <filename unknown>:0
[ERROR]:[API] - at DecorationMaster.DecorationMaster.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__10.MoveNext () [0x00000] in <filename unknown>:0
hm :/
[WARN]:[API] - Could not find object "Zote Death/Head" in scene "Fungus1_20_v02", requested by mod "DecorationMaster"
damn now I have to send one more byte each time a scene changes π©
would it be wise to create a pool of player objects instead of instantiating one every time a player enters the same scene as you to prevent microstutters?
something in the decorationmaster preloads for some reasong depends on gamemanager so hard that it stops existing completely if gamemanager isn't there
wait wut
Fallback handler could not load library E:/GOG/Hollow Knight Manhunt/hollow_knight_Data/Mono/data-A84A4010.dll
probably a good idea, with a start amount of the current amount of players on the server
simple moving of the modloading point to the previous point gives audio stuff
π
when assetbundling, is there a way to keep the shadders out of the bundle?
please ping me when answering
@sage holly according to https://docs.unity3d.com/Manual/AssetBundles-Browser.html, you can right click assets (or hit DEL on them) to remove them from bundles
is that safe to do? then I'll do that
i have never tested it (i personally don't use assetbundle browser), but according to unity's website it should be safe
ok
why is it that when i put my scene into the asset bundle browser, it wont let me put an audio clip in with it?
how come?
unity
i also don't know why, but unity says so
huh
keep modding ideas to #modding-discussion
is there an existing hook that triggers on parry and maybe exposes the enemy you just parried?
and related to this, where is parry damage calculated and processed?
Is it possible to preload an object which is loaded by a scene but not technically part of it? For reference I'm attempting to get "GG_Challenge_Door_Canvas" which is loaded with the GG_Atrium scene but isn't part of the scene's object hierarchy. I can probably do it manually but I'm wondering if there's a better way.
I think you just have to get those by reference since they don't exist in the scene to GameObject.Find
search shows GG_Challenge_Door (4)/Door/Unlocked Set/Inspect, Challenge UI fsm -> Open UI state -> first GameObject param to get a ref to that
maybe there's an easier way but that's usually what I do
Well, when I'm in the scene I can access it via Resources.FindObjectsOfTypeAll<GameObject>() but it seems that the current preload method just checks the objects within the scene, so I'd have to preload the scene myself to do it this way. I'll see about getting it by reference as you said.
I've asked this question a thousand times and yet I never remember the answer but
What do I do if the player isn't taking input until I go to the pause menu once
I've tried RegainControl
What changes when the player unpauses
Preload the object the fsm is on and get it from the fsm
Yeah, that works - better than what I was going to do otherwise anyway, hah
is there a way to get your public ip address in c#? I've just been creating a web request to a site that gives it to you and parsed the response
that is the way
checkip.dyndns.org or something
Every other thing seems far more inconvenient
https://www.ipify.org/ exists and can output both IPv4 and IPv6 (optionally in json if you really want)
ipify API is a simple public IP address API, easy enough to integrate into any application in seconds.
that's nice
I love unknown crashes too, since for some reason doing a foreach with all the doors on a map in among us to close all of them decides to crash
oom
I figured, could profiling hollow_knight.exe with rider find anything?
no idea
according to 2 unknowing people on the unity forums from 2018, that may be the place where hk needs more than ~3.5 GB of memory
what happened there
hollow knight tilt controls
but the I is capitalized
wtf it still spawned left
Hirungolwe L Saleh L
which fsm is that even?
Dream Entry-Control
hk but your big brother gave you the controller but won't let you sit in his gamer chair
try setting it to true
possible
In my Start function on Load Scene I am running the following code:
try
{
On.SceneManager.Start += OnSceneManagerStart;
}
catch(Exception e)
{
Modding.Logger.Log("--------------------------------");
Modding.Logger.Log("EXCEPTION::::: " + e);
}
prints: [INFO]:--------------------------------
[INFO]:EXCEPTION::::: System.InvalidCastException: Cannot cast from source type to destination type.
Appears to be an issue with version 1.4.3.2-58
a friend has version 1.4.3.2-57 and it runs fine on there side.
where can i grab the modding api versions to test myself? And does anyone know if anything has changes on the scenemanager start hook?
any stack trace
56, have fun with code from the sanctuary
incredibly interesting
wtf I've tried everything and the idiot still spawns on the left side
he's signing an nda
lmao
so facing right?
facing left
hm
does .faceright not make the knight face right?
i just instantiated wp03's dreamenter, which spawn you facing right
I'm instantiating WD's which also should just face you right
don't worry, 56 finds a way to shit on your entire codebase
i mean if you'd like
do you have a level id for wd?
don't want to open unity rn
nvm
but you do have a door transitionpoint in the scene, right?
with roughly these values?
it's the same one the scene uses I think
does your transitionpoint have alwaysEnterLeft set?
maybe, I'll have to check
good thinking
you were right :)
thank you
I forgot this was the scene where mebi forgot to not delete the door1 so I made my own
wait what ?
will you have my wifes kids ?
π€
π₯΄
Maybe a stupid question but why doesn't Ruins1_30 appear in the scene list in the FSM viewer?
Oh wait it is a stupid question, it's there but in the wrong order lmao
Don't mind me
can https://github.com/Ayugradow/ModInstaller/pull/48 be merged?
done
thanks!
api
updated
fixed
etc
Was this update specifically to fix whatever was causing DecoMaster and HollowTwitch to not work? Can I finally delete my macro that posts a link to Zaliant's upload of -57?
Also, is there a place to see changelogs of moddingAPI? I feel like there's a few mods like that that seem to update, but with no mention of what changed, and their github pages don't seem to be up-to-date. (The other that comes to mind is QoL)
well, it does still not work with decomaster, but we know what causes it at least, but that change would give audio fragments, similar to how it was before preloading was muted
just tested it btw
ah
we know what causes it
well, to put it in better words, we know how it will load, still no idea why it crashes in detail as that doesn't make sense, but a prototype solution is there
public void PlayMusic(AudioClip clip, float vol = 0f)
{
MusicCue musicCue = ScriptableObject.CreateInstance<MusicCue>();
List<MusicCue.MusicChannelInfo> channelInfos = new List<MusicCue.MusicChannelInfo>();
MusicCue.MusicChannelInfo channelInfo = new MusicCue.MusicChannelInfo();
channelInfo.SetAttr("clip", clip);
channelInfos.Add(channelInfo);
musicCue.SetAttr("channelInfos", channelInfos.ToArray());
GameManager.instance.AudioManager.ApplyMusicCue(musicCue, 0, 0, false);
}
any reason why this wont play my music in the custom scene
other sounds work
channelinfos has to be MusicCue.MusicChannelInfo[6], all 6 indizes are needed (null values possible)
hmm I didnt need to do this before
so do I just set the first index and leave the rest null?
that's not important
this is weird, the godhome custom scenes worked just fine
can you log what Log($"Snapshot: {musicCue.Snapshot}") logs as a string?
just out of curiosity, which scene do you call that method in?
because i think whatever area the method is getting called in, has a audiomixersnapshot loaded which doesn't play the main track
and GameManager.instance.AudioManager.ApplyMusicCue for some reason does the same as your volume parameter for the applySnapshot parameter, so your easiest solution is to copy the contents of MusicRegion.FadeIn() (important parts marked)
btw, you get the audiomixersnapshot with the simple line of
var yoursnapshot = Resources.FindObjectsOfTypeAll<AudioMixer>().First(x => x.name == "Music").FindSnapshot("Main Only");
@ornate rivet
that makes sense
Quick, what's the easiest way to rewire a boss's FSM to only use one attack?
in the state that makes decisions, manipulate the decision making
e.g.
var hkGO = to.Find("Hive Knight");
var hkFsm = hkGO.LocateMyFSM("Control");
var hkFsmVars = hkFsm.FsmVariables;
var srev3_1 = hkFsm.GetAction<SendRandomEventV3>("Phase 1", 1);
srev3_1.events = new FsmEvent[] { FsmEvent.FindEvent("JUMP") };
srev3_1.weights = new FsmFloat[] { 1.0f };
srev3_1.trackingInts = new FsmInt[] { hkFsmVars.FindFsmInt("Ct Jump") };
srev3_1.eventMax = new FsmInt[] { int.MaxValue };
srev3_1.trackingIntsMissed = new FsmInt[] { hkFsmVars.FindFsmInt("Ms Jump") };
srev3_1.missedMax = new FsmInt[] { 4 };
var srev3_2 = hkFsm.GetAction<SendRandomEventV3>("Phase 2", 2);
srev3_2.events = new FsmEvent[] { FsmEvent.FindEvent("JUMP") };
srev3_2.weights = new FsmFloat[] { 1.0f };
srev3_2.trackingInts = new FsmInt[] { hkFsmVars.FindFsmInt("Ct Jump") };
srev3_2.eventMax = new FsmInt[] { int.MaxValue };
srev3_2.trackingIntsMissed = new FsmInt[] { hkFsmVars.FindFsmInt("Ms Jump") };
srev3_2.missedMax = new FsmInt[] { 4 };
var srev3_3 = hkFsm.GetAction<SendRandomEventV3>("Phase 3", 1);
srev3_3.events = new FsmEvent[] { FsmEvent.FindEvent("JUMP") };
srev3_3.weights = new FsmFloat[] { 1.0f };
srev3_3.trackingInts = new FsmInt[] { hkFsmVars.FindFsmInt("Ct Jump") };
srev3_3.eventMax = new FsmInt[] { int.MaxValue };
srev3_3.trackingIntsMissed = new FsmInt[] { hkFsmVars.FindFsmInt("Ms Jump") };
srev3_3.missedMax = new FsmInt[] { 4 };
for hive jump knight
Ah, thanks
And then just plug in whatever I feel like
Thanks
Aight I'll need to continue tomorrow I guess
Didn't get to try this out yet
Thanks though
is there anything else I need to do to create a pool of any gameobject besides .CreatePool()?
when I spawn a pooled object I get this stack trace, even when I add an ActiveRecycler component to it:
System.NullReferenceException:
[INFO]: at (wrapper managed-to-native) UnityEngine.GameObject:GetComponentFastPath (System.Type,intptr)
[INFO]: at UnityEngine.GameObject.GetComponent[ActiveRecycler] () [0x00000] in <filename unknown>:0
[INFO]: at ObjectPool.orig_Spawn (UnityEngine.GameObject prefab, UnityEngine.Transform parent, Vector3 position, Quaternion rotation) [0x00000] in <filename unknown>:0
[INFO]: at ObjectPool.Spawn (UnityEngine.GameObject prefab, UnityEngine.Transform parent, Vector3 position, Quaternion rotation) [0x00000] in <filename unknown>:0
[INFO]: at ObjectPoolExtensions.Spawn (UnityEngine.GameObject prefab, Vector3 position) [0x00000] in <filename unknown>:0
ObjectPool.CreatePool(gameobject, 1); doesn't work?
oh, .CreatePool() is an extension, idk if it's because that, may be worth testing
mhm, shouldn't nullreference
same issue with regular ObjectPool.Spawn()
one workaround i could see is to copy all fields of an existing ActiveRecycler to the custom one
and if that doesn't help i'm completely out of ideas
hey folks, can anyone here help me figure out FSM viewer? (thanks grenade)
for the geo rock--what does final payout here mean?
see where its read, one of the states will have an intcompare
or some other action that reads an int
ah... i don't know what this means
when you click on the boxes, and you have state selected instead of variables
it'll list what that box does
one of them will do something with final payout
Dumb question, how do I replace the Unknown in "MyMod: UKNOWN" where mods are displayed in the menu screen
override GetVersion
Thanks!
Geo per hit * hits + final payout
i.e. the amount that drops when it destroys itself?
Names of the fsm variables, but yes
So I've been trying to write some code relating to FSM's, but I keep running into the issue of "PlaymakerFSM" could not be found, even though I have referenced ModCommon.dll, and used Using ModCommon.Util
Is there anything simple I'm missing?
reference PlayMaker.dll which is next to the other unity dlls from the game
Yes, thank you so much!
https://github.com/Ayugradow/ModInstaller/pull/49 that's what i get for putting a .dll link in the modlinks
thanks grenade!
Np
I'm returning from a custom scene and want to do the whole lying down animation so I was using the knight's "Dream Return" fsm, the animation plays just fine but the knight can be moved around even while they are lying down.
The fsm does go through a state that does relinquishctrl so idk why
If I have a mod that uses vasi that's gpl3 and distribute the dll to a few friends, does that mean i have to make the source public and gpl3 as well?
(depending on what you need from vasi, you could just use modcommon, which is MIT)
you're supposed to distribute the source w/ the dll
i can change that tbh
i don't care
mpl is better for a lib
oops
i still do not care do what you want
and muh modcommon bloat
modcommon's fsmutil is like 80 versions behind but it's a breaking change so i won't touch it
rip I still use it
that's the thing with fsm.GetAction<T>(...), right?
yeah
then i also use that
lmao
if u read the .net docs ur lame
neat
as π₯Ά
or do you want the old c style cast?
according to https://stackoverflow.com/a/4926702 i'm going to change that to old c style casts
i'm not that much into code conventions: with a cast, is a space between the bracket and the orig value after ok? vs removes that automatically so i'm unsure
same
i made vasi mplv2 now btw
noice
making it part of sfcore, just so i don't have to copy the file into every mod
another version frogchamp
nah, gonna pump every util i ever used in my mods in it before opening yet another pr
Why are they called Cores?
no i mean another fork of fsmutil
oh
oh right, there was a bit of fsmutil in the api, right?
hm, i thought i saw something like that
no
but then i can also have stuff like gameobject.FindGameObjectInChildren("name")
stole the naming scheme from other hk mods (like the predecesor of serecore) and several minecraft mods which also ended in "core"
core because it's a core mod, important for other mods
imagine calling anything descriptive
if i made a utility mod for my code, i'd probably call it code.dll 
best name tbh
mod: mod.dll
core mod: core.dll
other mod: code.dll
other core mod: helper.dll
and every last piece of content in those is obfuscated to hell and back
what happens if two mods share the same name
apparently i don't even need to obfuscate, canvasutil is black magic according to some 
if the name before : Mod is the same
file name: impossible, windows/modinstaller will overwrite the first one with the second
namespace: works fine as long as classname is different
namespace & class name: typename error i think
canvasutil has been pretty useful
would be better if you could set fadein and fadeout speed to match that of qol but you couldn't have known that it would've existed ahead of time 
Is the rando logic documented somewhere? I know it's in the mod repo in XML, I was just looking for any sort of primer to help me understand any semantics there. Is my only course of action to look at the code and semi-reverse-engineer it?
What do you mean? I don't think it's documented anywhere, but if you've seen https://github.com/homothetyhk/HollowKnight.RandomizerMod/tree/master/RandomizerMod3.0/Resources then it's fairly self explanatory (item rando uses macros.xml, waypoints.xml and items.xml; area rando also uses areas.xml for area transitions; room rando uses macros.xml, rooms.xml for transitions and items.xml)
I disagree on "it's fairly self-explanatory". I can grok a lot of it by looking at it but the actual meaning of the elements isn't noted anywhere. I know the code deserializes the XML and I could try to use that as context, that's what I mean by 'semi-reverse-engineer'. For example: what does the action element mean here? https://github.com/homothetyhk/HollowKnight.RandomizerMod/blob/master/RandomizerMod3.0/Resources/items.xml#L11
What about areaLogic vs. itemLogic? Why are they the same, what could they mean?
I'm not asking for direct answers to my questions, just wondering if there's some place in which they have already been answered that I can refer to. Otherwise I'll just put in the time and effort to figure it out, I don't want to bother someone to hold my hand. π
Oh I see. I mean I assumed you were just talking about the logic (which IMO refers to the parts which tell the randomizer where it's allowed to place items), rather than the other data. AFAIK there isn't anything documented anywhere 
area, room, and item are the different modes of randomizer, so they requires slightly different logic in some cases
especially with room rando, b/c you can be put directly into that item's room
the actual item logic is just this line
Okay, that gives me a lot of context, thanks @young walrus. It seems best bet is to spend the time looking through it all and asking questions here if it comes down to it.
this line is for crystal heart
>Upper_Crystal_Peak + (SUPERDASH | (CLAW + (DASH | WINGS | AIRSTALL)) | (WINGS + SHADESKIPS))
upper crystal peak is just a custom variable that says you can get to upper CP. similar to "right city"
a way to simplify the logic chains
so to get to CH, you need to get to upper CP. plus one of the other conditions
| means or. + means and
Got it. Is Upper_Crystal_Peak defined in another file?
That's the waypoint, so waypoints.xml
(For room rando, waypoints aren't a thing so it just uses macros in macros.xml)
In some cases you basically just have to figure out where the waypoints refer to - for instance it isn't necessarily obvious without looking at how they're used that "Upper_Basin", "Mid_Basin" and "Lower_Basin" refer to the bottom of the broken elevator, outside the lower tram and the basin toll bench respectively
Okay, that'll have me back here asking questions probably but it's good to know.
Aight, I need help finding the location of the Hive Knight's Globs
Their "location" is somewhere at the bottom of the screen, although I think it's at the right x-value
I'll send more when my pc unbluescreens itself
But basically yeah
If anyone has any ideas please tell
it's probably either somewhere in its fsm, or if it says something with spawnfromglobalpool, it can be spawned in a similar way
Wdym spawned?
I'm pretty sure it's the same three globs the whole fight, with the actual object staying offscreen somewhere
Damnit
i have no idea
it's just the same bees
if you kill them or they go off screen they deactivate until they're put at the top again
Ah, yeah, makes sense
uhh, sorry, but where can i instal gun mod, i can't find it pinned
sorryyy
https://github.com/Ayugradow/ModInstaller/pull/50 fixes SSL/TLS error on win7
So uh, how do i add enemies to my scene?
dont forget to set active and set their position to next to you lol
and sometimes you might have to edit the fsm, especially for bosses
are there hooks to when a player presses an input key/button?
or do I have to poll for them?
afaik you have to poll

but you could make your own "hook", with coroutines
You could hook the action's IsPressed property
IsPressed is the poll
that the game does, so it only gets ran when the game itself checks for an input
It's kinda the closest there is afaik if you want a hook but yeah, it's effectively the same thing
ok so i tried to preload a bench and my mod failed to initialize
is there something wrong with this? public override List<(string, string)> GetPreloadNames() { return new List<(string, string)> { ("Crossroads_47","Restbench") }; }
besides formatting lol
when a new mod is out
:modders:
thanks for reminding me to make a repo for CustomBgm
np 
I haven't played many fighting games, so I have to ask: are the number of anticipation frames for an attack in hk comparable to that of a fighting game?
i would say comparable, but faster
should ask Katie
wtf
has cyclone
yes
has cyclone
Hey, so I wanna replace the font sprites in Hollow Knight to recognize more non-English characters. Using TextMeshPro, what kind of file do I want from Unity exactly and would I get it into Hollow Knight?
To get it into hollow knight you would just assetbundle, for the actual font though idk
Well, I know what font Hollow Knight uses - Perpetua. I wanna generate a new font sprite for that would also include these characters: ΕΕ₯ΔΕ―ΕΔΔ; but I am unsure how to properly put it inside Hollow Knight. Do I want TextMeshPro to generate the whole custom .asset file and then somehow merge it with Hollow Knight?
I donβt know how fonts are stored, but if you mean replacing the gameβs files, not exactly the modern way of modding
I assume once youβve created the font or something youβd need to assetbundle the font, then replace the original font at runtime or something
If I could replace the font through the Modding API and not by replacing it original game files, that would be great. I'll use whatever I can get working.
What would be the best to way to change all of one enemies' FSMs? Like say I wanted to edit every crawlid in the game, what would be the way to go about doing it?
prob just do name contains on scene load
so I'm trying to handle generic types for writing to packets and I'm wondering if this kind of implementation is alright
public void Write<T>(T type, object value) where T : Type
{
if (type == typeof(byte))
Write((byte) value);
else if (type == typeof(byte[]))
Write((byte[]) value);
...
else if (typeof(IEnumerable).IsAssignableFrom(type))
{
Type listType = value.GetType().MakeGenericType(new[] {type});
Write(listType, ((IEnumerable) value).Cast<object>().ToList());
}
else
Log($"Writing to a packet with a value of type {type.Name} is not supported.");
}
with the last branch handling lists:
public void Write<T>(T elementType, List<object> list) where T : Type
{
foreach (object element in list)
{
Write(elementType, element);
}
}
why are you generic over T : Type and then have a T passed in
I'm not experienced
pretty sure you want just <T>(T value)
if you want type comparisons you can do typeof(T) == typeof(byte)
alright
My aim is to use reflection to get some PlayerData fields and send them over to clients
You could even do something like
switch (value)
{
case byte b:
Write(b);
// other cases...
}
which may or may not be more convenient
yeah
if you're going to reflect over fields then you want just the is or the switch
no point in the generic because it'll be just invoked with an object
why are you thinking me zaliant
so racist
oh I forgot to give a name to the var
thats why the switch didn't work
Maybe I should provide a big picture explanation of what I'm trying to do
so i've gotten the geo rock and bench into my scene. i tried to do the same with a primal aspid and it worked.... but it just sits there flying.
what gives
Would the name contains be fsm.FsmName.Contains?
nvm, i see that its more complicated than just having the one fsm
i mean like ```cs
UnityEngine.SceneManagement.SceneManager.activeSceneChanged += SceneChanged;
void SceneChanged(Scene from, Sceene to) {
foreach (var go in UnityEngien.Object.FindObjectsOfType<GameObject>()) {
if (!go.name.Contains("Crawler")) continue;
// do what you want
}
}
poll for inputs in monobehaviour attached to knight
send inputs to server, server sends them to clients
inputs are saved to a queue in a script similar to herocontroller minus singleton bs and attached to remote player object and processed there
Maybe a better question for Katie to answer
It worked. Thanks.
np
Isn't that where prediction would come in?
If you can afford to look for it
yes, it's called Hollow Point on the installer
(wrong channel too, this should be in #archived-modding-help)
oh sorry
I'm understanding a bit better what Katie meant by recreating the knight
Still a bit hazy on which parts exactly tho
hc, pd, heroanimctrler, heroaudioctrler prob, and all the fsms prob
is the rollback then based on the players fps or the fixedupdates?
idk yet
ig fixedupdate is better, as that is 60 times per second regardless of hardware (maybe lower when toaster)
so would it go something like this?
public void Write<T>(T value)
{
switch (value)
{
case byte val:
Write(val);
break;
case byte[] val:
Write(val);
break;
...
case List<T> val:
Write(val);
break;
default:
Log($"Writing to a packet with a value of type {value.GetType().Name} is not supported.");
break;
}
}
not sure if the List case is handled correctly
if i read this correctly, the list case will never happen as List<int> would be checked for the type List<List<int>>
I'm not entirely sure - I want to say no, but it's something to test. Alternatively, you could make an (IEnumerable<T> value) overload for the method and then just loop over and call the original Write for each item
Probably best for #modding-discussion.
UnityEngine.SceneManagement.SceneManager.activeSceneChanged += SceneChanged;
void SceneChanged(Scene from, Sceene to) {
foreach (var go in UnityEngien.Object.FindObjectsOfType<GameObject>()) {
if (!go.name.Contains("Crawler")) continue;
// do what you want
}
}```
How would I "assign" a gameobject var to what it selects?
Well, if the 'if' statement is false, that means the 'go' variable from the loop has a GameObject that contains the name of "Crawler". You just need to assign 'go' to a GameObject variable in your class like so.
GameObject crawler;
void SceneChanged(Scene from, Scene to) {
foreach (var go in UnityEngine.Object.FindObjectsOfType<GameObject>()) {
if (!go.name.Contains("Crawler")) continue;
crawler = go;
break;
}
}
Hey, sorry that this is rather offtopic, but this seems to be the only channel with devs around.
Does anybody have resources on how the HK autosplitter works? I know what a pointerpath is, but I'm not sure about the specifics like how an entrypoint is found.
My motivation is that I don't own a PC and have to make that stuff work on linux; this makes it a bit hard to figure things out, especially since I have no clue about unity internals and what translates from dotnet in windows to the mono implementation and what not.
I know C#, how to decompile the IL, and how to use gdb, if that helps.
livesplit doesn't exist on linux, so its basically accepted that the autosplitter won't work
autosplitter repo here: https://github.com/ShootMe/LiveSplit.HollowKnight
Are you trying to edit all of them
This is not entirely true, there are efforts to create a cross-platform lib.
Which is why I kind of want to see if I can write something on my own
I think I found the right sections in the github repo tho, it uses hex patterns, thanks Jamie
Yes. What Unordinal described worked, but only sometimes. It's wildly inconsistent. Sometimes they change, sometimes they don't. Sometimes if I use a different scene transition whether or not they change differs. Sometimes it doesn't matter. It's odd.
My code is meant to make the Crawlid bigger, give it more health, and make it faster, which I deem is enough for it to be good enough practice. Here is my code:
void SceneChanged(Scene from, Scene to)
{
foreach (var go in UnityEngine.Object.FindObjectsOfType<GameObject>())
{
if (!go.name.Contains("Crawler")) continue;
GameObject crawler = go;
//Makes the crawlid big.
crawler.transform.localScale *= 1.5f;
//Lifts the crawlid up a little so it doesn't clip.
Vector3 position = crawler.transform.position;
position.y += 1.0f;
crawler.transform.position = position;
//Gives it more health.
crawler.GetComponent<HealthManager>().hp = 40;
//Makes it faster.
PlayMakerFSM fsm = crawler.LocateMyFSM("Crawler");
fsm.GetAction<WalkLeftRight>("Walk", 1).walkSpeed = 8f;
fsm.GetAction<WalkLeftRight>("Maintain", 0).walkSpeed = 8f;
fsm.GetAction<WalkLeftRight>("Start R", 0).walkSpeed = 8f;
fsm.GetAction<WalkLeftRight>("Start L", 0).walkSpeed = 8f;
break;
}
}```
For some reason, it is only inconsistent in whether or not it changes when the FSM part is present. But it gets even weirder, (at least to me, it might make complete sense to you). It also affects whether or not it is big and has more health, even though both don't use FSM whatsoever.
Apologies for the wall.
is there a way to make custom knight textures quickere than manually editing each one
copy and paste 
yeh but their not all the same :/
The break; at the end will cause the loop to end after it's found one. You'll want to remove that line if you want all objects with the name of "Crawler" to be affected.
Then I assume the one it does is the one closest to where it loads in.
doubt that proximity would make a difference to what order FindObjectsOfType returns
the pointer paths are based on having one static reference by finding the hex and then following fields
so you have like GameManager.instance which is static and then you can get to any of the classes it has on fields by adding the offset of the field and then dereferencing
and repeat
which is the path part
If cheat engine's "mono disassembler" or whatever works on Linux then you can use that to get addresses and offsets very easily
besides that the other thing you'd need to change are the memory reading functions because they p/invoke winapi
if you have any other questions feel free to ping me
oh yeah and the entry point is based on that
There's a pdf devil has
UnityAutosplitters.pdf
Even if livesplit doesn't exist that's just the frontend of the autosplitter. The memory searching backend is the actually important part for performing the autosplitting
getting some weird values with reflection
data = new ExchangeData();
var pd = PlayerData.instance;
List<string> fieldNames = pd.GetType().GetFields().Select(fi => fi.Name).ToList();
foreach (FieldInfo fi in data.GetType().GetFields())
{
if (!fieldNames.Contains(fi.Name)) continue;
Log("FI Name: " + fi.Name);
Log("FI Value: " + Mirror.GetField<PlayerData, object>(pd, fi.Name));
//Mirror.SetField(data, fi.Name, Mirror.GetField<PlayerData, object>(pd, fi.Name));
}
ExchangeData being a non singleton ver of PlayerData
[INFO]:[Hero Tracker] FI Name: version
[INFO]:[Hero Tracker] FI Value: 1.4.3.2
[INFO]:[Hero Tracker] FI Name: playTime
[INFO]:[Hero Tracker] FI Value: PlayerData
[INFO]:[Hero Tracker] FI Name: completionPercent
[INFO]:[Hero Tracker] FI Value: PlayerData
[INFO]:[Hero Tracker] FI Name: openingCreditsPlayed
[ERROR]:[UNITY] - NullReferenceException: Object reference not set to an instance of an object
my bad, completely flooded your post
if you're looping using fieldinfos there's a function which takes those directly
the nre is weird
idk if i handle boxing
i'll look at it
Why are you using a new local variable? Just use go instead of crawler, they are the same thing
I didn't get an NRE but I did get an InvalidCastException
getting pd fields?
getting openingCreditsPlayed as an object instead of a bool
hmm from what I've read c# primitives inherit from ValueType which inherits from System.Object/object
they're structs
but structs have an implicit inheritance from valuetype
but like they aren't obj references for the most part
that's usually handled by auto-boxing
Oh and the nre might be it throwing on .ToString
i assume you want decent performance for this yeah?
yes
optimally i think this would be a source generator thing
if there's not a huge number of fields that you want to actually exchange then it'd be significantly more performant to do this by hand
I was afraid I'd have to do that
don't have to
just performance wise it's a decent difference
i wonder if there's a way to exchange generically
because the problem is the field iterations is at runtime so it can only call the getfield as an obj
Oh
I have a terrible idea
Gimme a bit
terrible ideas are nice
is it a good idea to JsonConvert pd and send that large string in a packet
I should've said exchangedata
which will only have the fields necessary to build a player
that doesn't seem terrible but i don't do servers
I planned on writing all the fields of exchangedata to a packet on their own but was having trouble generically handling collections so grenade suggested jsonconverting the class
tfw
Are you working on multiplayer?
Isn't coordinates in playerdata, unintuitively enough?
Or at least shade zone and stuff
class ExchangeData
{
int health;
int maxHealth;
int healthBlue;
int joniHealthBlue;
int nailDamage;
int nailRange;
int fireballLevel;
int quakeLevel;
int screamLevel;
};
i mean, the things with has{whatever} cann/will be set by local code and just the animations get synced
coords in playerdata?
Maybe it was changed from 1221 to 1432, but I swear I saw a ton of stuff in pd that made no sense to be in there but there it was π₯΄
Could be wrong on player coords tho lol
only postitions in playerdata are
- Shade position on the map
- Dreamgate postition on the map
- Positions of the customizable map pins
which are also the same fields that json.net can't read and displays as (0, 0, 0)
newtonsoft can't read vector3s?
LUL amazing
no, only with custom jsonconverters, but for all unity types that would be another thing bundled in the api
guess I'm removing any vec3s from exchangedata
I'm still gonna need many of the fields from pd if I'm gonna be simulating a copy of the knight entirely
what is marm
there's a marmConvoNailSmith bool
50k clones
first one is copy-paste second one is dynamic
might throw it in vasi
lemm says something about the nailsmith and stores in that if lemm already said that
would be the language string RELICDEALER_NAILSMITH
56, i heard you like bundling more assemblies into the modding api, so if you have nothing better to do, this may be worth a look: https://github.com/jilleJr/Newtonsoft.Json-for-Unity.Converters
π€
wtf
Don't think me
I'm right it's fucking 15mb
And you can't even search the modded version because of merging hooks in
modding api
hm i think i'll look if i can "get inspired" to just do vector3 converters
it's mit just rob it
you dont need to send max hp or jonis max hp, or both jonis and current hp
just how much hp they have right now
you also don't need 3 ints for fireball level, quake level, scream level
either use 6 bools or 1 short
i guess a short you could do 1 bit for mark of pride, longnail, vs, ss, scream, shreik, ddive, ddark
which does 4 of those ints in one quarter the space
so jsonconvert bad?
json is not particularly efficient
if you know the bit format of the packet you don't need identifiers
and you also don't need 128 bits to send 8 bits of data
not including the string to id it
which would be like another 1000bits just for that struct
guess I'll have to crunch through bit shifting
you can make an array of bytes
[ERROR]:[API] - Failed to read save using Json.NET (GameManager::LoadGame), falling back.
[ERROR]:[API] - System.InvalidCastException: Failed to read type 'Vector3'. Expected object start, got 'StartArray' <>
[ERROR]:[API] - at Modding.JsonConverters.PartialConverter`2[UnityEngine.Vector3,System.Single].InternalReadJson (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.JsonSerializer serializer, Boolean isNullableStruct) [0x00000] in <filename unknown>:0
good thing to test it before
and make a function like
public byte makebyte( bool[] b ){
byte out = 0 ;
for(int i = 0; i < 8; i++){
out += b[i] * (1 << i-1);
}
return out;
}
why did i type that as bit 
and to get them out you do something like
public bool[] getbits( byte b ){
bool[] out = new bool[8];
for( int i = 0; i < 8; i++){
out[i] = b & ((1 << i-1)) != 0
}
return out;
}
i guess you could use bit shifts to do the multiply in the other function too
probably faster
also you wouldnt send a full vector3 anyway
as the knights depth is known by the local player
so you only need to send x and y position
fortunately I've been doing that for spawning players
you could probably store position in one float by doing jank
and losing a slight amount of precision
by doing float pos = ypos * widthofroom + xpos
if pow 2 doesn't emit a shift I'd be shocked
this code is gonna be so indecipherable 
although you'd probably need some extra data for that to work
at which point its probably worth just doing it as halfs
which pd fields should we keep?
if we're going to be simulating all remote players i wrote the controller attached to them to be more or less the same as herocontroller
and each player is a clone of Knight minus herocontroller, heroanimationcontroller, heroaudiocontroller, converyormovementhero, all fsms, and vignette
Bleh, I've just learned that in Unity you should use == when checking for null and not is. There's a bit of time down the drain, hah.
I guess I should make use of the implicit conversion to bool after all
Yeah, I almost regret using nullability features in this now - fun times
I forgot what it was like to write C# without ?? and ?.
fuck newtonsoft, gives me "Integer": "0"
and if i try to (int) reader.Value, i get a fucking System.InvalidCastException: Cannot cast from source type to destination type
any int.Parse
my bad for the presentation of it, but it's a simple int as an object, i just logged it with " around
Convert.ToInt32
Tclass ret = ReadJson(token, (Tclass) existingValue);
how is this a NullReferenceException?
existingValue is passed in as what
gg
and if it wasn't already obious, i made the custom converter myself, as all others either wanted values as a list (???) or didn't want to accept vector3s in a list
i guess i also make the change back with the point of loading mods, so that decomaster, hollowtwitch and maybe a few others work again
oh fuck, i also have to test saving
works pog
now only to add the other 50 types of unity
i mean are the other 50 even used in pd
not in pd, but i think i'll help others a bit if i also include stuff like vector2
Cloth component serialization pog
isn't that already serializable because it's a component?
you really want the cloth component?
cloth should work with just a converter for vector3's added
got the Microsoft.Unity.Analyzers but it apparently doesn't check for 'is null' and 'is not null' so I guess I'm stuck manually find and replacing
just regex
π it π just π works π
https://github.com/fifty-six/HollowKnight.Modding/pull/12 a few tiny changes
do you even need the patch for StartManager
or was that to avoid the like 8 year cutscene at the start
it was to avoid the 8 year cutscene
good ol git blame
merged
poggers
why
... i may or may not have not added the docstring things
was the private set supposed to be there
for the converter types
because it is a dead setter
what happens at out += b[i] * (1 << i-1)?
set the bit based on bool value
if you have b[i] as true (i.e. 1) then you put a 1 in the spot
multiplication would be convenient because 0 would cancel it out
doesn't work as well in c# where you can't cast bools to ints
the 1 << (i - 1) puts the 1 i-1 bits into the byte

oh it was just pseudocode
i'd just do @out += b[i] ? (1 << (i - 1)) : 0;
i mean it'd work in like c
i gotta say return 0 instead of throwing really is not the play
yeah that's true
shouldn't it be << i
public static byte MakeByte(bool[] b)
{
int bLength = b.Length;
if (bLength >= 8) throw new Exception($"Cannot create a byte from a bool array of length {bLength}");
byte @out = 0;
for (int i = 0; i < 8; i++)
{
@out += (byte) (b[i] ? (1 << i) : 0);
}
return @out;
}
public static bool[] GetBits(byte b)
{
var @out = new bool[8];
for (int i = 0; i < 8; i++)
{
@out[i] = (b & (1 << i)) != 0;
}
return @out;
}
this look like it'd work?
yeah
do like invalidoperationexception though
could skip the cast if you iterate with a byte instead of an int
dunno if that actually changes the assembly
idts
guess I should handle other data types too
no idea how im gonna handle things like naildamage which players might have set to 999 through debug
either only account for the vanilla range or use what's availablefrom the 32bit integer (so 31 bits), but i guess only allowing 12 bits is enough, as one could get 4095 naildamage with that
You could use something like LEB128 if you really wanted
probably not worth the effort
actually I might have an implementation of it somewhere here if that's something you're interested in, gimmie a sec
it's been unit tested but you'd have to replace the Spans with regular arrays for .NET 3.5 https://gist.github.com/Unordinal/50480145fc1b9fe64d277e72c3b383ef
Usage is just LEB128.GetBytes(integer) to convert to bytes and LEB128.GetSigned(bytes) or LEB128.GetUnsigned(bytes) to convert back
the noise thing is because you re-added the loading of menu_title but that's done in the modloader
so it double loads
oh ufkc
wait no
it's not even supposed to load menu in the modloader
that was moved in during the first move
suffering
imma keep my thing, i just looked at https://github.com/fifty-six/HollowKnight.Modding/commit/cfc33db275611be1bf7f5d99831a9760ff78f9ec to see how it worked, must've have missed another change
poggers
this is not it
it's not supposed to look like that, right?
yeah
though i quite like the double or triple text the first few lines
@vocal spire uuwuu failed to load:
[ERROR]:[API] - Error: System.MissingMethodException: Method not found: 'FrogCore.JournalHelper.AddJournalEntry'.
[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
meanwhile i didn't get much over 4 GB
i just need to utterly hug ram, can't be that hard
hmmm
load some among us mods
oh wait nvm
forgot that the initialize is completely different
i be dumb
i think i'll settle for a GB of ints

memoryHugger = new int[268435456];

gigabyte of bytes?
no, a GB of int values
k
YES
cool
I'm currently trying to take a screenshot at runtime(very fun)
except in code
it's working out and not working out
6.1 GB poggers
ok but I bet most hk players have 8 gb ram max
also requires some rather unique methods
4 GB over 4 arrays is fine, but 4 GB in a single array is too much
[ERROR]:[API] - Error: System.OutOfMemoryException: Out of memory
makes sense
seems to work fine as long as the memory used per array is <=2GB
oh my god, pressgtodab criples my fps from 900 to 300
tf
will probably also break if one save&quits
all it does is add an anim to the knight's anim library and poll for key down G
nah, before the knight is loaded it checks every frame if the instance isn't null anymore, which utterly breaks on save&quit as the knight GO gets destroyed

but i can change that if you'd like
If you're updating Press G to Dab, then possibly add a config file to change the key?
Granted, I'm unsure how tedious that is.
i have no idea how i'd do that, but i'll look
will probably steal code from debugmod
putting effort into a shitpost mod
Oh my god
I had crystal blobbles, gatling aspid and g to dab this whole time...
Thats cursed
At a basic level, I'd assume you could just read a single line of a text file. The config could literally just be that one line.
And then make the line be whatever the constant is for the input. (I'm unsure how is used in the code, but requiring it to be the constant/input-name seems like it'd remove all of the tedium)
It's of upmost importance 
Canβt you just have the KeyCode enum with an string enum converter or whatever?
or one could save it like debug does, as a simple int
Yeah
crystalobbles should also be rather easy to make it not eat frames, with gatling aspid i'm not sure
holy shit is gatlingaspid bad good, every scene change the gamemanager gets another component
nvm, not another component, but another coroutine that basically doesn't stop

should be fine (no infinite coroutines anymore, just a hook On.PlayMakerFsm.Start)
pog
also
phase 2
correct
So I joined after godmaster and haven't experienced an update, will this require an api update?
will we wait for it to come out of beta?
its still in beta tho
wish there was a complete list of fixes
best case scenario we dont need to update our mods either right
probably
this answer does not fill me with confidence but it is understandable
netstandard
iflj
if it's a new version of dot net, would that also mean they are using a newer version of Unity too?
2020.2.2.33144
woah
oh dang
WOAH
that may brick mods that use asset bundling
π¦PALE COURT IS CANCELLED π¦
ok buddy
π¦
any reason for the name change
maybe because hk got updated
because someone said hk is shit
sigh
I wonder if the shader bug in assetbundling is fixed in unity 2020
probably right?
shader bug?
People will not uppatch if they can't get pale court
the one where we have to manually set the material's shader in game
I think I ran into that once where the default sprite shader was showing up as a missing shader in-game. I think i fixed it by removing it from the "Always Included Shaders" list
ah
can't wait to subtly roast tc with all my bug reports



