Rain World

Rain World

Traumatized Watcher Behavior
New Modder Support
Here's my code (ReputationPlus.cs) and modinfo.json, as you requested:

using System; using UnityEngine; public static class ReputationPlus { [ModInit] public static void OnModInit() { Debug.Log("REPUTATION+ INIT RAN"); On.Player.Jump += TestJumpHook; } private static void TestJumpHook(On.Player.orig_Jump orig, Player self) { Debug.Log("JUMP HOOK TRIGGERED"); orig(self); } }

{ "id": "ReputationPlus", "name": "Reputation+", "version": "0.1.1", "description": "Currently just spams annoying messages in the debug console. Will later make scavengers respect your pet lizards.", "requirements": [], "requirements_names": [], "checksum_override_version": true }

And yes, it's modinfo.json, not modinfo.json.txt or something dumb like that.
I'm seeing my mod in the remix tab, but those debug.log messages aren't showing up for Devtools or the console text file. I don't think it's anything to do with the code and honestly I'm close to giving up. :slugcatdead:
< >
Showing 1-15 of 16 comments
TheLazyCowboy1  [developer] Aug 5 @ 8:54am 
Firstly, almost every modder for the past several years (including myself) has started with this basic template: https://github.com/NoirCatto/RainWorldRemix/tree/master/Templates/TemplateMod

I THINK the following code will work for your mod, though:

using System; using UnityEngine; using RWCustom; using BepInEx; #pragma warning disable CS0618 [module: UnverifiableCode] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [BepInPlugin("ReputationPlus", "Reputation+", "0.1.1")] public class ReputationPlus : BaseUnityPlugin { public void OnEnable() { Logger.LogDebug("REPUTATION+ INIT RAN"); On.Player.Jump += TestJumpHook; } private void TestJumpHook(On.Player.orig_Jump orig, Player self) { Logger.LogDebug("JUMP HOOK TRIGGERED"); orig(self); self.jumpBoost *= 2; //make the player jump higher, for fun } }

Frankly, the biggest issue was that you were using the wrong function for debugging. You were trying to use Unity's debug function, which probably works, but I have no clue where the results go. The Logger.LogDebug function will show up in the RainWorld/Bepinex/LogOutput.log file, and it's by far the most convenient. It even puts your mod name at the start of the log.
You can also use Custom.Log("Message"); which is a lot simpler. Those debug logs can be seen by enabling devtools and pressing K. But I prefer the logs to be clearly labeled in a .txt file.
Last edited by TheLazyCowboy1; Aug 5 @ 8:58am
TheLazyCowboy1  [developer] Aug 5 @ 9:00am 
Also you might want to add "authors" to your modinfo.json. I'm not sure if it's required. But you should probably add "authors": "agent_blablabla",
Ok, thanks, I guess. I don't know how to use Github though so I'm kind of scared of it like most people are of DMS and SBCameraScroll and furries (I possess a burning hatred for furries and a normal level of DMSphobia but no hard feelings towards SBCamera (in fact I want it, although I'm not sure where to get it but it's probably on the Workshop) And no, you're not a furry for having a slugcat PFP. Slugcats are not furries :rwslugcat::rwscavenger:).

I didn't know about the alternate debug log methods, so thanks for that. I'm used to making stuff in Unity (I'm working on an FPS that is currently "officially" titled "Project Renegade" but I'm probably going to call it World Power).

Can you please explain the code line-by-line though, because I don't know what a lot of that is (and I'm used to simpler object based programming where my player controller uses the player controls I made with the input system). :slugcatdead:

Also, I have a couple of map modding ideas: A custom subregion to add to Garbage Wastes (the Crawlyard, inspired by HL2:E2), and a whole custom region (I don't have a name for it yet, but it's basically Drainage System XL). I found a decent guide on YT and know I should get RWE+ instead of the trash default editor, although I'm not sure how to get it because it's on Githib. :slugcatdead:
TheLazyCowboy1  [developer] Aug 5 @ 5:07pm 
@agent_blablabla, Haha, I also avoid using DMS and I'm frustrated by SBCameraScroll's seams (it's my dream to someday fix them). But GitHub will be an important reference for any mod you make. I've spent a while learning how to use GitHub (and it's scarily frustrating), but all you have to do is use it to read others' code. Just think of some mods, Google "Rain World [MOD NAME] mod GitHub" and see if anything comes up. I have numerous small mods that might be decent references, except I have a terrible habit of.... not leaving any comments.

Here's a line-by-line explanation:
// Dependencies; nothing special here; just add these as needed. using System; using UnityEngine; using RWCustom; using BepInEx; // I have NO CLUE what these 3 lines do, but almost every mod has them. #pragma warning disable CS0618 [module: UnverifiableCode] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] // Bepinex loads all BaseUnityPlugins with this BepinPlugin attribute. // This line tells the game that this is a Rain World mod, and the mod's ID, name, and verison. // The ID does not have to match modinfo.json, but it will cause problems if two mods have the same ID. // (My mod's ID is LazyCowboy.ScaredWatcher; I put my name so no one else will use this ID by accident.) // The name is used by the Logger.LogDebug function; it just makes logs easier to read. [BepInPlugin("ReputationPlus", "Reputation+", "0.1.1")] // Again, Bepinex loads BaseUnityPlugins, so this must extend BaseUnityPlugin. public class ReputationPlus : BaseUnityPlugin { // This function is called very early on in the game's startup process. public void OnEnable() { // This writes a line in the LogOutput.log file. Very useful for debugging. Logger.LogDebug("REPUTATION+ INIT RAN"); // This means: When the Player.Jump function is called, run TestJumpHook instead. On.Player.Jump += TestJumpHook; } // Hooks have the following parameters: // An orig function (the original Player.Jump function.) Calling this calls the original code for Player.Jump. // A "self" parameter UNLESS the function is static. The type is the class that contains the function. // Any other parameters in the original function come after these. private void TestJumpHook(On.Player.orig_Jump orig, Player self) { // Everything before orig runs immediately BEFORE the original code. // Think of everything in this section as adding code to the start of Player.Jump Logger.LogDebug("JUMP HOOK TRIGGERED"); // This runs the original code. This is basically the same as saying self.Jump() (except writing self.Jump() would cause an infinite loop; don't do that). // You CAN omit this line. Doing so replaces the entire function with your code. // However, omitting this line will break most other mods that hook Player.Jump orig(self); // This code runs immediately AFTER the original code. // In this case, the Player.Jump function sets the player's jumpBoost to ~7.5f. // Here, we double that number to easily make the player jump higher. self.jumpBoost *= 2; //make the player jump higher, for fun } }

Very important question: Which decompiler are you using? Reading other mods' code on GitHub will help a lot, but the most important part of modding is reading the game's code. I (and most others on Windows) use dnSpy.
My modding process is typically: 1. Think of something I want my mod to do (e.g: override the player's inputs (like this mod does)). 2. Find where in the code the player's inputs are set (e.g: Player.checkInput) (requires reading through the game's code; or better, using dnSpy to tell me what functions set Player.input). 3. Hook Player.checkInput so I can override the player's movements. 4. Repeat steps 1-3 with a different problem, etc.
TheLazyCowboy1  [developer] Aug 5 @ 5:11pm 
For RWE+, here: https://github.com/timofey260/RWE-Plus/releases/tag/2.6.9
Just select RWE+_win.zip if you're on Windows and unzip it once it finishes downloading.

Making regions/rooms is great because there's so much support out there for it. I imagine making rooms could be a stress-relieving activity, whereas code mods will always be frustrating to make.
As an attempted indee game dev who has used both Unity and Roblox, I can feel ya regarding the thing about map design vs coding. In Unity it can be frustrating to try and do level design (I've tried modeling levels in Blender but I'm not sure the best way to do that and you end up with wierd geometry problems (especially origin placement) of you're not careful...), and C# has plenty of orderly laws that, once you understand them, are easy to follow when you get into its orderly, structured nature. Meanwhile, Roblox's code (Lua) is a confusing, disorderly mess where methods exist and variables are declared without defining the types (it just assumes based on the initial value :steamfacepalm:), but its building system is easy (if you know what Legos are and how to make parts) and fun to use, and if course you can go beyond parts by making things like terrain or meshes (mesh editor not included, get Blender).

I haven't gone through the line-by-line (I'm on my phone right now :P), but thanks. I'll list you as a contributor if and when I publish Reputation+.

Although, what's the point of the templates? I decided to be stupid and stubborn ("I really am just a dumb bunny!" -Judy Hopps, Zootopia ) and not use one despite the recommendation by the video I watched. That was probably a really big mistake, because here I am caught in the Cycle of trying to get AI to fix it but Ono making it worse each time to the point I get frustrated and want to give up.

And I don't have a decompiler (yet). I didn't think I'd get that far yet, and didn't plan to get one until I actually got something to load.

And another thing: You're ugly.
No actually, I already tried downloading RWE+ but it failed. It's probably because I have Canopy Shield and so it, in typical Canopy fashion, thought "Oh! Agent-blablabla is doing something that has nothing to do with porn! That's super sus so I must be annoying and stop him with no explanation!"
But it got about 65% done before my browser (I use Microsoft Edge with the DuckDuckGo search engine) said "Oh no there's a problem sorry. Do you want to try again?" And when I say "It's fine keep going" it tries for a second and then stops with no additional progress.
Although I also have one more question about map editing: is it possible to do subregions?

For example, the Crawl Yard isn't going to be a whole separate region connected to Garbage Wastes, it'll be part of Garbage Wastes, like how the Gutter is part of Chimney Canopy. Meanwhile, for my other planned custom region, I want to split it into a few custom regions. How do you do that? I'm still pretty confused about the file management aspect of map editing.
TheLazyCowboy1  [developer] Aug 6 @ 10:41am 
Subregions aren't too hard. Adding the subregion text isn't super intuitive, but it's pretty easy if you know how. The Rain World modding wiki will have more than enough resources to figure that out.

Subregions really aren't distinct regions. They're just additional rooms in a region. If you wanted to add a subregion to Garbage Wastes, you would start your room names with GW (e.g: GW_ROOMNAME1) and add connections to them in the world_gw.txt file. The wiki has a pretty good tutorial for creating a room and adding it to Outskirts.

Multiple regions isn't too hard. For each region, you need a unique acronym (e.g: GW = Garbage Wastes; WARA = Watcher Aether Ridge-A) (it's important that no other regions use your acronym). Creating new regions is actually pretty easy: Add your region acronym to the world/regions.txt file; create a world/ACRONYM folder and put in it a world_ACRONYM.txt file that says how the rooms connect (and what creatures to spawn); put all your rooms into a world/ACRONYM-rooms folder.
The world_xx.txt file is the most important one. It defines room connections and creature spawns. Everything else isn't too important, like the map data (which can be generated through devtools).
Alright, I went through your version of my test script, and it still isn't showing up (although thanks for the tip about the other debug log, I even saw your mod!)
Granted, I'm still not using a template. What's the point of a template, and why should I need one? I feel like that's the big problem right now (and it shouldn't take a bunch of supercomputers visible from space to solve it).
TheLazyCowboy1  [developer] Aug 7 @ 2:09pm 
@agent_blablabla, It works for me with the following dependencies at the top of the script:
using BepInEx; using System.Security.Permissions; using System.Security;

Are you sure you're finding the debug log? If you're seeing logs from my mods, you probably have. Just in case, it should be here: C:\Program Files (x86)\Steam\steamapps\common\Rain World\BepInEx\LogOutput.log
Also be sure to check for: C:\Program Files (x86)\Steam\steamapps\common\Rain World\errorLog.txt
The error log only rarely shows up, but if it does show up, it'll probably have some important info.

Also, for debugging, it's good if you copy both the .dll and the .pdb files (produced when you build your mod) into your mod's plugins folder. The .pdb file tells you what line is causing the issue. In the past, I didn't copy the .pdb's; I regret that, haha.

Templates are mostly just useful for, well, all of this part. Whenever I make a new mod, the first step is to copy one of my old mods and trim it down into a template-like form. That ensures that the mod gets set up and functions properly, and it only takes a few minutes. Once you get any debug logs in the LogOutput.log file, though, there's not really any more need for a template.
OOOh. ChatGPT told me not to copy the .pdb lol. I guess I'll get a template.
TheLazyCowboy1  [developer] Aug 8 @ 9:06am 
@agent_blablabla, I don't much understand .csproj files, but this is how mine are set up now for all my mods:

(Note: You 100% don't have to do this, but I find it super convenient both time-wise and for debugging. Now I don't have the problem of forgetting to copy something and wondering why it doesn't work.)

<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net48</TargetFramework> <LangVersion>11</LangVersion> </PropertyGroup> <ItemGroup> <Reference Include="..\REFERENCES\*.dll" /> </ItemGroup> <ItemGroup> <Folder Include="Scared Watcher\plugins\" /> </ItemGroup> <Target Name="PostBuild" AfterTargets="PostBuildEvent"> <ItemGroup> <BuildFiles Include="$(Outdir)\ScaredWatcher.*" /> </ItemGroup> <Copy SourceFiles="@(BuildFiles)" DestinationFolder="Scared Watcher\plugins" /> <ItemGroup> <OutputFolder Include="Scared Watcher\*" /> </ItemGroup> <Copy SourceFiles="@(OutputFolder)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\Rain World\RainWorld_Data\StreamingAssets\mods\Scared Watcher" /> <Copy SourceFiles="@(BuildFiles)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\Rain World\RainWorld_Data\StreamingAssets\mods\Scared Watcher\plugins" /> </Target> </Project>

I have a folder named RainWorldMods. In that folder, I have a folder named REFERENCES (where I put all the .dll's from C:\Program Files (x86)\Steam\steamapps\common\Rain World\RainWorld_Data\Managed and C:\Program Files (x86)\Steam\steamapps\common\Rain World\BepInEx\core) and a folder named ScaredWatcher (the original name for this mod) (that contains the mod files/source code).

You might want to try slimming down the code to something like this:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net48</TargetFramework> <LangVersion>11</LangVersion> </PropertyGroup> <ItemGroup> <Reference Include="..\REFERENCES\*.dll" /> </ItemGroup> <Target Name="PostBuild" AfterTargets="PostBuildEvent"> <ItemGroup> <BuildFiles Include="$(Outdir)\ScaredWatcher.*" /> </ItemGroup> <Copy SourceFiles="@(BuildFiles)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\Rain World\RainWorld_Data\StreamingAssets\mods\Scared Watcher\plugins" /> </Target> </Project>

This nonsensical "code?" automatically copies over ScaredWatcher.dll and ScaredWatcher.pdb into my Scared Watcher mod's plugins folder. Just change "ScaredWatcher" and "Scared Watcher" to "ReputationPlus" and it should work for you, hopefully. Also be sure to put all the .dll's you need to reference inside a REFERENCES folder.
Hehe...
I didn't get any of that.
Look, I don't know much of anything about how Visual Studio ACTUALLY works. When I first decided to make a Rain World mod was the first time I ever opened VS myself. What I'm used to is double-clicking on my scripts in the Unity Editor and VS opens up with my scripts ready to be edited. I don't know what any of that other stuff is, so... uhh...
How about this: we'll do it like Michael Scott.

Explain the entire process of setting up a project, from the moment I turn on my Windows computer and open Visual Studio (opening VS is probably the first step) like I'm a 10-year-old. Who knows the basics of using a computer. And knows some middle-level C#.

Look, I really appreciate your patience and help. Maybe I need to just delete what I've got and start over with a fresh mindset. Maybe even do some mapmaking first, since that's apparently simpler.
Last edited by Agent_blablabla; Aug 8 @ 9:18am
TheLazyCowboy1  [developer] Aug 8 @ 11:42am 
At this point I'm considering making a video recording of me making a basic mod with explanations and give you a link to it on YouTube or something like that (I had to do that for my assignments in my basic C++ class, although I'm pretty bad at narration). I'll try to get some form of full explanation to you later, maybe this evening if i'm free.
< >
Showing 1-15 of 16 comments
Per page: 1530 50