Skip to content

Basic Notemods

Swifter edited this page Aug 20, 2025 · 10 revisions

Prerequisites

Property Translations

What is this?

Raw JSON ReMapper
c color
d cutDirection
a angleOffset
tb tailBeat
tx tailX
ty tailY
tc tailCutDirection
mu headLength
tmu tailLength
m anchorMode
sc links
s squish

Running Code On Each Note

A difficulty has arrays for all of the notes types: notes, bombs, arcs, and chains. It also has an allNotes array which combines all of these.

When we have an array (collection) of objects, we can "iterate" them, basically meaning we can go through the entire array and run code on every item.

An example of iterating every note in the difficulty and, adding a track to them for example, is as follows:

map.allNotes.forEach(note => {
    note.track.add('myTrack')
})

Animating Notes

You have 2 options to animate notes.

Option 1

You can animate notes using their path animations, which are available on their animation object. This does not require a track.

map.allNotes.forEach(note => {
    note.animation.offsetPosition = [
        [0, 10, 0, 0],
        [0, 0, 0, 0.5]
    ] // starts the note 10 units up and then moves it down by the time it's hit (t = 0.5)
})

Option 2

You can animate notes using a track. Set the note's track property to the same track you want to animate with an animation event.

map.allNotes.forEach(note => {
    note.track.add('myTrack')
})

// Dissolve notes out at beat 3 over the next 5 beats.
rm.animateTrack(map, {
    beat: 3,
    duration: 5,
    track: 'myTrack',
    animation: {
        dissolve: [
            [1, 0],
            [0, 1]
        ]
    }
})

Filtering Notes

"Filtering" notes is like running code on each note and then only continuing with the types of notes you want.

For example, let's say we want to filter only red color notes. We can iterate color notes and then add an if statement to only continue with red notes.

map.colorNotes.forEach(note => {
    if (note.color === rm.NoteColor.RED) {
        // code
    }
})
  • Notice how we used the colorNotes array instead of the allNotes array because bombs don't have a color!

Predicates System

You may need to pick and choose certain beats in a song that you want to effect notes, for this there's a couple of utilities:

  • between - filter between a start and end time
  • before - filter before a beat
  • after - filter after a beat
  • approximately - filter at a beat
// "after" example
map.allNotes.filter(rm.after(10)).forEach(x => {
   // code
})

You can join these predicates together with the following:

  • any - true if any predicate inside is true
  • all - true if all predicates inside are true

Let's say we want to filter between the beats 20 (inclusive) to 40 (exclusive), as well as exactly at the beat 50. Here's how we could do that:

map.allNotes.filter(rm.any(
    rm.between([20], 40),
    rm.approximately(50)
)).forEach(x => {
   // code
})

Fixing Missing Properties

Looking for a property on a note (perhaps from the above example) and you can't find it?

This is because whatever array you're iterating will only give you access to the properties that all of the notes in the array have.

If you try to iterate the allNotes array intending to edit spawnEffect for example, you'll get an error:

![img.png](images/missing property error.png)

As you can see in the screenshot above, your editor will tell you why the error has occured.

The error above is that Arc does not have the spawnEffect property, so TypeScript won't let you modify it in case one of the objects happen to be an Arc.

In order to get around this, you need to tell TypeScript that you are only going to change spawnEffect on the notes that have it. You can do this with a simple if statement, and it should recognize that you have access to that property inside of the if statement.

image

The above if statement states that the code inside of the block {} will only run if the object is NOT an Arc.

Clone this wiki locally