dashtools
Version:
Library for interacting with Geometry Dash servers
825 lines (770 loc) • 29.7 kB
JavaScript
import * as utils from "../utils.js"
export const OBJECT_IDS = {
DEFAULT_BLOCK: 1,
DEFAULT_SPIKE: 8,
NORMAL_GRAVITY_PORTAL: 10,
REVERSE_GRAVITY_PORTAL: 11,
CUBE_PORTAL: 12,
SHIP_PORTAL: 13,
BG_COLOR_TRIGGER: 29,
GROUND_COLOR_TRIGGER: 30,
START_POSITION: 31,
YELLOW_PAD: 35,
YELLOW_ORB: 36,
MIRROR_PORTAL: 45,
UNMIRROR_PORTAL: 46,
BALL_PORTAL: 47,
BLUE_PAD: 67,
BLUE_ORB: 84,
NORMAL_SIZE_PORTAL: 99,
MINI_SIZE_PORTAL: 101,
OBJ_COLOR_TRIGGER: 105,
UFO_PORTAL: 111,
PINK_PAD: 140,
PINK_ORB: 141,
SECRET_COIN: 142,
BREAKABLE_BLOCK: 143,
SLOW_SPEED_PORTAL: 200,
NORMAL_SPEED_PORTAL: 201,
FAST_SPEED_PORTAL: 202,
VERY_FAST_SPEED_PORTAL: 203,
COLOR_1_TRIGGER: 221,
DUAL_PORTAL: 286,
UNDUAL_PORTAL: 287,
WAVE_PORTAL: 660,
COLOR_2_TRIGGER: 717,
COLOR_3_TRIGGER: 718,
COLOR_4_TRIGGER: 743,
THREEDLINE_COLOR_TRIGGER: 744,
ROBOT_PORTAL: 745,
TELEPORT_PORTAL: 747,
COLOR_TRIGGER: 899,
GROUND2_COLOR_TRIGGER: 900,
MOVE_TRIGGER: 901,
TEXT: 914,
LINE_COLOR_TRIGGER: 915,
PULSE_TRIGGER: 1006,
ALPHA_TRIGGER: 1007,
GREEN_ORB: 1022,
TOGGLE_TRIGGER: 1049,
SPAWN_TRIGGER: 1268,
BLACK_ORB: 1330,
SPIDER_PORTAL: 1331,
RED_PAD: 1332,
RED_ORB: 1333,
VERY_VERY_FAST_SPEED_PORTAL: 1334,
ROTATE_TRIGGER: 1346,
TOGGLE_ORB: 1594,
COUNT_TRIGGER: 1611,
COUNTER: 1615,
STOP_TRIGGER: 1616,
DASH_ORB: 1704,
PINK_DASH_ORB: 1751,
D_BLOCK: 1755,
INSTANT_COUNT_TRIGGER: 1811,
J_BLOCK: 1813,
COLLISION_TRIGGER: 1815,
COLLISION_BLOCK: 1816,
PICKUP_TRIGGER: 1817,
S_BLOCK: 1829,
H_BLOCK: 1859,
RANDOM_TRIGGER: 1912,
SWING_PORTAL: 1933,
CHECKPOINT: 2063,
ORANGE_TELEPORT_PORTAL: 2064,
PARTICLE_EMITTER: 2065,
SCALE_TRIGGER: 2067,
SQUARE_FORCE_BLOCK: 2069,
F_BLOCK: 2866,
TEMPLATE_BLOCK: 2895,
TEMPLATE_SLOPE: 2896,
TEMPLATE_GENTLE_SLOPE: 2897,
OPTIONS_TRIGGER: 2899,
BLUE_TELEPORT_PORTAL: 2902,
SHADER_TRIGGER: 2904,
SHOCKWAVE_SHADER_TRIGGER: 2905,
FLIP_GRAVITY_PORTAL: 2926,
SPIDER_ORB: 3004,
SPIDER_PAD: 3005,
TELEPORT_ORB: 3027,
END_TRIGGER: 3600,
SFX_TRIGGER: 3602,
EDIT_SFX_TRIGGER: 3603,
EVENT_TRIGGER: 3604,
EDIT_SONG_TRIGGER: 3605,
BG_SPEED_TRIGGER: 3606,
SEQUENCE_TRIGGER: 3607,
SPAWN_PARTICLE_TRIGGER: 3608,
INSTANT_COLLISION_TRIGGER: 3609,
HAZARD_SQUARE: 3610,
HAZARD_CIRCLE: 3611,
MG_SPEED_TRIGGER: 3612,
UI_TRIGGER: 3613,
TIME_TRIGGER: 3614,
TIME_EVENT_TRIGGER: 3615,
TIME_CONTROL_TRIGGER: 3617,
RESET_TRIGGER: 3618,
ITEM_EDIT_TRIGGER: 3619,
ITEM_COMP_TRIGGER: 3620,
ITEM_PERS_TRIGGER: 3641,
BPM_TRIGGER: 3642,
CIRCLE_FORCE_BLOCK: 3645
}
for (let i of Object.entries(OBJECT_IDS)) {
OBJECT_IDS[i[1]] = i[0]
}
export const ROTATING_OBJECTS = [85, 86, 87, 88, 89, 97, 98, 137, 138, 139, 154, 155, 156, 180, 181, 182, 183, 184, 185, 186, 187, 188, 222, 223, 224, 375, 376, 377, 378, 394, 395, 396, 397, 398, 399, 675, 676, 677, 678, 679, 680, 740, 741, 742, 997, 998, 999, 1000, 1019, 1020, 1021, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1582, 1619, 1620, 1705, 1706, 1707, 1708, 1709, 1710, 1734, 1735, 1736, 1752, 1831, 1832, 1833, 1834]
export const ROTATING_ORBS = [1022, 1330]
export const ANIMATED_OBJECTS = [920, 921, 923, 924, 1050, 1051, 1052, 1053, 1054, 1329, 1516, 1518, 1519, 1583, 1591, 1592, 1593, 1618, 1697, 1698, 1699, 1839, 1840, 1841, 1842, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1860, 1936, 1937, 1938, 1939, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2223, 2246, 2605, 2629, 2630, 2694, 2864, 2865, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 3000, 3001, 3002, 3119, 3120, 3121, 3219, 3303, 3304, 3482, 3483, 3484, 3492, 3493, 4211, 4300]
export const Z_LAYERS = {
"-5": "B5",
"-3": "B4",
"-1": "B3",
"1": "B2",
"3": "B1",
"5": "T1",
"7": "T2",
"9": "T3",
"11": "T4",
B5: -5,
B4: -3,
B3: -1,
B2: 1,
B1: 3,
T1: 5,
T2: 7,
T3: 9,
T4: 11
}
export const TRIGGER_LAYERS = {
BG: 1,
MG: 2,
B5: 3,
B4: 4,
B3: 5,
B2: 6,
B1: 7,
P: 8,
T1: 9,
T2: 10,
T3: 11,
T4: 12,
G: 13,
UI: 14,
MAX: 15,
1: "BG",
2: "MG",
3: "B5",
4: "B4",
5: "B3",
6: "B2",
7: "B1",
8: "P",
9: "T1",
10: "T2",
11: "T3",
12: "T4",
13: "G",
14: "UI",
15: "MAX"
}
export const EASINGS = {
0: "NONE",
1: "EASE_IN_OUT",
2: "EASE_IN",
3: "EASE_OUT",
4: "ELASTIC_IN_OUT",
5: "ELASTIC_IN",
6: "ELASTIC_OUT",
7: "BOUNCE_IN_OUT",
8: "BOUNCE_IN",
9: "BOUNCE_OUT",
10: "EXPONENTIAL_IN_OUT",
11: "EXPONENTIAL_IN",
12: "EXPONENTIAL_OUT",
13: "SINE_IN_OUT",
14: "SINE_IN",
15: "SINE_OUT",
16: "BACK_IN_OUT",
17: "BACK_IN",
18: "BACK_OUT",
}
export class LevelData {
constructor(version) {
version = Number(version)
if (isNaN(version) || version < 10 || version > 22 || Math.floor(version) != version) {
throw new Error("Invalid level version. Acceptable values are 10-22")
}
this.settings = new LevelSettings()
this.objects = []
this.version = version
}
static fromString(string) {
let b64 = utils.base64DecodeBuffer(string)
let str = utils.tryUnzip(b64)
if (Buffer.compare(b64, Buffer.from(str)) == 0) {
str = string
}
return str
}
toString() {
}
addObject(object) {
this.objects.push(object)
}
}
export class LevelSettings {
constructor(opts) {
this.colors = {}
for (let i of Object.entries(opts)) {
this[i[0]] = i[1]
}
}
toString() {
}
}
export class LevelObject {
constructor(id, x, y) {
this.id = parseInt(id) || 1
this.x = parseFloat(x) || 0
this.y = parseFloat(y) || 0
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = new LevelObject(dict["1"], dict["2"], dict["3"])
function importBool(key, name) {
if (!!Number(dict[key])) obj[name] = true
}
function importInt(key, name) {
if (Number(dict[key])) obj[name] = parseInt(dict[key]) || 0
}
importBool("96", "noGlow")
importBool("134", "passable")
importBool("511", "extendedCollision")
importBool("136", "nonStickX")
importBool("289", "nonStickY")
importBool("495", "extraSticky")
importBool("496", "dontBoostY")
importBool("509", "dontBoostX")
importBool("356", "scaleStick")
importBool("372", "noAudioScale")
importInt("497", "singleColorType")
importBool("137", "ice")
importBool("193", "gripSlope")
importBool("121", "noTouch")
importInt("343", "enterChannel")
importInt("446", "material")
importBool("4", "flipH")
importBool("5", "flipV")
importInt("108", "linkedGroup")
importInt("20", "layer")
importInt("61", "layer2")
importBool("103", "highDetail")
if (dict["57"]) obj.groupIDs = dict["57"].split(".").map(e => parseInt(e))
if (dict["274"]) obj.groupParentIDs = dict["274"].split(".").map(e => parseInt(e))
importBool("64", "dontFade")
importBool("67", "dontEnter")
importBool("116", "noEffects")
importBool("507", "noParticles")
importInt("155", "unk155")
importInt("156", "unk156")
importInt("53", "unk53")
importInt("25", "zOrder")
importInt("131", "rotationY")
importInt("132", "rotationX")
if (!obj.rotationY && !obj.rotationX) importInt("6", "rotation")
importInt("21", "baseColorID")
importInt("22", "detailColorID")
importInt("24", "zLayer")
importInt("128", "scaleX")
importInt("129", "scaleY")
if (!obj.scaleY && !obj.scaleX) importInt("32", "scale")
importBool("34", "groupParent")
importBool("279", "areaParent")
importBool("41", "baseHSVEnabled")
importBool("42", "detailHSVEnabled")
if (dict["43"]) obj.baseHSV = HSV.fromString(dict["43"])
if (dict["44"]) obj.detailHSV = HSV.fromString(dict["44"])
return obj
}
toString() {
let str = `1,${this.id},2,${this.x},3,${this.y}`
function exportBool(key, name) {
if (this[name]) str += `,${key},1`
}
function exportInt(key, name, val) {
if (!val) {
if (this[name]) str += `,${key},${parseInt(this[name])}`
} else {
if (this[name] != val) str += `,${key},${parseInt(this[name])}`
}
}
exportBool("96", "noGlow")
exportBool("134", "passable")
exportBool("511", "extendedCollision")
exportBool("136", "nonStickX")
exportBool("289", "nonStickY")
exportBool("495", "extraSticky")
exportBool("496", "dontBoostY")
exportBool("509", "dontBoostX")
exportBool("356", "scaleStick")
exportBool("372", "noAudioScale")
exportInt("497", "singleColorType")
exportBool("137", "ice")
exportBool("193", "gripSlope")
exportBool("121", "noTouch")
exportInt("343", "enterChannel")
exportInt("446", "material")
exportBool("4", "flipH")
exportBool("5", "flipV")
exportInt("108", "linkedGroup")
exportInt("20", "layer")
exportInt("61", "layer2")
exportBool("103", "highDetail")
if (this.groupIDs) str += `,57,${this.groupIDs.join(".")}`
if (this.groupParentIDs) str += `,274,${this.groupParentIDs.join(".")}`
exportBool("64", "dontFade")
exportBool("67", "dontEnter")
exportBool("116", "noEffects")
exportBool("507", "noParticles")
exportInt("155", "unk155")
exportInt("156", "unk156")
exportInt("53", "unk53")
exportInt("25", "zOrder")
if (this.rotation) {
str += `,6,${this.rotation}`
} else if (this.rotationX || this.rotationY) {
if (this.rotationX == this.rotationY) {
str += `,6,`
} else {
str += `,131,${parseInt(this.rotationY) || 0},132,`
}
str += `${parseInt(this.rotationX) || 0}`
}
exportInt("21", "baseColorID")
exportInt("22", "detailColorID")
exportInt("24", "zLayer")
exportInt("32", "scale", 1)
exportInt("128", "scaleX", 1)
exportInt("129", "scaleY", 1)
exportBool("34", "groupParent")
exportBool("279", "areaParent")
if (this.baseHSV) {
str += `,41,1,43,${this.baseHSV}`
}
if (this.detailHSV) {
str += `,42,1,44,${this.detailHSV}`
}
return str
}
}
export class RotatingObject extends LevelObject {
constructor(id, x, y, rotationSpeed, disableRotation) {
super(id, x, y)
this.rotationSpeed = parseInt(rotationSpeed) || 0
this.disableRotation = !!disableRotation
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = super.fromString(string)
function importBool(key, name) {
if (!!Number(dict[key])) obj[name] = true
}
function importInt(key, name) {
if (Number(dict[key])) obj[name] = parseInt(dict[key]) || 0
}
importInt("97", "rotationSpeed")
importBool("98", "disableRotation")
return obj
}
toString() {
let str = super.toString()
function exportBool(key, name) {
if (this[name]) str += `,${key},1`
}
function exportInt(key, name, val) {
if (!val) {
if (this[name]) str += `,${key},${parseInt(this[name])}`
} else {
if (this[name] != val) str += `,${key},${parseInt(this[name])}`
}
}
exportInt("97", "rotationSpeed")
exportBool("98", "disableRotation")
return str
}
}
export class AnimatedObject extends LevelObject {
constructor(id, x, y, rotationSpeed, disableRotation) {
super(id, x, y)
this.rotationSpeed = parseInt(rotationSpeed) || 0
this.disableRotation = !!disableRotation
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = super.fromString(string)
function importBool(key, name) {
if (!!Number(dict[key])) obj[name] = true
}
function importInt(key, name) {
if (Number(dict[key])) obj[name] = parseInt(dict[key]) || 0
}
function importFloat(key, name) {
if (Number(dict[key])) obj[name] = parseFloat(dict[key]) || 0
}
importBool("106", "randomizeStart")
importBool("126", "disableDelayedLoop")
importBool("122", "useSpeed")
importFloat("107", "animationSpeed")
importBool("127", "disableAnimShine")
importBool("123", "animateOnTrigger")
importBool("214", "onlyIfActive")
importInt("462", "singleFrame")
importBool("592", "offsetAnim")
return obj
}
toString() {
let str = super.toString()
function exportBool(key, name) {
if (this[name]) str += `,${key},1`
}
function exportInt(key, name, val) {
if (!val) {
if (this[name]) str += `,${key},${parseInt(this[name])}`
} else {
if (this[name] != val) str += `,${key},${parseInt(this[name])}`
}
}
function exportFloat(key, name) {
if (Number(dict[key])) obj[name] = parseFloat(dict[key]) || 0
}
exportBool("106", "randomizeStart")
exportBool("126", "disableDelayedLoop")
exportBool("122", "useSpeed")
exportFloat("107", "animationSpeed")
exportBool("127", "disableAnimShine")
exportBool("123", "animateOnTrigger")
exportBool("214", "onlyIfActive")
exportInt("462", "singleFrame")
exportBool("592", "offsetAnim")
return str
}
}
export class ParticleEmitter extends AnimatedObject {
constructor(x, y, particleData, animateOnTrigger, animateActiveOnly) {
super(OBJECT_IDS.PARTICLE_EMITTER, x, y)
this.particleData = particleData
this.animateOnTrigger = !!animateOnTrigger
this.onlyIfActive = !!animateActiveOnly
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = super.fromString(string)
function importBool(key, name) {
if (!!Number(dict[key])) obj[name] = true
}
if (dict["145"]) obj.particleData = ParticleData.fromString(dict["145"])
importBool("146", "useObjColor")
if (!!Number(dict["147"])) obj.particleData.uniformObjColor = true
importBool("211", "quickStart")
return obj
}
toString() {
let str = super.toString()
function exportBool(key, name) {
if (this[name]) str += `,${key},1`
}
if (this.particleData) str += `,145,${obj.particleData}`
exportBool("146", "useObjColor")
if (this.particleData.uniformObjColor) str += `,147,1`
exportBool("211", "quickStart")
return str
}
}
export class Trigger extends LevelObject {
constructor(id, x, y) {
super(id, x, y)
}
}
export class MoveTrigger extends LevelObject {
constructor(x, y, groupId, ) {
super(OBJECT_IDS.MOVE_TRIGGER, x, y)
this.rotationSpeed = parseInt(rotationSpeed) || 0
this.disableRotation = !!disableRotation
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = super.fromString(string)
function importBool(key, name) {
if (!!Number(dict[key])) obj[name] = true
}
function importInt(key, name) {
if (Number(dict[key])) obj[name] = parseInt(dict[key]) || 0
}
importInt("97", "rotationSpeed")
importBool("98", "disableRotation")
return obj
}
toString() {
let str = super.toString()
function exportBool(key, name) {
if (this[name]) str += `,${key},1`
}
function exportInt(key, name, val) {
if (!val) {
if (this[name]) str += `,${key},${parseInt(this[name])}`
} else {
if (this[name] != val) str += `,${key},${parseInt(this[name])}`
}
}
exportInt("97", "rotationSpeed")
exportBool("98", "disableRotation")
return str
}
}
export class Color {
constructor(id, red, green, blue, opacity, blending) {
this.id = id
this.red = red
this.green = green
this.blue = blue
this.opacity = opacity || 1
this.blending = !!blending
this.enableOpacity = true
}
toString() {
let string = `1_${this.red}_2_${this.green}_3_${this.blue}_6_${this.id}`
if (this.playerColor) string += `_4_${this.playerColor}`
if (this.blending) string += `_5_${Number(!!this.blending)}`
if (this.opacity) string += `_7_${this.opacity}`
if (this.enableOpacity != undefined) string += `_8_${Number(!!this.enableOpacity)}`
if (this.copiedColor) string += `_9_${this.copiedColor}`
if (this.hsv) string += `_10_${this.hsv.toString()}`
if (this.copyOpacity) string += `_17_${Number(!!this.copyOpacity)}`
}
}
export class TextObject extends LevelObject {
constructor(x, y, text, kerning) {
super(OBJECT_IDS.TEXT_OBJECT, x, y)
this.text = text
this.kerning = kerning || 0
}
static fromString(string) {
let dict = utils.robTopSplitDict(string.split(";")[0], ",")
let obj = super.fromString(string)
if (dict["31"]) obj.text = utils.base64Decode(dict["31"])
if (Number(dict["488"])) obj.kerning = parseInt(dict["488"]) || 0
return obj
}
toString() {
let str = super.toString()
if (this.text) str += `,31,${utils.base64Encode(this.text)}`
if (Number(this.kerning)) str += `,488,${parseInt(this.kerning) || 0}`
return str
}
}
export class ShaderTrigger extends LevelObject {
constructor(x, y, lowestLayer, highestLayer, noPlayerParticles, disableAll, touchTrigger, spawnTrigger, multiTrigger) {
super(OBJECT_IDS.SHADER_TRIGGER, x, y)
this.lowestLayer = parseInt(lowestLayer) || TRIGGER_LAYERS.BG
this.highestLayer = parseInt(highestLayer) || TRIGGER_LAYERS.MAX
this.shaderParam13 = !!noPlayerParticles
this.shaderParam17 = !!disableAll
this.touchTriggered = !!touchTrigger
this.spawnTriggered = !!spawnTrigger
this.multiTriggered = !!multiTrigger
}
}
export class ShockwaveShaderTrigger extends LevelObject {
constructor(x, y, opts, touchTrigger, spawnTrigger, multiTrigger) {
// speed, strength, thickness, waveW, fadeIn, fadeOut, timeOff, maxSize, invert, target, relative, screenOffX, screenOffY, centerID, p1, p2, follow, inner, outer, animate, fadeTime, easing,
super(OBJECT_IDS.SHOCKWAVE_SHADER_TRIGGER, x, y)
this.shaderParam1 = parseFloat(opts.speed) || 1
this.shaderParam2 = parseFloat(opts.strength) || 1
this.shockTimeOff = parseFloat(opts.timeOff) || 0
this.shaderParam4 = parseFloat(opts.waveW) || 1
this.shaderParam5 = parseFloat(opts.thickness) || 1
this.shaderParam6 = parseFloat(opts.fadeIn) || 1
this.shaderParam7 = parseFloat(opts.fadeOut) || 1
this.shockWaveInner = parseFloat(opts.inner) || 0
this.shockInvert = !!opts.invert
this.shaderParam13 = !!opts.target
this.shaderParam15 = !!opts.follow
this.shaderParam16 = parseFloat(opts.outer) || 1
this.targetGroupID = parseInt(opts.centerID) || 0
this.touchTriggered = !!touchTrigger
this.spawnTriggered = !!spawnTrigger
this.multiTriggered = !!multiTrigger
}
}
export class HSV {
constructor(hue, saturation, value, saturationAbsolute, valueAbsolute) {
this.hue = (hue && !isNaN(Number(hue))) ? Number(hue) : 0
this.saturation = (saturation && !isNaN(Number(saturation))) ? Number(saturation) : 1
this.value = (value && !isNaN(Number(value))) ? Number(value) : 1
this.saturationAbsolute = !!saturationAbsolute
this.valueAbsolute = !!valueAbsolute
}
static fromString(string) {
let values = string.split("a")
return new HSV(Number(values[0]), Number(values[1]), Number(values[2]), !!Number(values[3]), !!Number(values[4]))
}
toString() {
return `${this.hue}a${this.saturation}a${this.value}a${Number(!!this.saturationAbsolute)}a${Number(!!this.valueAbsolute)}`
}
}
export class ParticleData {
constructor() {
// 30a-1a1a0.3a30a90a90a29a0a11a0a0a0a0a0a0a0a2a1a0a0a1a0a1a0a1a0a1a0a1a1a0a0a1a0a1a0a1a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a0a0a0a0a0a0a0
this.maxParticles = 30
this.duration = -1
this.lifetime = 1
this.lifetimeMargin = 0.3
this.emission = 30
this.angle = 90
this.angleMargin = 90
this.speed = 29
this.speedMargin = 0
this.posVarX = 11
this.posVarY = 0
this.gravityX = 0
this.gravityY = 0
this.accelRad = 0
this.accelRadMargin = 0
this.accelTan = 0
this.accelTanMargin = 0
this.startSize = 2
this.startSizeMargin = 1
this.startSpin = 2
this.startSpinMargin = 1
this.startRed = 1
this.startRedMargin = 0
this.startGreen = 1
this.startGreenMargin = 0
this.startBlue = 1
this.startBlueMargin = 0
this.startAlpha = 1
this.startAlphaMargin = 0
this.endSize = 2
this.endSizeMargin = 1
this.endSpin = 2
this.endSpinMargin = 1
this.endRed = 1
this.endRedMargin = 0
this.endGreen = 1
this.endGreenMargin = 0
this.endBlue = 1
this.endBlueMargin = 0
this.endAlpha = 1
this.endAlphaMargin = 0
this.fadeIn = 0
this.fadeInMargin = 0
this.fadeOut = 0
this.fadeOutMargin = 0
this.startRad = 0
this.startRadMargin = 0
this.endRad = 0
this.endRadMargin = 0
this.rotSec = 0
this.rotSecMargin = 0
this.mode = 0
this.extraMode = 0
this.additiveColor = true
this.startSpinEqualsEnd = false
this.startRotIsDir = false
this.dynamicRotation = false
this.texture = 0
this.uniformObjColor = false
this.frictionP = 0
this.frictionPMargin = 0
this.respawn = 0
this.respawnMargin = 0
this.orderSensitive = false
this.startSizeEqualsEnd = false
this.startRGBVarSync = false
this.endRGBVarSync = false
this.frictionS = 0
this.frictionSMargin = 0
this.frictionR = 0
this.frictionRMargin = 0
}
static fromString(string) {
let values = string.split("a")
let particle = new ParticleData()
particle.maxParticles = Number(values[0])
particle.duration = Number(values[1])
particle.lifetime = Number(values[2])
particle.lifetimeMargin = Number(values[3])
particle.emission = Number(values[4])
particle.angle = Number(values[5])
particle.angleMargin = Number(values[6])
particle.speed = Number(values[7])
particle.speedMargin = Number(values[8])
particle.posVarX = Number(values[9])
particle.posVarY = Number(values[10])
particle.gravityX = Number(values[11])
particle.gravityY = Number(values[12])
particle.accelRad = Number(values[13])
particle.accelRadMargin = Number(values[14])
particle.accelTan = Number(values[15])
particle.accelTanMargin = Number(values[16])
particle.startSize = Number(values[17])
particle.startSizeMargin = Number(values[18])
particle.startSpin = Number(values[19])
particle.startSpinMargin = Number(values[20])
particle.startRed = Number(values[21])
particle.startRedMargin = Number(values[22])
particle.startGreen = Number(values[23])
particle.startGreenMargin = Number(values[24])
particle.startBlue = Number(values[25])
particle.startBlueMargin = Number(values[26])
particle.startAlpha = Number(values[27])
particle.startAlphaMargin = Number(values[28])
particle.endSize = Number(values[29])
particle.endSizeMargin = Number(values[30])
particle.endSpin = Number(values[31])
particle.endSpinMargin = Number(values[32])
particle.endRed = Number(values[33])
particle.endRedMargin = Number(values[34])
particle.endGreen = Number(values[35])
particle.endGreenMargin = Number(values[36])
particle.endBlue = Number(values[37])
particle.endBlueMargin = Number(values[38])
particle.endAlpha = Number(values[39])
particle.endAlphaMargin = Number(values[40])
particle.fadeIn = Number(values[41])
particle.fadeInMargin = Number(values[42])
particle.fadeOut = Number(values[43])
particle.fadeOutMargin = Number(values[44])
particle.startRad = Number(values[45])
particle.startRadMargin = Number(values[46])
particle.endRad = Number(values[47])
particle.endRadMargin = Number(values[48])
particle.rotSec = Number(values[49])
particle.rotSecMargin = Number(values[50])
particle.mode = Number(values[51])
particle.extraMode = Number(values[52])
particle.additiveColor = !!Number(values[53])
particle.startSpinEqualsEnd = !!Number(values[54])
particle.startRotIsDir = !!Number(values[55])
particle.dynamicRotation = !!Number(values[56])
particle.texture = Number(values[57])
particle.uniformObjColor = !!Number(values[58])
particle.frictionP = Number(values[59])
particle.frictionPMargin = !!Number(values[60])
particle.respawn = Number(values[61])
particle.respawnMargin = Number(values[62])
particle.orderSensitive = !!Number(values[63])
particle.startSizeEqualsEnd = !!Number(values[64])
particle.startRGBVarSync = !!Number(values[65])
particle.endRGBVarSync = !!Number(values[66])
particle.frictionS = Number(values[67])
particle.frictionSMargin = Number(values[68])
particle.frictionR = Number(values[69])
particle.frictionRMargin = Number(values[70])
return particle
}
toString() {
return `${Number(this.maxParticles)}a${Number(this.duration)}a${Number(this.lifetime)}a${Number(this.lifetimeMargin)}a${Number(this.emission)}a${Number(this.angle)}a${Number(this.angleMargin)}a${Number(this.speed)}a${Number(this.speedMargin)}a${Number(this.posVarX)}a${Number(this.posVarY)}a${Number(this.gravityX)}a${Number(this.gravityY)}a${Number(this.accelRad)}a${Number(this.accelRadMargin)}a${Number(this.accelTan)}a${Number(this.accelTanMargin)}a${Number(this.startSize)}a${Number(this.startSizeMargin)}a${Number(this.startSpin)}a${Number(this.startSpinMargin)}a${Number(this.startRed)}a${Number(this.startRedMargin)}a${Number(this.startGreen)}a${Number(this.startGreenMargin)}a${Number(this.startBlue)}a${Number(this.startBlueMargin)}a${Number(this.startAlpha)}a${Number(this.startAlphaMargin)}a${Number(this.endSize)}a${Number(this.endSizeMargin)}a${Number(this.endSpin)}a${Number(this.endSpinMargin)}a${Number(this.endRed)}a${Number(this.endRedMargin)}a${Number(this.endGreen)}a${Number(this.endGreenMargin)}a${Number(this.endBlue)}a${Number(this.endBlueMargin)}a${Number(this.endAlpha)}a${Number(this.endAlphaMargin)}a${Number(this.fadeIn)}a${Number(this.fadeInMargin)}a${Number(this.fadeOut)}a${Number(this.fadeOutMargin)}a${Number(this.startRad)}a${Number(this.startRadMargin)}a${Number(this.endRad)}a${Number(this.endRadMargin)}a${Number(this.rotSec)}a${Number(this.rotSecMargin)}a${Number(this.mode)}a${Number(this.extraMode)}a${Number(this.additiveColor)}a${Number(this.startSpinEqualsEnd)}a${Number(this.startRotIsDir)}a${Number(this.dynamicRotation)}a${Number(this.texture)}a${Number(this.uniformObjColor)}a${Number(this.frictionP)}a${Number(this.frictionPMargin)}a${Number(this.respawn)}a${Number(this.respawnMargin)}a${Number(this.orderSensitive)}a${Number(this.startSizeEqualsEnd)}a${Number(this.startRGBVarSync)}a${Number(this.endRGBVarSync)}a${Number(this.frictionS)}a${Number(this.frictionSMargin)}a${Number(this.frictionR)}a${Number(this.frictionRMargin)}`
}
}