RUMBLE does not support other mod managers. If you want to use a manager, you must use the RUMBLE Mod Manager, a manager specifically designed for this game.
AdvancedStructureSkins
Customize your structures like we've never seen before! Supports all HLSL and Shader Graph shaders.
| Date uploaded | 5 days ago |
| Version | 2.0.2 |
| Download link | Cxntrxl-AdvancedStructureSkins-2.0.2.zip |
| Downloads | 15 |
| Dependency string | Cxntrxl-AdvancedStructureSkins-2.0.2 |
This mod requires the following mods to function
UlvakSkillz-RumbleModdingAPI
API to Help Modders Get Started and to remove the necessity of GameObject.Find
Preferred version: 5.3.0README
Advanced Structure Skins
Advanced Structure Skins allows users to create custom shaders for structures, providing creators with extreme flexibility, albeit also introducing additional complexity and potential incompatibilities.
This mod may remove game functionality, including but not limited to visible grounded effects, grounded vertex offsets and on-collision structure shaking, depending which shaders are used (as these features are implemented in the shader and must be rebuilt by skin creators.)
Don't forget to install AdvancedStructureSkins.Shared.dll in /RUMBLE/UserLibs!
You can watch a video tutorial for User setup and for getting started as a developer here:
NOTE: This video is slightly outdated! Advanced Structure Skins now uses a UIFramework implementation, so press F9 instead of F10 when selecting your skins! https://youtu.be/igGSTZQgDr0
For Users
Installing Skins
To find skins, head to the Rumble Modding Discord's #skin-share forum. Find a .bundle (v1.0.0 - v1.3.3) or .asb (v2.0.0+) file for a skin you like the look of and place it in /RUMBLE/UserData/Skins/. You may have to create this folder. Once you launch the game, your skin will be available to select in the UIFramework menu for Advanced Structure Skins.
There are two types of skins:
- Shaders, which have their visuals generated by code
- Textures, which are images placed on your structures
Some Shaders can sample Textures, allowing you to use a texture skin with a unique shader. .bundle files will only ever contain Shaders, but .asb files may contain either a Shader, a Texture Set, or both. In fact, .asb files can contain as many different Texture Sets as a developer wants.
Shaders are selectable in the Shaders tab in Advanced Structure Skins' UIFramework menu. Likewise, Textures are selectable in the Textures tab.
Manually Installing Texture Sets
Texture Sets may also be installed without using .asb files. Each Texture Set supports 4 images, Main.png, Normal.png, Mat.png and Grounded.png. Main images are typically a fairly normal looking image, a flat colour which contributes the majority of the texture's appearance. Normal, despite the name, is not a normal map any more due to changes in RUMBLE's art pipeline. Instead, it is typically a red and yellow image, which applies highlights and shadows to a structure's surface.
Installing Texture Sets manually is fairly straightforward. Here's the folder structure you'll want to create:
RUMBLE
| - UserData
| | - Skins
| | | - StructureName
| | | | - Mat.png
| | | | - Main.png
| | | | - Normal.png
| | | | - Grounded.png
Valid structure names are Disc, Pillar, Ball, Cube, Wall, SmallRock and LargeRock.
If you want to use multiple textures, add your textures to a subfolder under the StructureName, and the game will automatically load the textures on launch. Textures can then be selected from the Textures tab.
If you want to prevent a skin from loading without deleting the skin permanently, just add an Underscore (_) to the beginning of the folder name and the game will ignore it.
Example folder structure:
RUMBLE
| - UserData
| | - Skins
| | | - StructureName
| | | | - SkinName (can be anything)
| | | | | - Main.png
| | | | | - Normal.png
| | | | | - Mat.png
| | | | | - Grounded.png
| | | | - SkinName2
| | | | | - Main.png
| | | | | - Normal.png
| | | | | - Mat.png
| | | | | - Grounded.png
If you want to use multiple textures of the same type for a single skin (like if you wanted a playing card which changed the Main texture randomly, but kept the same Normal, simply add a folder for that type of texture to your SkinName folder.
Example:
RUMBLE
| - UserData
| | - Skins
| | | - StructureName
| | | | - Main
| | | | | - tex1.png (can be anything)
| | | | | - tex2.png (can be anything)
| | | | | - tex3.png (can be anything)
| | | | - Normal.png
| | | | - Mat.png
| | | | - Grounded.png
You can combine this with the previous example too - placing the skin files in a SkinName folder will load multiple skins with multiple textures.
For Developers
Creating Skins
There's a bunch of useful tools and example shaders in the SDK available on GitHub. The most important of which is the Shader Asset Bundle Builder, which you can access via the Tools tab at the top of the window. It should be relatively straightforward to use if you already know your way around unity.
Next, creating shaders. Advanced Structure Skins supports loading shaders made in either raw HLSL or through Unity's Shader Graph. To make them compatible with the game, you'll need to ensure some of your property names match the game's existing shaders. You can read the list of Supported Shader Properties here.
The grounded effect is probably the most important part to implement in a shader, since it has some pretty solid gameplay consequences, so I've included a couple helper functions to make life easier when implementing it.
You can include these functions in your HLSL shaders by adding #include "Assets/ExampleShaders/Shaders/AdditionalFunctions/GroundMask.hlsl" to your includes, or in your Shader Graphs by adding a Custom Function node and selecting the GroundMask.hlsl file from the AdditionalFunctions folder. Your Custom Function node will require a Vector3 input taking in the Worldspace Position, 3 float inputs taking in the _FloorHeight, _Stable and a Floor Height Offset, as well as 1 float output, returning white for any surface above the floor. You can name the function either GroundMask or GroundMaskGradient depending on which format suits your needs.
For vert offsets (such as shaking during hitstop or merging with the ground when grounded), you can implement the StructureVertOffsets(float3 worldPos, float floorHeight, float stable, float offset, float floorBlendAmount, float shake, float shakeAmount, float shakeFrequency) function by adding #include "Assets/ExampleShaders/Shaders/AdditionalFunctions/StructureVertOffsets.hlsl" to your includes, or in your Shader Graphs by adding a Custom Function node and selecting the StructureVertOffsets.hlsl file from the AdditionalFunctions folder. An example of implementation of this function is available in the Shaders folder.
There's also a couple other simple shader examples in the SDK project which should help give some idea on how other shader properties are implemented - it's up to you how you use the tools provided.
You can also add multiple materials to a single structure, creating multipass skins. Unfortunately, due to RUMBLE's base functionality, the properties _FloorHeight, _Stable, _shake, _shakeAmount and _shakeFrequency are not always updated reliably on all materials. Because of this, it's important that Element 0 of your Skin Manifest's Shaders is the material that makes up the majority of your skins's visual composition. This material will always receive reliable property values from the game.
All other material properties will be updated consistently on additional materials, so you can safely use them on other passes.
Creating Expansion Mods
You can now create your own expansions to Advanced Structure Skins, adding custom ShaderFeature classes to the mod. These allow you to use code to easily manage properties on a shader on a per-structure or global level.
To create a ShaderFeature, first add Advanced Structure Skins as a reference. Then, override either ShaderFeature or TimedShaderFeature, depending on your use case. Your ShaderFeature will require a constructor. It'll want three parameters, AdvancedSkin target ShaderPropertyType type, string propertyName and object defaultValue. Your ShaderFeature's constructor shouldn't require a type, propertyName or defaultValue input, and instead should set them explicitly in the base class's underlying constructor.
It's important that the value you assign in the base class's constructor is a valid input for your property's type, otherwise it will throw an error in OnEnable(). TimedShaderFeatures don't have to assign a default value, and will default to 999f. You can still provide a different default value if you want though.
public class CurrentVelocity : ShaderFeature
{
private Structure Structure => target.structure;
public CurrentVelocity(AdvancedSkin target) : base(target, ShaderPropertyType.Vector, "_currentVelocity", Vector3.zero) { }
protected override void OnUpdate()
{
base.OnUpdate();
SetProperty(Structure.CurrentVelocity);
}
}
Once you've made your ShaderFeature class, register it with the Advanced Structure Skins API in your mod's LateInitializeMelon() function by calling AssAPI.RegisterShaderFeature<[ShaderFeature]>().
After which, you'll need to add functionality to your ShaderFeature yourself. If your ShaderFeature reacts to game events, you'll need to harmony patch your target event to patch in your feature's response. You'll need to be able to access a reference to an AdvancedSkin component on your target structure, at which point you can call AdvancedSkin.GetShaderFeature<[ShaderFeature]>(); to get a reference to that structure's instance of your ShaderFeature and interact with it accordingly.
ShaderFeature Functions
| Function | Description |
|---|---|
OnEnable() |
Called when a structure is enabled. |
OnUpdate() |
Called once every frame. |
OnFixedUpdate() |
Called 50 times per second. |
SetProperty(T value) |
Sets the property on the ShaderFeature's materials. Will throw an error if value is not an acceptable type for the ShaderFeature's ShaderPropertyType. |
You can override SetProperty() to add extra functionality before or after the base function, but it is recommended you include base.ShaderProperty(value) in your override to ensure the properties are set correctly.
TimedShaderFeature Functions
- As
TimedShaderFeatureis an inheritor ofShaderFeature, it also has access to all previously listed functions.
| Function | Description |
|---|---|
ResetTimer() |
Resets the timer to 0. |
PauseTimer(bool counting = false) |
Pauses the timer. Setting counting to true will resume it. |
ResumeTimer(bool counting = true) |
Resumes the timer. Setting counting to false will pause it. |
PauseTimer() and ResumeTimer() are functionally the same thing (with inverted default parameters), but can be overridden separately in inheriting classes, so you're able to add unique functionality to each of them if you wish.
ShaderFeatures are automatically enabled and disabled when new materials are applied to a structure, depending on whether or not the material's property list contains the ShaderFeature's propertyName, so ShaderFeatures which are heavy on performance won't be running unless they have to be.
CHANGELOG
Version 2.0.2
Fixed more critical bug in 2.0.2 which occasionally broke.. everything?
Version 2.0.1
Fixed critical bug in 2.0.0 preventing shader features from enabling during multiplayer sessions
Version 2.0.0
This version contains an ENORMOUS internal restructure, evolving past the old, frankly hacked together codebase I used to have. This should make it far easier to update the mod and to develop new features in general. It should've also fixed the vast majority of the bugs from the older versions.
I've also changed the skin bundle format from .bundle to .asb. While the name change is purely cosmetic, it signifies a larger internal rework of the format. .bundle files can still be loaded fine, and will be supported indefinitely, but .asb files are the new format going forward.
.asb files can also store more than just shaders - they can work as entire texture packs. This means skin developers can build textures to a .asb file if they wish, allowing users to import them with a single drag-and-drop, rather than the sluggish folder-based system that existed previously. Don't worry though, the old folder system is also still supported, so updating to this version will keep compatibility with all previous setups.
Additions
Added UIFramework support, replacing ModUI.
Added Custom UI, streamlining shader and texture skin selection - HUGE thanks to IListenToSound for his incredible work on UIFramework.
Added "ShaderFeatures", an internal system for adding additional 'effects' shaders can play with. Read more in the Supported Shader Properties wiki page.
Added "Competitive Mode", a toggle in the mod's UIFramework menu which automatically disables skins which provide a reasonably measurable competitive advantage (higher visibility grounded effects, hitstop indicators, ect)
Added "Debug Mode", a toggle in the mod's UIFramework menu which enables verbose logs, providing greater detail for debugging purposes. These logs are disabled by default so users don't have their consoles filled with unnecessary logs.
Version 1.3.3
Fixes
Fixed an incompatibility with DieHarder by TacoSlayer
Version 1.3.2
Fixes
Fixed error in loading persistent settings where the mod would fail to initialize if I attempted to load a setting that doesn't exist.
Version 1.3.1 - [BROKEN]
Changes
Implemented support for OptimizedGraphicsFix to improve mod compatibility
Version 1.3.0
Fixes
Shaders now display lighting correctly again. Existing shaders will need to be rebuilt to ignore normals, as the default normal map is now stylized.
Version 1.2.1 - [EXPERIMENTAL]
Fixes
Fixes texture tinting for structure textures on default shaders
Version 1.2.0 - [EXPERIMENTAL]
Fixes
Basic mod functionality for RUMBLE 0.5.0.1
This version is experimental! Existing texture skins will not work as structure models have changed, and existing shaders may behave strangely.
Version 1.1.0
Additions
Added a warning the first time you enter the Gym with Simple Visuals enabled. This will only appear once, and won't prevent the mod from working (as some shaders do work with simple shading!) Thanks to Orangenal for the idea!
Added persistent settings! This should be the last time your selected skins reset when you update the mod - I've implemented a custom save file system which should hopefully reduce friction on future updates.
Version 1.0.6
Fixes
Fixed a bug in texture loading which caused skin application to fail under certain conditions.
Thanks to Orangenal For the report!
Version 1.0.5
Fixes
Fixed bug in texture loading which caused the mod's initialization to fail if the user is missing certain skin directories.
Thanks to Huntersgaminggrounds for the report!
Version 1.0.4
Additions
Added random texture selection! If you want to use multiple textures, add your textures to a subfolder under the StructureName, and the game will automatically select between different skins randomly. If you want to disable this functionality without deleting the skin permanently, just add an Underscore (_) to the beginning of the folder name and the game will ignore it.
Example folder structure:
RUMBLE
| - UserData
| | - Skins
| | | - StructureName
| | | | - SkinName (can be anything)
| | | | | - Main.png
| | | | | - Normal.png
| | | | | - Mat.png
| | | | | - Grounded.png
| | | | - SkinName2
| | | | | - Main.png
| | | | | - Normal.png
| | | | | - Mat.png
| | | | | - Grounded.png
If you want to use multiple textures of the same type for a single skin (like if you wanted a playing card which changed the Main texture randomly, but kept the same Normal, simply add a folder for that type of texture to your SkinName folder.
Example:
RUMBLE
| - UserData
| | - Skins
| | | - StructureName
| | | | - SkinName (can be anything)
| | | | | - Main
| | | | | | - tex1.png (can be anything)
| | | | | | - tex2.png (can be anything)
| | | | | | - tex3.png (can be anything)
| | | | | - Normal.png
| | | | | - Mat.png
| | | | | - Grounded.png
Also, textures can now be hot-reloaded by holding F6 while in game. This means you can swap in and out textures from your game files and reload the ones you're using on the fly, without having to restart your game.
Version 1.0.3
Additions
Added random shader selection! Enter random as the ModUI shader settings to select a random shader from your /RUMBLE/UserData/Skins/ folder.
Enter StructureType/random to select from the shaders in /RUMBLE/UserData/Skins/StructureType/ folder, allowing for a different random pool per structure.
Fixes
Fixed issues in material caching which caused balls to revert to default shading after entering a multiplayer scene.
Thanks to Pompyy and Dr.Rock for the bug report!
Version 1.0.2
Additions
Added a "Clear Cache" bind (Hold F6 for 3 seconds) to allow for hot-reload of structure shaders, allowing developers to iterrate on shaders faster without having to restart their games.
Fixes
Fixed issues in material application logic which caused structures to take the wrong material properties when reloaded using F5.
Version 1.0.1
Fixes
ModUI shader settings now accept either myShader or myShader.bundle as valid input