Skip to content

Making a custom ball

kyfex edited this page Feb 13, 2026 · 7 revisions

Making a custom ball is super simple :3

First, make sure you've set up your development environment. Make sure you've also created a mod; once both are done, you can move forward to making your custom ball :3

Setup

To make a custom ball, there are 2 files you need:

  • A texture at <mod folder>/overwrites/balls_textures/<YourName-YourMod-YourBall>.png
  • A BallResource at <mod folder>/overwrites/data/balls_data/<YourName-YourMod-YourBall>.tres

Next, you want to make sure those files are loaded into the game. In your mod_main.gd inside the _init() function, add the following code:

CUE.take_over(MOD_DIR, "data/balls_data/<YourName-YourMod-YourBall>.tres")

Note that the file path in CUE.take_over ends the same the path of the BallResource. Whenever you create a file in the data folder, you'll want to add a corresponding CUE.take_over.

Properties

Next, edit the BallResource with your desired properties. Here's a cheatsheet for what the properties do:

Cheatsheet
  • health: Currently unused. Most balls set this to -1, so setting this to -1 probably won't introduce any problems in the future.
  • from_set: The set this ball can spawn with. If this ball's set shows up in the shop, this ball will have a chance to spawn in the shop. If you leave it blank, the ball will not spawn in the shop; if you don't want your ball to spawn, it's recommended to set can_drop instead.
  • name: The translation key of your ball's name. To keep things organized, it should be of the form BALL_<your ball name>_NAME
  • description: The translation key of your ball's description. To keep things organized, it should be of the form BALL_<your ball name>_DESC
  • level_modifiers: A /-separated list of strings for your ball's description. These take the place of any {}s.
  • level_modifiers_: A /-separated list of strings for your ball's description. These take the place of any {2}s.
    • Note: more level_modifiers past 2 are a planned feature :3
  • texture: The texture for your ball. You can create one using an image editor, or using the blender template.
  • can_drop: If the ball can show up in the shop.
  • rarity: The rarity of your ball. This influences how often they show up in the shop, how much they cost, their likelihood of spawning higher than level 1, and their likelihood of spawning mixed.
  • tags: An array of tags that your ball has. Look through the vanilla balls to see what tags you might want; these affect some balls's abilities (like the TAG_FRIEND tag marking a ball as buffable by Pet Food)
  • base_score: The default score your ball will have when pocketed, and how much score the ball will gain when upgraded
  • start_level: Basically unused, you can leave this at 1
  • pocket_effect: Using custom events is preferred over this. The effect this ball should have when pocketed. If you want a custom effect, set this to your ball's name.
  • start_round_effect: Using custom events is preferred over this. The effect this ball should have when it spawns, not just when the round starts. If you want a custom effect, set this to your ball's name
  • has_card: If this ball should show an info card
  • upgradeable: Unused
  • requires_achievement: If this ball requires an achievement to be gotten before being unlocked
  • id: The id of this ball. It should be the same as the ball's filename (minus the .tres of course)
  • main_color: The secondary color of this ball's description card

Events

Adding custom events is just as easy as custom properties! Inside your _init() function, add the following snippet of code:

CUE.register_ball_event("<YourName-YourMod-YourBall>", CUE.Events.EVENT, 
    func(ball, assorted:Dictionary, isMixedSide:bool):
        # Your code here
        return)

This chunk of code will be your template for whenever you want to add custom behavior to your ball. Replace <YourName-YourMod-YourBall> with your ball's name, and replace CUE.Events.EVENT with whatever event you want. (If you type CUE.Events. in the Godot editor, Intellisense should show you all the events you can use.)

Then, write your code! This function will run every time the specified event happens. If you want to know how some vanilla balls manage their events, check in res://event_manager.gd.

Note that a chunk of vanilla events check to make sure that the ball is alive before running the event; Cue doesn't do this. If you want that alive check, you'll have to add it yourself. if !ball.will_be_alive(): return is the way vanilla checks for it :3

Mass and Scale

To set your initial weight, you can call CUE.set_initial_weight("<your ball id>", weight:Ball.WEIGHT_LEVEL).

If you want more fine-grained control over your mass, scale and weight, you can call CUE.initial_mass_scale_callback("<your ball id>", callback:Callable). The callable you'll supply to this should be of the form: func(ball:Ball) -> { weight_state:Ball.WEIGHT_STATE, mass:float, scale:float }. The default mass and scale are 1, and the default weight_state is Ball.WEIGHT_STATE.NORMAL.

Clone this wiki locally