Content generated with AI — it may contain mistakes.

The catalogue

Animations

The six ways a colour can move over text, the eighteen shipped, and the one clock behind all of them.

An animation is not something a player wears. It is a movement declared once in animations.yml and then borrowed: a tag, a nick colour, a chat colour or a rank colour says animation: <id>, and from then on it is drawn moving. Nothing in the file is browsable, nothing in it is owned, and no player ever picks one directly.

The entry

plugins/ExyliaChatCosmetics/cosmetics/animations.yml
animations:
  shine:
    type: gradient_shift
    period: 60                                 # ticks for one full cycle; 20 = one second
    colors: ['#ffd700', '#ffffff', '#ffd700']  # optional; without it, the cosmetic's own
    intensity: 1.0                             # 0 to 1

There is no categories section and no menu fields. An entry is four keys and nothing else.

KeyWhat it does
typeone of the six below. An entry naming anything else is reported with its path and skipped
periodticks for one full cycle. Anything below 1 is read as 1. Default 40
colorsthe stops to move through, written in the usual colour grammar. Leave it out to move through the colour of whatever wears the animation
intensity0 to 1, clamped. What it means depends on the type. Default 1.0

A stop may be a hex colour, a named colour or a palette token, and a gradient written as one stop is read as its stops in order — colors: ['#a:#b'] and colors: ['#a', '#b'] are the same thing.

The six types

typeWhat it looks likeReads colorsReads intensity
gradient_shiftthe stops slide along the text and wrap aroundyesno
rainbowevery hue in turn, sliding along the textnoyes, as saturation
cyclethe whole text is one colour, walking through the stops togetheryesno
wavea brightness ripple runs along the textnoyes, as depth
pulsethe whole text breathes brighter and darker at oncenoyes, as depth
flickercharacters dim at random, like a bad bulbnoyes, as how many

The split in those last two columns is the thing worth knowing. gradient_shift and cycle decide the colour outright, so they are the two that read colors. wave, pulse and flicker do not decide a colour at all — they dim the colour that is already there — so colors on one of them is read and then never used. And rainbow computes a hue from nothing, so it ignores both colors and the cosmetic's colour; only intensity reaches it, as how saturated the hues come out.

flicker picks its victims from a cheap hash of the character's position and the moment, so the same frame always dims the same characters and a cached frame stays honest. At intensity: 1.0 about one character in six is dimmed to just over a third of its brightness on any given frame; at 0.7, one in nine; at 0.35, one in eighteen.

What an animation moves through

An entry that leaves colors out borrows the colour of the cosmetic that named it, which is what makes the same animation read differently on every gradient wearing it.

The cosmetic's own colourThe animation moves through
a gradientits own stops, unchanged
a single colourthat colour and white
none at allwhite and {primary}

Of the eighteen shipped, thirteen borrow like that, three carry stops of their own — shine, cycle and house — and two, rainbow and spectrum, ignore colour entirely.

The eighteen that ship

idtypeperiodintensityColours
rushgradient_shift30—the cosmetic's own
shinegradient_shift60—#ffd700, #ffffff, #ffd700
flowgradient_shift70—the cosmetic's own
housegradient_shift100—{primary}, {secondary_light}, {letters}, {secondary}
driftgradient_shift160—the cosmetic's own
spectrumrainbow401.0its own hues
rainbowrainbow800.9its own hues
cycle_owncycle90—the cosmetic's own
cyclecycle120—{primary}, {secondary}, {accent}
emberwave280.8the cosmetic's own
wavewave400.6the cosmetic's own
sweepwave600.35the cosmetic's own
glowpulse260.7the cosmetic's own
pulsepulse400.5the cosmetic's own
breathepulse900.3the cosmetic's own
staticflicker101.0the cosmetic's own
sparkleflicker160.35the cosmetic's own
flickerflicker200.7the cosmetic's own

The two palette entries are the ones to look at first. house and cycle are written in palette tokens rather than hex, so they follow your server's colors.yml: a server that repaints its palette repaints those two animations with it, and every cosmetic wearing them.

Naming one

animation: goes on the entry that wants it, in four of the catalogue files.

FileOn
tags.ymla tag
nick-colors.ymla nick colour
chat-colors.ymla chat colour
rank-colors.ymla rank colour
plugins/ExyliaChatCosmetics/cosmetics/chat-colors.yml
chat_colors:
  aurora:
    category: premium
    name: '{primary}&lAURORA'
    gradient: ['#00f260', '#0575e6', '#8a51c4']
    animation: flow
    icon: END_ROD
    description: 'Northern lights, in a sentence.'

Shadow colours, fonts and modifiers name none — the key is not read there. A cosmetic a player made carries the same field on its row and is drawn with it when the row names one, though nothing in the commands or the menus writes one yet.

An id nothing declares is not an error and stops nothing: the cosmetic is simply drawn in its own colour, standing still. The same is true after a reload that removed an animation some entry still names.

In chat, a line is one frame

A chat message that has been delivered never changes. The client holds what it was sent, and no plugin can go back and repaint it. So a message carries the frame of the moment it was sent, and "animated" in chat means that every line is a different frame of the same movement — not that any one line moves.

Menus are the other half of that. The browsers redraw on the clock, so a row wearing an animation moves while a player is looking at it, and what they see in the menu is what the animation actually does. Anything printed to chat, /cc preview included, is one frame of it.

A tag is cached before it is animated

Rendered tags, prefixes and suffixes are kept per player so that a chat line does not rebuild them. What is kept is the tag before its animation is applied — kept after, the frame it was first drawn on would be the frame every later line showed, and a player would think the animation had stopped.

The clock

One timer for the whole server, and its only job is to count.

plugins/ExyliaChatCosmetics/config.yml
animations:
  # Ticks between animation frames. Lower is smoother and costs more
  tick: 2

A cycle holds period / tick frames: flow, at a period of 70 and a tick of 2, is 35 frames long.

Nothing about an animation is per player. A frame is a function of the animation, the colour under it, how many characters there are and which frame it is — so two players wearing the same animated tag are the same computed colours, and a chat line only ever reads an array somebody else already computed. The cache holds up to 4096 of those arrays and forgets one five minutes after it was last read. /cca reload empties it, since the animation it was computed from may have changed.

That is where animations.tick earns its place. Raising it to 4 halves the number of frames in every cycle, which halves the arrays to compute and halves the redraws for every menu that is open. Lowering it to 1 is smoother and costs the opposite.

Rank colours animate the letters only

When rank-colors.repaint is letters — the default — an animated rank colour runs its frame over the letters and digits alone, the same characters the colour under it paints. An animation that reached the brackets of &8[&eVIP&8] would undo the very thing letters-only mode is for.

Something missing on this page? Tell us on Discord