Skip to content

MilyMC ITM (Modcharts)

Mily_0 edited this page Aug 27, 2026 · 5 revisions

mily mc itm 401

Uma ferramenta de modcharting 100% em Lua, desenvolvida especialmente para esta engine. Um sistema livre, poderoso e de código aberto, criado para facilitar o modcharting em músicas de Friday Night Funkin'.

Important

THIS IS REAAAAAAAAAALLY OUTDATED DO NOT USE FOR NOW!!! MILY 4.0.1 IS PRETTY DIFFERENT x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x

x


O que é Mily MC ITM?

  • Facilidade e agilidade
  • API própria
  • Lésbica
  • Inúmeras animações matemáticas iradas
  • Customização praticamente infinita
  • Suporte a modifiers customizados[1]

Os modcharts de música ficam em:

mods/<seu mod>/songs/<nome-da-musica>/modchart.lua

Se um modchart.lua tiver erro de sintaxe, a engine tenta avisar no debug em vez de quebrar o backend inteiro do MilyMC.

Variáveis Icon-newtenma

Esses são os targets principais:

Target O que controla
BF_Strum / "bf" / "player" Lado do player
DAD_Strum / "dad" / "opponent" Lado do opponent
Strum_Gen / "gen" / "all" / "both" Os dois lados
0 até 7 Uma lane específica
{0, 1, 2, 3} Várias lanes, apenas nos helpers por lane como setStrumX/Y/Z
setModchart('drunk', 1, BF_Strum)
setModchart('flip', 1, DAD_Strum)
setModchart('confusion', 90, 4)
setStrumAngle({0, 3, 4, 7}, 15)

Em HScript/Haxe, use strings para os lados:

game.setModchart("drunk", 1, "bf");
game.setModchart("flip", 1, "dad");
game.setModchart("confusion", 90, 4);

Se o target não for passado, a maioria das funções usa Strum_Gen.


Callbacks Icon-newtenma

Os callbacks do modchart usam nomes próprios para não bater com scripts normais.

Original Modchart
function onCreate() function modChartCreate()
function onCreatePost() function modChartCreatePost()
function onUpdate(elapsed) function modChartUpdate(elapsed)
function onUpdatePost(elapsed) function modChartUpdatePost(elapsed)
function onBeatHit() function modChartBeatHit()
function onStepHit() function modChartStepHit()
function onSectionHit() function modChartSectionHit()
function onMoveCamera(focus) function modChartFocus(focus)
function goodNoteHit(id, nd, nt, sus) function modChartBFNote(id, nd, nt, sus)
function opponentNoteHit(id, nd, nt, sus) function modChartDADNote(id, nd, nt, sus)
function goodNoteHitPre(id, nd, nt, sus) function modChartBFNotePre(id, nd, nt, sus)
function opponentNoteHitPre(id, nd, nt, sus) function modChartDADNotePre(id, nd, nt, sus)
function noteMiss(id, nd, nt, sus) function modChartMiss(id, nd, nt, sus)
function noteMissPress(id, nd, nt, sus) function modChartMissPress(id, nd, nt, sus)
function onSongStart() function modChartSongStart()
function modChartCreatePost()
    setModchart('drunk', 0.6, BF_Strum)
end

function modChartStepHit()
    if curStep == 128 then
        easeModchart('dadFlipIn', 'flip', 1, 1, 'expoOut', DAD_Strum)
    end
end

function modChartFocus(focus)
    if focus == 'boyfriend' then
        kickPulse('focusBF', BF_Strum, 0.12, 0.45, 'expoOut')
    elseif focus == 'dad' then
        kickPulse('focusDAD', DAD_Strum, 0.12, 0.45, 'expoOut')
    end
end

API Base Icon-newtenma

Registrar Modifiers

addModchart inicializa um modifier. Muita coisa inicializa sozinha quando você usa setModchart/easeModchart, mas registrar deixa o debug mais claro.

image
Ação Lua HScript/Haxe
Adicionar addModchart('drunk') game.addModchart("drunk");
Remover clearModchart('drunk') game.clearModchart("drunk");
function modChartCreatePost()
    addModchart('drunk')
    addModchart('beat')
    addModchart('receptorScroll')
end
function onCreatePost() {
    game.addModchart("drunk");
    game.addModchart("beat");
    game.addModchart("receptorScroll");
}

Setar Valor

setModchart muda um modifier imediatamente.

Lua HScript/Haxe
setModchart('drunk', 1.5, BF_Strum) game.setModchart("drunk", 1.5, "bf");
setModchart('confusion', 90, 4) game.setModchart("confusion", 90, 4);
function modChartStepHit()
    if curStep == 64 then
        setModchart('drunk', 1.5, BF_Strum)
        setModchart('invert', 1, DAD_Strum)
    end
end

Fazer Tween

easeModchart faz tween de um modifier.

easeModchart('tagDoTween', 'drunk', 1.5, 4, 'linear', BF_Strum)

O formato antigo ainda funciona:

easeModchart('drunk', 1.5, 4, 'linear', BF_Strum)

Em HScript/Haxe, o wrapper atual usa o formato antigo:

game.easeModchart("drunk", 1.5, 4, "linear", "bf");

Para saber quando um tween com tag terminou:

function modChartTweenFinished(tag)
    if tag == 'tagDoTween' then
        debugPrint('Tween terminou!')
    end
end

Agendar por Step

Use queueSet e queueEase quando a mudança já tem step certo.

Ação Lua HScript/Haxe
Set agendado queueSet(64, 'flip', 1, BF_Strum) game.queueSetModchart(64, "flip", 1, "bf");
Ease agendado queueEase(128, 160, 'drunk', 1.4, 'expoOut', Strum_Gen) game.queueEaseModchart(128, 160, "drunk", 1.4, "expoOut", "gen");
function modChartCreatePost()
    queueSet(64, 'flip', 1, BF_Strum)
    queueEase(128, 160, 'drunk', 1.4, 'expoOut', Strum_Gen)
    queueEase(192, 224, 'drunk', 0, 'expoInOut', Strum_Gen)
end

Também existem versões em porcentagem:

queueSetP(64, 'stealth', 50, BF_Strum)
queueEaseP(96, 128, 'stealth', 0, 'quadOut', BF_Strum)

Ler Valores

getMod lê o valor atual. getModDef lê o valor atual ou retorna um padrão.

local curDrunk = getMod('drunk', true, 4)
local curScale = getModDef('receptorScaleX', true, 1, 4)

O segundo argumento é isPlayer: true para BF, false para DAD.


Receptors Icon-newtenma

Esses helpers mexem diretamente em receptors/lanes. Eles são mais específicos que transformX/Y/Z.

Função O que faz Exemplo
setStrumX(target, value) Offset X instantâneo setStrumX(4, 30)
setStrumY(target, value) Offset Y instantâneo setStrumY(BF_Strum, -20)
setStrumZ(target, value) Offset Z instantâneo setStrumZ(Strum_Gen, 0.2)
setStrumAngle(target, value) Ângulo instantâneo setStrumAngle({0, 1, 2, 3}, 15)
setStrumScale(target, value) Escala instantânea setStrumScale(BF_Strum, 0.85)
setStrumAlpha(target, value) Alpha instantâneo setStrumAlpha(DAD_Strum, 0.4)
Tween Exemplo
easeStrumX / tweenStrumX easeStrumX('bfX', BF_Strum, 80, 1, 'expoOut')
easeStrumY / tweenStrumY easeStrumY('dadY', DAD_Strum, -60, 1, 'quadOut')
easeStrumZ / tweenStrumZ easeStrumZ('zoomLane', 4, 0.2, 0.8, 'expoOut')
easeStrumAngle / tweenStrumAngle easeStrumAngle('spinLane', 7, 360, 1.2, 'cubeOut')
easeStrumScale / tweenStrumScale easeStrumScale('tinyBF', BF_Strum, 0.7, 0.6, 'quadOut')
easeStrumAlpha / strumTweenAlpha easeStrumAlpha('hideDad', DAD_Strum, 0.2, 0.4, 'linear')

Para voltar ao valor original:

setStrumX(BF_Strum, 'og')
setStrumAlpha(DAD_Strum, 'og')

Em HScript/Haxe não existe helper direto para todos eles ainda, mas você pode mexer nos modifiers internos:

game.setModchart("strumX4", 30, 4);
game.easeModchart("strumAngle7", 360, 1.2, "cubeOut", 7);

Transform Icon-newtenma

transformX/Y/Z move o playfield inteiro. Use isso para deslocamentos grandes de lado/cena. Use setStrumX/Y/Z quando quiser mexer em lanes/receptors específicos.

Função O que faz Exemplo
setTransformX(target, value) Move o playfield no X setTransformX(BF_Strum, 120)
setTransformY(target, value) Move o playfield no Y setTransformY(DAD_Strum, -60)
setTransformZ(target, value) Move o playfield no Z setTransformZ(Strum_Gen, 0.15)
easeTransformX / tweenTransformX Tween no X easeTransformX('bfSlide', BF_Strum, 0, 1, 'expoOut')
easeTransformY / tweenTransformY Tween no Y easeTransformY('dadDrop', DAD_Strum, 80, 0.8, 'bounceOut')
easeTransformZ / tweenTransformZ Tween no Z easeTransformZ('allDepth', Strum_Gen, 0, 1, 'quadOut')

Variação em HScript/Haxe:

game.setModchart("transformX", 120, "bf");
game.easeModchart("transformY", 80, 0.8, "bounceOut", "dad");
game.easeModchart("transformZ", 0, 1, "quadOut", "gen");

Scroll Icon-newtenma

Essas funções são só atalhos para modifiers de scroll/layout. Elas não são modifiers separados.

easeScroll

Alterna entre 0 e 1 automaticamente:

easeScroll(BF_Strum, 'opposite', 0.75, 'expoOut', 'bfReverseToggle')

Ou define um valor exato:

easeScroll(DAD_Strum, 'opposite', 1, 0.75, 'expoOut', 'dadReverseOn')

setScroll

Define/tweeta direto:

setScroll(BF_Strum, 'upscroll', 1, 0.5, 'quadOut', 'bfUp')
setScroll(BF_Strum, 'downscroll', 0, 0.5, 'quadOut', 'bfDown')
setScroll(Strum_Gen, 'cross', 1, 0.6, 'expoOut', 'crossOn')
setScroll(Strum_Gen, 'receptorScroll', 1, 1, 'expoOut', 'recScroll')

Nomes comuns: opposite, reverse, scroll, upscroll, downscroll, cross, alternate, receptorScroll, oppSwap.


Kick Shots Icon-newtenma

Kick shots são impactos curtos: setam um modifier para um valor forte e fazem tween de volta.

kickShot(tag, target, modName, startVal, endVal, duration, ease)

Exemplos:

function modChartBeatHit()
    if curBeat % 4 == 0 then
        kickShot('beat_' .. curBeat, Strum_Gen, 'beat', 0.22, 0, 0.55, 'expoOut')
    end

    if curBeat % 8 == 4 then
        kickOut('scale_' .. curBeat, BF_Strum, 0.18, 0.45, 'cubeOut')
    end
end

Atalhos:

Função O que faz
kickIn(tag, target, intensity, duration, ease) Diminui e volta
kickOut(tag, target, intensity, duration, ease) Aumenta e volta
kickPulse(tag, target, intensity, duration, ease) Pulso de escala
kickEarthquake(tag, target, intensity, duration, ease) Tremor curto
kickSusPulse(tag, target, intensity, duration, ease) Pulso nas sustain notes

Quando o modName é beat, o kickShot também mexe internamente no beatKick, então o impacto aparece mesmo quando a onda normal do beat estaria em uma parte fraca.


Modifiers Icon-newtenma

Essa seção é só a lista dos modifiers. Os helpers e atalhos ficam nas categorias de cima.

Categoria Modifier O que faz Visual
Ondas drunk Move notes no X em onda. Ajustes: drunkSpeed, drunkPeriod, drunkOffset. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ondas tipsy Move notes no Y em onda. Ajustes: tipsySpeed, tipsyPeriod, tipsyOffset. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ondas tipZ Move notes no Z em onda. Ajustes: tipZSpeed, tipZPeriod, tipZOffset. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ondas float Efeito flutuante nos receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ondas zigzag Faz as notes andarem em zigzag no caminho. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout flip Espelha as colunas do lado escolhido. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout invert Troca colunas vizinhas: esquerda com baixo, cima com direita. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout opposite / reverse Inverte o sentido do scroll do alvo. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout cross Inverte apenas as colunas do meio. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout alternate Inverte colunas alternadas. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout middle / centered Centraliza o playfield no X. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout middle2 Move colunas para posições mais extremas. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout oppSwap Troca visualmente o lado do opponent e do player. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Layout receptorScroll Faz receptors rolarem e deixa notes mais estáticas. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Posição transformX, transformY, transformZ Move o playfield inteiro. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Posição strumX, strumY, strumZ Move receptors/lanes específicas. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Posição bumpX Offset extra no X da lane. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Posição z Profundidade extra para notes/receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação rX, rY, rZ Rotaciona usando a strumline como referência. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação centerRX, centerRY, centerRZ Rotaciona usando o centro da tela. Aliases: centerRotateX/Y/Z, crx/cry/crz. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação rotate0X até rotate7Z Rotação por lane. Também funciona com centerRotate0X etc. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação confusion Gira notes e receptors juntos por graus. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação noteAngle Gira só as notes. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação receptorAngle Gira só os receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Rotação spin Gira notes que não são sustain. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ritmo beat Move o campo no ritmo da música. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ritmo beatZ Versão em profundidade do beat. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ritmo earthquake, earthquakeX, earthquakeY Treme o playfield. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ritmo susPulse Pulso visual nas sustain notes. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Ritmo temna Efeito especial de movimento/rotação. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Velocidade boost Desacelera antes e acelera perto do receptor. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Velocidade wave Alterna velocidade no caminho, criando efeito de onda. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Velocidade brake Acelera no começo e freia perto do receptor. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Visibilidade stealth Primeiro clareia a note, depois começa a apagar. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Visibilidade hidden / hiddenOffset Esconde notes conforme elas chegam perto do receptor. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Visibilidade sudden / suddenOffset Faz notes aparecerem perto do receptor. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Visibilidade blink Pisca a visibilidade das notes. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Visibilidade dark Apaga os receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Escala globalScale Aumenta ou diminui tudo. 0 é normal. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Escala mini, miniX, miniY Diminui notes e receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Escala squish, stretch Espreme ou estica. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Escala receptorScaleX, receptorScaleY Escala só os receptors. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)
Escala noteScaleX, noteScaleY Escala só as notes. 2026-04-1600-58-27online-video-cutter com-ezgif com-video-to-gif-converter (2) (2)

Exemplo:

function modChartCreatePost()
    setModchart('drunkSpeed', 1.2, Strum_Gen)
    setModchart('drunkPeriod', 0.9, Strum_Gen)
    setModchart('hiddenOffset', 0.35, BF_Strum)

    queueEase(64, 96, 'drunk', 1, 'expoOut', BF_Strum)
    queueEase(96, 128, 'tipsy', 0.8, 'expoOut', DAD_Strum)
    queueEase(128, 160, 'receptorScroll', 1, 'quadInOut', BF_Strum)
    queueEase(160, 192, 'centerRotateZ', 0.12, 'expoOut', Strum_Gen)
end

Modifiers Customizados Icon-newtenma

Custom modifiers são criados com defineModifier. A ideia é: você cria um nome, recebe um ctx, muda os campos dele, e depois controla esse modifier com setModchart, easeModchart, queueEase e tudo mais.

defineModifier('nomeDoModifier', {
    note = function(ctx, value)
        -- roda apenas em notes
    end,

    sustain = function(ctx, value)
        -- roda em sustain notes
    end,

    strum = function(ctx, value)
        -- roda em receptors
    end
})

Callbacks possíveis:

Callback Quando roda
apply(ctx, value) Notes e receptors
note(ctx, value) Só notes
sustain(ctx, value) Só sustain notes
strum(ctx, value) Só receptors
receptor(ctx, value) Alias de strum

Campos úteis do ctx:

Campo O que é
ctx.x, ctx.y, ctx.z Posição final
ctx.angle Ângulo final
ctx.scaleX, ctx.scaleY Escala final
ctx.alpha Transparência
ctx.brightness Brilho usado por efeitos tipo stealth
ctx.distance Distância da note até o receptor
ctx.beat, ctx.songPos Tempo da música
ctx.strumID, ctx.col Lane absoluta e coluna local
ctx.isPlayer true se for player
ctx.strumE true se for receptor
ctx.isSustainNote true se for sustain

Exemplo simples:

function modChartCreatePost()
    defineModifier('myWave', {
        note = function(ctx, value)
            ctx.x = ctx.x + math.sin(ctx.distance * 0.01 + ctx.beat) * 80 * value
        end,

        strum = function(ctx, value)
            ctx.angle = ctx.angle + math.sin(ctx.beat) * 15 * value
        end
    })

    easeModchart('myWaveIn', 'myWave', 1, 2, 'expoOut', BF_Strum)
end

Exemplo com sustain separado:

function modChartCreatePost()
    defineModifier('softLongs', {
        sustain = function(ctx, value)
            ctx.alpha = ctx.alpha * (1 - value * 0.35)
            ctx.brightness = math.max(ctx.brightness, value * 0.3)
        end
    })

    setModchart('softLongs', 1, Strum_Gen)
end

addCustomModifier também existe como alias de defineModifier.

Custom modifiers são Lua por enquanto. Em HScript/Haxe você pode pilotar modifiers já criados com game.setModchart, game.easeModchart, game.queueSetModchart e game.queueEaseModchart.

Clone this wiki locally