#archived-modding-development

1 messages · Page 514 of 1

stone elm
#

Well, yes it will. That's what it says it'll do.

#

It just isn't clear, from what you're saying, what you're trying to do.

dark wigeon
#

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

cedar hemlock
#

i just want 1 of the items to change from true to false without touching the first 3rd or 4th one

stone elm
#

During initialization or after? That's the part that's confusing here, bub.

dark wigeon
#
public List<bool> gotCharms = new List<bool>() { true, true, true, true };
//later
gotCharms[1] = false;

no?

stone elm
#

If during, do what I said. If after, do what nes said.

cedar hemlock
dark wigeon
#

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 };
dark wigeon
stone elm
#

You don't need bool in there. Just a statement like gotCharms[1] = false.

cedar hemlock
#

gotCharms doesn't exist (in current context)

#

i did

public List<bool> gotCharms = new List<bool>() { true, true, true, true };
...
//later
gotCharms[1] = false
dark wigeon
#

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

cedar hemlock
#
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 :(

vocal spire
#

settings.gotCharms

cedar hemlock
#

thx

#

i'll look at it

stone elm
#

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.

cedar hemlock
#

so, Settings.gotCharms[1] = false;?

stone elm
#

^ yes

cedar hemlock
#

it seems to work

vocal spire
stone elm
#

Well okie-dokie then ¯_(ツ)_/¯

jolly oriole
cedar hemlock
#

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

jolly oriole
#

in theory yes, but it will break once you save+exit 100%

deep wave
#

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

jolly oriole
#

no

cedar hemlock
#

but still i should not have it at the start of a save right?

jolly oriole
#

depends on how the flag is initialized

deep wave
#

if you have loaded any other save with uumuu killed on that game launch then it will definitely still be true

jolly oriole
#

but if you are a normal human being, yes, it should not have it at the start

deep wave
#

don't store stuff like that in fields in the mod, use SaveSettings

cedar hemlock
#

but why do i have it at the start of a new save?

deep wave
#

idk, how are you initialising the flag

cedar hemlock
#
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
jolly oriole
#

the only thing missing is the declaration of uuwuugone

#

because the charm stuff probably works

cedar hemlock
#
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

deep wave
#

why does it look like CharmHelperExample closes immediately after you declare uuwuugone

cedar hemlock
#

it may not be very efficient

cedar hemlock
#

but it may not be smart to send the whole class here

#

if you want i ofc can

jolly oriole
#

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

deep wave
#

this

#

don't read the bool on every frame, just see when the bool is set and set yours at that point

cedar hemlock
#

but will my version break the gotCharm or smth?

deep wave
#

not sure but you may also have to hook game load? don't think loading the game triggers setplayerbool

jolly oriole
#

holy shit i was pepega with the setbool thing, doesn't return anything

jolly oriole
deep wave
#

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)
  }
}
steady comet
#

SetBoolInternal?

deep wave
#

yeah that one

#

im not reading docs im just vibing rn

steady comet
#

I can't remember if the docs are wrong

deep wave
#

whichever one of those is in Modding zote

cedar hemlock
#

i just wanna know, what part of my code breaks it (so i know what i did wrong)

jolly oriole
#

yes

cedar hemlock
#

so, no idea?

deep wave
#

i mean i don't know your code

#

you can add more logging and see exactly where it breaks

floral furnace
#

if the script just stops working its probably throwing an exception

light zodiac
jolly oriole
#

it does work it's just useless

copper nacelle
#

uh huh

deep wave
#

i mean init is called immediately after the field is initialised with value false zote

copper nacelle
#

these is a large difference between the statements "called after field initialization" and "if statements don't work"

deep wave
#

i agree

vocal spire
#

I wanted to point that out but thought someone else had them fix it

jolly jungle
#

What type are fsm variables?

#

Not their values

#

The variables themselves

#

As in, what would be the type of the thing marked here

jolly oriole
#

FsmFloat i think

deep wave
jolly jungle
#

Thanks, both of you

steady comet
#

Why are there so many acid detectors in the collector's room? (Ruins2_11)

jolly oriole
jolly jungle
#

w
why

copper nacelle
#

to detect acid

jolly oriole
#

i don't even know if they are used, haven't checked that

jolly oriole
steady comet
#

Hmm, maybe they just copied and pasted from jars in rooms with acid? It's still kinda funny

jolly jungle
jolly oriole
nimble lake
astral hull
#

slightly off topic but how does someone start getting into modding a game from scratch

#

like how did hollow knight mods start out

cedar hemlock
astral hull
#

ty

cedar hemlock
#
[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
deep wave
#

an nre

copper nacelle
#

a null reference

#

so true jamie

deep wave
#

ikr we're so helpful

jolly oriole
#

buttons crashed

cedar hemlock
#

it says something about button but i have nothing in my mod that has to do with a button

jolly oriole
#

maybe you crashed initialize so hard that other stuff crashed

cedar hemlock
#

it happens when i open inv, and i try to go up to the charms that are equiped

jolly oriole
#

or the set/getbool stuff

deep wave
cedar hemlock
deep wave
#

could be that whatever you're doing on charm update is crashing or something

cedar hemlock
#

i can see if it still does it when i remove the charm part

jolly oriole
deep wave
#

that sounds confident

cedar hemlock
#

lol

#

i forgot a _

#

lets try again

#

ok it works, thx!

vocal spire
jolly oriole
#

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)

jolly oriole
#

this should not have worked (testing changes for the 1.5 mapi)

vocal spire
#

Nice

#

“Severely break the entire game”

primal latch
#

@jolly oriole @copper nacelle just wondering: how severely will 1.5 break mods?

copper nacelle
#

depends on what you mean by break

primal latch
#

Will most mods still work or will they all have to be updated?

deep wave
#

i assume all mods will need to be recompiled targeting 4.7.2 at the very least?

jolly oriole
#

4.0

copper nacelle
#

should be doing netstandard

jolly oriole
#

oh yea, netstandard 2 was it sadly

copper nacelle
#

mfw sadly

jolly oriole
#

4.x would've been way better

copper nacelle
#

what

#

this is untrue

#

net standard is newer and more standardized

jolly oriole
#

but i wouldn't have had to make a custom json.net

#

or does the netstandard one work?

copper nacelle
#

the issue is unrelated to net standard itself, just a unity change

jolly oriole
copper nacelle
#

i have an unpushed change already

copper nacelle
#

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

jolly oriole
#

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

copper nacelle
#

idk ask serena

#

probably some good reaosn

#

i think you can specify assembly load order in the attribute but i might be remembering wrong

#

This is what you can load with Resources.Load

#

there's some shaders and materials

#

not much else

#

some language data ig

copper nacelle
#

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

copper nacelle
#

*FindObjectsOfTypeAll

jolly oriole
#

then yes

#

returns everything that is loaded according to the docs

copper nacelle
#

chad

jolly oriole
#

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*

jolly oriole
#

i think it's possible to resolve assemblies into a loadorder

jolly oriole
#

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("");
}
stone elm
#

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

jolly oriole
#

the modding api already loads assemblies manually

stone elm
#

Correct, but that isn't the same as a full load-order control for all assemblies.

#

Dependencies get auto-loaded, down the tree

jolly oriole
#

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.

stone elm
#

Yeah, you can mess with type resolution a little more easily

copper nacelle
#

i changed my mind don't do standard

#

it is a pain and if you use 2.1 it breaks

jolly oriole
#

so framework 472?

#

or 4.0?

stone elm
#

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

copper nacelle
#

yeah 472

fickle sparrow
copper nacelle
jolly oriole
#

of course not

copper nacelle
#

it's for il2cpp so it shouldn't depend on enit

jolly oriole
#

it's a unity package

copper nacelle
#

ok and

jolly oriole
#

it's not directly a dll i can download and infect my pc with

copper nacelle
#

fair

#

I just install and take the dll out

jolly oriole
#

are unitypackages for specific unity versions or can i just plonk it in any version?

#

apparently it just works

copper nacelle
#

nice

#

It comes with unity converters too

jolly oriole
#

nvm i think i downloaded the wrong thing

#

where should i find the newtonsoft dll then?

#

maybe doesn't work with unity 2017

copper nacelle
#

I'll try it in a bit

jolly oriole
#

yep, apparently requires unity 2018+? testing with 2020

#

... after it decides to finally start

#

works with 2020

vocal spire
#

Nice

copper nacelle
#

Sick

vocal spire
#

ModdingApi using this now?

jolly oriole
#

not yet

torn birch
#

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

vocal spire
#

Is there a class inheriting the mod class(or a abstract class inheriting the mod class)

fallen elk
#

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

jolly oriole
copper nacelle
#

I reverted it idk if I pushed

fickle sparrow
#

yeah master is still on 2.1

copper nacelle
#

suicide

fickle sparrow
jolly oriole
fickle sparrow
#

have you considered using netstandard2.1 and simply not miscompiling split

copper nacelle
#

I pushed

jolly oriole
#

just saw 👍

vocal spire
#

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

vocal spire
copper nacelle
#

thoughts on sha256 for 1.5

ornate rivet
#

sounds like a good idea

jolly oriole
#

sounds good, gives me even more time to make my shit available on 1.5

vocal spire
jolly oriole
#

probably to replace the sha1

vocal spire
#

where is sha1 used?

#

Haven’t explored that part of the api much(?)

jolly oriole
#

the modinstaller

fallen elk
#

Is there any way to detect a parry?

copper nacelle
#

HeroController::NailParry

fallen elk
#

Awesome thanks

#

What is that btw?

#

Is that a function?

#

i'm just starting out

copper nacelle
#

yeah

primal latch
#

How would I go about replacing the sprites for the circled items?

vocal spire
#

(Solved)

silent marsh
#

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)

deep wave
#

you can put misc dlls in the mods folder

#

or use ILmerge to merge them into your mod's dll if you wish

silent marsh
#

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

stone elm
#

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

silent marsh
#

I mean, isn't it nicer to have a single DLL to install ? What's the problem with this tool ?

deep wave
silent marsh
#

Oh ok thanks

deep wave
#

its just a frustratingly long string at the top of the screen maggotPrime

stone elm
silent marsh
#

Makes sense, thanks 🙂

stone elm
#

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)

silent marsh
#

Hmm ok I see

silent marsh
stone elm
#

What dll does your mod rely on?

silent marsh
#

Wait I might be dumb

stone elm
#

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?

silent marsh
#

Yes I have a few things usually (Custom Knight, Grass mod, some tests of mine, etc.)

deep wave
#

maybe check modlog.txt in case its just modconsole that's crashed?

silent marsh
stone elm
#

Check your unity logs then, there might be an exception in there that doesn't appear in the modlogs

copper nacelle
#

there's nothing in modlog?

#

it's usually a type load exception

stone elm
#

Considering the razer sdk has native dlls, it could be possible unity shat the bed somehow.

silent marsh
# copper nacelle there's nothing in modlog?

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
cedar hemlock
#

You ever isntalled DRPC? 👀

silent marsh
#

What is this thing ?

cedar hemlock
#

Oh just a mod that breaks everything

#

If you never installed it then thats not the problem

silent marsh
silent marsh
stone elm
#

It is output_log

#

You could post it and others can take a look, I suppose.

silent marsh
#

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()
stone elm
#

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

silent marsh
#

Regarding the bitness of the system it should be right if the DLL works with Razer's C# sample app ?

stone elm
#

idk, I don't integrate native dlls ¯_(ツ)_/¯

silent marsh
#

Wise choice

stone elm
#

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

silent marsh
#

Well anyway thanks a lot for your help and your quick answers everyone

primal latch
#

But how did you know?

cedar hemlock
#

Guess or recent stream

primal latch
#

Yeah. I just realised that the name of the cloak was in the shot

cedar hemlock
#

The name of ddark

primal latch
#

Ah. Yeah.

jolly jungle
#

Yep :)

#

And I remembered you were looking for translators for the mod

silent marsh
#

(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)

jolly oriole
#

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

silent marsh
#

Yes it should be doable somehow, I'll look into that, thanks

stone elm
#

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

silent marsh
#

Well yeah but as we saw that crashes Unity

stone elm
#

I'd advise against permanently editing a user's PATH unless otherwise specifically noted.

stone elm
silent marsh
#

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)

stone elm
#

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

silent marsh
#

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)

stone elm
#

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 hivetired

cedar hemlock
#

Dont download it

silent marsh
#

No problem, thanks for all your help. I'll look into temporarily modifying the PATH, that may simply be easier

cedar hemlock
silent marsh
#

Well, seems like

Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";hollow_knight_Data\\Managed\\Mods\\MyCoolMod");

simply works

Almost too easy

stone elm
#

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

silent marsh
#

Well I don't see it in my PATH after closing the game so I'd say that it is temporary

silent marsh
stone elm
#

Is that your user PATH or machine PATH? Did you check both?

stone elm
silent marsh
#

I put that as early as I could but I guess it makes more sense in Intialize, you're right

silent marsh
stone elm
#

I just checked the SetEnvironmentVariable method docs and it mentions it's for the current process.

#

So you may actually be okay there

silent marsh
#

Nice 🙂

#

Thanks 🙂

copper nacelle
#

Env variables are always process localized unless you change the defaults

#

Which I assume would be some win32 dllimport shit

silent marsh
#

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

jolly jungle
#

Can anyone explain the logistics of this?

jolly oriole
#

arrays

jolly jungle
#

I may be using the word logistics wrong

#

But yeah

#

If anyone can explain whatever this is meant to do it'll be nice

copper nacelle
#

indices correspond

jolly jungle
#

Specifically, all the "tracking" stuff

jolly oriole
#

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')

copper nacelle
#

eventMax is the max times something can happen in a row iirc?

jolly jungle
#

Ah

#

Thanks

#

So it all tracks how many times things happened/ hadn't happened in a row?

jolly oriole
#

yes

jolly jungle
#

Epic, thanks

jolly oriole
#

how can i get the type of a private struct inside a class

copper nacelle
#

getnestedtype

jolly oriole
#

nvm, i just made my own type for generic stuff

#

maybe works

vocal spire
copper nacelle
#

it's a nested type bro

vocal spire
#

Oh

copper nacelle
#

you just typeof(Outer).GetNestedType("inner", binding flags that I can't be bothered writing on mobile)

jolly oriole
#

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

stone elm
#

Sorry, what's your Q or did you figure it out?

jolly oriole
#

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));
stone elm
#

That's a mouthful

copper nacelle
#

yeah you can't cast

#

If you're on 1.5 you can use dynamic for public fields

jolly oriole
#

i mean, this works and i only need it twice per enemy spawned

stone elm
#

I suggest caching the FieldInfo objects if you're doing this often (in other words: more than once ever)

jolly oriole
#

meh

stone elm
#

Just to avoid repetitive reflection lookups... Although I think reflection has a cache in .NET I'm not sure

jolly oriole
#

the only time it could lag is with bosses that spawn enemies or the colosseum

#

otherwise it's just loading screen

copper nacelle
#

No it doesn't have a cache

#

If you don't cache your field lookups you are wrong

#

and you should feel wrong

jolly oriole
copper nacelle
#

this is a terrible sentence

#

my eyes bleed

steady comet
#

Speaking about reflection, is there any difference between

InputHandler input = ReflectionHelper.GetAttr<HeroController, InputHandler>(HeroController.instance, "inputHandler");

and

InputHandler input = GameManager.instance.inputHandler;
``` ?
stone elm
#

Where does ReflectionHelper come from?

#

I'll just look at the source to check for you

copper nacelle
#

The difference is that the former is based around emitting methods at runtime to have fast private field access

steady comet
#

Afaik it just gets the private HeroController.instance.inputHandler

copper nacelle
#

Utility wise though no

stone elm
#

Yeah, found it. I'd say yes, about the same.

steady comet
#

Is there any reason to use one over the other? (And just to check, they are the same object?)

jolly oriole
#

idk inputHandler's visibility, but if it's public there's no need for the first option

stone elm
jolly oriole
#

in this exact scenario

steady comet
jolly oriole
#

oh, missed that

copper nacelle
#

if it compiles to calling the interface stuff then it might work if you include the intrinsic

stone elm
#

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

copper nacelle
#

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

vocal spire
charred topaz
# copper nacelle because reflection emit is not supported there

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/

copper nacelle
#

Pretty sure I tried that but it was reffing mscorlib for emit stuff

#

I can give it another shot though

steady comet
#

Is the AfterTakeDamageHook sometimes not called?

copper nacelle
#

shouldn't

steady comet
#

My code:

ModHooks.Instance.AfterTakeDamageHook += DisableDamage;

private static int DisableDamage(int hazardType, int damageAmount)
{
    return 0;
}

Doesn't work on the second dunk

jolly oriole
#

that's because iframes lol

steady comet
steady comet
#

OK so it's a bug in the modding API basically?

jolly oriole
#

yes

steady comet
#

oK, thanks

jolly oriole
#

alternative, use the OnTakeDamage hook

steady comet
#

Uh

#

Is OnTakeDamage for the 1.5 mapi?

jolly oriole
#

i have no clue

steady comet
#

OK

jolly oriole
#

apparently

steady comet
#

Well it said the latest commit was Jul 2020, but VS refuses to acknowledge ModHooks.Instance.OnTakeDamage

jolly oriole
#

yea, it's not part of the 1432 mapi i think

steady comet
#

(maybe because it's internal?)

steady comet
#

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?

jolly oriole
#

teamcherry🍝

stone elm
#

Cherries in spaghetti sounds awful

steady comet
#

I see, I suppose I should have expected as much

silent marsh
#

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 ?

cedar hemlock
#

when you save?

#

theres no thing for just when you bench sadly

#

i've searched for it before

silent marsh
#

Ok thanks

copper nacelle
#

TakeDamageHook @steady comet

jolly oriole
#

is it in 1432?

copper nacelle
#

yeah

#

everything is in 1432

#

I only removed hooks

jolly oriole
#

just because it's not on the api docs lol

steady comet
copper nacelle
#

what

#

you use it instead of after take damage hook

cedar hemlock
#

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??

jolly oriole
#

looks like a keynotfoundexception

#

when a dictionary doesn't have the key you request

cedar hemlock
#

ah i found it

#

thnx for the help

steady comet
#

I think TakeDamageHook is too early

jolly oriole
#

yes

copper nacelle
#

yeah

#

I can fix it but I'm not backporting it

steady comet
#

Fair enough, the spaghetti is good enough for me if I have to use 1432

silent marsh
# cedar hemlock theres no thing for just when you bench sadly

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

fair rampart
#

yo

#

how do i get hollowpoint

copper nacelle
#

have you tried reading the channel description

fair rampart
#

my mistake

ornate rivet
#

toxic

primal latch
#

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

jolly oriole
#

who even has a exactly 512 MB assetbundle

primal latch
#

Oops. I am sorry that I pinged you.

#

I guess your name is correct

jolly oriole
#

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)

primal latch
#

I don’t think it’s the asset bundle. I moved sprites to an assetbundle to stop this from happening on some other bosses

jolly oriole
#

hm

primal latch
#

And they now work fine

#

It might be that I’m not adding compression

jolly oriole
#

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)

primal latch
#

I’ll try moving the PV sprite to it’s own asset bundle

#

Could it also be the compression on the asset bundle?

jolly oriole
#

compression shouldn't be an issue, but you can try it

primal latch
#

Ok

#

I thought I read something about that

jolly oriole
#

though slightly different

  • different output folder
  • made it 2 buttons for testing, 1 compressed, 1 uncompressed
primal latch
#

I might try it. We are using assetbundles browser

cedar hemlock
#

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

deep wave
#

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

cedar hemlock
#

boss.GetComponent<tk2dSprite>().GetCurrentSpriteDef().material.mainTexture = EnemyTextures[boss.TryGetValue(string key, out string Value)];?

#

cus that gives me 4 errors

deep wave
#

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

cedar hemlock
#

i dont understand it lol
i have no idea where to put .TryGetValue(string key, out Texture Value)

cedar hemlock
#

oo

silent marsh
#

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

fair rampart
#

hi , where i can find some info or documentation about hk modding?

jolly oriole
ornate rivet
#

please for the love of all things good

#

disable these notifications

copper nacelle
#

TRUE

#

I despise these

#

I get like 1-4 a day

unborn flicker
#

It is incredible that there is no way to turn them off.

jolly oriole
#

apparently you can turn those off

charred topaz
#

Is it not possible to change the functionality of the getters and/or setters of properties using the ON namespace?

copper nacelle
#

It is in theory

#

In reality it is a gambling game

#

Small methods are often inlined by the JIT

elder radish
#

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?

primal latch
#

Does it have a colider?

jolly oriole
#

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

elder radish
#

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

jolly oriole
#

i think layer 9 was enemies, could be wrong though

elder radish
#

enemy also has a rigidbody2d

jolly oriole
#

oh, layer 11 is enemies, should work then

#

layer 9 was player

elder radish
#

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

jolly oriole
#

may i ask what name the enemy gameobject has?

elder radish
#

Witch

jolly oriole
#

the only way that doesn't work then is your naildamage is 0

elder radish
#

Is it possible though

jolly oriole
#

it should fully work unless:

  • your nailDamage is 0
  • your HealthManager is dead
  • your HealthManager has iframes from the last attack
elder radish
#

what does the last one means?

jolly oriole
#

when an enemy gets hit, it has iframes for 0.15/0.2 seconds

elder radish
#

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

jolly oriole
#

the first one is just for hooks, so you get notified and can execute code when a method of the latter one gets called

steady comet
#

Were all the On.??? hooks generated automatically by the monomod?

jolly oriole
steady comet
#

I mean, as opposed to someone having to manually create all of them (I'm guessing that's the case with the ModHooks?)

elder radish
#

It seems like that hook is not working

#

This hook works on custom scenes too right?

jolly oriole
#

then there probably is an exception

steady comet
jolly oriole
# elder radish This hook works on custom scenes too right?

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

elder radish
#

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

#
  1. How did you select the HealthManager values that you set after foreach loop?
#
  1. Is using Resources.FindObjectOfType an alternative to preloading?
jolly oriole
#
  1. 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)
  2. 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

elder radish
#

again thank you very much for help

light zodiac
#

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

maiden umbra
#

im looking for dialogues stored in dnspy, does someone know where i can find them

copper nacelle
#

not in dnspy

maiden umbra
#

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

copper nacelle
#

you can log the sheet and key w/ the result in there

maiden umbra
#

i saw that note on the radiance.host site as well, but how would i do that

#

thanks for your vid btw

copper nacelle
#
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

maiden umbra
#

thank you!

copper nacelle
#

that's true

runic wind
#

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

uneven radish
fluid furnace
#

heyo, anybody here know how to make HK mods?

ornate rivet
#

hk mods?

#

pretty sure modding hk is impossible

vocal spire
vocal spire
fluid furnace
#

but

#

people have made mods

#

._.

#

isn't that why these channels exist

copper nacelle
#

it is a joke

fluid furnace
#

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

ornate rivet
#

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

fluid furnace
#

true

#

that seems to be the case with most modding communities

fluid furnace
#

could you point me in the direction of some of those mods

vocal spire
#

but everyone has thought of a tiso boss at some point, so there's prob more

fluid furnace
#

well then

#

I suppose the question becomes "anyone here working on or know who's working on a Tiso boss mod"

fluid furnace
#

now just gotta figure out how to make HK mods

#

learning mod development go brrr

vocal spire
#

Do you know c#?

fluid furnace
#

no

#

.-.

vocal spire
#

You should probably learn it first

fluid furnace
#

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

vocal spire
#

Ah yeah, terraria modding is fun

fluid furnace
#

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#

vocal spire
#

You should also probably learn a bit of how to work with unity(ex: basic knowledge of how to use monobehaviors and gameobjects)

jolly jungle
#

I wanted to make a mod where we actually witness Tiso's death, but that's probably not what you meant

fluid furnace
#

no, I was thinking about adding a Tiso boss fight

#

probably accessed by dream nailing his corpse

light zodiac
#

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

summer siren
#

hello can I talk about skin development in this chat

light zodiac
summer siren
#

ok

#

thank you

jolly oriole
light zodiac
#

how would i copy the inspect elements

jolly oriole
# light zodiac 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

light zodiac
#

how do i spawn gg_battle_transitions

#

and for 3 and 4 its just EventRegister.SendEvent("BOX DOWN DREAM");?

jolly oriole
jolly oriole
jolly oriole
steady comet
#

Why does PlayMakerFSM.BroadcastEvent not work?

jolly oriole
#

because the method doesn't exist?

#

or i haven't found it

jolly oriole
#

oh, then i haven't found it

steady comet
#

Oh wait, you said ("eventname", false)

#

That overload doesn't seem to exist

jolly oriole
#

the false is only to also send it to itself lol

steady comet
#

Oh I see lmao

jolly oriole
#

i just found that because SendMessageByName used that

steady comet
#

In the 1.5 mapi do you have to broadcast an FsmEvent rather than a string fsmEventName?

jolly oriole
#

i have no idea

steady comet
#

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)

jolly oriole
#

i could check rn

#

the static method still exists, so no

steady comet
#

Awesome thanks hollowknice

light zodiac
#

and this is the thing i preloaded ("GG_Workshop","Inspect")

jolly oriole
jolly oriole
light zodiac
jolly oriole
#

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)

light zodiac
jolly oriole
#
foreach (var item in go.GetComponentsInChildren<PlayMakerFSM>())
      item.SendEvent("lol");

with go being the thing you have + .Value

light zodiac
#

It works!!

#

Thank you so much

jolly oriole
#

ez, not a single thing of this was tested 😎

twin gull
#

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

cedar hemlock
#

Change some guy to Someone to be more accurate

twin gull
cedar hemlock
twin gull
#

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

cedar hemlock
#

The only time i used joy2key was when i connected my wii controller and all hell broke loose

twin gull
#

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

cedar hemlock
#

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

twin gull
cedar hemlock
#

It seems to be the right one

twin gull
#

But this is for the 1.5 beta

cedar hemlock
#

Ah

cedar hemlock
#

Hollow knight 1.5 is a beta release

young walrus
#

1432-60 is the current active version on the installer

twin gull
cedar hemlock
#

Well both

#

That api is still a beta b/c that version of hk is still a beta

twin gull
#

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?

jolly oriole
#

yes

#

there's a beta option in the properties

twin gull
#

cool, that all makes sense

jolly oriole
twin gull
#

so does anyone know where in the mod api code we interact with the controller or input?

#

is it InputHandler.cs?

cedar hemlock
#

I guess?

young walrus
stone elm
#

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.

cedar hemlock
#

y the embed tho

stone elm
#

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

young walrus
#

too many clicks to type brackets

twin gull
#

yeah, i know how to use github & its codesearch (& that it sucks & you probably have to just clone & search the fs)

young walrus
#

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"

twin gull
#

sure, but does anyone know exactly where we hijack the input, and more importantly why?

jolly oriole
#

i think 56 would know

young walrus
#

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

twin gull
#

i'm pretty sure you're right

cedar hemlock
#

If the what is causing it, why its causing it and how to fix it was known then the bug wouldn't exist

young walrus
#

I'm sure it's fixable, but figuring out why the interaction is happening like it is.... will take a ton of debugging

twin gull
#

no i don't mean why it's causing it, i mean why do we hijack input in the first place

young walrus
#

like I said.... tmk.... we don't

#

at least not on purpose

twin gull
#

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

young walrus
#

the assembly file is the main launching file of the game

cedar hemlock
#

Its a side effect of something its just not known of what

young walrus
#

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

twin gull
#

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?

jolly oriole
#

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

twin gull
#

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

young walrus
#

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

twin gull
#

i think sfgrenade may be on to something tho

young walrus
#

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

twin gull
jolly oriole
#

i have no clue about that, just heard something like that once

twin gull
#

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)

runic wind
#

Is there a way to add a mod option in the pause menu? I’m not seeing anything in the docs

vocal spire
runic wind
#

Alright, thanks

twin gull
#

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.

twin gull
#

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.
copper nacelle
#

InControl is standard

#

it's what hk uses for input as a whole

#

one of the issues with controllers is xinput

#

varies between platforms

twin gull
#

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.
vocal spire
#

I guess it's a missing library then

twin gull
#

@copper nacelle earlier sfgrenade suggested that on some platforms, we patch the asm without adding xinput for some platforms

copper nacelle
#

On Linux and mac the universal binary is built against the windows assembly yes

twin gull
#

which prompted me to try using my replica switch pro controller in actual-switch mode, which kinda worked

copper nacelle
#

Which means native functions aren't tied in

#

Controllers are still fucked on windows anyways though

twin gull
copper nacelle
#

the api labeled universal is just built against windows because for the most part everything is the same

twin gull
#

so presumably, InControl is statically linked to the mac/linux binaries, and running the mod installer is wiping them out somehow?

vocal spire
#

not running mod installer, using the ModdingApi

copper nacelle
#

InControl has pinvokes

twin gull
#

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

copper nacelle
#

No

#

That'd be a pain

#

you prebuild the api and just overwrite

vocal spire
#

just replacing the assembly with the modded one

copper nacelle
#

Can't trust the average user to have .net core let alone msbuild

vocal spire
#

can't trust the average user to know what clicking install on a mod does

copper nacelle
#

that's true

#

It's just a matter of building against the other vanilla folder

#

Pretty sure I have it already

twin gull
#

so i could fix this by building HollowKnight.Modding myself against my own vanilla hk dir, assuming I knew how to apply the result?

vocal spire
twin gull
#

presumably i would want to git co 1.4.3.2-60 first

copper nacelle
#

yeah

#

it's fairly simple

#

build in release

#

Provided you're on Mac or Linux

twin gull
#

for steps 3-4, is it just msbuild -p:Configuration=Debug or what?

copper nacelle
#

don't use debug

#

Release

#

but yeah

#

also add /restore

#

I should replace those

twin gull
#

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.```
copper nacelle
#

if you'd like I can just build against the Linux binaries in like 20m

#

Otherwise yeah

twin gull
#

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

copper nacelle
#

Cool

twin gull
#

i'm actually installing dotnet-sdk anyway, but i sorta doubt that'll solve everything

runic wind
#

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

copper nacelle
#

did you get the targeting pack

runic wind
#

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?

copper nacelle
#

I believe that includes the targeting pack

runic wind
#

it does? ok then

copper nacelle
#

3.5 is a pain

#

there's also .net 3.5 dev tools in the vs installer but you said you already did that

deep wave
#

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)

copper nacelle
#

inner peace

ornate rivet
#

56 really is shifu

twin gull
#

@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

copper nacelle
#

yeah that's annoying

#

i could maybe fix that later

#

but yeah you can install and just overwrite again

twin gull
#

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

copper nacelle
#

yeah

runic wind
#

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

copper nacelle
#

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

copper nacelle
#

but 35 because you're presumably using 1.4.3.2

jolly oriole
jolly oriole
#

CallMethodProper sux, doesn't want to store fsm variables for me

jolly oriole
#

got the inv page working better, idk how the journal doesn't break

vocal spire
#

I found out a while ago how it doesn’t break but since I don’t need to again I won’t

jolly oriole
#

yo, with your journalHelper, you have it made using instances, but everything else is basically static, why not change it all to static?

runic wind
#

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?

copper nacelle
#

latter

jolly oriole
runic wind
#

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?

jolly oriole
#

reference them in your project and then have

using {}

at the top of a .cs file (one using for each namespace)

vocal spire
#

Making a big update to frog core anyways

runic wind
#

how would I get the game object for the Shade? to change its fsm

vocal spire
copper nacelle
#

SceneManager has a HollowShadeObject

runic wind
#

what's causing this error? The other error is "Cannot resolve symbol 'GameObject'". Am I missing a dependency?

#

sorry for being clueless zote

light zodiac
#

Right click on it and let it generate a function for you

runic wind
#

doesn't help

#

the problem is it doesn't recognize GameObject so it thinks it has the wrong signature

light zodiac
#

Did you write GameObject or gameObject

runic wind
#

I wrote literally exactly what it wants

#

as well as used the auto generated function

steady comet
#

@runic wind you need using UnityEngine; - do you have that?

runic wind
#

yeah, but it says it's not being used

steady comet
#

Uhh

#

Do you have the right project references?

runic wind
#

probably not

steady comet
runic wind
#

I think OnEnemyEnable will work fine

#

what references should I have?

steady comet
#

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?)

runic wind
#

using rider because visual studio did not like .NET 3.5

steady comet
#

Oh - I assume you can also in rider but I don't know how to

runic wind
#

yeah I know how

#

I believe I referenced UnityEngine.dll but I'm trying to find the .csproj to make sure

light zodiac
#

screenshot your code

#

nvm I'm blind

runic wind
#

yeah UnityEngine.dll is referenced

steady comet
#

Does it not recognise the GameObject keyword? What happens if you right click it?

runic wind
#

doesn't recognize it

#

top suggestion is to create that type

steady comet
#

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 :/

light zodiac
#

try UnityEngine.GameObject

runic wind
#

I still get "Cannot resolve symbol 'GameObject'"

light zodiac
#

add refeerence to UnityEngine.CoreModule

runic wind
#

that worked!

#

thank you mathulLove

light zodiac
runic wind
#

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

sleek tulip
#

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.

cedar hemlock
vocal spire
cedar hemlock
#

This is modding-dev lol

vocal spire
#

Oh

#

lol

cedar hemlock
#

xD

sleek tulip
#

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.

cedar hemlock
#

An IDE, such as visual studio in which to code

#

That IDE also makes a dll

#

Also watch the modding tutorial by 56

sleek tulip
#

ok thanks

pseudo pond
#

c# is pretty easy to pick up, its very similar to java

#

seems pretty intuitive as far as coding languages come

sleek tulip
#

If I ever finish some kind of mod where do you post it?

cedar hemlock
#

Either pr the modlinks.xml yourself, ask me or someone else to do it or ask for more explanation

sleek tulip
#

ok I'll come to that when I get there then

cedar hemlock
#

You know what github is?

sleek tulip
#

yes

#

I know there are some example mods there that can show you how the code works

cedar hemlock
#

Instructions are on top

sleek tulip
#

Alright I'll just save the page then

pseudo pond
#

would there be any downside to just referencing all of the unity.dll s?

jolly oriole
#

The .csproj file is bigger

copper nacelle
#

true

light zodiac
#

would the .dll be bigger?

jolly oriole
#

Maybe, it also contains the references

#

Yea*

#

But that is diminishingly small

deep wave
#

iirc resharper has a tool to remove all unused references once you're done

#

but that costs money so niceWeh

jolly oriole
#

not if you're a student afaik

pseudo pond
#

when implementing ITogglableMod what do i put inside the Unload method

copper nacelle
#

Generally you want to unhook what you hooked in Initialize and if you created stuff destroy that

pseudo pond
#

got it, thanks

steady comet
#

C sharp question, is there a good way to swap two variables? Like

a, b = b, a

in python.

stone elm
#

Just tested
(b, a) = (a, b);
and it works

steady comet
#

Oh, I didn't realise you need the brackets lmao (I tested without)

#

thanks!

stone elm
#

New-ish tuple syntax lets us do fun stuff in C# too

runic wind
#

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?

primal latch
#

@runic wind from what I know, playmaker doesn’t use Time.DeltaTime which means that everything scales eitht he amount of frames

jolly oriole
#

if i were at home, i could check exactly that

vocal spire
steady comet
pseudo pond
#

when changing things in PlayerData can i just use PlayerData.instance.(variable)=(whatever i want)?

steady comet
#

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

pseudo pond
#

what is the correct way to do so?

steady comet
#

If it's a bool, then

PlayerData.instance.SetBool(nameof(PlayerData.???), ???)
pseudo pond
#

thank you very much!

steady comet
#

The nameof(PlayerData.???) is just a compiler thing that means you're less likely to have a typo

pseudo pond
#

mostly because im dumb lmao

pseudo pond
#

is there a hook for when the player receives a charm notch?

young walrus
#

There's a hook for everything

pseudo pond
#

is it included in the charmupdate hook?

young walrus
#

¯_(ツ)_/¯

#

probably not charmupdate

vocal spire
young walrus
#

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

pseudo pond
#

so i could just use the setint hook for PlayerData.charmSlots?

young walrus
#

try it

pseudo pond
#

uh oh

#

that went poorly

#

game just crashed, think it's because of the way in which i tried to test if it works

vocal spire
#

What’s your code

pseudo pond
#
/*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);
        }*/
cedar hemlock
#

```
message
```

#

do that

#

not the right ones

pseudo pond
#

thank you

copper nacelle
#

do not call setint in a setinthook

pseudo pond
#

oh

#

makes sense 🤦‍♂️

vocal spire
#

Stack overflow lol

#

SetIntInternal?

cedar hemlock
#

you can also do cs ater `
```cs
message
```
for colours

pseudo pond
#

oh that's cool

#

the more you know

vocal spire
#

Color is cool

pseudo pond
#

what is the diff between SetIntInternal and SetInt?

vocal spire
#

SetInt calls the hooks SetIntInternal doesn’t tmk

pseudo pond
#

well that's useful, thank you very much

#

ill see if it works

vocal spire
#

So the only place you should really use SetIntInternal is the hook

pseudo pond
#

ok

jovial gazelle
#

The example mod given on the apidocs is hellmod, is that what I should be using? Seems like it isn't

copper nacelle
#

using as what

jolly oriole
#

an example probably

jovial gazelle
#

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

copper nacelle
#

It's a decent example yeah

jovial gazelle
#

Alright

pseudo pond
#

i'd start with that and then go from there using hellmod as an example