Modding Tutorial

All Modding references in a single article

## Information

Starblast Modding interface can be found here: https://starblast.io/modding.html (ECP required)

Starblast Modding interface allows you to create custom mods for Starblast. The interface is made of a code editor window, on the left, and a console window, on the right. The code editor is where you type the JavaScript code for your mod. The console is where you can type commands to start your mod, stop it or interact with it while it is running.

Main programming language used in this interface is JavaScript (ECMAScript)

## Documentation and Tutorial

### Important Notes

In newer versions of browsers' updates, you can't use the Modding Client in incognito mode anymore as they restrict some incognito features which are used by the editor.

And make sure to read all of these from the start to the end so that you won't miss any important info!

### Creating your first mod

In the Mod Code window, type the code for your first mod:

```
this.options = {
 root\_mode: "survival",
 map\_size: 30
};

this.tick = function(game) {
};

```

### Running and testing a mod

#### Change region

Once your mod code is ready, in the console, start by selecting your preferred region for modding using the command `region <region name>`. For example with Europe:

```
> region Europe
Region set to Europe
> █
```

(Currently modding is only available in these 3 zones: Europe, America, Asia)

#### Start mod

Then to start running your mod, type command `start`:

```
> start
Mod started
https://starblast.io#1234@12.34.56.78:2000
Use 'test' to open game frame for testing
> █
```

#### Test the mod

As instructed by the console, you may want to open a test window to join your modded game with a Starblast client. Type `test`:

```
> test
> █
```

#### ALWAYS keep the Mod Editor Tab being active while running the mod!

This is one of the most important things you need to keep in your mind!

Why? Because that's nuances of how browsers work.

Browsers slow down all javascript in non-active tabs in order to decrease the CPU processes.

For some mods (e.g Battle Royale), it doesn't matter like with ship tree and options only,

but for other mods where some logic in tick function or events - it will affect them A LOT!

Ticks start to work slower and slower...

Soon everything will be lagging in game; any reactions on mod buttons, any mod logic like spawning something in tick, etc.

And... depending on mod complexity it can CRASH THE ENTIRE MOD - locally, server will continue to work so game will still run but without mod logic anymore.

So, always keep the mod editor tab online or you may have unpredictable results!

Also, you need to have a stable internet connection if you don't want your mods becoming laggy.

#### Stop the currently running mod

You can stop your mod anytime by using the command `stop`. Note that this will kill the game and disconnect all connected players:

```
> stop
Mod stopped
> █
```

#### Other terminal commands

##### `echo`

Print any values to the terminal; can be used in both mod code (after mod started) and terminal

Syntax: `echo(<item>)`

```
> echo("Message from terminal!")
Message from terminal!
> █
```

##### `clear`

Clear the terminal, only available in the terminal

Syntax: `clear`

##### `help`

Display help message inside the terminal, terminal use only

Syntax: `help`

### Main code parts

#### Options

##### Definition

Stored in `this.options` is a data structure where you can set options for your custom modded game. These options are used for initializing the game when you start your mod. Changing them while the mod is running does not affect the game.

##### Custom ships and custom tree

You can import ships made within the Starblast Ship Editor. Use "Mod Export" feature to export a JavaScript code snippet for the modding interface. Then paste this snipped in the coding window and add this:

```
var myship\_101 = "{ … … <this is your exported ship code> …";

var ships = [myship\_101]; // add your ship to an array of ship

this.options = {
 root\_mode: "survival",
 ships: ships, // specifying a list of ships to complement / replace existing ships
 reset\_tree: true, // set to true if you want to remove the original ship tree, false if you just want to replace some of the ships
 map\_size: 30
};

this.tick = function(game) {
};

```

Then run your mod. If your ship is set to level=1 model=1, your ship will replace the Fly. You can replace other ships in the tree in a similar way, using `reset_tree: false`. Or you can remove the original ship tree completely and provide a whole new one using `reset_tree: true`.

##### Customizing the emote-chat system

The vocabulary used for the emote-chat system can be customized by setting the field `vocabulary` in the game option as follows:

```
var vocabulary = [
 { text: "Hello", icon: "\u0045", key: "O" },
 { text: "Bye", icon: "\u0046", key: "B" },
 { text: "Yes", icon: "\u004c", key: "Y" },
 { text: "No", icon: "\u004d", key: "N" },

 { text: "Flower", icon: "\u{1F33B}", key: "F" },
 { text: "Snowman", icon: "\u26c4", key: "M" },
 { text: "Shark", icon: "\u{1F988}", key: "S" },
 { text: "Ghost", icon: "\u{1F47B}", key: "G" }
];

this.options = {
 vocabulary: vocabulary,
 // ...
};

```

This allows using Starblast built-in emote icons, which are listed here for reference: https://starblast.io/glyphs.html

You can also use unicode icons, here is a good source for reference: https://unicode.org/emoji/charts/full-emoji-list.html

Note that wide unicode characters (using more than 2 bytes) requires a specific Javascript syntax as shown in the example above (example: `\u{1F47B}`)

##### Custom asteroids maps

You can create a custom map of asteroids. This allows creating a maze for example. The custom map you provide is actually a JavaScript character string that is used to "paint" the map.

For example:

```
var map =
"999999999999999999999999999999\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"99 99\n"+
"999999999999999999999999999999" ;

this.options = {
 custom\_map: map,
 map\_size: 30
}

```

In the example above, 9 sets the biggest size of the asteroid. You can use smaller values for adding smaller asteroids to the grid. Any value other than a digit will be interpreted as no asteroid. If your `map_size` is set to 30, make sure to create 30 lines and 30 columns, or you may get unpredictable results.

**Note:** Use `""` for blank custom map

You can use Online Map Editor (a community tool) to create, edit and export maps.

##### Other common options

Most of the options are inherited from the usual custom games. A few more options have been added, specifically for modding (top of the list):

##### Deatmatch mode specific options

Example:

```
ship\_groups: [
 ["U-Sniper","Howler"],
 ["Crusader","Pioneer"]
]

```

#### Ticking

##### Definition

Found in `this.tick` is a JavaScript function that is called 60 times per second. In this function’s body, you will be able to code specific actions that your mod needs to take automagically while the game is running. This function can be modified while the modded game is running and the changes will apply automagically.

#### Events

##### General

Your mod can receive events through the function `this.event`:

```
this.event = function(event,game) {
 switch (event.name)
 {
 case "ship\_spawned":
 if (event.ship != null)
 {
 shipJustSpawned(event.ship) ;
 }
 break ;
 }
} ;

```

##### Available events

 ship\_destroyed
 alien\_destroyed
 asteroid\_destroyed
 collectible\_picked
 ui\_component\_clicked

**Note:** \* means that this event only works with unspecified `root_mode` (`root_mode: ""`)

### Map

#### Definition

All entities and objects in the game are moving on a 2D plane called "map"

Map can be painted with asteroids using `this.options.custom_map` and set size by `this.options.map_size` (even value from 20 to 200)

All Modding commands relating to coordinates will be visualized on this map

#### Coordinates

##### Axes

 Y
 Z

##### Grid

The map is divided into "grids".

A Grid is a 10x10 square area which can only contain 1 static asteroid (which equals to 1 character to "paint" the map in `this.options.custom_map`)

`map_size` is the number of grids along each dimension, which means that the number of grids in the map is calculated by the formula `map_size`2.

For example: `map_size` being 30 means that there are 30 grid length along the X Axis and Y Axis, and 302 = 900 grids total in the map

##### Center and Boundaries

Map center (x:0, y:0) is located in the Sun

Based on the Grid definition, we have:

Each Axis will have `map_size` / 2 grids length in both negative and positive part

Because each grid is a 10x10 square, the boundary of each part is `map_size` / 2 x 10 = `map_size` x 5

Means that each Axis varies from -`map_size` x 5 to `map_size` x 5

For example: with `map_size` = 30, each Axis in the map varies from -300 (`-60x5`) to 300 (`60x5`)

### Game step

#### Definition

Can be accessible through `game.step`; an integer presenting the game's duration

#### Unit

The unit of this value is tick, where 1 tick = 1/60 seconds

Which means that 60 ticks = 1 second, 120 ticks = 2 seconds and so on.

#### Uses

This code uses to set the first ship in the list to the center of the map in the first minute of the mod and reset its crystals every 5 seconds (assume that there is one ship staying from the start of the mod):

```
this.tick = function (game)
{
 if (game.step == 3600) { // 1 minute = 60 seconds \* 60
 game.ships[0].set({x:0,y:0}); // Center teleport
 }
 if (game.step % 300 === 0) { // 5 seconds \* 60
 game.ships[0].set({crystals: 0}); // Reset crystals
 }
}

```

### Ships

You can access the list of ships (players) through the array `game.ships`

You can also find a ship with a specific id using `game.findShip(id)`, which returns an object representing the matched ship or `null` (if no ships are matching the provided id)

#### Accessible fields

You have read access to the ship’s main fields and options:

#### Configuration

You can set different options on the ships. For example:

```
> game.ships[0].set({x:0,y:0});
> █
```

Will move the first ship in the list to the center of the map

List of accepted options when using `ship.set`:

#### Intermission

You can send the ship to intermission (a screen with results, offering to respawn). This screen allows you to display custom results information:

```
> game.ships[0].intermission({"Best Achievement":"Managed to run the mod","Score":1234});
> █
```

#### Triggering and Customizing player's GameOver screen

You can also trigger the gameover screen for any given ship. Here again, you can pass results information to pass on to the player:

```
> game.ships[0].gameover({"Rating":"Can do better","Score":1234});
> █
```

#### Instructor

##### Calling instructor

You can have the flight instructor send instructions to the player. For this find the player's ship and use:

```
> ship.instructorSays("Hello!")
> █
```

You can hide the instructor window using:

```
> ship.hideInstructor()
> █
```

You can later show it again using:

```
> ship.showInstructor()
> █
```

A second, optional parameter allows you to choose which one of the instructor characters will talk to the player. Example:

```
> ship.instructorSays("Here is your report, Commander","Maria")
> █
```

#### Custom UI components

##### General

The mod can create custom UI components that will show up on the player’s screen. This is done by calling `setUIComponent` on the ship - passing in a component descriptor.

For example:

```
> ship.setUIComponent({
    id:"myid",
    position:[0,0,25,25],
    clickable: true,
    shortcut: "X",
    visible: true,
    components: [
      { type:"box",position:[0,0,100,100],fill:"#456",stroke:"#CDE",width:2},
      { type: "text",position: [0,0,100,50],color: "#FFF",value: "My Text"},
      { type: "player",id: 1, position: [0,0,50,50],color: "#FFF"},
    ]
  })
> █
```

Here is the list of UIComponent's accepted options:

 position
 visible
 clickable
 shortcut
 components

##### Combining with events

The example below creates a warp button for every player, which can be clicked and results in the ship warping to another random location, adding 3 seconds invulnerability to it:

Full example: https://github.com/pmgl/starblast-modding/blob/master/examples/warp\_button.js

```
var warp\_button = {
 id: "warp",
 position: [2,50,8,14],
 clickable: true,
 shortcut: "W",
 visible: true,
 components: [
 { type:"round",position:[0,0,100,100],fill:"#456",stroke:"#CDE",width:2},
 { type: "text",position:[10,35,80,30],value:"WARP",color:"#CDE"},
 { type: "text",position:[20,70,60,20],value:"[W]",color:"#CDE"}
 ]
};

var warpShip = function(ship) {
 x = (Math.random()-.5) \* ship.game.options.map\_size\*10 ;
 y = (Math.random()-.5) \* ship.game.options.map\_size\*10 ;
 ship.set({x:x,y:y,vx:0,vy:0,invulnerable:180}) ;
} ;

this.tick = function(game) {
 if (game.step%60==0) // ensure this is done only once per second
 {
 for (var i=0;i<game.ships.length;i++)
 {
 var ship = game.ships[i] ;
 if (!ship.custom.warp\_button\_installed)
 {
 ship.custom.warp\_button\_installed = true;
 ship.setUIComponent(warp\_button);
 }
 }
 }
} ;

this.event = function(event,game) {
 switch (event.name)
 {
 case "ui\_component\_clicked":
 var ship = event.ship ;
 var component = event.id ;
 if (component == "warp") // check that this is our component "warp"
 {
 warpShip(ship);
 }
 break ;
 }
} ;

```

##### Customizing the scoreboard or radar

The built-in scoreboard or radar can be replaced by your own custom scoreboard/radar component. As soon as an UI component with id `"scoreboard"` or `"radar_background"` is created, you will be responsible for updating the scoreboard/radar. Your custom scoreboard/radar component does not have to include a `position` because it will automatically fill the area already reserved for the perspective UI Component.

##### Global UI

You can use `game.setUIComponent({ options })` to set the UI to all current players in the game

### Aliens

You can access the list of aliens through the array `game.aliens`

You can also find an alien with a specific id using `game.findAlien(id)`, which returns an object representing the matched alien or `null` (if no aliens are matching the provided id)

#### Creation

To create an alien, use `game.addAlien({ options })`

List of accepted options:

(Note: Server will respond with `Incorrect data` when at least one input property value is improper)

Here is the list of supported codes:

A new `Alien` object is immediately added to `game.aliens`; however, it cannot be used before it has been assigned an id (natural number, a.k.a non-negative integer) by the server.

#### Limits

You can only have **300** alive aliens (including aliens generated by the game mode) at any time in your game

The server will respond with `Too many aliens` for each alien passing the limit

#### Accessible fields

For each alien object in `game.aliens`, You have access to the same properties as the available ones when you add aliens, plus some additional properties:

 id

#### Configuration

Once an alien is live and has an assigned id, you can set options to it. For example:

```
> game.aliens[0].set({x:0,y:0});
> █
```

Will move the first alien in the list to the center of the map

Accepted options when using `alien.set`:

### Collectibles

You can spawn collectible weapons in the playfield

You can also find a collectible with a specific id using `game.findCollectible(id)`, which returns an object represents the matched collectible or `null` (if no collectibles are matching the provided id)

#### Creation

Here is an example:

```
> game.addCollectible({code:10,x:0,y:0});
> █
```

This will add a new collectible pack of rockets to coordinates (0;0)

Here is the list of supported codes:

(Note: Server will respond with `Incorrect data` when at least one input property value is improper)

 11
 12
 20
 21
 40
 41
 42
 90
 91

#### Limits

You can only have **50** active collectibles (including collectibles generated by the game mode) at any time in your game

The server will respond with `Too many Collectibles` for each collectible passing the limit

#### Accessing

For each collectible object in `game.collectibles`, You have access to the same properties as the available ones when you add collectibles, plus some additional properties:

 id

### Asteroids

You can access the list of moving asteroids through the array `game.asteroids`

You can also find an asteroid with a specific id using `game.findAsteroid(id)`, which returns an object represents the matched asteroid or `null` (if no asteroids are matching the provided id)

#### Creation

To create an asteroid, use `game.addAsteroid({ options })`.

Here is the list of accepted options:

(Note: Server will respond with `Incorrect data` when at least one input property value is improper)

 y
 vx
 vy
 size

A new `Asteroid` object is immediately added to `game.asteroids` ; however, it cannot be used before it has been assigned an id (natural number, a.k.a non-negative integer) by the server.

#### Limits

You can only have **300** alive asteroids (including moving asteroids generated by the game mode) at any time in your game

The server will respond with `Too many asteroids` for each asteroid passing the limit

#### Accessible fields

For each asteroid object in `game.asteroids`, You have access to the same properties as the available ones when you add asteroids, plus some additional properties:

 id

#### Configuration

Once an asteroid is live and has an assigned id, you can set options to it. For example:

```
> game.asteroids[0].set({x:0,y:0});
> █
```

Will move the first asteroid in the list to the center of the map

List of accepted options when using `asteroid.set`:

 y
 vx
 vy
 size
 kill

### Add 3D objects to the scenery

The mod can create custom, textured 3D objects and add them to the scenery using `game.setObject` method.

#### Notes

* All URLs included in this method must satisfy these conditions:
	1. The protocol must be `https`
	2. The domain only matches one of these domains:
	+ `starblast.io` (Official Starblast site)
	+ `starblast.data.neuronality.com` (Starblast Data site)
	+ `raw.githubusercontent.com` (Raw GitHub)
* A dimensional property included in this method is defined as an object with three fields represent 3 Axes in Coordinates

 y
 z

#### Object instance options

 type
 scale
 rotation

#### Object physics options

**Note:** We recommend not to use this property as it usually doesn't work as expected

 shape

For example:

```
var cube = {
 id: "cube",
 obj: "https://raw.githubusercontent.com/pmgl/starblast-modding/master/objects/cube/cube.obj",
 diffuse: "https://raw.githubusercontent.com/pmgl/starblast-modding/master/objects/cube/diffuse.jpg"
} ;

game.setObject({
 id: "cube",
 type: cube,
 position: {x:0,y:0,z:0},
 rotation: {x:0,y:0,z:0},
 scale: {x:1,y:1,z:1}
}) ;

```

#### Accessing

Game property `game.objects` stores all active 3D Objects maintained by the mod

You shouldn't modify this property to keep the mod running smoothly

#### Changing or moving an object

Use `game.setObject` again with the same object instance id.

#### Removing an object

`game.removeObject(id)` removes the object with given id. You can omit the id parameter, which will remove all custom objects in the scene.

#### Example

Working example, adding cube objects to the scenery: https://github.com/pmgl/starblast-modding/blob/master/examples/adding\_cube.js

### Reading game's detailed options

#### Accessing

Once the mod starts running, all detailed options will be passed into the `game.options` object

#### Accessible fields

This includes all properties defined in `this.options`, plus some extended fields listed below (except if they are not defined):

 max\_tier\_lives

#### Team mode specific accessible fields

 crystal\_capacity
 deposit\_shieldspawning\_shieldstructure\_shield
 deposit\_regenspawning\_regenstructure\_regen

### Assigning custom properties to some entities/objects

You can assign properties into some game entities or objects as side notes/indicators

#### Accessing and assigning

Simply just call out their `custom` property (which is always an object) and assign properties to it.

#### Supported objects/entities

* `game` object
* all ships
* all aliens
* all collectibles
* all asteroids

#### Example

```
game.custom.hasMod = true // game object
game.ships[0].custom.userScore = 6712 // ship entity
game.aliens[0].custom = {created: true, rating: "10stars"} // alien entity
game.asteroids[0].custom = {init: true} // asteroid entity

```

### Other game instances and methods

#### Set custom maps in-game

You can use `game.setCustomMap(<map pattern>)` to set custom map while the game is running

where `<map pattern>` has the same format as the custom map in `this.options`

#### Lock/unlock the mod from attracting new players

Use `game.setOpen(true/false)` to lock/unlock the mod to be visible to players (only for Modding Space mods)

There is also game boolean properties `game.is_open` is used to determine if the mod is open or not

### Common problems and how to fix them

#### Black screen issue

In most cases, you're getting a black screen after loading your mod due to a bad ship tree.

Follow these rules to avoid it:

1. Your ship tree must have a ship with type/code 101.
2. If your ship tree has level 2 ships, then it should have level 1 ships too.
3. Either models should go in the right order without gaps: 1, 2, 3 etc (not 1, 6, 17) or control all ship tree routes by `next` parameter in ship codes (but keep correct order for unreachable ships).
4. You can't have possibly infinite ship tree routes, made by `next` parameters - all routes should end at some ship, there shouldn't be able to come back to some ship again.

#### My mod closed accidentally but the game is not stopped

Sometimes, some unexpected problems can crash the mod, but it only disconnects from the modding side, or so-called "controller" side, the game itself will continue running without control from your modding client until it meets the closing requirements (or even in some serious occasions, game developers - like PMGL - need to close it by themselves).

Here are some reasons which can lead to mod crashing:

1. Closing/Reloading the modding tab/window without stopping the mod first (Most common one)
2. Very unstable internet connection
3. Server resolve error (which will automatically disconnect the controller by itself)
4. Browser tab hangs/crashes (careful of infinite while/for loops)

Also keep in mind that you can't reconnect to your previously crashed server, even if it's still running.

### Modding tips and tricks

#### How can I set the sun in my mod to be like this (which could be seen in every ACW/AOW games)?

You will only need to set `max_players` to a value higher or equal to 200, and `root_mode` as `"team"`

## Community resources

### Tutorials and Documentation

* Modding Tutorial - GitHub version
* Ship Editor Tutorial
* How to add ship to the mod - by InterdictorSD
* Modding Live #2 by PMGL
* General modding tutorial by Wolfan

### Tools

* Mod Editor
* Ship Editor
* Map Editor (by community)

### Code resources

* Community Mods Archive
* Starblast code reference by Bhpsngum
* Starblast code reference by Wolfan