diff --git a/README.md b/README.md
index 8f4d51f8..24d415c6 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,6 @@
Known issues in the alpha:
- Some options are missing
- Week 6 still have no dialogue
-- Week 7 have no running tankman
Build instructions are below. Press TAB on the main menu to switch mods.
@@ -13,7 +12,7 @@ Also, `lime test windows` uses the source assets folder instead of the export on
## Codename Engine
-Codename Engine is a new Friday Night Funkin' Engine aimed for easier modding, along with extensiblity and ease of use.
+Codename Engine is a new Friday Night Funkin' Engine aimed at simplifying modding, along with extensiblity and ease of use.
### It includes many new features, as seen [here](FEATURES.md)
@@ -54,12 +53,10 @@ Latest builds for the engine can be found in the [Actions](https://github.com/Yo
-6. Once the installation is done, close Visual Studio Installer.
-7. Download and install [`git-scm`](https://git-scm.com/download/win).
+6. Once you finish downloading those components, download and install [`git-scm`](https://git-scm.com/download/win).
- Leave all installation options as default.
-8. Open the Codename Engine source folder, click on the address bar and type `cmd` to open a command prompt window.
-9. On the command prompt, run `update.bat`, and wait for the libraries to install.
-10. Once the libraries are installed, run `haxelib run lime test windows` to compile and launch the game (may take a long time)
+7. Run `update.bat` using cmd or double-clicking it, and wait for the libraries to install.
+8. Once the libraries are installed, run `haxelib run lime test windows` to compile and launch the game (may take a long time)
- ℹ You can run `haxelib run lime setup` to make the lime command global, allowing you to execute `lime test windows` directly.
diff --git a/art/veryimportant.png b/art/veryimportant.png
new file mode 100644
index 00000000..bbfb5482
Binary files /dev/null and b/art/veryimportant.png differ
diff --git a/assets/data/characters/bf-christmas.xml b/assets/data/characters/bf-christmas.xml
index 0be8b263..94a30701 100644
--- a/assets/data/characters/bf-christmas.xml
+++ b/assets/data/characters/bf-christmas.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/characters/bf-holding-gf.xml b/assets/data/characters/bf-holding-gf.xml
index 83d28039..555c83be 100644
--- a/assets/data/characters/bf-holding-gf.xml
+++ b/assets/data/characters/bf-holding-gf.xml
@@ -9,5 +9,5 @@
-
+
diff --git a/assets/data/characters/bf-pixel.xml b/assets/data/characters/bf-pixel.xml
index 8dce0b58..5658389c 100644
--- a/assets/data/characters/bf-pixel.xml
+++ b/assets/data/characters/bf-pixel.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/characters/pico-speakers.xml b/assets/data/characters/pico-speakers.xml
index 4cff7e01..519b5bf9 100644
--- a/assets/data/characters/pico-speakers.xml
+++ b/assets/data/characters/pico-speakers.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/characters/senpai-angry.xml b/assets/data/characters/senpai-angry.xml
index f40d7450..d0cd24fb 100644
--- a/assets/data/characters/senpai-angry.xml
+++ b/assets/data/characters/senpai-angry.xml
@@ -1,10 +1,8 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
diff --git a/assets/data/characters/senpai.xml b/assets/data/characters/senpai.xml
index e5bf62d3..eb9419f6 100644
--- a/assets/data/characters/senpai.xml
+++ b/assets/data/characters/senpai.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/characters/spirit.hx b/assets/data/characters/spirit.hx
new file mode 100644
index 00000000..137787e8
--- /dev/null
+++ b/assets/data/characters/spirit.hx
@@ -0,0 +1,16 @@
+import flixel.addons.effects.FlxTrail;
+
+var self = this;
+var trail:FlxTrail;
+function postCreate() {
+ trail = new FlxTrail(self, null, 4, 24, 0.3, 0.069);
+}
+
+var toAdd:Bool = true; // Using this just to make sure
+function update(elpased) {
+ if(toAdd) {
+ toAdd = false;
+ PlayState.instance.insert(PlayState.instance.members.indexOf(self), trail);
+ disableScript();
+ }
+}
\ No newline at end of file
diff --git a/assets/data/config/credits.xml b/assets/data/config/credits.xml
index c10e7b05..56a5cafd 100644
--- a/assets/data/config/credits.xml
+++ b/assets/data/config/credits.xml
@@ -1,5 +1,7 @@
diff --git a/assets/data/stages/limo.xml b/assets/data/stages/limo.xml
index 64f8b0c8..0adddccd 100644
--- a/assets/data/stages/limo.xml
+++ b/assets/data/stages/limo.xml
@@ -7,23 +7,23 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/assets/data/stages/mall-evil.hx b/assets/data/stages/mall-evil.hx
new file mode 100644
index 00000000..ef8685cf
--- /dev/null
+++ b/assets/data/stages/mall-evil.hx
@@ -0,0 +1,24 @@
+var idk:CustomShader = null;
+function create() {
+ if(!Options.gameplayShaders) {
+ disableScript();
+ return;
+ }
+
+ idk = new CustomShader('coloredVignette');
+ idk.color = [1, 0, 0];
+ camGame.addShader(idk);
+}
+
+var adder:Int = 0;
+function postUpdate(elapsed:Float) { // Doing it like this so at least the red bump doesnt look too much instant
+ var toAdd:Int = lerp(adder, 0, elapsed);
+ idk.amount = camGame.zoom * camHUD.zoom + toAdd;
+ idk.strength = (camGame.zoom - camHUD.zoom + toAdd) * 5;
+ if(adder > 0) adder -= 0.0001 * camZoomingStrength;
+}
+
+function beatHit() {
+ if(Options.camZoomOnBeat && camZooming && FlxG.camera.zoom < maxCamZoom && curBeat % camZoomingInterval == 0)
+ adder = 0.05 * camZoomingStrength;
+}
\ No newline at end of file
diff --git a/assets/data/stages/mall.xml b/assets/data/stages/mall.xml
index f78d6c2b..278b6561 100644
--- a/assets/data/stages/mall.xml
+++ b/assets/data/stages/mall.xml
@@ -3,17 +3,18 @@
-
+
-
+
-
+
+
diff --git a/assets/data/stages/philly.hx b/assets/data/stages/philly.hx
index 9f77a933..2a4b9780 100644
--- a/assets/data/stages/philly.hx
+++ b/assets/data/stages/philly.hx
@@ -19,6 +19,7 @@ var trainCooldown:Int = 0;
function create() {
// defaultCamZoom = 0.5;
+ phillyTrain.moves = true; // Def value false in funkinsprite
light.color = colors[curColor];
trainSound = FlxG.sound.load(Paths.sound("train_passes"));
}
diff --git a/assets/data/stages/school-evil.hx b/assets/data/stages/school-evil.hx
index a7cbdee4..af086dab 100644
--- a/assets/data/stages/school-evil.hx
+++ b/assets/data/stages/school-evil.hx
@@ -1,4 +1,9 @@
function create() {
importScript("data/scripts/pixel");
isSpooky = true;
+
+ // Make transition work between school types
+ if(PlayState.smoothTransitionData?.stage == "school") PlayState.smoothTransitionData.stage = curStage;
+
+ disableScript();
}
\ No newline at end of file
diff --git a/assets/data/stages/school.xml b/assets/data/stages/school.xml
index 4f734d04..73f6649c 100644
--- a/assets/data/stages/school.xml
+++ b/assets/data/stages/school.xml
@@ -1,5 +1,5 @@
-
+
@@ -11,10 +11,12 @@
+ antialiasing="false" scale="4.797" scroll="0.9" updateHitbox="true" type="loop"/>
-
+
+
+
+
-
+
@@ -28,11 +28,11 @@
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/data/weeks/weeks/week5.xml b/assets/data/weeks/weeks/week5.xml
index 063005a9..0c94627f 100644
--- a/assets/data/weeks/weeks/week5.xml
+++ b/assets/data/weeks/weeks/week5.xml
@@ -2,5 +2,5 @@
Cocoa
Eggnog
- Winter Horrorland
+ Winter Horrorland
\ No newline at end of file
diff --git a/assets/images/game/cutscenes/weeb/senpaiCrazy.png b/assets/images/game/cutscenes/weeb/senpaiCrazy.png
new file mode 100644
index 00000000..43989202
Binary files /dev/null and b/assets/images/game/cutscenes/weeb/senpaiCrazy.png differ
diff --git a/assets/images/game/cutscenes/weeb/senpaiCrazy.xml b/assets/images/game/cutscenes/weeb/senpaiCrazy.xml
new file mode 100644
index 00000000..07a2a09b
--- /dev/null
+++ b/assets/images/game/cutscenes/weeb/senpaiCrazy.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/school/animatedEvilSchool.png b/assets/images/stages/school/animatedEvilSchool.png
index 9ff993f2..fddca234 100644
Binary files a/assets/images/stages/school/animatedEvilSchool.png and b/assets/images/stages/school/animatedEvilSchool.png differ
diff --git a/assets/images/stages/school/animatedEvilSchool.xml b/assets/images/stages/school/animatedEvilSchool.xml
index 16ef5869..97b0cd4e 100644
--- a/assets/images/stages/school/animatedEvilSchool.xml
+++ b/assets/images/stages/school/animatedEvilSchool.xml
@@ -1,45 +1,46 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/school/bgFreaks.png b/assets/images/stages/school/bgFreaks.png
index 53777203..00487b13 100644
Binary files a/assets/images/stages/school/bgFreaks.png and b/assets/images/stages/school/bgFreaks.png differ
diff --git a/assets/images/stages/school/bgFreaks.xml b/assets/images/stages/school/bgFreaks.xml
index 8e0ae99d..f7685c65 100644
--- a/assets/images/stages/school/bgFreaks.xml
+++ b/assets/images/stages/school/bgFreaks.xml
@@ -1,65 +1,66 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/school/petals.png b/assets/images/stages/school/petals.png
index 921f62c5..5d9ff017 100644
Binary files a/assets/images/stages/school/petals.png and b/assets/images/stages/school/petals.png differ
diff --git a/assets/images/stages/school/petals.xml b/assets/images/stages/school/petals.xml
index 2f24d147..d42aecc6 100644
--- a/assets/images/stages/school/petals.xml
+++ b/assets/images/stages/school/petals.xml
@@ -1,61 +1,62 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/school/weebTrees.png b/assets/images/stages/school/weebTrees.png
index f9114cd5..e88ffa0e 100644
Binary files a/assets/images/stages/school/weebTrees.png and b/assets/images/stages/school/weebTrees.png differ
diff --git a/assets/images/stages/school/weebTrees.txt b/assets/images/stages/school/weebTrees.txt
deleted file mode 100644
index 7846c008..00000000
--- a/assets/images/stages/school/weebTrees.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-trees_0 = 0 0 512 512
-trees_1 = 513 0 512 512
-trees_2 = 1539 1026 512 512
-trees_3 = 2052 513 512 512
-trees_4 = 2565 0 512 512
-trees_5 = 3078 0 512 512
-trees_6 = 2565 513 512 512
-trees_7 = 2052 1026 512 512
-trees_8 = 2565 1026 512 512
-trees_9 = 3078 513 512 512
-trees_10 = 1026 0 512 512
-trees_11 = 0 513 512 512
-trees_12 = 513 513 512 512
-trees_13 = 0 1026 512 512
-trees_14 = 513 1026 512 512
-trees_15 = 1026 513 512 512
-trees_16 = 1026 1026 512 512
-trees_17 = 1539 0 512 512
-trees_18 = 1539 513 512 512
-trees_19 = 2052 0 512 512
\ No newline at end of file
diff --git a/assets/images/stages/school/weebTrees.xml b/assets/images/stages/school/weebTrees.xml
new file mode 100644
index 00000000..4f87bae0
--- /dev/null
+++ b/assets/images/stages/school/weebTrees.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/tank/tankmanKilled1.png b/assets/images/stages/tank/tankmanKilled1.png
index 566e743a..c6553402 100644
Binary files a/assets/images/stages/tank/tankmanKilled1.png and b/assets/images/stages/tank/tankmanKilled1.png differ
diff --git a/assets/images/stages/tank/tankmanKilled1.xml b/assets/images/stages/tank/tankmanKilled1.xml
index 0324c9e1..9ba72d98 100644
--- a/assets/images/stages/tank/tankmanKilled1.xml
+++ b/assets/images/stages/tank/tankmanKilled1.xml
@@ -14,14 +14,14 @@
-
+
-
+
-
+
-
-
+
+
@@ -34,13 +34,13 @@
-
+
-
+
-
+
-
+
diff --git a/assets/shaders/chromaticAberration.frag b/assets/shaders/chromaticAberration.frag
new file mode 100644
index 00000000..aa1ca662
--- /dev/null
+++ b/assets/shaders/chromaticAberration.frag
@@ -0,0 +1,17 @@
+#pragma header
+
+uniform vec2 redOff;
+uniform vec2 greenOff;
+uniform vec2 blueOff;
+
+void main()
+{
+ vec2 uv = getCamPos(openfl_TextureCoordv);
+ vec4 col;
+ col.r = textureCam(bitmap, uv + redOff).r;
+ col.g = textureCam(bitmap, uv + greenOff).g;
+ col.b = textureCam(bitmap, uv + blueOff).b;
+ col.a = texture2D(bitmap, openfl_TextureCoordv).a;
+
+ gl_FragColor = col;
+}
\ No newline at end of file
diff --git a/assets/shaders/coloredVignette.frag b/assets/shaders/coloredVignette.frag
new file mode 100644
index 00000000..a012e78f
--- /dev/null
+++ b/assets/shaders/coloredVignette.frag
@@ -0,0 +1,15 @@
+#pragma header
+
+uniform vec3 color;
+uniform float amount;
+uniform float strength;
+
+void main() {
+ vec2 uv = getCamPos(openfl_TextureCoordv);
+ vec3 col = pow(textureCam(bitmap, uv).rgb, vec3(1.0 / strength));
+
+ float vignette = mix(1.0, 1.0 - amount, distance(uv, vec2(0.5)));
+ col = pow(mix(col * color, col, vignette), vec3(strength));
+
+ gl_FragColor = vec4(col, 1.0);
+}
\ No newline at end of file
diff --git a/assets/songs/guns/cutscene.hx b/assets/songs/guns/cutscene.hx
index 9f4d2e75..af4d9be9 100644
--- a/assets/songs/guns/cutscene.hx
+++ b/assets/songs/guns/cutscene.hx
@@ -53,12 +53,4 @@ function focusOn(char) {
var camPos = char.getCameraPosition();
game.camFollow.setPosition(camPos.x, camPos.y);
camPos.put();
-}
-
-function update(elapsed:Float) {
- lipSync(tankTalk);
-}
-
-function lipSync(sound:FlxSound) {
- tankman.animateAtlas.anim.curFrame = Std.int(tankman.animateAtlas.anim.length / (sound.length-1) * sound.time);
}
\ No newline at end of file
diff --git a/assets/songs/roses/end-cutscene.hx b/assets/songs/roses/end-cutscene.hx
new file mode 100644
index 00000000..885a2b55
--- /dev/null
+++ b/assets/songs/roses/end-cutscene.hx
@@ -0,0 +1,71 @@
+static var roses_shouldPlayOnThorns = false;
+var self = this;
+__script__.setParent(PlayState.instance);
+
+function create() {
+ var red:FlxSprite;
+ red = new FlxSprite().makeSolid(FlxG.width + 100, FlxG.height + 100, 0xFFff1b31);
+ red.screenCenter();
+ red.scrollFactor.set();
+ red.alpha = 0;
+ add(red);
+
+ // reorder dad
+ remove(dad);
+ insert(PlayState.instance.members.indexOf(red) + 1, dad);
+
+ playDadUpdate = true;
+ dad.animation.finishCallback = (name:String) -> {
+ if(name == "idle") {
+ dad.animation.finishCallback = null;
+ playDadUpdate = false;
+
+ new FlxTimer().start(0.3, function(swagTimer:FlxTimer) {
+ red.alpha += 0.15;
+ camHUD.alpha -= 0.15;
+ var c = FlxMath.lerp(255, 0, red.alpha);
+ dad.color = FlxColor.fromRGB(c, c, c, 255);
+ if(red.alpha < 1) swagTimer.reset();
+ else {
+ if (Options.gameplayShaders) {
+ aberration = new CustomShader('chromaticAberration');
+ camGame.addShader(aberration);
+ change = true;
+ }
+
+ FlxG.camera.followLerp = 0;
+ FlxTween.tween(camGame.scroll, {x: -366, y: 192}, 3, {
+ ease: FlxEase.cubeInOut,
+ onComplete: (_) -> {
+ roses_shouldPlayOnThorns = true;
+ self.close();
+ }
+ });
+ }
+ });
+ }
+ }
+ if(dad.animation.curAnim.name != "idle")
+ dad.playAnim("idle", true);
+ else if(dad.animation.curAnim.finished)
+ dad.animation.finishCallback("idle");
+}
+
+var playDadUpdate = false;
+function postUpdate(elapsed) {
+ if(playDadUpdate)
+ dad.update(elapsed);
+}
+
+var change:Bool = false;
+var aberration:CustomShader = null;
+function update(elapsed:Float) {
+ if(change && intens < (Options.week6PixelPerfect ? 0.005 : 0.005)) setGeneralIntensity(intens + 0.00001);
+}
+
+var intens:Float = 0;
+function setGeneralIntensity(val:Float) {
+ intens = val;
+ aberration.redOff = [intens, 0];
+ aberration.blueOff = [-intens, 0];
+}
\ No newline at end of file
diff --git a/assets/songs/stress/cutscene.hx b/assets/songs/stress/cutscene.hx
index f57e4b72..dd55a3da 100644
--- a/assets/songs/stress/cutscene.hx
+++ b/assets/songs/stress/cutscene.hx
@@ -3,7 +3,7 @@ import funkin.system.FunkinSprite;
import funkin.options.Options;
var tankman, pico:FunkinSprite;
-var gf:Character;
+var bf, gf:Character;
var stressCutscene:FlxSound;
var step:Int = 0;
@@ -13,10 +13,15 @@ function create() {
game.persistentUpdate = true;
game.gf.visible = false;
- gf = new Character(game.gf.x, game.gf.y, "gf-tankmen");
+ gf = new Character(game.gf.x + game.gf.globalOffset.x - 115, game.gf.y + game.gf.globalOffset.y + 85, "gf-tankmen");
gf.scrollFactor.set(0.95, 0.95);
gf.playAnim("dance-cutscene");
- game.insert(game.members.indexOf(game.gf), gf);
+ game.insert(game.members.indexOf(game.gf) + 1, gf);
+
+ game.boyfriend.visible = false;
+ bf = new Character(game.boyfriend.x + game.boyfriend.globalOffset.x, game.boyfriend.y + game.boyfriend.globalOffset.y - 350, "boyfriend", true);
+ bf.scrollFactor.set(0.95, 0.95);
+ game.insert(game.members.indexOf(game.boyfriend) + 1, bf);
stressCutscene = FlxG.sound.load(Paths.sound(Options.naughtyness ? 'cutscenes/tank/stress' : 'cutscenes/tank/stress-censor'));
@@ -46,14 +51,13 @@ function create() {
pico.scrollFactor.set(0.95, 0.95);
pico.playAnim("idle");
pico.visible = false;
- game.insert(game.members.indexOf(game.gf), pico);
-
- game.insert(game.members.indexOf(game.dad), tankman);
+ game.insert(game.members.indexOf(game.gf) + 1, pico);
+ game.insert(game.members.indexOf(game.dad) + 1, tankman);
game.dad.visible = false;
-
focusOn(game.dad);
}
+
function update(elapsed) {
if (FlxG.keys.justPressed.F5)
FlxG.resetState();
@@ -78,6 +82,14 @@ function update(elapsed) {
FlxG.camera.zoom = 0.8;
step = 2;
pico.playAnim('saves', true);
+ game.remove(bf);
+ bf.destroy();
+ game.boyfriend.visible = true;
+ game.boyfriend.playAnim('bfCatch');
+ game.boyfriend.animation.finishCallback = function(anim:String) {
+ game.boyfriend.dance();
+ game.boyfriend.animation.finishCallback = null;
+ };
}
case 2:
if (stressCutscene.time > 19600) {
@@ -93,8 +105,22 @@ function update(elapsed) {
}
case 4:
lipSync(tankman, 19500, stressCutscene.length);
- if (pico.isAnimFinished() && pico.getAnimName() == "saves")
- pico.playAnim("idle");
+ pico.animation.finishCallback = pico.playAnim("idle");
+
+ if(stressCutscene.time > 31500) {
+ focusOn(game.boyfriend, true);
+ FlxG.camera.zoom = game.defaultCamZoom * 1.4;
+ FlxTween.tween(FlxG.camera, {zoom: FlxG.camera.zoom + 0.1}, 0.5, {ease: FlxEase.elasticOut});
+ game.boyfriend.playAnim('singUPmiss');
+ game.boyfriend.animation.finishCallback = function(anim:String)
+ {
+ FlxG.camera.zoom /= 1.4;
+ focusOn(game.dad, true);
+ game.boyfriend.dance();
+ game.boyfriend.animation.finishCallback = null;
+ };
+ step = 5;
+ }
}
}
@@ -102,8 +128,9 @@ function lipSync(char:FunkinSprite, begin:Float, end:Float) {
char.animateAtlas.anim.curFrame = Std.int(FlxMath.remapToRange(stressCutscene.time, begin, end, 0, char.animateAtlas.anim.length-1));
}
-function focusOn(char) {
+function focusOn(char, snap:Bool = false) {
var camPos = char.getCameraPosition();
game.camFollow.setPosition(camPos.x, camPos.y);
+ if(snap) FlxG.camera.snapToTarget();
camPos.put();
}
\ No newline at end of file
diff --git a/assets/songs/stress/scripts/tankmenRun.hx b/assets/songs/stress/scripts/tankmenRun.hx
new file mode 100644
index 00000000..2b519b11
--- /dev/null
+++ b/assets/songs/stress/scripts/tankmenRun.hx
@@ -0,0 +1,157 @@
+import flixel.FlxSprite;
+
+var tankmanRun:Array = [];
+var grpTankmanRun:FlxTypedGroup = [];
+
+var spawnTimes = []; // [[time, direction]]
+var tankmanPool = [];
+
+function recycleTankman() {
+ if(tankmanPool.length == 0) {
+ var a = new TankmenBG();
+ a.self = a;
+ a.fuckingnewfuckingnew();
+ return a;
+ } else {
+ return tankmanPool.shift(); // can be pop but it causes it to be less random
+ }
+}
+
+function getTankman(data:Array) {
+ var tankman:TankmenBG = recycleTankman();
+ tankman.strumTime = data[0];
+ tankman.resetShit(500, 200 + FlxG.random.int(50, 100), data[1] < 2);
+ return tankman;
+}
+
+function postCreate() {
+ grpTankmanRun = new FlxTypedGroup();
+ insert(members.indexOf(gf) - 1, grpTankmanRun);
+ if(inCutscene) grpTankmanRun.visible = false;
+
+ /*var tempTankman:TankmenBG = recycleTankman();
+ tempTankman.strumTime = 10;
+ tempTankman.resetShit(20, 600, true);
+ tankmanRun.push(tempTankman);
+ grpTankmanRun.add(tempTankman.sprite);*/
+ graphicCache.cache(Paths.image('stages/tank/tankmanKilled1'));
+
+ for (note in strumLines.members[2].notes.members) {
+ if (FlxG.random.bool(16)) {
+ spawnTimes.push([note.strumTime, note.noteData]);
+ }
+ }
+
+ //spawnTimes.reverse(); // no need to reverse it since the notes are already reversed
+}
+
+function onStartCountdown() {
+ if(PlayState.instance.seenCutscene) grpTankmanRun.visible = true;
+}
+
+function spawnTankmen() {
+ var time = Conductor.songPosition;
+ //trace(spawnTimes);
+ while(spawnTimes.length > 0 && spawnTimes[spawnTimes.length-1][0] - 1500 < time) {
+ var tankmen = getTankman(spawnTimes.pop());
+
+ //trace("Spawning Tankman", tankmen.sprite.offset, tankmen.goingRight);
+
+ tankmanRun.push(tankmen);
+ grpTankmanRun.add(tankmen.sprite);
+ }
+}
+
+function update(elapsed) {
+ spawnTankmen();
+
+ var length = tankmanRun.length;
+ for(i in 0...length) {
+ var reverseIndex = length - i - 1;
+ var tankmen = tankmanRun[reverseIndex];
+ tankmen.update(elapsed);
+ }
+}
+
+class TankmenBG
+{
+ var strumTime = 0;
+ var goingRight = false;
+ var tankSpeed = 0.7;
+
+ var endingOffset = null;
+ var sprite = null;
+
+ var self = null;
+ var killed = false;
+
+ var fuckingnewfuckingnew = function()
+ {
+ this.sprite = new FlxSprite();
+ var sprite = this.sprite;
+
+ sprite.frames = Paths.getSparrowAtlas('stages/tank/tankmanKilled1');
+ sprite.antialiasing = true;
+ sprite.animation.addByPrefix('run', 'tankman running', 24, true);
+
+ sprite.animation.play('run');
+
+ sprite.updateHitbox();
+
+ sprite.setGraphicSize(Std.int(sprite.width * 0.8));
+ sprite.updateHitbox();
+ }
+
+ var resetShit = function(x, y, isGoingRight)
+ {
+ var sprite = this.sprite;
+ sprite.revive();
+ sprite.setPosition(x, y);
+ sprite.offset.set(0, 0);
+ goingRight = isGoingRight;
+ endingOffset = FlxG.random.float(50, 200);
+ tankSpeed = FlxG.random.float(0.6, 1);
+ sprite.animation.remove("shot");
+ sprite.animation.addByPrefix('shot', 'John Shot ' + FlxG.random.int(1, 2), 24, false);
+ sprite.animation.play("run");
+ sprite.animation.curAnim.curFrame = FlxG.random.int(0, sprite.animation.curAnim.numFrames - 1);
+
+ killed = false;
+ sprite.flipX = goingRight;
+ }
+
+ var update = function(elapsed)
+ {
+ var sprite = this.sprite;
+ sprite.visible = !(sprite.x >= FlxG.width * 1.5 || sprite.x <= FlxG.width * -0.5);
+
+ if (sprite.animation.curAnim.name == 'run')
+ {
+ var endDirection:Float = (FlxG.width * 0.74) + endingOffset;
+
+ if (goingRight) {
+ endDirection = (FlxG.width * 0.02) - endingOffset;
+ sprite.x = (endDirection + (Conductor.songPosition - strumTime) * tankSpeed);
+ }
+ else sprite.x = (endDirection - (Conductor.songPosition - strumTime) * tankSpeed);
+ }
+
+ if (Conductor.songPosition > strumTime)
+ {
+ sprite.animation.play('shot');
+ sprite.animation.finishCallback = function(_) {
+ killed = true;
+ grpTankmanRun.remove(sprite, true);
+ sprite.kill();
+ tankmanPool.push(self);
+ tankmanRun.remove(self);
+ }
+
+ if (goingRight)
+ {
+ sprite.offset.y = 200;
+ sprite.offset.x = 300;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/songs/thorns/charts/easy.json b/assets/songs/thorns/charts/easy.json
index 0ff75236..dc496fa8 100644
--- a/assets/songs/thorns/charts/easy.json
+++ b/assets/songs/thorns/charts/easy.json
@@ -1 +1 @@
-{"song":{"stage":"school-evil","gf":"gf-pixel","song":"Thorns","bpm":190.0,"needsVoices":true,"player1":"bf-pixel","player2":"spirit","speed":1.1,"notes":[{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[0.0,3,157.89473],[631.5789,1,157.89473],[947.3684,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[1263.15784,3,0.0],[1736.842,3,0.0],[2210.52612,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[2526.31567,3,0.0],[2842.10522,3,0.0],[3157.89453,1,0.0],[3473.684,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[3789.47363,3,0.0],[4263.15771,3,0.0],[4736.842,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[5052.63135,3,157.89473],[5684.21045,1,157.89473],[5999.99951,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[6315.789,3,0.0],[6789.473,3,0.0],[7263.15771,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[7578.94727,3,0.0],[7894.73633,3,0.0],[8210.526,1,0.0],[8526.315,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[8842.10449,3,0.0],[9315.789,3,0.0],[9789.474,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[10105.2627,2,157.89473],[10736.8418,2,0.0],[10894.7363,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[11368.4209,2,157.89473],[11842.1045,2,157.89473],[12315.7891,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[12631.5781,2,157.89473],[13263.1572,2,0.0],[13421.0518,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[13894.7363,2,157.89473],[14368.42,2,157.89473],[14842.1045,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[15157.8945,2,157.89473],[15789.4727,2,0.0],[15947.3682,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[16421.0527,2,157.89473],[16894.7363,2,157.89473],[17368.42,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[17684.209,2,157.89473],[18315.79,2,0.0],[18473.6836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[18947.3672,2,157.89473],[19421.05,2,157.89473],[19894.7363,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[20210.5254,1,0.0],[20526.3145,3,0.0],[21000.0,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[21473.6836,2,0.0],[21947.3672,2,0.0],[22421.05,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[22736.8418,1,0.0],[23052.63,3,0.0],[23526.3145,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[23999.998,2,0.0],[24473.6836,2,0.0],[24789.4727,4,0.0],[24947.3672,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[25263.1563,1,0.0],[25578.9453,3,0.0],[26052.63,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[26526.3145,2,0.0],[26999.998,2,0.0],[27473.6836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[27789.4727,1,0.0],[28105.2617,3,0.0],[28578.9453,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[29052.63,2,0.0],[29526.3145,2,0.0],[29999.998,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[30315.79,2,0.0],[30631.5781,3,0.0],[30947.3672,3,0.0],[31263.1563,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[31578.9453,0,0.0],[31894.7363,0,0.0],[32210.5254,3,0.0],[32526.3145,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[32842.1055,0,0.0],[33157.8945,0,0.0],[33473.6836,0,0.0],[33789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[34105.26,1,0.0],[34421.05,1,0.0],[34736.84,1,0.0],[35052.63,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[35368.418,2,0.0],[35684.207,3,0.0],[36000.0,3,0.0],[36315.79,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[36631.58,0,0.0],[36947.3672,0,0.0],[37263.1563,3,0.0],[37578.9453,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[37894.7344,0,0.0],[38210.5234,0,0.0],[38526.3125,0,0.0],[38842.1,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[39157.8945,1,0.0],[39473.6836,1,0.0],[39789.4727,1,0.0],[40105.26,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[40421.05,0,0.0],[40736.84,0,0.0],[41052.63,3,0.0],[41368.418,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[41684.207,2,0.0],[42315.79,2,0.0],[42631.58,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[42947.3672,0,0.0],[43263.1563,0,0.0],[43578.9453,3,0.0],[43894.7344,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[44210.5234,2,0.0],[44842.1,2,0.0],[45157.8945,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[45473.6836,0,0.0],[45789.4727,0,0.0],[46105.26,3,0.0],[46421.05,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[46736.84,2,0.0],[47368.418,2,0.0],[47684.207,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[47999.9961,0,0.0],[48315.79,0,0.0],[48631.58,3,0.0],[48947.3672,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[49263.1563,2,0.0],[49894.7344,2,0.0],[50210.5234,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[50526.3125,3,157.89473],[51157.89,1,157.89473],[51473.6836,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[51789.4727,3,0.0],[52263.1563,3,0.0],[52736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[53052.63,3,0.0],[53368.418,3,0.0],[53684.207,1,0.0],[53999.9961,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[54315.7852,3,0.0],[54789.4727,3,0.0],[55263.1563,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[55578.9453,3,157.89473],[56210.5234,1,157.89473],[56526.3125,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[56842.1,3,0.0],[57315.7852,3,0.0],[57789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[58105.26,3,0.0],[58421.05,3,0.0],[58736.84,1,0.0],[59052.63,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[59368.418,3,0.0],[59842.1,3,0.0],[60315.7852,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[60631.58,2,0.0],[60947.3672,3,0.0],[61263.1563,3,0.0],[61578.9453,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[61894.7344,0,0.0],[62210.5234,0,0.0],[62526.3125,3,0.0],[62842.1,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[63157.89,0,0.0],[63473.68,0,0.0],[63789.4727,0,0.0],[64105.26,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[64421.05,1,0.0],[64736.84,1,0.0],[65052.63,1,0.0],[65368.418,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[65684.21,2,0.0],[66000.0,3,0.0],[66315.79,3,0.0],[66631.58,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[66947.37,0,0.0],[67263.16,0,0.0],[67578.9453,3,0.0],[67894.7344,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[68210.52,0,0.0],[68526.31,0,0.0],[68684.21,3,0.0],[68842.1,0,0.0],[69157.89,3,0.0],[69315.79,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[69473.68,1,0.0],[69789.47,1,0.0],[70105.26,1,0.0],[70421.05,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[70736.8359,0,0.0],[71052.625,0,0.0],[71368.4141,3,0.0],[71684.21,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[72000.0,2,0.0],[72631.58,2,0.0],[72947.37,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[73263.16,0,0.0],[73578.9453,0,0.0],[73894.7344,3,0.0],[74210.52,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[74526.31,2,0.0],[75157.89,2,0.0],[75473.68,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[75789.47,0,0.0],[76105.26,0,0.0],[76421.05,3,0.0],[76736.8359,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[77052.625,2,0.0],[77684.2,2,0.0],[78000.0,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[78315.79,0,0.0],[78631.58,0,0.0],[78947.37,3,0.0],[79263.16,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[79578.9453,2,0.0],[80210.52,2,0.0],[80526.31,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[80842.1,2,0.0],[81473.68,0,0.0],[81631.58,3,0.0],[81789.47,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[82105.26,2,0.0],[82736.8359,0,0.0],[82894.7344,3,0.0],[83052.625,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[83368.4141,2,0.0],[84000.0,0,0.0],[84157.89,3,0.0],[84315.79,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[84631.58,2,0.0],[85263.16,0,0.0],[85421.05,3,0.0],[85578.9453,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[85894.7344,2,0.0],[86526.31,0,0.0],[86684.2,3,0.0],[86842.1,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[87157.89,2,0.0],[87789.47,0,0.0],[87947.37,3,0.0],[88105.26,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[88421.05,2,0.0],[89052.625,0,0.0],[89210.52,3,0.0],[89368.4141,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[89684.2,2,0.0],[90315.79,0,0.0],[90473.68,3,0.0],[90631.58,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[90947.37,3,157.89473],[91578.9453,1,157.89473],[91894.7344,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[92210.52,3,0.0],[92684.2,3,0.0],[93157.89,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[93473.68,3,0.0],[93789.47,3,0.0],[94105.26,1,0.0],[94421.05,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[94736.8359,3,0.0],[95210.52,3,0.0],[95684.2,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[95999.99,3,157.89473],[96631.58,1,157.89473],[96947.37,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[97263.16,3,0.0],[97736.8359,3,0.0],[98210.52,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[98526.31,3,0.0],[98842.1,3,0.0],[99157.89,1,0.0],[99473.68,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[99789.47,3,0.0],[100263.156,3,0.0],[100736.836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]}]},"generatedBy":"SNIFF ver.6"}
\ No newline at end of file
+{"events":[{"params":[1],"name":"Camera Movement","time":5052.63157894737},{"params":[0],"name":"Camera Movement","time":10105.2631578947},{"params":[1],"name":"Camera Movement","time":15157.8947368421},{"params":[0],"name":"Camera Movement","time":20210.5263157895},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":20210.5263157895},{"params":[1],"name":"Camera Movement","time":25263.1578947368},{"params":[0],"name":"Camera Movement","time":30315.7894736842},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":30315.7894736842},{"params":[1],"name":"Camera Movement","time":35368.4210526316},{"params":[0],"name":"Camera Movement","time":40421.0526315789},{"params":[1],"name":"Camera Movement","time":45473.6842105263},{"params":[0],"name":"Camera Movement","time":50526.3157894737},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":50526.3157894737},{"params":[1],"name":"Camera Movement","time":55578.947368421},{"params":[0],"name":"Camera Movement","time":60631.5789473684},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":60631.5789473684},{"params":[1],"name":"Camera Movement","time":65684.2105263157},{"params":[0],"name":"Camera Movement","time":70736.8421052631},{"params":[1],"name":"Camera Movement","time":75789.4736842105},{"params":[0],"name":"Camera Movement","time":80842.1052631578},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":80842.1052631578},{"params":[1],"name":"Camera Movement","time":85894.7368421052},{"params":[0],"name":"Camera Movement","time":90947.3684210525},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":90947.3684210525},{"params":[1],"name":"Camera Movement","time":95999.9999999999}],"scrollSpeed":1.1,"strumLines":[{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":0,"type":0},{"id":1,"sLen":157.89473,"time":631.5789,"type":0},{"id":0,"sLen":0,"time":947.3684,"type":0},{"id":3,"sLen":0,"time":1263.15784,"type":0},{"id":3,"sLen":0,"time":1736.842,"type":0},{"id":3,"sLen":0,"time":2210.52612,"type":0},{"id":3,"sLen":0,"time":2526.31567,"type":0},{"id":3,"sLen":0,"time":2842.10522,"type":0},{"id":1,"sLen":0,"time":3157.89453,"type":0},{"id":0,"sLen":0,"time":3473.684,"type":0},{"id":3,"sLen":0,"time":3789.47363,"type":0},{"id":3,"sLen":0,"time":4263.15771,"type":0},{"id":3,"sLen":0,"time":4736.842,"type":0},{"id":2,"sLen":157.894729999998,"time":10105.2627,"type":0},{"id":2,"sLen":0,"time":10736.8418,"type":0},{"id":3,"sLen":0,"time":10894.7363,"type":0},{"id":2,"sLen":157.89473,"time":11368.4209,"type":0},{"id":2,"sLen":157.89473,"time":11842.1045,"type":0},{"id":2,"sLen":157.89473,"time":12315.7891,"type":0},{"id":2,"sLen":157.89473,"time":12631.5781,"type":0},{"id":2,"sLen":0,"time":13263.1572,"type":0},{"id":3,"sLen":0,"time":13421.0518,"type":0},{"id":2,"sLen":157.89473,"time":13894.7363,"type":0},{"id":2,"sLen":157.89473,"time":14368.42,"type":0},{"id":0,"sLen":157.89473,"time":14842.1045,"type":0},{"id":1,"sLen":0,"time":20210.5254,"type":0},{"id":3,"sLen":0,"time":20526.3145,"type":0},{"id":3,"sLen":0,"time":21000,"type":0},{"id":2,"sLen":0,"time":21473.6836,"type":0},{"id":2,"sLen":0,"time":21947.3672,"type":0},{"id":3,"sLen":0,"time":22421.05,"type":0},{"id":1,"sLen":0,"time":22736.8418,"type":0},{"id":3,"sLen":0,"time":23052.63,"type":0},{"id":3,"sLen":0,"time":23526.3145,"type":0},{"id":2,"sLen":0,"time":23999.998,"type":0},{"id":2,"sLen":0,"time":24473.6836,"type":0},{"id":3,"sLen":0,"time":24947.3672,"type":0},{"id":2,"sLen":0,"time":30315.79,"type":0},{"id":3,"sLen":0,"time":30631.5781,"type":0},{"id":3,"sLen":0,"time":30947.3672,"type":0},{"id":0,"sLen":0,"time":31263.1563,"type":0},{"id":0,"sLen":0,"time":31578.9453,"type":0},{"id":0,"sLen":0,"time":31894.7363,"type":0},{"id":3,"sLen":0,"time":32210.5254,"type":0},{"id":1,"sLen":0,"time":32526.3145,"type":0},{"id":0,"sLen":0,"time":32842.1055,"type":0},{"id":0,"sLen":0,"time":33157.8945,"type":0},{"id":0,"sLen":0,"time":33473.6836,"type":0},{"id":3,"sLen":0,"time":33789.4727,"type":0},{"id":1,"sLen":0,"time":34105.26,"type":0},{"id":1,"sLen":0,"time":34421.05,"type":0},{"id":1,"sLen":0,"time":34736.84,"type":0},{"id":1,"sLen":236.842100000002,"time":35052.63,"type":0},{"id":0,"sLen":0,"time":40421.05,"type":0},{"id":0,"sLen":0,"time":40736.84,"type":0},{"id":3,"sLen":0,"time":41052.63,"type":0},{"id":0,"sLen":0,"time":41368.418,"type":0},{"id":2,"sLen":0,"time":41684.207,"type":0},{"id":2,"sLen":0,"time":42315.79,"type":0},{"id":0,"sLen":0,"time":42631.58,"type":0},{"id":0,"sLen":0,"time":42947.3672,"type":0},{"id":0,"sLen":0,"time":43263.1563,"type":0},{"id":3,"sLen":0,"time":43578.9453,"type":0},{"id":0,"sLen":0,"time":43894.7344,"type":0},{"id":2,"sLen":0,"time":44210.5234,"type":0},{"id":2,"sLen":0,"time":44842.1,"type":0},{"id":3,"sLen":0,"time":45157.8945,"type":0},{"id":3,"sLen":157.89473,"time":50526.3125,"type":0},{"id":1,"sLen":157.89473,"time":51157.89,"type":0},{"id":0,"sLen":0,"time":51473.6836,"type":0},{"id":3,"sLen":0,"time":51789.4727,"type":0},{"id":3,"sLen":0,"time":52263.1563,"type":0},{"id":3,"sLen":0,"time":52736.84,"type":0},{"id":3,"sLen":0,"time":53052.63,"type":0},{"id":3,"sLen":0,"time":53368.418,"type":0},{"id":1,"sLen":0,"time":53684.207,"type":0},{"id":0,"sLen":0,"time":53999.9961,"type":0},{"id":3,"sLen":0,"time":54315.7852,"type":0},{"id":3,"sLen":0,"time":54789.4727,"type":0},{"id":3,"sLen":0,"time":55263.1563,"type":0},{"id":2,"sLen":0,"time":60631.58,"type":0},{"id":3,"sLen":0,"time":60947.3672,"type":0},{"id":3,"sLen":0,"time":61263.1563,"type":0},{"id":0,"sLen":0,"time":61578.9453,"type":0},{"id":0,"sLen":0,"time":61894.7344,"type":0},{"id":0,"sLen":0,"time":62210.5234,"type":0},{"id":3,"sLen":0,"time":62526.3125,"type":0},{"id":1,"sLen":0,"time":62842.1,"type":0},{"id":0,"sLen":0,"time":63157.89,"type":0},{"id":0,"sLen":0,"time":63473.68,"type":0},{"id":0,"sLen":0,"time":63789.4727,"type":0},{"id":3,"sLen":0,"time":64105.26,"type":0},{"id":1,"sLen":0,"time":64421.05,"type":0},{"id":1,"sLen":0,"time":64736.84,"type":0},{"id":1,"sLen":0,"time":65052.63,"type":0},{"id":1,"sLen":236.842100000002,"time":65368.418,"type":0},{"id":0,"sLen":0,"time":70736.8359,"type":0},{"id":0,"sLen":0,"time":71052.625,"type":0},{"id":3,"sLen":0,"time":71368.4141,"type":0},{"id":0,"sLen":0,"time":71684.21,"type":0},{"id":2,"sLen":0,"time":72000,"type":0},{"id":2,"sLen":0,"time":72631.58,"type":0},{"id":0,"sLen":0,"time":72947.37,"type":0},{"id":0,"sLen":0,"time":73263.16,"type":0},{"id":0,"sLen":0,"time":73578.9453,"type":0},{"id":3,"sLen":0,"time":73894.7344,"type":0},{"id":0,"sLen":0,"time":74210.52,"type":0},{"id":2,"sLen":0,"time":74526.31,"type":0},{"id":2,"sLen":0,"time":75157.89,"type":0},{"id":3,"sLen":0,"time":75473.68,"type":0},{"id":2,"sLen":0,"time":80842.1,"type":0},{"id":0,"sLen":0,"time":81473.68,"type":0},{"id":3,"sLen":0,"time":81631.58,"type":0},{"id":1,"sLen":0,"time":81789.47,"type":0},{"id":2,"sLen":0,"time":82105.26,"type":0},{"id":0,"sLen":0,"time":82736.8359,"type":0},{"id":3,"sLen":0,"time":82894.7344,"type":0},{"id":1,"sLen":0,"time":83052.625,"type":0},{"id":2,"sLen":0,"time":83368.4141,"type":0},{"id":0,"sLen":0,"time":84000,"type":0},{"id":3,"sLen":0,"time":84157.89,"type":0},{"id":1,"sLen":0,"time":84315.79,"type":0},{"id":2,"sLen":0,"time":84631.58,"type":0},{"id":0,"sLen":0,"time":85263.16,"type":0},{"id":3,"sLen":0,"time":85421.05,"type":0},{"id":1,"sLen":0,"time":85578.9453,"type":0},{"id":3,"sLen":157.89473,"time":90947.37,"type":0},{"id":1,"sLen":157.89473,"time":91578.9453,"type":0},{"id":0,"sLen":0,"time":91894.7344,"type":0},{"id":3,"sLen":0,"time":92210.52,"type":0},{"id":3,"sLen":0,"time":92684.2,"type":0},{"id":3,"sLen":0,"time":93157.89,"type":0},{"id":3,"sLen":0,"time":93473.68,"type":0},{"id":3,"sLen":0,"time":93789.47,"type":0},{"id":1,"sLen":0,"time":94105.26,"type":0},{"id":0,"sLen":0,"time":94421.05,"type":0},{"id":3,"sLen":0,"time":94736.8359,"type":0},{"id":3,"sLen":0,"time":95210.52,"type":0},{"id":3,"sLen":0,"time":95684.2,"type":0}],"position":"dad","type":0,"characters":["spirit"]},{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":5052.63135,"type":0},{"id":1,"sLen":157.89473,"time":5684.21045,"type":0},{"id":0,"sLen":0,"time":5999.99951,"type":0},{"id":3,"sLen":0,"time":6315.789,"type":0},{"id":3,"sLen":0,"time":6789.473,"type":0},{"id":3,"sLen":0,"time":7263.15771,"type":0},{"id":3,"sLen":0,"time":7578.94727,"type":0},{"id":3,"sLen":0,"time":7894.73633,"type":0},{"id":1,"sLen":0,"time":8210.526,"type":0},{"id":0,"sLen":0,"time":8526.315,"type":0},{"id":3,"sLen":0,"time":8842.10449,"type":0},{"id":3,"sLen":0,"time":9315.789,"type":0},{"id":3,"sLen":0,"time":9789.474,"type":0},{"id":2,"sLen":157.89473,"time":15157.8945,"type":0},{"id":2,"sLen":0,"time":15789.4727,"type":0},{"id":3,"sLen":0,"time":15947.3682,"type":0},{"id":2,"sLen":157.89473,"time":16421.0527,"type":0},{"id":2,"sLen":157.89473,"time":16894.7363,"type":0},{"id":2,"sLen":157.89473,"time":17368.42,"type":0},{"id":2,"sLen":157.89473,"time":17684.209,"type":0},{"id":2,"sLen":0,"time":18315.79,"type":0},{"id":3,"sLen":0,"time":18473.6836,"type":0},{"id":2,"sLen":157.89473,"time":18947.3672,"type":0},{"id":2,"sLen":157.89473,"time":19421.05,"type":0},{"id":0,"sLen":157.89473,"time":19894.7363,"type":0},{"id":0,"sLen":0,"time":24789.4727,"type":0},{"id":1,"sLen":0,"time":25263.1563,"type":0},{"id":3,"sLen":0,"time":25578.9453,"type":0},{"id":3,"sLen":0,"time":26052.63,"type":0},{"id":2,"sLen":0,"time":26526.3145,"type":0},{"id":2,"sLen":0,"time":26999.998,"type":0},{"id":3,"sLen":0,"time":27473.6836,"type":0},{"id":1,"sLen":0,"time":27789.4727,"type":0},{"id":3,"sLen":0,"time":28105.2617,"type":0},{"id":3,"sLen":0,"time":28578.9453,"type":0},{"id":2,"sLen":0,"time":29052.63,"type":0},{"id":2,"sLen":0,"time":29526.3145,"type":0},{"id":3,"sLen":0,"time":29999.998,"type":0},{"id":2,"sLen":0,"time":35368.418,"type":0},{"id":3,"sLen":0,"time":35684.207,"type":0},{"id":3,"sLen":0,"time":36000,"type":0},{"id":0,"sLen":0,"time":36315.79,"type":0},{"id":0,"sLen":0,"time":36631.58,"type":0},{"id":0,"sLen":0,"time":36947.3672,"type":0},{"id":3,"sLen":0,"time":37263.1563,"type":0},{"id":1,"sLen":0,"time":37578.9453,"type":0},{"id":0,"sLen":0,"time":37894.7344,"type":0},{"id":0,"sLen":0,"time":38210.5234,"type":0},{"id":0,"sLen":0,"time":38526.3125,"type":0},{"id":3,"sLen":0,"time":38842.1,"type":0},{"id":1,"sLen":0,"time":39157.8945,"type":0},{"id":1,"sLen":0,"time":39473.6836,"type":0},{"id":1,"sLen":0,"time":39789.4727,"type":0},{"id":1,"sLen":236.842100000002,"time":40105.26,"type":0},{"id":0,"sLen":0,"time":45473.6836,"type":0},{"id":0,"sLen":0,"time":45789.4727,"type":0},{"id":3,"sLen":0,"time":46105.26,"type":0},{"id":0,"sLen":0,"time":46421.05,"type":0},{"id":2,"sLen":0,"time":46736.84,"type":0},{"id":2,"sLen":0,"time":47368.418,"type":0},{"id":0,"sLen":0,"time":47684.207,"type":0},{"id":0,"sLen":0,"time":47999.9961,"type":0},{"id":0,"sLen":0,"time":48315.79,"type":0},{"id":3,"sLen":0,"time":48631.58,"type":0},{"id":0,"sLen":0,"time":48947.3672,"type":0},{"id":2,"sLen":0,"time":49263.1563,"type":0},{"id":2,"sLen":0,"time":49894.7344,"type":0},{"id":3,"sLen":0,"time":50210.5234,"type":0},{"id":3,"sLen":157.89473,"time":55578.9453,"type":0},{"id":1,"sLen":157.89473,"time":56210.5234,"type":0},{"id":0,"sLen":0,"time":56526.3125,"type":0},{"id":3,"sLen":0,"time":56842.1,"type":0},{"id":3,"sLen":0,"time":57315.7852,"type":0},{"id":3,"sLen":0,"time":57789.4727,"type":0},{"id":3,"sLen":0,"time":58105.26,"type":0},{"id":3,"sLen":0,"time":58421.05,"type":0},{"id":1,"sLen":0,"time":58736.84,"type":0},{"id":0,"sLen":0,"time":59052.63,"type":0},{"id":3,"sLen":0,"time":59368.418,"type":0},{"id":3,"sLen":0,"time":59842.1,"type":0},{"id":3,"sLen":0,"time":60315.7852,"type":0},{"id":2,"sLen":0,"time":65684.21,"type":0},{"id":3,"sLen":0,"time":66000,"type":0},{"id":3,"sLen":0,"time":66315.79,"type":0},{"id":0,"sLen":0,"time":66631.58,"type":0},{"id":0,"sLen":0,"time":66947.37,"type":0},{"id":0,"sLen":0,"time":67263.16,"type":0},{"id":3,"sLen":0,"time":67578.9453,"type":0},{"id":1,"sLen":0,"time":67894.7344,"type":0},{"id":0,"sLen":0,"time":68210.52,"type":0},{"id":0,"sLen":0,"time":68526.31,"type":0},{"id":3,"sLen":0,"time":68684.21,"type":0},{"id":0,"sLen":0,"time":68842.1,"type":0},{"id":3,"sLen":0,"time":69157.89,"type":0},{"id":1,"sLen":0,"time":69315.79,"type":0},{"id":1,"sLen":0,"time":69473.68,"type":0},{"id":1,"sLen":0,"time":69789.47,"type":0},{"id":1,"sLen":0,"time":70105.26,"type":0},{"id":1,"sLen":236.842099999994,"time":70421.05,"type":0},{"id":0,"sLen":0,"time":75789.47,"type":0},{"id":0,"sLen":0,"time":76105.26,"type":0},{"id":3,"sLen":0,"time":76421.05,"type":0},{"id":0,"sLen":0,"time":76736.8359,"type":0},{"id":2,"sLen":0,"time":77052.625,"type":0},{"id":2,"sLen":0,"time":77684.2,"type":0},{"id":0,"sLen":0,"time":78000,"type":0},{"id":0,"sLen":0,"time":78315.79,"type":0},{"id":0,"sLen":0,"time":78631.58,"type":0},{"id":3,"sLen":0,"time":78947.37,"type":0},{"id":0,"sLen":0,"time":79263.16,"type":0},{"id":2,"sLen":0,"time":79578.9453,"type":0},{"id":2,"sLen":0,"time":80210.52,"type":0},{"id":3,"sLen":0,"time":80526.31,"type":0},{"id":2,"sLen":0,"time":85894.7344,"type":0},{"id":0,"sLen":0,"time":86526.31,"type":0},{"id":3,"sLen":0,"time":86684.2,"type":0},{"id":1,"sLen":0,"time":86842.1,"type":0},{"id":2,"sLen":0,"time":87157.89,"type":0},{"id":0,"sLen":0,"time":87789.47,"type":0},{"id":3,"sLen":0,"time":87947.37,"type":0},{"id":1,"sLen":0,"time":88105.26,"type":0},{"id":2,"sLen":0,"time":88421.05,"type":0},{"id":0,"sLen":0,"time":89052.625,"type":0},{"id":3,"sLen":0,"time":89210.52,"type":0},{"id":1,"sLen":0,"time":89368.4141,"type":0},{"id":2,"sLen":0,"time":89684.2,"type":0},{"id":0,"sLen":0,"time":90315.79,"type":0},{"id":3,"sLen":0,"time":90473.68,"type":0},{"id":1,"sLen":0,"time":90631.58,"type":0},{"id":3,"sLen":157.89473,"time":95999.99,"type":0},{"id":1,"sLen":157.89473,"time":96631.58,"type":0},{"id":0,"sLen":0,"time":96947.37,"type":0},{"id":3,"sLen":0,"time":97263.16,"type":0},{"id":3,"sLen":0,"time":97736.8359,"type":0},{"id":3,"sLen":0,"time":98210.52,"type":0},{"id":3,"sLen":0,"time":98526.31,"type":0},{"id":3,"sLen":0,"time":98842.1,"type":0},{"id":1,"sLen":0,"time":99157.89,"type":0},{"id":0,"sLen":0,"time":99473.68,"type":0},{"id":3,"sLen":0,"time":99789.47,"type":0},{"id":3,"sLen":0,"time":100263.156,"type":0},{"id":3,"sLen":0,"time":100736.836,"type":0}],"position":"boyfriend","type":1,"characters":["bf-pixel"]},{"notes":[],"visible":false,"position":"girlfriend","type":2,"characters":["gf-pixel"]}],"codenameChart":true,"stage":"school-evil","noteTypes":[]}
\ No newline at end of file
diff --git a/assets/songs/thorns/charts/hard.json b/assets/songs/thorns/charts/hard.json
index 0ef906ff..d6852ebe 100644
--- a/assets/songs/thorns/charts/hard.json
+++ b/assets/songs/thorns/charts/hard.json
@@ -1 +1 @@
-{"song":{"stage":"school-evil","gf":"gf-pixel","song":"Thorns","bpm":190.0,"needsVoices":true,"player1":"bf-pixel","player2":"spirit","speed":1.5,"notes":[{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[0.0,3,157.89473],[315.789459,3,0.0],[473.6842,3,0.0],[631.5789,1,157.89473],[947.3684,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[1263.15784,3,0.0],[1578.94727,1,0.0],[1736.842,3,0.0],[2052.63159,1,0.0],[2210.52612,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[2526.31567,3,0.0],[2684.21045,3,0.0],[2842.10522,3,0.0],[2999.99976,3,0.0],[3157.89453,1,0.0],[3315.78931,1,0.0],[3473.684,0,0.0],[3631.57886,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[3789.47363,3,0.0],[4105.263,1,0.0],[4263.15771,3,0.0],[4578.94727,1,0.0],[4736.842,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[5052.63135,3,157.89473],[5368.421,3,0.0],[5526.31543,3,0.0],[5684.21045,1,157.89473],[5999.99951,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[6315.789,3,0.0],[6631.57861,1,0.0],[6789.473,3,0.0],[7105.2627,1,0.0],[7263.15771,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[7578.94727,3,0.0],[7736.842,3,0.0],[7894.73633,3,0.0],[8052.63135,3,0.0],[8210.526,1,0.0],[8368.421,1,0.0],[8526.315,0,0.0],[8684.21,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[8842.10449,3,0.0],[9157.895,1,0.0],[9315.789,3,0.0],[9631.578,1,0.0],[9789.474,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[10105.2627,2,157.89473],[10421.0518,1,78.9473648],[10736.8418,2,0.0],[10894.7363,3,0.0],[11052.6309,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[11368.4209,2,157.89473],[11684.21,1,0.0],[11842.1045,2,157.89473],[12157.8945,1,0.0],[12315.7891,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[12631.5781,2,157.89473],[12947.3682,1,78.9473648],[13263.1572,2,0.0],[13421.0518,3,0.0],[13578.9463,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[13894.7363,2,157.89473],[14210.5254,1,0.0],[14368.42,2,157.89473],[14684.21,1,0.0],[14842.1045,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[15157.8945,2,157.89473],[15473.6836,1,78.9473648],[15789.4727,2,0.0],[15947.3682,3,0.0],[16105.2627,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[16421.0527,2,157.89473],[16736.8418,1,0.0],[16894.7363,2,157.89473],[17210.5254,1,0.0],[17368.42,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[17684.209,2,157.89473],[18000.0,1,78.9473648],[18315.79,2,0.0],[18473.6836,3,0.0],[18631.5781,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[18947.3672,2,157.89473],[19263.1563,1,0.0],[19421.05,2,157.89473],[19736.8418,1,0.0],[19894.7363,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[20210.5254,1,0.0],[20368.42,0,0.0],[20526.3145,3,0.0],[20684.209,1,0.0],[20842.1035,0,0.0],[21000.0,3,0.0],[21157.8945,1,0.0],[21315.79,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[21473.6836,2,0.0],[21631.5781,1,0.0],[21789.4727,0,0.0],[21947.3672,2,0.0],[22105.2617,1,0.0],[22263.1563,0,0.0],[22421.05,3,0.0],[22578.9473,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[22736.8418,1,0.0],[22894.7363,0,0.0],[23052.63,3,0.0],[23210.5254,1,0.0],[23368.42,0,0.0],[23526.3145,3,0.0],[23684.209,1,0.0],[23842.1035,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[23999.998,2,0.0],[24157.8945,1,0.0],[24315.79,0,0.0],[24473.6836,2,0.0],[24631.5781,1,0.0],[24789.4727,7,0.0],[24789.4727,0,0.0],[24947.3672,6,0.0],[24947.3672,3,0.0],[25105.2617,4,0.0],[25105.2617,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[25263.1563,1,0.0],[25421.05,0,0.0],[25578.9453,3,0.0],[25736.8418,1,0.0],[25894.7363,0,0.0],[26052.63,3,0.0],[26210.5254,1,0.0],[26368.42,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[26526.3145,2,0.0],[26684.209,1,0.0],[26842.1035,0,0.0],[26999.998,2,0.0],[27157.8926,1,0.0],[27315.79,0,0.0],[27473.6836,3,0.0],[27631.5781,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[27789.4727,1,0.0],[27947.3672,0,0.0],[28105.2617,3,0.0],[28263.1563,1,0.0],[28421.05,0,0.0],[28578.9453,3,0.0],[28736.84,1,0.0],[28894.7363,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[29052.63,2,0.0],[29210.5254,1,0.0],[29368.42,0,0.0],[29526.3145,2,0.0],[29684.209,1,0.0],[29842.1035,0,0.0],[29999.998,3,0.0],[30157.8926,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[30315.79,2,0.0],[30473.6836,0,0.0],[30631.5781,3,0.0],[30789.4727,1,0.0],[30947.3672,3,236.8421],[31263.1563,0,0.0],[31421.05,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[31578.9453,0,0.0],[31736.84,2,0.0],[31894.7363,0,0.0],[32052.63,1,0.0],[32210.5254,3,236.8421],[32526.3145,1,0.0],[32684.209,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[32842.1055,0,0.0],[33000.0,2,0.0],[33157.8945,0,0.0],[33315.79,3,0.0],[33473.6836,0,0.0],[33631.58,2,0.0],[33789.4727,3,0.0],[33947.3672,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[34105.26,1,0.0],[34263.1563,0,0.0],[34421.05,1,0.0],[34578.9453,3,0.0],[34736.84,1,0.0],[34894.7344,0,0.0],[35052.63,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[35368.418,2,0.0],[35526.3125,0,0.0],[35684.207,3,0.0],[35842.1055,1,0.0],[36000.0,3,236.8421],[36315.79,0,0.0],[36473.6836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[36631.58,0,0.0],[36789.4727,2,0.0],[36947.3672,0,0.0],[37105.26,1,0.0],[37263.1563,3,236.8421],[37578.9453,1,0.0],[37736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[37894.7344,0,0.0],[38052.63,2,0.0],[38210.5234,0,0.0],[38368.418,3,0.0],[38526.3125,0,0.0],[38684.207,2,0.0],[38842.1,3,0.0],[39000.0,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[39157.8945,1,0.0],[39315.79,0,0.0],[39473.6836,1,0.0],[39631.58,3,0.0],[39789.4727,1,0.0],[39947.3672,0,0.0],[40105.26,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[40421.05,0,0.0],[40578.9453,1,0.0],[40736.84,0,0.0],[40894.7344,2,0.0],[41052.63,3,0.0],[41210.5234,1,0.0],[41368.418,0,0.0],[41526.3125,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[41684.207,2,0.0],[41842.1,0,0.0],[42000.0,1,0.0],[42157.8945,0,0.0],[42315.79,2,0.0],[42473.6836,3,0.0],[42631.58,0,0.0],[42789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[42947.3672,0,0.0],[43105.26,1,0.0],[43263.1563,0,0.0],[43421.05,2,0.0],[43578.9453,3,0.0],[43736.84,1,0.0],[43894.7344,0,0.0],[44052.63,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[44210.5234,2,0.0],[44368.418,0,0.0],[44526.3125,1,0.0],[44684.207,0,0.0],[44842.1,2,0.0],[44999.9961,0,0.0],[45157.8945,3,0.0],[45315.79,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[45473.6836,0,0.0],[45631.58,1,0.0],[45789.4727,0,0.0],[45947.3672,2,0.0],[46105.26,3,0.0],[46263.1563,1,0.0],[46421.05,0,0.0],[46578.9453,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[46736.84,2,0.0],[46894.7344,0,0.0],[47052.63,1,0.0],[47210.5234,0,0.0],[47368.418,2,0.0],[47526.3125,3,0.0],[47684.207,0,0.0],[47842.1,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[47999.9961,0,0.0],[48157.89,1,0.0],[48315.79,0,0.0],[48473.6836,2,0.0],[48631.58,3,0.0],[48789.4727,1,0.0],[48947.3672,0,0.0],[49105.26,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[49263.1563,2,0.0],[49421.05,0,0.0],[49578.9453,1,0.0],[49736.84,0,0.0],[49894.7344,2,0.0],[50052.63,0,0.0],[50210.5234,3,0.0],[50368.418,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[50526.3125,3,157.89473],[50842.1,3,0.0],[50999.9961,3,0.0],[51157.89,1,157.89473],[51473.6836,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[51789.4727,3,0.0],[52105.26,1,0.0],[52263.1563,3,0.0],[52578.9453,1,0.0],[52736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[53052.63,3,0.0],[53210.5234,3,0.0],[53368.418,3,0.0],[53526.3125,3,0.0],[53684.207,1,0.0],[53842.1,1,0.0],[53999.9961,0,0.0],[54157.89,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[54315.7852,3,0.0],[54631.58,1,0.0],[54789.4727,3,0.0],[55105.26,1,0.0],[55263.1563,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[55578.9453,3,157.89473],[55894.7344,3,0.0],[56052.63,3,0.0],[56210.5234,1,157.89473],[56526.3125,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[56842.1,3,0.0],[57157.89,1,0.0],[57315.7852,3,0.0],[57631.58,1,0.0],[57789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[58105.26,3,0.0],[58263.1563,3,0.0],[58421.05,3,0.0],[58578.9453,3,0.0],[58736.84,1,0.0],[58894.7344,1,0.0],[59052.63,0,0.0],[59210.5234,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[59368.418,3,0.0],[59684.207,1,0.0],[59842.1,3,0.0],[60157.89,1,0.0],[60315.7852,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[60631.58,2,0.0],[60789.4727,0,0.0],[60947.3672,3,0.0],[61105.26,1,0.0],[61263.1563,3,0.0],[61421.05,3,0.0],[61578.9453,0,0.0],[61736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[61894.7344,0,0.0],[62052.63,2,0.0],[62210.5234,0,0.0],[62368.418,1,0.0],[62526.3125,3,0.0],[62684.207,3,0.0],[62842.1,1,0.0],[62999.9961,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[63157.89,0,0.0],[63315.7852,2,0.0],[63473.68,0,0.0],[63631.5742,3,0.0],[63789.4727,0,0.0],[63947.3672,2,0.0],[64105.26,3,0.0],[64263.1563,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[64421.05,1,0.0],[64578.9453,0,0.0],[64736.84,1,0.0],[64894.7344,3,0.0],[65052.63,1,0.0],[65210.5234,0,0.0],[65368.418,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[65684.21,2,0.0],[65842.1,0,0.0],[66000.0,3,0.0],[66157.89,1,0.0],[66315.79,3,0.0],[66473.68,3,0.0],[66631.58,0,0.0],[66789.47,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[66947.37,0,0.0],[67105.26,2,0.0],[67263.16,0,0.0],[67421.05,1,0.0],[67578.9453,3,0.0],[67736.8359,3,0.0],[67894.7344,1,0.0],[68052.625,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[68210.52,0,0.0],[68368.4141,2,0.0],[68526.31,0,0.0],[68684.21,3,0.0],[68842.1,0,0.0],[69000.0,2,0.0],[69157.89,3,0.0],[69315.79,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[69473.68,1,0.0],[69631.58,0,0.0],[69789.47,1,0.0],[69947.37,3,0.0],[70105.26,1,0.0],[70263.16,0,0.0],[70421.05,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[70736.8359,0,0.0],[70894.7344,1,0.0],[71052.625,0,0.0],[71210.52,2,0.0],[71368.4141,3,0.0],[71526.31,1,0.0],[71684.21,0,0.0],[71842.1,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[72000.0,2,0.0],[72157.89,0,0.0],[72315.79,1,0.0],[72473.68,0,0.0],[72631.58,2,0.0],[72789.47,3,0.0],[72947.37,0,0.0],[73105.26,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[73263.16,0,0.0],[73421.05,1,0.0],[73578.9453,0,0.0],[73736.8359,2,0.0],[73894.7344,3,0.0],[74052.625,1,0.0],[74210.52,0,0.0],[74368.4141,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[74526.31,2,0.0],[74684.21,0,0.0],[74842.1,1,0.0],[75000.0,0,0.0],[75157.89,2,0.0],[75315.79,0,0.0],[75473.68,3,0.0],[75631.58,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[75789.47,0,0.0],[75947.37,1,0.0],[76105.26,0,0.0],[76263.16,2,0.0],[76421.05,3,0.0],[76578.9453,1,0.0],[76736.8359,0,0.0],[76894.7344,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[77052.625,2,0.0],[77210.52,0,0.0],[77368.4141,1,0.0],[77526.31,0,0.0],[77684.2,2,0.0],[77842.1,3,0.0],[78000.0,0,0.0],[78157.89,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[78315.79,0,0.0],[78473.68,1,0.0],[78631.58,0,0.0],[78789.47,2,0.0],[78947.37,3,0.0],[79105.26,1,0.0],[79263.16,0,0.0],[79421.05,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[79578.9453,2,0.0],[79736.8359,0,0.0],[79894.7344,1,0.0],[80052.625,0,0.0],[80210.52,2,0.0],[80368.4141,0,0.0],[80526.31,3,0.0],[80684.2,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[80842.1,2,0.0],[81000.0,3,0.0],[81157.89,1,0.0],[81315.79,3,0.0],[81473.68,0,0.0],[81631.58,3,0.0],[81789.47,1,0.0],[81947.37,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[82105.26,2,0.0],[82263.16,3,0.0],[82421.05,1,0.0],[82578.9453,3,0.0],[82736.8359,0,0.0],[82894.7344,3,0.0],[83052.625,1,0.0],[83210.52,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[83368.4141,2,0.0],[83526.31,3,0.0],[83684.2,1,0.0],[83842.1,3,0.0],[84000.0,0,0.0],[84157.89,3,0.0],[84315.79,1,0.0],[84473.68,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[84631.58,2,0.0],[84789.47,3,0.0],[84947.37,1,0.0],[85105.26,3,0.0],[85263.16,0,0.0],[85421.05,3,0.0],[85578.9453,1,0.0],[85736.8359,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[85894.7344,2,0.0],[86052.625,3,0.0],[86210.52,1,0.0],[86368.4141,3,0.0],[86526.31,0,0.0],[86684.2,3,0.0],[86842.1,1,0.0],[86999.99,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[87157.89,2,0.0],[87315.79,3,0.0],[87473.68,1,0.0],[87631.58,3,0.0],[87789.47,0,0.0],[87947.37,3,0.0],[88105.26,1,0.0],[88263.16,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[88421.05,2,0.0],[88578.9453,3,0.0],[88736.8359,1,0.0],[88894.7344,3,0.0],[89052.625,0,0.0],[89210.52,3,0.0],[89368.4141,1,0.0],[89526.31,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[89684.2,2,0.0],[89842.1,3,0.0],[89999.99,1,0.0],[90157.89,3,0.0],[90315.79,0,0.0],[90473.68,3,0.0],[90631.58,1,0.0],[90789.47,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[90947.37,3,157.89473],[91263.16,3,0.0],[91421.05,3,0.0],[91578.9453,1,157.89473],[91894.7344,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[92210.52,3,0.0],[92526.31,1,0.0],[92684.2,3,0.0],[92999.99,1,0.0],[93157.89,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[93473.68,3,0.0],[93631.58,3,0.0],[93789.47,3,0.0],[93947.37,3,0.0],[94105.26,1,0.0],[94263.16,1,0.0],[94421.05,0,0.0],[94578.9453,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[94736.8359,3,0.0],[95052.625,1,0.0],[95210.52,3,0.0],[95526.31,1,0.0],[95684.2,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[95999.99,3,157.89473],[96315.78,3,0.0],[96473.68,3,0.0],[96631.58,1,157.89473],[96947.37,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[97263.16,3,0.0],[97578.9453,1,0.0],[97736.8359,3,0.0],[98052.625,1,0.0],[98210.52,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[98526.31,3,0.0],[98684.2,3,0.0],[98842.1,3,0.0],[98999.99,3,0.0],[99157.89,1,0.0],[99315.78,1,0.0],[99473.68,0,0.0],[99631.58,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[99789.47,3,0.0],[100105.258,1,0.0],[100263.156,3,0.0],[100578.945,1,0.0],[100736.836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]}]},"generatedBy":"SNIFF ver.6"}
\ No newline at end of file
+{"events":[{"params":[1],"name":"Camera Movement","time":5052.63157894737},{"params":[0],"name":"Camera Movement","time":10105.2631578947},{"params":[1],"name":"Camera Movement","time":15157.8947368421},{"params":[0],"name":"Camera Movement","time":20210.5263157895},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":20210.5263157895},{"params":[1],"name":"Camera Movement","time":25263.1578947368},{"params":[0],"name":"Camera Movement","time":30315.7894736842},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":30315.7894736842},{"params":[1],"name":"Camera Movement","time":35368.4210526316},{"params":[0],"name":"Camera Movement","time":40421.0526315789},{"params":[1],"name":"Camera Movement","time":45473.6842105263},{"params":[0],"name":"Camera Movement","time":50526.3157894737},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":50526.3157894737},{"params":[1],"name":"Camera Movement","time":55578.947368421},{"params":[0],"name":"Camera Movement","time":60631.5789473684},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":60631.5789473684},{"params":[1],"name":"Camera Movement","time":65684.2105263157},{"params":[0],"name":"Camera Movement","time":70736.8421052631},{"params":[1],"name":"Camera Movement","time":75789.4736842105},{"params":[0],"name":"Camera Movement","time":80842.1052631578},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":80842.1052631578},{"params":[1],"name":"Camera Movement","time":85894.7368421052},{"params":[0],"name":"Camera Movement","time":90947.3684210525},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":90947.3684210525},{"params":[1],"name":"Camera Movement","time":95999.9999999999}],"scrollSpeed":1.5,"strumLines":[{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":0,"type":0},{"id":3,"sLen":0,"time":315.789459,"type":0},{"id":3,"sLen":0,"time":473.6842,"type":0},{"id":1,"sLen":157.89473,"time":631.5789,"type":0},{"id":0,"sLen":0,"time":947.3684,"type":0},{"id":3,"sLen":0,"time":1263.15784,"type":0},{"id":1,"sLen":0,"time":1578.94727,"type":0},{"id":3,"sLen":0,"time":1736.842,"type":0},{"id":1,"sLen":0,"time":2052.63159,"type":0},{"id":3,"sLen":0,"time":2210.52612,"type":0},{"id":3,"sLen":0,"time":2526.31567,"type":0},{"id":3,"sLen":0,"time":2684.21045,"type":0},{"id":3,"sLen":0,"time":2842.10522,"type":0},{"id":3,"sLen":0,"time":2999.99976,"type":0},{"id":1,"sLen":0,"time":3157.89453,"type":0},{"id":1,"sLen":0,"time":3315.78931,"type":0},{"id":0,"sLen":0,"time":3473.684,"type":0},{"id":0,"sLen":0,"time":3631.57886,"type":0},{"id":3,"sLen":0,"time":3789.47363,"type":0},{"id":1,"sLen":0,"time":4105.263,"type":0},{"id":3,"sLen":0,"time":4263.15771,"type":0},{"id":1,"sLen":0,"time":4578.94727,"type":0},{"id":3,"sLen":0,"time":4736.842,"type":0},{"id":2,"sLen":157.894729999998,"time":10105.2627,"type":0},{"id":1,"sLen":78.9473648000021,"time":10421.0518,"type":0},{"id":2,"sLen":0,"time":10736.8418,"type":0},{"id":3,"sLen":0,"time":10894.7363,"type":0},{"id":1,"sLen":78.9473647999985,"time":11052.6309,"type":0},{"id":2,"sLen":157.89473,"time":11368.4209,"type":0},{"id":1,"sLen":0,"time":11684.21,"type":0},{"id":2,"sLen":157.89473,"time":11842.1045,"type":0},{"id":1,"sLen":0,"time":12157.8945,"type":0},{"id":2,"sLen":157.89473,"time":12315.7891,"type":0},{"id":2,"sLen":157.89473,"time":12631.5781,"type":0},{"id":1,"sLen":78.9473648000003,"time":12947.3682,"type":0},{"id":2,"sLen":0,"time":13263.1572,"type":0},{"id":3,"sLen":0,"time":13421.0518,"type":0},{"id":1,"sLen":78.9473648000003,"time":13578.9463,"type":0},{"id":2,"sLen":157.89473,"time":13894.7363,"type":0},{"id":1,"sLen":0,"time":14210.5254,"type":0},{"id":2,"sLen":157.89473,"time":14368.42,"type":0},{"id":1,"sLen":0,"time":14684.21,"type":0},{"id":0,"sLen":157.89473,"time":14842.1045,"type":0},{"id":1,"sLen":0,"time":20210.5254,"type":0},{"id":0,"sLen":0,"time":20368.42,"type":0},{"id":3,"sLen":0,"time":20526.3145,"type":0},{"id":1,"sLen":0,"time":20684.209,"type":0},{"id":0,"sLen":0,"time":20842.1035,"type":0},{"id":3,"sLen":0,"time":21000,"type":0},{"id":1,"sLen":0,"time":21157.8945,"type":0},{"id":0,"sLen":0,"time":21315.79,"type":0},{"id":2,"sLen":0,"time":21473.6836,"type":0},{"id":1,"sLen":0,"time":21631.5781,"type":0},{"id":0,"sLen":0,"time":21789.4727,"type":0},{"id":2,"sLen":0,"time":21947.3672,"type":0},{"id":1,"sLen":0,"time":22105.2617,"type":0},{"id":0,"sLen":0,"time":22263.1563,"type":0},{"id":3,"sLen":0,"time":22421.05,"type":0},{"id":1,"sLen":0,"time":22578.9473,"type":0},{"id":1,"sLen":0,"time":22736.8418,"type":0},{"id":0,"sLen":0,"time":22894.7363,"type":0},{"id":3,"sLen":0,"time":23052.63,"type":0},{"id":1,"sLen":0,"time":23210.5254,"type":0},{"id":0,"sLen":0,"time":23368.42,"type":0},{"id":3,"sLen":0,"time":23526.3145,"type":0},{"id":1,"sLen":0,"time":23684.209,"type":0},{"id":0,"sLen":0,"time":23842.1035,"type":0},{"id":2,"sLen":0,"time":23999.998,"type":0},{"id":1,"sLen":0,"time":24157.8945,"type":0},{"id":0,"sLen":0,"time":24315.79,"type":0},{"id":2,"sLen":0,"time":24473.6836,"type":0},{"id":1,"sLen":0,"time":24631.5781,"type":0},{"id":0,"sLen":0,"time":24789.4727,"type":0},{"id":3,"sLen":0,"time":24947.3672,"type":0},{"id":1,"sLen":0,"time":25105.2617,"type":0},{"id":2,"sLen":0,"time":30315.79,"type":0},{"id":0,"sLen":0,"time":30473.6836,"type":0},{"id":3,"sLen":0,"time":30631.5781,"type":0},{"id":1,"sLen":0,"time":30789.4727,"type":0},{"id":3,"sLen":236.842100000002,"time":30947.3672,"type":0},{"id":0,"sLen":0,"time":31263.1563,"type":0},{"id":3,"sLen":0,"time":31421.05,"type":0},{"id":0,"sLen":0,"time":31578.9453,"type":0},{"id":2,"sLen":0,"time":31736.84,"type":0},{"id":0,"sLen":0,"time":31894.7363,"type":0},{"id":1,"sLen":0,"time":32052.63,"type":0},{"id":3,"sLen":236.842100000002,"time":32210.5254,"type":0},{"id":1,"sLen":0,"time":32526.3145,"type":0},{"id":3,"sLen":0,"time":32684.209,"type":0},{"id":0,"sLen":0,"time":32842.1055,"type":0},{"id":2,"sLen":0,"time":33000,"type":0},{"id":0,"sLen":0,"time":33157.8945,"type":0},{"id":3,"sLen":0,"time":33315.79,"type":0},{"id":0,"sLen":0,"time":33473.6836,"type":0},{"id":2,"sLen":0,"time":33631.58,"type":0},{"id":3,"sLen":0,"time":33789.4727,"type":0},{"id":1,"sLen":0,"time":33947.3672,"type":0},{"id":1,"sLen":0,"time":34105.26,"type":0},{"id":0,"sLen":0,"time":34263.1563,"type":0},{"id":1,"sLen":0,"time":34421.05,"type":0},{"id":3,"sLen":0,"time":34578.9453,"type":0},{"id":1,"sLen":0,"time":34736.84,"type":0},{"id":0,"sLen":0,"time":34894.7344,"type":0},{"id":1,"sLen":236.842100000002,"time":35052.63,"type":0},{"id":0,"sLen":0,"time":40421.05,"type":0},{"id":1,"sLen":0,"time":40578.9453,"type":0},{"id":0,"sLen":0,"time":40736.84,"type":0},{"id":2,"sLen":0,"time":40894.7344,"type":0},{"id":3,"sLen":0,"time":41052.63,"type":0},{"id":1,"sLen":0,"time":41210.5234,"type":0},{"id":0,"sLen":0,"time":41368.418,"type":0},{"id":3,"sLen":0,"time":41526.3125,"type":0},{"id":2,"sLen":0,"time":41684.207,"type":0},{"id":0,"sLen":0,"time":41842.1,"type":0},{"id":1,"sLen":0,"time":42000,"type":0},{"id":0,"sLen":0,"time":42157.8945,"type":0},{"id":2,"sLen":0,"time":42315.79,"type":0},{"id":3,"sLen":0,"time":42473.6836,"type":0},{"id":0,"sLen":0,"time":42631.58,"type":0},{"id":3,"sLen":0,"time":42789.4727,"type":0},{"id":0,"sLen":0,"time":42947.3672,"type":0},{"id":1,"sLen":0,"time":43105.26,"type":0},{"id":0,"sLen":0,"time":43263.1563,"type":0},{"id":2,"sLen":0,"time":43421.05,"type":0},{"id":3,"sLen":0,"time":43578.9453,"type":0},{"id":1,"sLen":0,"time":43736.84,"type":0},{"id":0,"sLen":0,"time":43894.7344,"type":0},{"id":3,"sLen":0,"time":44052.63,"type":0},{"id":2,"sLen":0,"time":44210.5234,"type":0},{"id":0,"sLen":0,"time":44368.418,"type":0},{"id":1,"sLen":0,"time":44526.3125,"type":0},{"id":0,"sLen":0,"time":44684.207,"type":0},{"id":2,"sLen":0,"time":44842.1,"type":0},{"id":0,"sLen":0,"time":44999.9961,"type":0},{"id":3,"sLen":0,"time":45157.8945,"type":0},{"id":0,"sLen":0,"time":45315.79,"type":0},{"id":3,"sLen":157.89473,"time":50526.3125,"type":0},{"id":3,"sLen":0,"time":50842.1,"type":0},{"id":3,"sLen":0,"time":50999.9961,"type":0},{"id":1,"sLen":157.89473,"time":51157.89,"type":0},{"id":0,"sLen":0,"time":51473.6836,"type":0},{"id":3,"sLen":0,"time":51789.4727,"type":0},{"id":1,"sLen":0,"time":52105.26,"type":0},{"id":3,"sLen":0,"time":52263.1563,"type":0},{"id":1,"sLen":0,"time":52578.9453,"type":0},{"id":3,"sLen":0,"time":52736.84,"type":0},{"id":3,"sLen":0,"time":53052.63,"type":0},{"id":3,"sLen":0,"time":53210.5234,"type":0},{"id":3,"sLen":0,"time":53368.418,"type":0},{"id":3,"sLen":0,"time":53526.3125,"type":0},{"id":1,"sLen":0,"time":53684.207,"type":0},{"id":1,"sLen":0,"time":53842.1,"type":0},{"id":0,"sLen":0,"time":53999.9961,"type":0},{"id":0,"sLen":0,"time":54157.89,"type":0},{"id":3,"sLen":0,"time":54315.7852,"type":0},{"id":1,"sLen":0,"time":54631.58,"type":0},{"id":3,"sLen":0,"time":54789.4727,"type":0},{"id":1,"sLen":0,"time":55105.26,"type":0},{"id":3,"sLen":0,"time":55263.1563,"type":0},{"id":2,"sLen":0,"time":60631.58,"type":0},{"id":0,"sLen":0,"time":60789.4727,"type":0},{"id":3,"sLen":0,"time":60947.3672,"type":0},{"id":1,"sLen":0,"time":61105.26,"type":0},{"id":3,"sLen":0,"time":61263.1563,"type":0},{"id":3,"sLen":0,"time":61421.05,"type":0},{"id":0,"sLen":0,"time":61578.9453,"type":0},{"id":3,"sLen":0,"time":61736.84,"type":0},{"id":0,"sLen":0,"time":61894.7344,"type":0},{"id":2,"sLen":0,"time":62052.63,"type":0},{"id":0,"sLen":0,"time":62210.5234,"type":0},{"id":1,"sLen":0,"time":62368.418,"type":0},{"id":3,"sLen":0,"time":62526.3125,"type":0},{"id":3,"sLen":0,"time":62684.207,"type":0},{"id":1,"sLen":0,"time":62842.1,"type":0},{"id":3,"sLen":0,"time":62999.9961,"type":0},{"id":0,"sLen":0,"time":63157.89,"type":0},{"id":2,"sLen":0,"time":63315.7852,"type":0},{"id":0,"sLen":0,"time":63473.68,"type":0},{"id":3,"sLen":0,"time":63631.5742,"type":0},{"id":0,"sLen":0,"time":63789.4727,"type":0},{"id":2,"sLen":0,"time":63947.3672,"type":0},{"id":3,"sLen":0,"time":64105.26,"type":0},{"id":1,"sLen":0,"time":64263.1563,"type":0},{"id":1,"sLen":0,"time":64421.05,"type":0},{"id":0,"sLen":0,"time":64578.9453,"type":0},{"id":1,"sLen":0,"time":64736.84,"type":0},{"id":3,"sLen":0,"time":64894.7344,"type":0},{"id":1,"sLen":0,"time":65052.63,"type":0},{"id":0,"sLen":0,"time":65210.5234,"type":0},{"id":1,"sLen":236.842100000002,"time":65368.418,"type":0},{"id":0,"sLen":0,"time":70736.8359,"type":0},{"id":1,"sLen":0,"time":70894.7344,"type":0},{"id":0,"sLen":0,"time":71052.625,"type":0},{"id":2,"sLen":0,"time":71210.52,"type":0},{"id":3,"sLen":0,"time":71368.4141,"type":0},{"id":1,"sLen":0,"time":71526.31,"type":0},{"id":0,"sLen":0,"time":71684.21,"type":0},{"id":3,"sLen":0,"time":71842.1,"type":0},{"id":2,"sLen":0,"time":72000,"type":0},{"id":0,"sLen":0,"time":72157.89,"type":0},{"id":1,"sLen":0,"time":72315.79,"type":0},{"id":0,"sLen":0,"time":72473.68,"type":0},{"id":2,"sLen":0,"time":72631.58,"type":0},{"id":3,"sLen":0,"time":72789.47,"type":0},{"id":0,"sLen":0,"time":72947.37,"type":0},{"id":3,"sLen":0,"time":73105.26,"type":0},{"id":0,"sLen":0,"time":73263.16,"type":0},{"id":1,"sLen":0,"time":73421.05,"type":0},{"id":0,"sLen":0,"time":73578.9453,"type":0},{"id":2,"sLen":0,"time":73736.8359,"type":0},{"id":3,"sLen":0,"time":73894.7344,"type":0},{"id":1,"sLen":0,"time":74052.625,"type":0},{"id":0,"sLen":0,"time":74210.52,"type":0},{"id":3,"sLen":0,"time":74368.4141,"type":0},{"id":2,"sLen":0,"time":74526.31,"type":0},{"id":0,"sLen":0,"time":74684.21,"type":0},{"id":1,"sLen":0,"time":74842.1,"type":0},{"id":0,"sLen":0,"time":75000,"type":0},{"id":2,"sLen":0,"time":75157.89,"type":0},{"id":0,"sLen":0,"time":75315.79,"type":0},{"id":3,"sLen":0,"time":75473.68,"type":0},{"id":0,"sLen":0,"time":75631.58,"type":0},{"id":2,"sLen":0,"time":80842.1,"type":0},{"id":3,"sLen":0,"time":81000,"type":0},{"id":1,"sLen":0,"time":81157.89,"type":0},{"id":3,"sLen":0,"time":81315.79,"type":0},{"id":0,"sLen":0,"time":81473.68,"type":0},{"id":3,"sLen":0,"time":81631.58,"type":0},{"id":1,"sLen":0,"time":81789.47,"type":0},{"id":1,"sLen":0,"time":81947.37,"type":0},{"id":2,"sLen":0,"time":82105.26,"type":0},{"id":3,"sLen":0,"time":82263.16,"type":0},{"id":1,"sLen":0,"time":82421.05,"type":0},{"id":3,"sLen":0,"time":82578.9453,"type":0},{"id":0,"sLen":0,"time":82736.8359,"type":0},{"id":3,"sLen":0,"time":82894.7344,"type":0},{"id":1,"sLen":0,"time":83052.625,"type":0},{"id":1,"sLen":0,"time":83210.52,"type":0},{"id":2,"sLen":0,"time":83368.4141,"type":0},{"id":3,"sLen":0,"time":83526.31,"type":0},{"id":1,"sLen":0,"time":83684.2,"type":0},{"id":3,"sLen":0,"time":83842.1,"type":0},{"id":0,"sLen":0,"time":84000,"type":0},{"id":3,"sLen":0,"time":84157.89,"type":0},{"id":1,"sLen":0,"time":84315.79,"type":0},{"id":1,"sLen":0,"time":84473.68,"type":0},{"id":2,"sLen":0,"time":84631.58,"type":0},{"id":3,"sLen":0,"time":84789.47,"type":0},{"id":1,"sLen":0,"time":84947.37,"type":0},{"id":3,"sLen":0,"time":85105.26,"type":0},{"id":0,"sLen":0,"time":85263.16,"type":0},{"id":3,"sLen":0,"time":85421.05,"type":0},{"id":1,"sLen":0,"time":85578.9453,"type":0},{"id":1,"sLen":0,"time":85736.8359,"type":0},{"id":3,"sLen":157.89473,"time":90947.37,"type":0},{"id":3,"sLen":0,"time":91263.16,"type":0},{"id":3,"sLen":0,"time":91421.05,"type":0},{"id":1,"sLen":157.89473,"time":91578.9453,"type":0},{"id":0,"sLen":0,"time":91894.7344,"type":0},{"id":3,"sLen":0,"time":92210.52,"type":0},{"id":1,"sLen":0,"time":92526.31,"type":0},{"id":3,"sLen":0,"time":92684.2,"type":0},{"id":1,"sLen":0,"time":92999.99,"type":0},{"id":3,"sLen":0,"time":93157.89,"type":0},{"id":3,"sLen":0,"time":93473.68,"type":0},{"id":3,"sLen":0,"time":93631.58,"type":0},{"id":3,"sLen":0,"time":93789.47,"type":0},{"id":3,"sLen":0,"time":93947.37,"type":0},{"id":1,"sLen":0,"time":94105.26,"type":0},{"id":1,"sLen":0,"time":94263.16,"type":0},{"id":0,"sLen":0,"time":94421.05,"type":0},{"id":0,"sLen":0,"time":94578.9453,"type":0},{"id":3,"sLen":0,"time":94736.8359,"type":0},{"id":1,"sLen":0,"time":95052.625,"type":0},{"id":3,"sLen":0,"time":95210.52,"type":0},{"id":1,"sLen":0,"time":95526.31,"type":0},{"id":3,"sLen":0,"time":95684.2,"type":0}],"position":"dad","type":0,"characters":["spirit"]},{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":5052.63135,"type":0},{"id":3,"sLen":0,"time":5368.421,"type":0},{"id":3,"sLen":0,"time":5526.31543,"type":0},{"id":1,"sLen":157.89473,"time":5684.21045,"type":0},{"id":0,"sLen":0,"time":5999.99951,"type":0},{"id":3,"sLen":0,"time":6315.789,"type":0},{"id":1,"sLen":0,"time":6631.57861,"type":0},{"id":3,"sLen":0,"time":6789.473,"type":0},{"id":1,"sLen":0,"time":7105.2627,"type":0},{"id":3,"sLen":0,"time":7263.15771,"type":0},{"id":3,"sLen":0,"time":7578.94727,"type":0},{"id":3,"sLen":0,"time":7736.842,"type":0},{"id":3,"sLen":0,"time":7894.73633,"type":0},{"id":3,"sLen":0,"time":8052.63135,"type":0},{"id":1,"sLen":0,"time":8210.526,"type":0},{"id":1,"sLen":0,"time":8368.421,"type":0},{"id":0,"sLen":0,"time":8526.315,"type":0},{"id":0,"sLen":0,"time":8684.21,"type":0},{"id":3,"sLen":0,"time":8842.10449,"type":0},{"id":1,"sLen":0,"time":9157.895,"type":0},{"id":3,"sLen":0,"time":9315.789,"type":0},{"id":1,"sLen":0,"time":9631.578,"type":0},{"id":3,"sLen":0,"time":9789.474,"type":0},{"id":2,"sLen":157.89473,"time":15157.8945,"type":0},{"id":1,"sLen":78.9473648000003,"time":15473.6836,"type":0},{"id":2,"sLen":0,"time":15789.4727,"type":0},{"id":3,"sLen":0,"time":15947.3682,"type":0},{"id":1,"sLen":78.9473648000003,"time":16105.2627,"type":0},{"id":2,"sLen":157.89473,"time":16421.0527,"type":0},{"id":1,"sLen":0,"time":16736.8418,"type":0},{"id":2,"sLen":157.89473,"time":16894.7363,"type":0},{"id":1,"sLen":0,"time":17210.5254,"type":0},{"id":2,"sLen":157.89473,"time":17368.42,"type":0},{"id":2,"sLen":157.89473,"time":17684.209,"type":0},{"id":1,"sLen":78.9473647999985,"time":18000,"type":0},{"id":2,"sLen":0,"time":18315.79,"type":0},{"id":3,"sLen":0,"time":18473.6836,"type":0},{"id":1,"sLen":78.9473647999985,"time":18631.5781,"type":0},{"id":2,"sLen":157.89473,"time":18947.3672,"type":0},{"id":1,"sLen":0,"time":19263.1563,"type":0},{"id":2,"sLen":157.89473,"time":19421.05,"type":0},{"id":1,"sLen":0,"time":19736.8418,"type":0},{"id":0,"sLen":157.89473,"time":19894.7363,"type":0},{"id":3,"sLen":0,"time":24789.4727,"type":0},{"id":2,"sLen":0,"time":24947.3672,"type":0},{"id":0,"sLen":0,"time":25105.2617,"type":0},{"id":1,"sLen":0,"time":25263.1563,"type":0},{"id":0,"sLen":0,"time":25421.05,"type":0},{"id":3,"sLen":0,"time":25578.9453,"type":0},{"id":1,"sLen":0,"time":25736.8418,"type":0},{"id":0,"sLen":0,"time":25894.7363,"type":0},{"id":3,"sLen":0,"time":26052.63,"type":0},{"id":1,"sLen":0,"time":26210.5254,"type":0},{"id":0,"sLen":0,"time":26368.42,"type":0},{"id":2,"sLen":0,"time":26526.3145,"type":0},{"id":1,"sLen":0,"time":26684.209,"type":0},{"id":0,"sLen":0,"time":26842.1035,"type":0},{"id":2,"sLen":0,"time":26999.998,"type":0},{"id":1,"sLen":0,"time":27157.8926,"type":0},{"id":0,"sLen":0,"time":27315.79,"type":0},{"id":3,"sLen":0,"time":27473.6836,"type":0},{"id":1,"sLen":0,"time":27631.5781,"type":0},{"id":1,"sLen":0,"time":27789.4727,"type":0},{"id":0,"sLen":0,"time":27947.3672,"type":0},{"id":3,"sLen":0,"time":28105.2617,"type":0},{"id":1,"sLen":0,"time":28263.1563,"type":0},{"id":0,"sLen":0,"time":28421.05,"type":0},{"id":3,"sLen":0,"time":28578.9453,"type":0},{"id":1,"sLen":0,"time":28736.84,"type":0},{"id":0,"sLen":0,"time":28894.7363,"type":0},{"id":2,"sLen":0,"time":29052.63,"type":0},{"id":1,"sLen":0,"time":29210.5254,"type":0},{"id":0,"sLen":0,"time":29368.42,"type":0},{"id":2,"sLen":0,"time":29526.3145,"type":0},{"id":1,"sLen":0,"time":29684.209,"type":0},{"id":0,"sLen":0,"time":29842.1035,"type":0},{"id":3,"sLen":0,"time":29999.998,"type":0},{"id":1,"sLen":0,"time":30157.8926,"type":0},{"id":2,"sLen":0,"time":35368.418,"type":0},{"id":0,"sLen":0,"time":35526.3125,"type":0},{"id":3,"sLen":0,"time":35684.207,"type":0},{"id":1,"sLen":0,"time":35842.1055,"type":0},{"id":3,"sLen":236.842100000002,"time":36000,"type":0},{"id":0,"sLen":0,"time":36315.79,"type":0},{"id":3,"sLen":0,"time":36473.6836,"type":0},{"id":0,"sLen":0,"time":36631.58,"type":0},{"id":2,"sLen":0,"time":36789.4727,"type":0},{"id":0,"sLen":0,"time":36947.3672,"type":0},{"id":1,"sLen":0,"time":37105.26,"type":0},{"id":3,"sLen":236.842100000002,"time":37263.1563,"type":0},{"id":1,"sLen":0,"time":37578.9453,"type":0},{"id":3,"sLen":0,"time":37736.84,"type":0},{"id":0,"sLen":0,"time":37894.7344,"type":0},{"id":2,"sLen":0,"time":38052.63,"type":0},{"id":0,"sLen":0,"time":38210.5234,"type":0},{"id":3,"sLen":0,"time":38368.418,"type":0},{"id":0,"sLen":0,"time":38526.3125,"type":0},{"id":2,"sLen":0,"time":38684.207,"type":0},{"id":3,"sLen":0,"time":38842.1,"type":0},{"id":1,"sLen":0,"time":39000,"type":0},{"id":1,"sLen":0,"time":39157.8945,"type":0},{"id":0,"sLen":0,"time":39315.79,"type":0},{"id":1,"sLen":0,"time":39473.6836,"type":0},{"id":3,"sLen":0,"time":39631.58,"type":0},{"id":1,"sLen":0,"time":39789.4727,"type":0},{"id":0,"sLen":0,"time":39947.3672,"type":0},{"id":1,"sLen":236.842100000002,"time":40105.26,"type":0},{"id":0,"sLen":0,"time":45473.6836,"type":0},{"id":1,"sLen":0,"time":45631.58,"type":0},{"id":0,"sLen":0,"time":45789.4727,"type":0},{"id":2,"sLen":0,"time":45947.3672,"type":0},{"id":3,"sLen":0,"time":46105.26,"type":0},{"id":1,"sLen":0,"time":46263.1563,"type":0},{"id":0,"sLen":0,"time":46421.05,"type":0},{"id":3,"sLen":0,"time":46578.9453,"type":0},{"id":2,"sLen":0,"time":46736.84,"type":0},{"id":0,"sLen":0,"time":46894.7344,"type":0},{"id":1,"sLen":0,"time":47052.63,"type":0},{"id":0,"sLen":0,"time":47210.5234,"type":0},{"id":2,"sLen":0,"time":47368.418,"type":0},{"id":3,"sLen":0,"time":47526.3125,"type":0},{"id":0,"sLen":0,"time":47684.207,"type":0},{"id":3,"sLen":0,"time":47842.1,"type":0},{"id":0,"sLen":0,"time":47999.9961,"type":0},{"id":1,"sLen":0,"time":48157.89,"type":0},{"id":0,"sLen":0,"time":48315.79,"type":0},{"id":2,"sLen":0,"time":48473.6836,"type":0},{"id":3,"sLen":0,"time":48631.58,"type":0},{"id":1,"sLen":0,"time":48789.4727,"type":0},{"id":0,"sLen":0,"time":48947.3672,"type":0},{"id":3,"sLen":0,"time":49105.26,"type":0},{"id":2,"sLen":0,"time":49263.1563,"type":0},{"id":0,"sLen":0,"time":49421.05,"type":0},{"id":1,"sLen":0,"time":49578.9453,"type":0},{"id":0,"sLen":0,"time":49736.84,"type":0},{"id":2,"sLen":0,"time":49894.7344,"type":0},{"id":0,"sLen":0,"time":50052.63,"type":0},{"id":3,"sLen":0,"time":50210.5234,"type":0},{"id":0,"sLen":0,"time":50368.418,"type":0},{"id":3,"sLen":157.89473,"time":55578.9453,"type":0},{"id":3,"sLen":0,"time":55894.7344,"type":0},{"id":3,"sLen":0,"time":56052.63,"type":0},{"id":1,"sLen":157.89473,"time":56210.5234,"type":0},{"id":0,"sLen":0,"time":56526.3125,"type":0},{"id":3,"sLen":0,"time":56842.1,"type":0},{"id":1,"sLen":0,"time":57157.89,"type":0},{"id":3,"sLen":0,"time":57315.7852,"type":0},{"id":1,"sLen":0,"time":57631.58,"type":0},{"id":3,"sLen":0,"time":57789.4727,"type":0},{"id":3,"sLen":0,"time":58105.26,"type":0},{"id":3,"sLen":0,"time":58263.1563,"type":0},{"id":3,"sLen":0,"time":58421.05,"type":0},{"id":3,"sLen":0,"time":58578.9453,"type":0},{"id":1,"sLen":0,"time":58736.84,"type":0},{"id":1,"sLen":0,"time":58894.7344,"type":0},{"id":0,"sLen":0,"time":59052.63,"type":0},{"id":0,"sLen":0,"time":59210.5234,"type":0},{"id":3,"sLen":0,"time":59368.418,"type":0},{"id":1,"sLen":0,"time":59684.207,"type":0},{"id":3,"sLen":0,"time":59842.1,"type":0},{"id":1,"sLen":0,"time":60157.89,"type":0},{"id":3,"sLen":0,"time":60315.7852,"type":0},{"id":2,"sLen":0,"time":65684.21,"type":0},{"id":0,"sLen":0,"time":65842.1,"type":0},{"id":3,"sLen":0,"time":66000,"type":0},{"id":1,"sLen":0,"time":66157.89,"type":0},{"id":3,"sLen":0,"time":66315.79,"type":0},{"id":3,"sLen":0,"time":66473.68,"type":0},{"id":0,"sLen":0,"time":66631.58,"type":0},{"id":3,"sLen":0,"time":66789.47,"type":0},{"id":0,"sLen":0,"time":66947.37,"type":0},{"id":2,"sLen":0,"time":67105.26,"type":0},{"id":0,"sLen":0,"time":67263.16,"type":0},{"id":1,"sLen":0,"time":67421.05,"type":0},{"id":3,"sLen":0,"time":67578.9453,"type":0},{"id":3,"sLen":0,"time":67736.8359,"type":0},{"id":1,"sLen":0,"time":67894.7344,"type":0},{"id":3,"sLen":0,"time":68052.625,"type":0},{"id":0,"sLen":0,"time":68210.52,"type":0},{"id":2,"sLen":0,"time":68368.4141,"type":0},{"id":0,"sLen":0,"time":68526.31,"type":0},{"id":3,"sLen":0,"time":68684.21,"type":0},{"id":0,"sLen":0,"time":68842.1,"type":0},{"id":2,"sLen":0,"time":69000,"type":0},{"id":3,"sLen":0,"time":69157.89,"type":0},{"id":1,"sLen":0,"time":69315.79,"type":0},{"id":1,"sLen":0,"time":69473.68,"type":0},{"id":0,"sLen":0,"time":69631.58,"type":0},{"id":1,"sLen":0,"time":69789.47,"type":0},{"id":3,"sLen":0,"time":69947.37,"type":0},{"id":1,"sLen":0,"time":70105.26,"type":0},{"id":0,"sLen":0,"time":70263.16,"type":0},{"id":1,"sLen":236.842099999994,"time":70421.05,"type":0},{"id":0,"sLen":0,"time":75789.47,"type":0},{"id":1,"sLen":0,"time":75947.37,"type":0},{"id":0,"sLen":0,"time":76105.26,"type":0},{"id":2,"sLen":0,"time":76263.16,"type":0},{"id":3,"sLen":0,"time":76421.05,"type":0},{"id":1,"sLen":0,"time":76578.9453,"type":0},{"id":0,"sLen":0,"time":76736.8359,"type":0},{"id":3,"sLen":0,"time":76894.7344,"type":0},{"id":2,"sLen":0,"time":77052.625,"type":0},{"id":0,"sLen":0,"time":77210.52,"type":0},{"id":1,"sLen":0,"time":77368.4141,"type":0},{"id":0,"sLen":0,"time":77526.31,"type":0},{"id":2,"sLen":0,"time":77684.2,"type":0},{"id":3,"sLen":0,"time":77842.1,"type":0},{"id":0,"sLen":0,"time":78000,"type":0},{"id":3,"sLen":0,"time":78157.89,"type":0},{"id":0,"sLen":0,"time":78315.79,"type":0},{"id":1,"sLen":0,"time":78473.68,"type":0},{"id":0,"sLen":0,"time":78631.58,"type":0},{"id":2,"sLen":0,"time":78789.47,"type":0},{"id":3,"sLen":0,"time":78947.37,"type":0},{"id":1,"sLen":0,"time":79105.26,"type":0},{"id":0,"sLen":0,"time":79263.16,"type":0},{"id":3,"sLen":0,"time":79421.05,"type":0},{"id":2,"sLen":0,"time":79578.9453,"type":0},{"id":0,"sLen":0,"time":79736.8359,"type":0},{"id":1,"sLen":0,"time":79894.7344,"type":0},{"id":0,"sLen":0,"time":80052.625,"type":0},{"id":2,"sLen":0,"time":80210.52,"type":0},{"id":0,"sLen":0,"time":80368.4141,"type":0},{"id":3,"sLen":0,"time":80526.31,"type":0},{"id":0,"sLen":0,"time":80684.2,"type":0},{"id":2,"sLen":0,"time":85894.7344,"type":0},{"id":3,"sLen":0,"time":86052.625,"type":0},{"id":1,"sLen":0,"time":86210.52,"type":0},{"id":3,"sLen":0,"time":86368.4141,"type":0},{"id":0,"sLen":0,"time":86526.31,"type":0},{"id":3,"sLen":0,"time":86684.2,"type":0},{"id":1,"sLen":0,"time":86842.1,"type":0},{"id":1,"sLen":0,"time":86999.99,"type":0},{"id":2,"sLen":0,"time":87157.89,"type":0},{"id":3,"sLen":0,"time":87315.79,"type":0},{"id":1,"sLen":0,"time":87473.68,"type":0},{"id":3,"sLen":0,"time":87631.58,"type":0},{"id":0,"sLen":0,"time":87789.47,"type":0},{"id":3,"sLen":0,"time":87947.37,"type":0},{"id":1,"sLen":0,"time":88105.26,"type":0},{"id":1,"sLen":0,"time":88263.16,"type":0},{"id":2,"sLen":0,"time":88421.05,"type":0},{"id":3,"sLen":0,"time":88578.9453,"type":0},{"id":1,"sLen":0,"time":88736.8359,"type":0},{"id":3,"sLen":0,"time":88894.7344,"type":0},{"id":0,"sLen":0,"time":89052.625,"type":0},{"id":3,"sLen":0,"time":89210.52,"type":0},{"id":1,"sLen":0,"time":89368.4141,"type":0},{"id":1,"sLen":0,"time":89526.31,"type":0},{"id":2,"sLen":0,"time":89684.2,"type":0},{"id":3,"sLen":0,"time":89842.1,"type":0},{"id":1,"sLen":0,"time":89999.99,"type":0},{"id":3,"sLen":0,"time":90157.89,"type":0},{"id":0,"sLen":0,"time":90315.79,"type":0},{"id":3,"sLen":0,"time":90473.68,"type":0},{"id":1,"sLen":0,"time":90631.58,"type":0},{"id":1,"sLen":0,"time":90789.47,"type":0},{"id":3,"sLen":157.89473,"time":95999.99,"type":0},{"id":3,"sLen":0,"time":96315.78,"type":0},{"id":3,"sLen":0,"time":96473.68,"type":0},{"id":1,"sLen":157.89473,"time":96631.58,"type":0},{"id":0,"sLen":0,"time":96947.37,"type":0},{"id":3,"sLen":0,"time":97263.16,"type":0},{"id":1,"sLen":0,"time":97578.9453,"type":0},{"id":3,"sLen":0,"time":97736.8359,"type":0},{"id":1,"sLen":0,"time":98052.625,"type":0},{"id":3,"sLen":0,"time":98210.52,"type":0},{"id":3,"sLen":0,"time":98526.31,"type":0},{"id":3,"sLen":0,"time":98684.2,"type":0},{"id":3,"sLen":0,"time":98842.1,"type":0},{"id":3,"sLen":0,"time":98999.99,"type":0},{"id":1,"sLen":0,"time":99157.89,"type":0},{"id":1,"sLen":0,"time":99315.78,"type":0},{"id":0,"sLen":0,"time":99473.68,"type":0},{"id":0,"sLen":0,"time":99631.58,"type":0},{"id":3,"sLen":0,"time":99789.47,"type":0},{"id":1,"sLen":0,"time":100105.258,"type":0},{"id":3,"sLen":0,"time":100263.156,"type":0},{"id":1,"sLen":0,"time":100578.945,"type":0},{"id":3,"sLen":0,"time":100736.836,"type":0}],"position":"boyfriend","type":1,"characters":["bf-pixel"]},{"notes":[],"visible":false,"position":"girlfriend","type":2,"characters":["gf-pixel"]}],"codenameChart":true,"stage":"school-evil","noteTypes":[]}
\ No newline at end of file
diff --git a/assets/songs/thorns/charts/normal.json b/assets/songs/thorns/charts/normal.json
index cacf9935..3de9605d 100644
--- a/assets/songs/thorns/charts/normal.json
+++ b/assets/songs/thorns/charts/normal.json
@@ -1 +1 @@
-{"song":{"stage":"school-evil","gf":"gf-pixel","song":"Thorns","bpm":190.0,"needsVoices":true,"player1":"bf-pixel","player2":"spirit","speed":1.3,"notes":[{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[0.0,3,157.89473],[631.5789,1,157.89473],[947.3684,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[1263.15784,3,0.0],[1578.94727,1,0.0],[1736.842,3,0.0],[2052.63159,1,0.0],[2210.52612,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[2526.31567,3,0.0],[2842.10522,3,0.0],[3157.89453,1,0.0],[3473.684,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[3789.47363,3,0.0],[4105.263,1,0.0],[4263.15771,3,0.0],[4578.94727,1,0.0],[4736.842,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[5052.63135,3,157.89473],[5684.21045,1,157.89473],[5999.99951,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[6315.789,3,0.0],[6631.57861,1,0.0],[6789.473,3,0.0],[7105.2627,1,0.0],[7263.15771,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[7578.94727,3,0.0],[7894.73633,3,0.0],[8210.526,1,0.0],[8526.315,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[8842.10449,3,0.0],[9157.895,1,0.0],[9315.789,3,0.0],[9631.578,1,0.0],[9789.474,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[10105.2627,2,157.89473],[10736.8418,2,0.0],[10894.7363,3,0.0],[11052.6309,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[11368.4209,2,157.89473],[11842.1045,2,157.89473],[12315.7891,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[12631.5781,2,157.89473],[13263.1572,2,0.0],[13421.0518,3,0.0],[13578.9463,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[13894.7363,2,157.89473],[14368.42,2,157.89473],[14842.1045,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[15157.8945,2,157.89473],[15789.4727,2,0.0],[15947.3682,3,0.0],[16105.2627,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[16421.0527,2,157.89473],[16894.7363,2,157.89473],[17368.42,2,157.89473]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[17684.209,2,157.89473],[18315.79,2,0.0],[18473.6836,3,0.0],[18631.5781,1,78.9473648]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[18947.3672,2,157.89473],[19421.05,2,157.89473],[19894.7363,0,157.89473]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[20210.5254,1,0.0],[20526.3145,3,0.0],[20684.209,1,0.0],[21000.0,3,0.0],[21157.8945,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[21473.6836,2,0.0],[21631.5781,1,0.0],[21947.3672,2,0.0],[22105.2617,1,0.0],[22421.05,3,0.0],[22578.9473,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[22736.8418,1,0.0],[23052.63,3,0.0],[23210.5254,1,0.0],[23526.3145,3,0.0],[23684.209,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[23999.998,2,0.0],[24157.8945,1,0.0],[24473.6836,2,0.0],[24631.5781,1,0.0],[24789.4727,7,0.0],[24947.3672,6,0.0],[24947.3672,3,0.0],[25105.2617,4,0.0],[25105.2617,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[25263.1563,1,0.0],[25578.9453,3,0.0],[25736.8418,1,0.0],[26052.63,3,0.0],[26210.5254,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[26526.3145,2,0.0],[26684.209,1,0.0],[26999.998,2,0.0],[27157.8926,1,0.0],[27473.6836,3,0.0],[27631.5781,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[27789.4727,1,0.0],[28105.2617,3,0.0],[28263.1563,1,0.0],[28578.9453,3,0.0],[28736.84,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[29052.63,2,0.0],[29210.5254,1,0.0],[29526.3145,2,0.0],[29684.209,1,0.0],[29999.998,3,0.0],[30157.8926,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[30315.79,2,0.0],[30631.5781,3,0.0],[30789.4727,1,0.0],[30947.3672,3,0.0],[31263.1563,0,0.0],[31421.05,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[31578.9453,0,0.0],[31894.7363,0,0.0],[32052.63,1,0.0],[32210.5254,3,0.0],[32526.3145,1,0.0],[32684.209,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[32842.1055,0,0.0],[33157.8945,0,0.0],[33315.79,3,0.0],[33473.6836,0,0.0],[33789.4727,3,0.0],[33947.3672,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[34105.26,1,0.0],[34421.05,1,0.0],[34578.9453,3,0.0],[34736.84,1,0.0],[35052.63,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[35368.418,2,0.0],[35684.207,3,0.0],[35842.1055,1,0.0],[36000.0,3,0.0],[36315.79,0,0.0],[36473.6836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[36631.58,0,0.0],[36947.3672,0,0.0],[37105.26,1,0.0],[37263.1563,3,0.0],[37578.9453,1,0.0],[37736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[37894.7344,0,0.0],[38210.5234,0,0.0],[38368.418,3,0.0],[38526.3125,0,0.0],[38842.1,3,0.0],[39000.0,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[39157.8945,1,0.0],[39473.6836,1,0.0],[39631.58,3,0.0],[39789.4727,1,0.0],[40105.26,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[40421.05,0,0.0],[40736.84,0,0.0],[41052.63,3,0.0],[41210.5234,1,0.0],[41368.418,0,0.0],[41526.3125,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[41684.207,2,0.0],[42000.0,1,0.0],[42315.79,2,0.0],[42473.6836,3,0.0],[42631.58,0,0.0],[42789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[42947.3672,0,0.0],[43263.1563,0,0.0],[43578.9453,3,0.0],[43736.84,1,0.0],[43894.7344,0,0.0],[44052.63,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[44210.5234,2,0.0],[44526.3125,1,0.0],[44842.1,2,0.0],[44999.9961,0,0.0],[45157.8945,3,0.0],[45315.79,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[45473.6836,0,0.0],[45789.4727,0,0.0],[46105.26,3,0.0],[46263.1563,1,0.0],[46421.05,0,0.0],[46578.9453,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[46736.84,2,0.0],[47052.63,1,0.0],[47368.418,2,0.0],[47526.3125,3,0.0],[47684.207,0,0.0],[47842.1,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[47999.9961,0,0.0],[48315.79,0,0.0],[48631.58,3,0.0],[48789.4727,1,0.0],[48947.3672,0,0.0],[49105.26,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[49263.1563,2,0.0],[49578.9453,1,0.0],[49894.7344,2,0.0],[50052.63,0,0.0],[50210.5234,3,0.0],[50368.418,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[50526.3125,3,157.89473],[51157.89,1,157.89473],[51473.6836,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[51789.4727,3,0.0],[52105.26,1,0.0],[52263.1563,3,0.0],[52578.9453,1,0.0],[52736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[53052.63,3,0.0],[53368.418,3,0.0],[53684.207,1,0.0],[53999.9961,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[54315.7852,3,0.0],[54631.58,1,0.0],[54789.4727,3,0.0],[55105.26,1,0.0],[55263.1563,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[55578.9453,3,157.89473],[56210.5234,1,157.89473],[56526.3125,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[56842.1,3,0.0],[57157.89,1,0.0],[57315.7852,3,0.0],[57631.58,1,0.0],[57789.4727,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[58105.26,3,0.0],[58421.05,3,0.0],[58736.84,1,0.0],[59052.63,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[59368.418,3,0.0],[59684.207,1,0.0],[59842.1,3,0.0],[60157.89,1,0.0],[60315.7852,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[60631.58,2,0.0],[60947.3672,3,0.0],[61105.26,1,0.0],[61263.1563,3,0.0],[61578.9453,0,0.0],[61736.84,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[61894.7344,0,0.0],[62210.5234,0,0.0],[62368.418,1,0.0],[62526.3125,3,0.0],[62842.1,1,0.0],[62999.9961,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[63157.89,0,0.0],[63473.68,0,0.0],[63631.5742,3,0.0],[63789.4727,0,0.0],[64105.26,3,0.0],[64263.1563,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[64421.05,1,0.0],[64736.84,1,0.0],[64894.7344,3,0.0],[65052.63,1,0.0],[65368.418,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[65684.21,2,0.0],[66000.0,3,0.0],[66157.89,1,0.0],[66315.79,3,0.0],[66631.58,0,0.0],[66789.47,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[66947.37,0,0.0],[67263.16,0,0.0],[67421.05,1,0.0],[67578.9453,3,0.0],[67894.7344,1,0.0],[68052.625,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[68210.52,0,0.0],[68526.31,0,0.0],[68684.21,3,0.0],[68842.1,0,0.0],[69157.89,3,0.0],[69315.79,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[69473.68,1,0.0],[69789.47,1,0.0],[69947.37,3,0.0],[70105.26,1,0.0],[70421.05,1,236.8421]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[70736.8359,0,0.0],[71052.625,0,0.0],[71368.4141,3,0.0],[71526.31,1,0.0],[71684.21,0,0.0],[71842.1,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[72000.0,2,0.0],[72315.79,1,0.0],[72631.58,2,0.0],[72789.47,3,0.0],[72947.37,0,0.0],[73105.26,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[73263.16,0,0.0],[73578.9453,0,0.0],[73894.7344,3,0.0],[74052.625,1,0.0],[74210.52,0,0.0],[74368.4141,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[74526.31,2,0.0],[74842.1,1,0.0],[75157.89,2,0.0],[75315.79,0,0.0],[75473.68,3,0.0],[75631.58,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[75789.47,0,0.0],[76105.26,0,0.0],[76421.05,3,0.0],[76578.9453,1,0.0],[76736.8359,0,0.0],[76894.7344,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[77052.625,2,0.0],[77368.4141,1,0.0],[77684.2,2,0.0],[77842.1,3,0.0],[78000.0,0,0.0],[78157.89,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[78315.79,0,0.0],[78631.58,0,0.0],[78947.37,3,0.0],[79105.26,1,0.0],[79263.16,0,0.0],[79421.05,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[79578.9453,2,0.0],[79894.7344,1,0.0],[80210.52,2,0.0],[80368.4141,0,0.0],[80526.31,3,0.0],[80684.2,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[80842.1,2,0.0],[81157.89,1,0.0],[81473.68,0,0.0],[81631.58,3,0.0],[81789.47,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[82105.26,2,0.0],[82421.05,1,0.0],[82736.8359,0,0.0],[82894.7344,3,0.0],[83052.625,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[83368.4141,2,0.0],[83684.2,1,0.0],[84000.0,0,0.0],[84157.89,3,0.0],[84315.79,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[84631.58,2,0.0],[84947.37,1,0.0],[85263.16,0,0.0],[85421.05,3,0.0],[85578.9453,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[85894.7344,2,0.0],[86210.52,1,0.0],[86526.31,0,0.0],[86684.2,3,0.0],[86842.1,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[87157.89,2,0.0],[87473.68,1,0.0],[87789.47,0,0.0],[87947.37,3,0.0],[88105.26,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[88421.05,2,0.0],[88736.8359,1,0.0],[89052.625,0,0.0],[89210.52,3,0.0],[89368.4141,1,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[89684.2,2,0.0],[89999.99,1,0.0],[90315.79,0,0.0],[90473.68,3,0.0],[90631.58,1,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[90947.37,3,157.89473],[91578.9453,1,157.89473],[91894.7344,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[92210.52,3,0.0],[92526.31,1,0.0],[92684.2,3,0.0],[92999.99,1,0.0],[93157.89,3,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[93473.68,3,0.0],[93789.47,3,0.0],[94105.26,1,0.0],[94421.05,0,0.0]]},{"lengthInSteps":16,"mustHitSection":false,"sectionNotes":[[94736.8359,3,0.0],[95052.625,1,0.0],[95210.52,3,0.0],[95526.31,1,0.0],[95684.2,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[95999.99,3,157.89473],[96631.58,1,157.89473],[96947.37,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[97263.16,3,0.0],[97578.9453,1,0.0],[97736.8359,3,0.0],[98052.625,1,0.0],[98210.52,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[98526.31,3,0.0],[98842.1,3,0.0],[99157.89,1,0.0],[99473.68,0,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[[99789.47,3,0.0],[100105.258,1,0.0],[100263.156,3,0.0],[100578.945,1,0.0],[100736.836,3,0.0]]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]},{"lengthInSteps":16,"mustHitSection":true,"sectionNotes":[]}]},"generatedBy":"SNIFF ver.6"}
\ No newline at end of file
+{"events":[{"params":[1],"name":"Camera Movement","time":5052.63157894737},{"params":[0],"name":"Camera Movement","time":10105.2631578947},{"params":[1],"name":"Camera Movement","time":15157.8947368421},{"params":[0],"name":"Camera Movement","time":20210.5263157895},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":20210.5263157895},{"params":[1],"name":"Camera Movement","time":25263.1578947368},{"params":[0],"name":"Camera Movement","time":30315.7894736842},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":30315.7894736842},{"params":[1],"name":"Camera Movement","time":35368.4210526316},{"params":[0],"name":"Camera Movement","time":40421.0526315789},{"params":[1],"name":"Camera Movement","time":45473.6842105263},{"params":[0],"name":"Camera Movement","time":50526.3157894737},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":50526.3157894737},{"params":[1],"name":"Camera Movement","time":55578.947368421},{"params":[0],"name":"Camera Movement","time":60631.5789473684},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":60631.5789473684},{"params":[1],"name":"Camera Movement","time":65684.2105263157},{"params":[0],"name":"Camera Movement","time":70736.8421052631},{"params":[1],"name":"Camera Movement","time":75789.4736842105},{"params":[0],"name":"Camera Movement","time":80842.1052631578},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":80842.1052631578},{"params":[1],"name":"Camera Movement","time":85894.7368421052},{"params":[0],"name":"Camera Movement","time":90947.3684210525},{"params":["aberrationCoolThing",""],"name":"HScript Call","time":90947.3684210525},{"params":[1],"name":"Camera Movement","time":95999.9999999999}],"scrollSpeed":1.3,"strumLines":[{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":0,"type":0},{"id":1,"sLen":157.89473,"time":631.5789,"type":0},{"id":0,"sLen":0,"time":947.3684,"type":0},{"id":3,"sLen":0,"time":1263.15784,"type":0},{"id":1,"sLen":0,"time":1578.94727,"type":0},{"id":3,"sLen":0,"time":1736.842,"type":0},{"id":1,"sLen":0,"time":2052.63159,"type":0},{"id":3,"sLen":0,"time":2210.52612,"type":0},{"id":3,"sLen":0,"time":2526.31567,"type":0},{"id":3,"sLen":0,"time":2842.10522,"type":0},{"id":1,"sLen":0,"time":3157.89453,"type":0},{"id":0,"sLen":0,"time":3473.684,"type":0},{"id":3,"sLen":0,"time":3789.47363,"type":0},{"id":1,"sLen":0,"time":4105.263,"type":0},{"id":3,"sLen":0,"time":4263.15771,"type":0},{"id":1,"sLen":0,"time":4578.94727,"type":0},{"id":3,"sLen":0,"time":4736.842,"type":0},{"id":2,"sLen":157.894729999998,"time":10105.2627,"type":0},{"id":2,"sLen":0,"time":10736.8418,"type":0},{"id":3,"sLen":0,"time":10894.7363,"type":0},{"id":1,"sLen":78.9473647999985,"time":11052.6309,"type":0},{"id":2,"sLen":157.89473,"time":11368.4209,"type":0},{"id":2,"sLen":157.89473,"time":11842.1045,"type":0},{"id":2,"sLen":157.89473,"time":12315.7891,"type":0},{"id":2,"sLen":157.89473,"time":12631.5781,"type":0},{"id":2,"sLen":0,"time":13263.1572,"type":0},{"id":3,"sLen":0,"time":13421.0518,"type":0},{"id":1,"sLen":78.9473648000003,"time":13578.9463,"type":0},{"id":2,"sLen":157.89473,"time":13894.7363,"type":0},{"id":2,"sLen":157.89473,"time":14368.42,"type":0},{"id":0,"sLen":157.89473,"time":14842.1045,"type":0},{"id":1,"sLen":0,"time":20210.5254,"type":0},{"id":3,"sLen":0,"time":20526.3145,"type":0},{"id":1,"sLen":0,"time":20684.209,"type":0},{"id":3,"sLen":0,"time":21000,"type":0},{"id":1,"sLen":0,"time":21157.8945,"type":0},{"id":2,"sLen":0,"time":21473.6836,"type":0},{"id":1,"sLen":0,"time":21631.5781,"type":0},{"id":2,"sLen":0,"time":21947.3672,"type":0},{"id":1,"sLen":0,"time":22105.2617,"type":0},{"id":3,"sLen":0,"time":22421.05,"type":0},{"id":1,"sLen":0,"time":22578.9473,"type":0},{"id":1,"sLen":0,"time":22736.8418,"type":0},{"id":3,"sLen":0,"time":23052.63,"type":0},{"id":1,"sLen":0,"time":23210.5254,"type":0},{"id":3,"sLen":0,"time":23526.3145,"type":0},{"id":1,"sLen":0,"time":23684.209,"type":0},{"id":2,"sLen":0,"time":23999.998,"type":0},{"id":1,"sLen":0,"time":24157.8945,"type":0},{"id":2,"sLen":0,"time":24473.6836,"type":0},{"id":1,"sLen":0,"time":24631.5781,"type":0},{"id":3,"sLen":0,"time":24947.3672,"type":0},{"id":1,"sLen":0,"time":25105.2617,"type":0},{"id":2,"sLen":0,"time":30315.79,"type":0},{"id":3,"sLen":0,"time":30631.5781,"type":0},{"id":1,"sLen":0,"time":30789.4727,"type":0},{"id":3,"sLen":0,"time":30947.3672,"type":0},{"id":0,"sLen":0,"time":31263.1563,"type":0},{"id":3,"sLen":0,"time":31421.05,"type":0},{"id":0,"sLen":0,"time":31578.9453,"type":0},{"id":0,"sLen":0,"time":31894.7363,"type":0},{"id":1,"sLen":0,"time":32052.63,"type":0},{"id":3,"sLen":0,"time":32210.5254,"type":0},{"id":1,"sLen":0,"time":32526.3145,"type":0},{"id":3,"sLen":0,"time":32684.209,"type":0},{"id":0,"sLen":0,"time":32842.1055,"type":0},{"id":0,"sLen":0,"time":33157.8945,"type":0},{"id":3,"sLen":0,"time":33315.79,"type":0},{"id":0,"sLen":0,"time":33473.6836,"type":0},{"id":3,"sLen":0,"time":33789.4727,"type":0},{"id":1,"sLen":0,"time":33947.3672,"type":0},{"id":1,"sLen":0,"time":34105.26,"type":0},{"id":1,"sLen":0,"time":34421.05,"type":0},{"id":3,"sLen":0,"time":34578.9453,"type":0},{"id":1,"sLen":0,"time":34736.84,"type":0},{"id":1,"sLen":236.842100000002,"time":35052.63,"type":0},{"id":0,"sLen":0,"time":40421.05,"type":0},{"id":0,"sLen":0,"time":40736.84,"type":0},{"id":3,"sLen":0,"time":41052.63,"type":0},{"id":1,"sLen":0,"time":41210.5234,"type":0},{"id":0,"sLen":0,"time":41368.418,"type":0},{"id":3,"sLen":0,"time":41526.3125,"type":0},{"id":2,"sLen":0,"time":41684.207,"type":0},{"id":1,"sLen":0,"time":42000,"type":0},{"id":2,"sLen":0,"time":42315.79,"type":0},{"id":3,"sLen":0,"time":42473.6836,"type":0},{"id":0,"sLen":0,"time":42631.58,"type":0},{"id":3,"sLen":0,"time":42789.4727,"type":0},{"id":0,"sLen":0,"time":42947.3672,"type":0},{"id":0,"sLen":0,"time":43263.1563,"type":0},{"id":3,"sLen":0,"time":43578.9453,"type":0},{"id":1,"sLen":0,"time":43736.84,"type":0},{"id":0,"sLen":0,"time":43894.7344,"type":0},{"id":3,"sLen":0,"time":44052.63,"type":0},{"id":2,"sLen":0,"time":44210.5234,"type":0},{"id":1,"sLen":0,"time":44526.3125,"type":0},{"id":2,"sLen":0,"time":44842.1,"type":0},{"id":0,"sLen":0,"time":44999.9961,"type":0},{"id":3,"sLen":0,"time":45157.8945,"type":0},{"id":0,"sLen":0,"time":45315.79,"type":0},{"id":3,"sLen":157.89473,"time":50526.3125,"type":0},{"id":1,"sLen":157.89473,"time":51157.89,"type":0},{"id":0,"sLen":0,"time":51473.6836,"type":0},{"id":3,"sLen":0,"time":51789.4727,"type":0},{"id":1,"sLen":0,"time":52105.26,"type":0},{"id":3,"sLen":0,"time":52263.1563,"type":0},{"id":1,"sLen":0,"time":52578.9453,"type":0},{"id":3,"sLen":0,"time":52736.84,"type":0},{"id":3,"sLen":0,"time":53052.63,"type":0},{"id":3,"sLen":0,"time":53368.418,"type":0},{"id":1,"sLen":0,"time":53684.207,"type":0},{"id":0,"sLen":0,"time":53999.9961,"type":0},{"id":3,"sLen":0,"time":54315.7852,"type":0},{"id":1,"sLen":0,"time":54631.58,"type":0},{"id":3,"sLen":0,"time":54789.4727,"type":0},{"id":1,"sLen":0,"time":55105.26,"type":0},{"id":3,"sLen":0,"time":55263.1563,"type":0},{"id":2,"sLen":0,"time":60631.58,"type":0},{"id":3,"sLen":0,"time":60947.3672,"type":0},{"id":1,"sLen":0,"time":61105.26,"type":0},{"id":3,"sLen":0,"time":61263.1563,"type":0},{"id":0,"sLen":0,"time":61578.9453,"type":0},{"id":3,"sLen":0,"time":61736.84,"type":0},{"id":0,"sLen":0,"time":61894.7344,"type":0},{"id":0,"sLen":0,"time":62210.5234,"type":0},{"id":1,"sLen":0,"time":62368.418,"type":0},{"id":3,"sLen":0,"time":62526.3125,"type":0},{"id":1,"sLen":0,"time":62842.1,"type":0},{"id":3,"sLen":0,"time":62999.9961,"type":0},{"id":0,"sLen":0,"time":63157.89,"type":0},{"id":0,"sLen":0,"time":63473.68,"type":0},{"id":3,"sLen":0,"time":63631.5742,"type":0},{"id":0,"sLen":0,"time":63789.4727,"type":0},{"id":3,"sLen":0,"time":64105.26,"type":0},{"id":1,"sLen":0,"time":64263.1563,"type":0},{"id":1,"sLen":0,"time":64421.05,"type":0},{"id":1,"sLen":0,"time":64736.84,"type":0},{"id":3,"sLen":0,"time":64894.7344,"type":0},{"id":1,"sLen":0,"time":65052.63,"type":0},{"id":1,"sLen":236.842100000002,"time":65368.418,"type":0},{"id":0,"sLen":0,"time":70736.8359,"type":0},{"id":0,"sLen":0,"time":71052.625,"type":0},{"id":3,"sLen":0,"time":71368.4141,"type":0},{"id":1,"sLen":0,"time":71526.31,"type":0},{"id":0,"sLen":0,"time":71684.21,"type":0},{"id":3,"sLen":0,"time":71842.1,"type":0},{"id":2,"sLen":0,"time":72000,"type":0},{"id":1,"sLen":0,"time":72315.79,"type":0},{"id":2,"sLen":0,"time":72631.58,"type":0},{"id":3,"sLen":0,"time":72789.47,"type":0},{"id":0,"sLen":0,"time":72947.37,"type":0},{"id":3,"sLen":0,"time":73105.26,"type":0},{"id":0,"sLen":0,"time":73263.16,"type":0},{"id":0,"sLen":0,"time":73578.9453,"type":0},{"id":3,"sLen":0,"time":73894.7344,"type":0},{"id":1,"sLen":0,"time":74052.625,"type":0},{"id":0,"sLen":0,"time":74210.52,"type":0},{"id":3,"sLen":0,"time":74368.4141,"type":0},{"id":2,"sLen":0,"time":74526.31,"type":0},{"id":1,"sLen":0,"time":74842.1,"type":0},{"id":2,"sLen":0,"time":75157.89,"type":0},{"id":0,"sLen":0,"time":75315.79,"type":0},{"id":3,"sLen":0,"time":75473.68,"type":0},{"id":0,"sLen":0,"time":75631.58,"type":0},{"id":2,"sLen":0,"time":80842.1,"type":0},{"id":1,"sLen":0,"time":81157.89,"type":0},{"id":0,"sLen":0,"time":81473.68,"type":0},{"id":3,"sLen":0,"time":81631.58,"type":0},{"id":1,"sLen":0,"time":81789.47,"type":0},{"id":2,"sLen":0,"time":82105.26,"type":0},{"id":1,"sLen":0,"time":82421.05,"type":0},{"id":0,"sLen":0,"time":82736.8359,"type":0},{"id":3,"sLen":0,"time":82894.7344,"type":0},{"id":1,"sLen":0,"time":83052.625,"type":0},{"id":2,"sLen":0,"time":83368.4141,"type":0},{"id":1,"sLen":0,"time":83684.2,"type":0},{"id":0,"sLen":0,"time":84000,"type":0},{"id":3,"sLen":0,"time":84157.89,"type":0},{"id":1,"sLen":0,"time":84315.79,"type":0},{"id":2,"sLen":0,"time":84631.58,"type":0},{"id":1,"sLen":0,"time":84947.37,"type":0},{"id":0,"sLen":0,"time":85263.16,"type":0},{"id":3,"sLen":0,"time":85421.05,"type":0},{"id":1,"sLen":0,"time":85578.9453,"type":0},{"id":3,"sLen":157.89473,"time":90947.37,"type":0},{"id":1,"sLen":157.89473,"time":91578.9453,"type":0},{"id":0,"sLen":0,"time":91894.7344,"type":0},{"id":3,"sLen":0,"time":92210.52,"type":0},{"id":1,"sLen":0,"time":92526.31,"type":0},{"id":3,"sLen":0,"time":92684.2,"type":0},{"id":1,"sLen":0,"time":92999.99,"type":0},{"id":3,"sLen":0,"time":93157.89,"type":0},{"id":3,"sLen":0,"time":93473.68,"type":0},{"id":3,"sLen":0,"time":93789.47,"type":0},{"id":1,"sLen":0,"time":94105.26,"type":0},{"id":0,"sLen":0,"time":94421.05,"type":0},{"id":3,"sLen":0,"time":94736.8359,"type":0},{"id":1,"sLen":0,"time":95052.625,"type":0},{"id":3,"sLen":0,"time":95210.52,"type":0},{"id":1,"sLen":0,"time":95526.31,"type":0},{"id":3,"sLen":0,"time":95684.2,"type":0}],"position":"dad","type":0,"characters":["spirit"]},{"visible":true,"notes":[{"id":3,"sLen":157.89473,"time":5052.63135,"type":0},{"id":1,"sLen":157.89473,"time":5684.21045,"type":0},{"id":0,"sLen":0,"time":5999.99951,"type":0},{"id":3,"sLen":0,"time":6315.789,"type":0},{"id":1,"sLen":0,"time":6631.57861,"type":0},{"id":3,"sLen":0,"time":6789.473,"type":0},{"id":1,"sLen":0,"time":7105.2627,"type":0},{"id":3,"sLen":0,"time":7263.15771,"type":0},{"id":3,"sLen":0,"time":7578.94727,"type":0},{"id":3,"sLen":0,"time":7894.73633,"type":0},{"id":1,"sLen":0,"time":8210.526,"type":0},{"id":0,"sLen":0,"time":8526.315,"type":0},{"id":3,"sLen":0,"time":8842.10449,"type":0},{"id":1,"sLen":0,"time":9157.895,"type":0},{"id":3,"sLen":0,"time":9315.789,"type":0},{"id":1,"sLen":0,"time":9631.578,"type":0},{"id":3,"sLen":0,"time":9789.474,"type":0},{"id":2,"sLen":157.89473,"time":15157.8945,"type":0},{"id":2,"sLen":0,"time":15789.4727,"type":0},{"id":3,"sLen":0,"time":15947.3682,"type":0},{"id":1,"sLen":78.9473648000003,"time":16105.2627,"type":0},{"id":2,"sLen":157.89473,"time":16421.0527,"type":0},{"id":2,"sLen":157.89473,"time":16894.7363,"type":0},{"id":2,"sLen":157.89473,"time":17368.42,"type":0},{"id":2,"sLen":157.89473,"time":17684.209,"type":0},{"id":2,"sLen":0,"time":18315.79,"type":0},{"id":3,"sLen":0,"time":18473.6836,"type":0},{"id":1,"sLen":78.9473647999985,"time":18631.5781,"type":0},{"id":2,"sLen":157.89473,"time":18947.3672,"type":0},{"id":2,"sLen":157.89473,"time":19421.05,"type":0},{"id":0,"sLen":157.89473,"time":19894.7363,"type":0},{"id":3,"sLen":0,"time":24789.4727,"type":0},{"id":2,"sLen":0,"time":24947.3672,"type":0},{"id":0,"sLen":0,"time":25105.2617,"type":0},{"id":1,"sLen":0,"time":25263.1563,"type":0},{"id":3,"sLen":0,"time":25578.9453,"type":0},{"id":1,"sLen":0,"time":25736.8418,"type":0},{"id":3,"sLen":0,"time":26052.63,"type":0},{"id":1,"sLen":0,"time":26210.5254,"type":0},{"id":2,"sLen":0,"time":26526.3145,"type":0},{"id":1,"sLen":0,"time":26684.209,"type":0},{"id":2,"sLen":0,"time":26999.998,"type":0},{"id":1,"sLen":0,"time":27157.8926,"type":0},{"id":3,"sLen":0,"time":27473.6836,"type":0},{"id":1,"sLen":0,"time":27631.5781,"type":0},{"id":1,"sLen":0,"time":27789.4727,"type":0},{"id":3,"sLen":0,"time":28105.2617,"type":0},{"id":1,"sLen":0,"time":28263.1563,"type":0},{"id":3,"sLen":0,"time":28578.9453,"type":0},{"id":1,"sLen":0,"time":28736.84,"type":0},{"id":2,"sLen":0,"time":29052.63,"type":0},{"id":1,"sLen":0,"time":29210.5254,"type":0},{"id":2,"sLen":0,"time":29526.3145,"type":0},{"id":1,"sLen":0,"time":29684.209,"type":0},{"id":3,"sLen":0,"time":29999.998,"type":0},{"id":1,"sLen":0,"time":30157.8926,"type":0},{"id":2,"sLen":0,"time":35368.418,"type":0},{"id":3,"sLen":0,"time":35684.207,"type":0},{"id":1,"sLen":0,"time":35842.1055,"type":0},{"id":3,"sLen":0,"time":36000,"type":0},{"id":0,"sLen":0,"time":36315.79,"type":0},{"id":3,"sLen":0,"time":36473.6836,"type":0},{"id":0,"sLen":0,"time":36631.58,"type":0},{"id":0,"sLen":0,"time":36947.3672,"type":0},{"id":1,"sLen":0,"time":37105.26,"type":0},{"id":3,"sLen":0,"time":37263.1563,"type":0},{"id":1,"sLen":0,"time":37578.9453,"type":0},{"id":3,"sLen":0,"time":37736.84,"type":0},{"id":0,"sLen":0,"time":37894.7344,"type":0},{"id":0,"sLen":0,"time":38210.5234,"type":0},{"id":3,"sLen":0,"time":38368.418,"type":0},{"id":0,"sLen":0,"time":38526.3125,"type":0},{"id":3,"sLen":0,"time":38842.1,"type":0},{"id":1,"sLen":0,"time":39000,"type":0},{"id":1,"sLen":0,"time":39157.8945,"type":0},{"id":1,"sLen":0,"time":39473.6836,"type":0},{"id":3,"sLen":0,"time":39631.58,"type":0},{"id":1,"sLen":0,"time":39789.4727,"type":0},{"id":1,"sLen":236.842100000002,"time":40105.26,"type":0},{"id":0,"sLen":0,"time":45473.6836,"type":0},{"id":0,"sLen":0,"time":45789.4727,"type":0},{"id":3,"sLen":0,"time":46105.26,"type":0},{"id":1,"sLen":0,"time":46263.1563,"type":0},{"id":0,"sLen":0,"time":46421.05,"type":0},{"id":3,"sLen":0,"time":46578.9453,"type":0},{"id":2,"sLen":0,"time":46736.84,"type":0},{"id":1,"sLen":0,"time":47052.63,"type":0},{"id":2,"sLen":0,"time":47368.418,"type":0},{"id":3,"sLen":0,"time":47526.3125,"type":0},{"id":0,"sLen":0,"time":47684.207,"type":0},{"id":3,"sLen":0,"time":47842.1,"type":0},{"id":0,"sLen":0,"time":47999.9961,"type":0},{"id":0,"sLen":0,"time":48315.79,"type":0},{"id":3,"sLen":0,"time":48631.58,"type":0},{"id":1,"sLen":0,"time":48789.4727,"type":0},{"id":0,"sLen":0,"time":48947.3672,"type":0},{"id":3,"sLen":0,"time":49105.26,"type":0},{"id":2,"sLen":0,"time":49263.1563,"type":0},{"id":1,"sLen":0,"time":49578.9453,"type":0},{"id":2,"sLen":0,"time":49894.7344,"type":0},{"id":0,"sLen":0,"time":50052.63,"type":0},{"id":3,"sLen":0,"time":50210.5234,"type":0},{"id":0,"sLen":0,"time":50368.418,"type":0},{"id":3,"sLen":157.89473,"time":55578.9453,"type":0},{"id":1,"sLen":157.89473,"time":56210.5234,"type":0},{"id":0,"sLen":0,"time":56526.3125,"type":0},{"id":3,"sLen":0,"time":56842.1,"type":0},{"id":1,"sLen":0,"time":57157.89,"type":0},{"id":3,"sLen":0,"time":57315.7852,"type":0},{"id":1,"sLen":0,"time":57631.58,"type":0},{"id":3,"sLen":0,"time":57789.4727,"type":0},{"id":3,"sLen":0,"time":58105.26,"type":0},{"id":3,"sLen":0,"time":58421.05,"type":0},{"id":1,"sLen":0,"time":58736.84,"type":0},{"id":0,"sLen":0,"time":59052.63,"type":0},{"id":3,"sLen":0,"time":59368.418,"type":0},{"id":1,"sLen":0,"time":59684.207,"type":0},{"id":3,"sLen":0,"time":59842.1,"type":0},{"id":1,"sLen":0,"time":60157.89,"type":0},{"id":3,"sLen":0,"time":60315.7852,"type":0},{"id":2,"sLen":0,"time":65684.21,"type":0},{"id":3,"sLen":0,"time":66000,"type":0},{"id":1,"sLen":0,"time":66157.89,"type":0},{"id":3,"sLen":0,"time":66315.79,"type":0},{"id":0,"sLen":0,"time":66631.58,"type":0},{"id":3,"sLen":0,"time":66789.47,"type":0},{"id":0,"sLen":0,"time":66947.37,"type":0},{"id":0,"sLen":0,"time":67263.16,"type":0},{"id":1,"sLen":0,"time":67421.05,"type":0},{"id":3,"sLen":0,"time":67578.9453,"type":0},{"id":1,"sLen":0,"time":67894.7344,"type":0},{"id":3,"sLen":0,"time":68052.625,"type":0},{"id":0,"sLen":0,"time":68210.52,"type":0},{"id":0,"sLen":0,"time":68526.31,"type":0},{"id":3,"sLen":0,"time":68684.21,"type":0},{"id":0,"sLen":0,"time":68842.1,"type":0},{"id":3,"sLen":0,"time":69157.89,"type":0},{"id":1,"sLen":0,"time":69315.79,"type":0},{"id":1,"sLen":0,"time":69473.68,"type":0},{"id":1,"sLen":0,"time":69789.47,"type":0},{"id":3,"sLen":0,"time":69947.37,"type":0},{"id":1,"sLen":0,"time":70105.26,"type":0},{"id":1,"sLen":236.842099999994,"time":70421.05,"type":0},{"id":0,"sLen":0,"time":75789.47,"type":0},{"id":0,"sLen":0,"time":76105.26,"type":0},{"id":3,"sLen":0,"time":76421.05,"type":0},{"id":1,"sLen":0,"time":76578.9453,"type":0},{"id":0,"sLen":0,"time":76736.8359,"type":0},{"id":3,"sLen":0,"time":76894.7344,"type":0},{"id":2,"sLen":0,"time":77052.625,"type":0},{"id":1,"sLen":0,"time":77368.4141,"type":0},{"id":2,"sLen":0,"time":77684.2,"type":0},{"id":3,"sLen":0,"time":77842.1,"type":0},{"id":0,"sLen":0,"time":78000,"type":0},{"id":3,"sLen":0,"time":78157.89,"type":0},{"id":0,"sLen":0,"time":78315.79,"type":0},{"id":0,"sLen":0,"time":78631.58,"type":0},{"id":3,"sLen":0,"time":78947.37,"type":0},{"id":1,"sLen":0,"time":79105.26,"type":0},{"id":0,"sLen":0,"time":79263.16,"type":0},{"id":3,"sLen":0,"time":79421.05,"type":0},{"id":2,"sLen":0,"time":79578.9453,"type":0},{"id":1,"sLen":0,"time":79894.7344,"type":0},{"id":2,"sLen":0,"time":80210.52,"type":0},{"id":0,"sLen":0,"time":80368.4141,"type":0},{"id":3,"sLen":0,"time":80526.31,"type":0},{"id":0,"sLen":0,"time":80684.2,"type":0},{"id":2,"sLen":0,"time":85894.7344,"type":0},{"id":1,"sLen":0,"time":86210.52,"type":0},{"id":0,"sLen":0,"time":86526.31,"type":0},{"id":3,"sLen":0,"time":86684.2,"type":0},{"id":1,"sLen":0,"time":86842.1,"type":0},{"id":2,"sLen":0,"time":87157.89,"type":0},{"id":1,"sLen":0,"time":87473.68,"type":0},{"id":0,"sLen":0,"time":87789.47,"type":0},{"id":3,"sLen":0,"time":87947.37,"type":0},{"id":1,"sLen":0,"time":88105.26,"type":0},{"id":2,"sLen":0,"time":88421.05,"type":0},{"id":1,"sLen":0,"time":88736.8359,"type":0},{"id":0,"sLen":0,"time":89052.625,"type":0},{"id":3,"sLen":0,"time":89210.52,"type":0},{"id":1,"sLen":0,"time":89368.4141,"type":0},{"id":2,"sLen":0,"time":89684.2,"type":0},{"id":1,"sLen":0,"time":89999.99,"type":0},{"id":0,"sLen":0,"time":90315.79,"type":0},{"id":3,"sLen":0,"time":90473.68,"type":0},{"id":1,"sLen":0,"time":90631.58,"type":0},{"id":3,"sLen":157.89473,"time":95999.99,"type":0},{"id":1,"sLen":157.89473,"time":96631.58,"type":0},{"id":0,"sLen":0,"time":96947.37,"type":0},{"id":3,"sLen":0,"time":97263.16,"type":0},{"id":1,"sLen":0,"time":97578.9453,"type":0},{"id":3,"sLen":0,"time":97736.8359,"type":0},{"id":1,"sLen":0,"time":98052.625,"type":0},{"id":3,"sLen":0,"time":98210.52,"type":0},{"id":3,"sLen":0,"time":98526.31,"type":0},{"id":3,"sLen":0,"time":98842.1,"type":0},{"id":1,"sLen":0,"time":99157.89,"type":0},{"id":0,"sLen":0,"time":99473.68,"type":0},{"id":3,"sLen":0,"time":99789.47,"type":0},{"id":1,"sLen":0,"time":100105.258,"type":0},{"id":3,"sLen":0,"time":100263.156,"type":0},{"id":1,"sLen":0,"time":100578.945,"type":0},{"id":3,"sLen":0,"time":100736.836,"type":0}],"position":"boyfriend","type":1,"characters":["bf-pixel"]},{"notes":[],"visible":false,"position":"girlfriend","type":2,"characters":["gf-pixel"]}],"codenameChart":true,"stage":"school-evil","noteTypes":[]}
\ No newline at end of file
diff --git a/assets/songs/thorns/cutscene.hx b/assets/songs/thorns/cutscene.hx
new file mode 100644
index 00000000..88369443
--- /dev/null
+++ b/assets/songs/thorns/cutscene.hx
@@ -0,0 +1,89 @@
+import flixel.addons.util.FlxSimplex;
+
+static var roses_shouldPlayOnThorns = false;
+var self = this;
+__script__.setParent(PlayState.instance);
+
+var scream:FlxSound;
+var senpaiEvil:FlxSprite;
+var dfx = 0;
+var dfy = 0;
+function create() {
+ // Cutscene stuff
+ if(!roses_shouldPlayOnThorns) {
+ disableScript();
+ self.close();
+ return;
+ }
+ roses_shouldPlayOnThorns = false;
+ camHUD.visible = false;
+
+ var red:FlxSprite = new FlxSprite().makeSolid(FlxG.width + 100, FlxG.height + 100, 0xFFff1b31);
+ red.screenCenter();
+ red.scrollFactor.set();
+ add(red);
+
+ senpaiEvil = new FlxSprite();
+ senpaiEvil.frames = Paths.getSparrowAtlas('game/cutscenes/weeb/senpaiCrazy');
+ senpaiEvil.animation.addByPrefix('idle', 'Senpai Pre Explosion', 24, false);
+ senpaiEvil.animation.play('idle');
+ senpaiEvil.setGraphicSize(Std.int(senpaiEvil.width * daPixelZoom));
+ senpaiEvil.scrollFactor.set();
+ senpaiEvil.updateHitbox();
+ senpaiEvil.screenCenter();
+ senpaiEvil.x += daPixelZoom * 51;
+ dfx = senpaiEvil.x;
+ dfy = senpaiEvil.y;
+ add(senpaiEvil);
+
+ var white:FlxSprite = new FlxSprite().makeSolid(FlxG.width + 100, FlxG.height + 100, FlxColor.WHITE);
+ white.screenCenter();
+ white.scrollFactor.set();
+ white.alpha = 0;
+ add(white);
+
+ new FlxTimer().start(3.2, function(deadTime:FlxTimer)
+ {
+ FlxG.camera.fade(FlxColor.WHITE, 1.6, false, function() {
+ remove(senpaiEvil, true);
+ senpaiEvil.destroy();
+ remove(red, true);
+ red.destroy();
+
+ white.alpha = 1;
+ });
+ });
+ scream = FlxG.sound.play(Paths.sound('cutscenes/weeb/Senpai_Dies'), 1, false, null, true, function()
+ {
+ new FlxTimer().start(0.2, function(swagTimer:FlxTimer) {
+ white.alpha -= 0.15;
+
+ if(white.alpha > 0) swagTimer.reset();
+ else {
+ remove(white, true);
+ white.destroy();
+
+ camHUD.visible = true;
+ self.close();
+ }
+ });
+
+ FlxG.camera.fade(FlxColor.WHITE, 0.0001, true);
+ });
+}
+
+var sVal = 0;
+var seed = FlxG.random.float(-4000, 4000);
+var sShkv = 50; // shake range
+var sSpeed = 240;
+
+function update(elapsed:Float) {
+ if(scream?.time > 2350) {
+ sVal += sSpeed * elapsed;
+
+ var vx = sShkv * FlxSimplex.simplexOctaves(sVal, seed, 0.07, 0.25, 4);
+ var vy = sShkv * FlxSimplex.simplexOctaves(sVal + 500, seed, 0.07, 0.25, 4);
+
+ senpaiEvil.setPosition(dfx + vx, dfy + vy);
+ }
+}
\ No newline at end of file
diff --git a/assets/songs/thorns/scripts/aberration.hx b/assets/songs/thorns/scripts/aberration.hx
new file mode 100644
index 00000000..369d0655
--- /dev/null
+++ b/assets/songs/thorns/scripts/aberration.hx
@@ -0,0 +1,37 @@
+var aberration:CustomShader = null;
+function create() {
+ if(!Options.gameplayShaders) return;
+ aberration = new CustomShader('chromaticAberration');
+ setGeneralIntensity(Options.week6PixelPerfect ? 0.0005 : 0.005);
+ camGame.addShader(aberration);
+}
+
+var intens:Float = 0;
+function setGeneralIntensity(val:Float) {
+ intens = val;
+ aberration.redOff = [intens, 0];
+ aberration.blueOff = [-intens, 0];
+}
+
+var canBump:Bool = false;
+function aberrationCoolThing() {
+ canBump = !canBump;
+ if(!canBump) {
+ if(Options.gameplayShaders) setGeneralIntensity(Options.week6PixelPerfect ? 0.0005 : 0.005); // Just to make sure if anything goes wrong
+ maxCamZoom = 1.35;
+ } else maxCamZoom = 0;
+}
+
+function update(elapsed:Float) {
+ if(Options.gameplayShaders && canBump && intens > (Options.week6PixelPerfect ? 0.0005 : 0.005)) setGeneralIntensity(intens - (Options.week6PixelPerfect ? 0.0001 : 0.001));
+}
+
+function beatHit(curBeat:Float) {
+ if(canBump && curBeat % 2 != 0) {
+ if(Options.gameplayShaders) setGeneralIntensity(Options.week6PixelPerfect ? 0.005 : 0.05);
+ if(Options.camZoomOnBeat) {
+ FlxG.camera.zoom += 0.015 * camZoomingStrength;
+ camHUD.zoom += 0.03 * camZoomingStrength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/songs/ugh/cutscene.hx b/assets/songs/ugh/cutscene.hx
index 9a97c206..f1167d57 100644
--- a/assets/songs/ugh/cutscene.hx
+++ b/assets/songs/ugh/cutscene.hx
@@ -64,13 +64,4 @@ function focusOn(char) {
var camPos = char.getCameraPosition();
game.camFollow.setPosition(camPos.x, camPos.y);
camPos.put();
-}
-
-function update(elapsed:Float) {
- if (tankTalk1.playing) lipSync(tankTalk1);
- if (tankTalk2.playing) lipSync(tankTalk2);
-}
-
-function lipSync(sound:FlxSound) {
- tankman.animateAtlas.anim.curFrame = Std.int(tankman.animateAtlas.anim.length / (sound.length-1) * sound.time);
}
\ No newline at end of file
diff --git a/assets/songs/winter horrorland/cutscene.hx b/assets/songs/winter horrorland/cutscene.hx
new file mode 100644
index 00000000..f2fa3109
--- /dev/null
+++ b/assets/songs/winter horrorland/cutscene.hx
@@ -0,0 +1,17 @@
+var self = this;
+__script__.setParent(PlayState.instance);
+
+function create() {
+ FlxG.sound.play(Paths.sound('Lights_Turn_On'));
+ camFollow.setPosition(500, -2050);
+ FlxG.camera.focusOn(camFollow.getPosition());
+ FlxG.camera.zoom = 1.5;
+
+ FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, {
+ ease: FlxEase.quadInOut, startDelay: 0.8,
+ onComplete: function(twn:FlxTween)
+ {
+ self.close();
+ }
+ });
+}
\ No newline at end of file
diff --git a/assets/songs/winter horrorland/scripts/funniBump.hx b/assets/songs/winter horrorland/scripts/funniBump.hx
new file mode 100644
index 00000000..57de7c28
--- /dev/null
+++ b/assets/songs/winter horrorland/scripts/funniBump.hx
@@ -0,0 +1,12 @@
+function beatHit(curBeat:Int) {
+ switch(curBeat) {
+ case 120:
+ camZoomingInterval = 2;
+ case 153:
+ camZoomingInterval = 4;
+ case 216:
+ camZoomingInterval = 2;
+ case 230:
+ camZoomingInterval = 4;
+ }
+}
\ No newline at end of file
diff --git a/assets/sounds/cutscenes/weeb/Senpai_Dies.mp3 b/assets/sounds/cutscenes/weeb/Senpai_Dies.mp3
new file mode 100644
index 00000000..e5749a14
Binary files /dev/null and b/assets/sounds/cutscenes/weeb/Senpai_Dies.mp3 differ
diff --git a/assets/sounds/cutscenes/weeb/Senpai_Dies.ogg b/assets/sounds/cutscenes/weeb/Senpai_Dies.ogg
new file mode 100644
index 00000000..38d94612
Binary files /dev/null and b/assets/sounds/cutscenes/weeb/Senpai_Dies.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-1.ogg b/assets/sounds/jeffGameover/jeffGameover-1.ogg
new file mode 100644
index 00000000..d068b943
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-1.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-10.ogg b/assets/sounds/jeffGameover/jeffGameover-10.ogg
new file mode 100644
index 00000000..d7f32626
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-10.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-11.ogg b/assets/sounds/jeffGameover/jeffGameover-11.ogg
new file mode 100644
index 00000000..ddfbc9db
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-11.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-12.ogg b/assets/sounds/jeffGameover/jeffGameover-12.ogg
new file mode 100644
index 00000000..4f86a638
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-12.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-13.ogg b/assets/sounds/jeffGameover/jeffGameover-13.ogg
new file mode 100644
index 00000000..a1602b0f
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-13.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-14.ogg b/assets/sounds/jeffGameover/jeffGameover-14.ogg
new file mode 100644
index 00000000..92730ff6
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-14.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-15.ogg b/assets/sounds/jeffGameover/jeffGameover-15.ogg
new file mode 100644
index 00000000..fee53455
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-15.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-16.ogg b/assets/sounds/jeffGameover/jeffGameover-16.ogg
new file mode 100644
index 00000000..a3985937
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-16.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-17.ogg b/assets/sounds/jeffGameover/jeffGameover-17.ogg
new file mode 100644
index 00000000..84cf12ba
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-17.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-18.ogg b/assets/sounds/jeffGameover/jeffGameover-18.ogg
new file mode 100644
index 00000000..20f7b51b
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-18.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-19.ogg b/assets/sounds/jeffGameover/jeffGameover-19.ogg
new file mode 100644
index 00000000..73b13b26
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-19.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-2.ogg b/assets/sounds/jeffGameover/jeffGameover-2.ogg
new file mode 100644
index 00000000..25a6ae62
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-2.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-20.ogg b/assets/sounds/jeffGameover/jeffGameover-20.ogg
new file mode 100644
index 00000000..01074a39
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-20.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-21.ogg b/assets/sounds/jeffGameover/jeffGameover-21.ogg
new file mode 100644
index 00000000..d766ed12
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-21.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-22.ogg b/assets/sounds/jeffGameover/jeffGameover-22.ogg
new file mode 100644
index 00000000..3c76a965
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-22.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-23.ogg b/assets/sounds/jeffGameover/jeffGameover-23.ogg
new file mode 100644
index 00000000..ced36771
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-23.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-24.ogg b/assets/sounds/jeffGameover/jeffGameover-24.ogg
new file mode 100644
index 00000000..bcd68e76
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-24.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-25.ogg b/assets/sounds/jeffGameover/jeffGameover-25.ogg
new file mode 100644
index 00000000..705c6b82
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-25.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-3.ogg b/assets/sounds/jeffGameover/jeffGameover-3.ogg
new file mode 100644
index 00000000..2d4103f9
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-3.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-4.ogg b/assets/sounds/jeffGameover/jeffGameover-4.ogg
new file mode 100644
index 00000000..1f94b9dd
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-4.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-5.ogg b/assets/sounds/jeffGameover/jeffGameover-5.ogg
new file mode 100644
index 00000000..ca08c59b
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-5.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-6.ogg b/assets/sounds/jeffGameover/jeffGameover-6.ogg
new file mode 100644
index 00000000..5432304b
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-6.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-7.ogg b/assets/sounds/jeffGameover/jeffGameover-7.ogg
new file mode 100644
index 00000000..aaa92afc
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-7.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-8.ogg b/assets/sounds/jeffGameover/jeffGameover-8.ogg
new file mode 100644
index 00000000..54a5024b
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-8.ogg differ
diff --git a/assets/sounds/jeffGameover/jeffGameover-9.ogg b/assets/sounds/jeffGameover/jeffGameover-9.ogg
new file mode 100644
index 00000000..1d7d2dbb
Binary files /dev/null and b/assets/sounds/jeffGameover/jeffGameover-9.ogg differ
diff --git a/source/funkin/backend/FunkinSprite.hx b/source/funkin/backend/FunkinSprite.hx
index a2f86f1b..53e87114 100644
--- a/source/funkin/backend/FunkinSprite.hx
+++ b/source/funkin/backend/FunkinSprite.hx
@@ -1,5 +1,6 @@
package funkin.backend;
+import funkin.backend.utils.XMLUtil.BeatAnim;
import funkin.backend.utils.XMLUtil.AnimData;
import funkin.backend.utils.XMLUtil.IXMLEvents;
import flixel.system.FlxAssets.FlxGraphicAsset;
@@ -34,13 +35,17 @@ abstract XMLAnimType(Int)
class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
{
public var spriteAnimType:XMLAnimType = NONE;
- public var beatAnims:Array = [];
+ public var beatAnims:Array = [];
public var name:String;
public var zoomFactor:Float = 1;
public var initialZoom:Float = 1;
public var debugMode:Bool = false;
public var animDatas:Map = [];
+ public var beatInterval:Int = 1;
+ public var beatOffset:Int = 0;
+ public var skipNegativeBeats:Bool = false;
+
public var animateAtlas:FlxAnimate;
@:noCompletion public var atlasPlayingAnim:String;
@:noCompletion public var atlasPath:String;
@@ -108,13 +113,16 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
moves = true;
}
+ private var countedBeat = 0;
public function beatHit(curBeat:Int)
{
- if (beatAnims.length > 0)
+ if (beatAnims.length > 0 && (curBeat + beatOffset) % beatInterval == 0)
{
- var anim = beatAnims[FlxMath.wrap(curBeat, 0, beatAnims.length - 1)];
- if (anim != null && anim != "null" && anim != "none")
- playAnim(anim);
+ if(skipNegativeBeats && curBeat < 0) return;
+ // TODO: find a solution without countedBeat
+ var anim = beatAnims[FlxMath.wrap(countedBeat++, 0, beatAnims.length - 1)];
+ if (anim.name != null && anim.name != "null" && anim.name != "none")
+ playAnim(anim.name, anim.forced);
}
}
diff --git a/source/funkin/backend/chart/BaseGameParser.hx b/source/funkin/backend/chart/BaseGameParser.hx
index 8093813c..d37360ba 100644
--- a/source/funkin/backend/chart/BaseGameParser.hx
+++ b/source/funkin/backend/chart/BaseGameParser.hx
@@ -60,6 +60,15 @@ class BaseGameParser {
});
}
+ if (section.altAnim == null) section.altAnim = false;
+ if (altAnims != (altAnims = section.altAnim)) {
+ result.events.push({
+ time: curTime,
+ name: "Alt Animation Toggle",
+ params: [0, altAnims]
+ });
+ }
+
if (section.sectionNotes != null) for(note in section.sectionNotes) {
if (note[1] < 0) continue;
@@ -129,6 +138,6 @@ typedef SwagSection =
var mustHitSection:Bool;
var bpm:Float;
var changeBPM:Bool;
- var altAnim:Bool;
+ var altAnim:Null;
@:optional var camTarget:Null;
}
diff --git a/source/funkin/backend/system/github/GitHub.hx b/source/funkin/backend/system/github/GitHub.hx
index 2d900518..d869fcf2 100644
--- a/source/funkin/backend/system/github/GitHub.hx
+++ b/source/funkin/backend/system/github/GitHub.hx
@@ -9,8 +9,8 @@ import haxe.Http;
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
- * @param user
- * @param repository
+ * @param user The user/group that owns the repository
+ * @param repository The repository name
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array {
@@ -29,6 +29,12 @@ class GitHub {
return [];
}
+ /**
+ * Gets the contributors list from a specific GitHub repository using the GitHub API.
+ * @param user The user/group that owns the repository
+ * @param repository The repository name
+ * @return Contributors List
+ */
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array {
try {
var url = 'https://api.github.com/repos/${user}/${repository}/contributors';
@@ -45,6 +51,27 @@ class GitHub {
return [];
}
+ /**
+ * Gets a specific GitHub user/group using the GitHub API.
+ * @param user The user/group to get
+ * @return User/Group
+ */
+ public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
+ try {
+ var url = 'https://api.github.com/users/$user';
+
+ var data = Json.parse(__requestOnGitHubServers(url));
+ if (Reflect.hasField(data, "documentation_url"))
+ throw __parseGitHubException(data);
+
+ return data;
+ } catch(e) {
+ if (onError != null)
+ onError(e);
+ }
+ return null;
+ }
+
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
@@ -58,29 +85,52 @@ class GitHub {
public static function __requestOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
+
var r = null;
+ h.onStatus = function(s) {
+ if(isRedirect(s))
+ r = __requestOnGitHubServers(h.responseHeaders.get("Location"));
+ };
+
h.onData = function(d) {
- r = d;
+ if(r == null) r = d;
}
h.onError = function(e) {
throw e;
}
+
h.request(false);
return r;
}
public static function __requestBytesOnGitHubServers(url:String) {
var h = new Http(url);
h.setHeader("User-Agent", "request");
+
var r = null;
+ h.onStatus = function(s) {
+ if(isRedirect(s))
+ r = __requestBytesOnGitHubServers(h.responseHeaders.get("Location"));
+ };
+
h.onBytes = function(d) {
- r = d;
+ if(r == null) r = d;
}
h.onError = function(e) {
throw e;
}
+
h.request(false);
return r;
}
+ private static function isRedirect(status:Int):Bool {
+ switch (status) {
+ // 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex_isDumb
+ case 301 | 302 | 307 | 308 :
+ trace("Redirected with status code: " + status);
+ return true;
+ }
+ return false;
+ }
private static function __parseGitHubException(obj:Dynamic):GitHubException {
var msg:String = "(No message)";
var url:String = "(No API url)";
@@ -99,18 +149,33 @@ import haxe.Exception;
class GitHub {
/**
* Gets all the releases from a specific GitHub repository using the GitHub API.
- * @param user
- * @param repository
+ * @param user The user/group that owns the repository
+ * @param repository The repository name
* @return Releases
*/
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array {
return [];
}
+ /**
+ * Gets the contributors list from a specific GitHub repository using the GitHub API.
+ * @param user The user/group that owns the repository
+ * @param repository The repository name
+ * @return Contributors List
+ */
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array {
return [];
}
+ /**
+ * Gets a specific GitHub user/group using the GitHub API.
+ * @param user The user/group to get
+ * @return User/Group
+ */
+ public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
+ return null;
+ }
+
/**
* Filters all releases gotten by `getReleases`
* @param releases Releases
@@ -130,5 +195,14 @@ class GitHub {
private static function __parseGitHubException(obj:Dynamic):GitHubException {
return null;
}
+ private static function isRedirect(status:Int):Bool {
+ switch (status) {
+ // 301: Moved Permanently, 302: Found (Moved Temporarily), 307: Temporary Redirect, 308: Permanent Redirect - Nex_isDumb
+ case 301 | 302 | 307 | 308 :
+ trace("Redirected with status code: " + status);
+ return true;
+ }
+ return false;
+ }
}
#end
\ No newline at end of file
diff --git a/source/funkin/backend/system/macros/ScriptsMacro.hx b/source/funkin/backend/system/macros/ScriptsMacro.hx
index 013d58b6..0014af3d 100644
--- a/source/funkin/backend/system/macros/ScriptsMacro.hx
+++ b/source/funkin/backend/system/macros/ScriptsMacro.hx
@@ -20,7 +20,7 @@ class ScriptsMacro {
"flixel.addons.plugin", "flixel.addons.text", "flixel.addons.tile", "flixel.addons.transition",
"flixel.addons.util",
// OTHER LIBRARIES & STUFF
- "away3d", "flx3d",
+ #if THREE_D_SUPPORT "away3d", "flx3d", #end
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
// BASE HAXE
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
diff --git a/source/funkin/backend/utils/CoolUtil.hx b/source/funkin/backend/utils/CoolUtil.hx
index 0b4cf25f..d476fc23 100644
--- a/source/funkin/backend/utils/CoolUtil.hx
+++ b/source/funkin/backend/utils/CoolUtil.hx
@@ -28,6 +28,16 @@ class CoolUtil
public static function getLastExceptionStack():String {
return CallStack.toString(CallStack.exceptionStack());
}
+
+ /*
+ * Returns `v` if not null
+ * @param v The value
+ * @return A bool value
+ */
+ public static inline function isNotNull(v:Null):Bool {
+ return v != null && !isNaN(v);
+ }
+
/*
* Returns `v` if not null, `defaultValue` otherwise.
* @param v The value
@@ -135,7 +145,7 @@ class CoolUtil
/**
* Returns a string representation of a size, following this format: `1.02 GB`, `134.00 MB`
- * @param size Size to convert ot string
+ * @param size Size to convert to string
* @return String Result string representation
*/
public static function getSizeString(size:Float):String {
@@ -149,6 +159,15 @@ class CoolUtil
return '${Std.int(rSize) + "." + addZeros(Std.string(Std.int((rSize % 1) * 100)), 2)}${labels[label]}';
}
+ /**
+ * Replaces in a string any kind of IP with `[Your IP]` making the string safer to trace.
+ * @param msg String to check and edit
+ * @return String Result without any kind of IP
+ */
+ public static inline function removeIP(msg:String):String {
+ return ~/\d+.\d+.\d+.\d+/.replace(msg, "[Your IP]"); // For now its just IPs but who knows in the future.. - Nex_isDumb
+ }
+
/**
* Alternative linear interpolation function for each frame use, without worrying about framerate changes.
* @param v1 Begin value
diff --git a/source/funkin/backend/utils/XMLUtil.hx b/source/funkin/backend/utils/XMLUtil.hx
index 01d7aa8d..b7120680 100644
--- a/source/funkin/backend/utils/XMLUtil.hx
+++ b/source/funkin/backend/utils/XMLUtil.hx
@@ -21,7 +21,7 @@ class XMLUtil {
*/
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
if (!property.has.name || !property.has.type || !property.has.value) {
- Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
+ Logs.trace('Failed to apply XML property: XML Element is missing name, type, or value attributes.', WARNING);
return MISSING_PROPERTY;
}
@@ -72,54 +72,86 @@ class XMLUtil {
spr.loadSprite(Paths.image('$parentFolder${node.getAtt("sprite")}', null, true));
- if (spr.frames != null && spr.frames.frames != null) {
- spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true);
- spr.animation.play("idle");
+ spr.spriteAnimType = defaultAnimType;
+ if (node.has.type) {
+ spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
}
- spr.spriteAnimType = defaultAnimType;
- if (node.has.type)
- spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
-
- var x:Null = node.has.x ? Std.parseFloat(node.att.x) : null;
- var y:Null = node.has.y ? Std.parseFloat(node.att.y) : null;
- if (x != null) spr.x = x;
- if (y != null) spr.y = y;
+ if(node.has.x) {
+ var x:Null = Std.parseFloat(node.att.x);
+ if (x.isNotNull()) spr.x = x;
+ }
+ if(node.has.y) {
+ var y:Null = Std.parseFloat(node.att.y);
+ if (y.isNotNull()) spr.y = y;
+ }
if (node.has.scroll) {
var scroll:Null = Std.parseFloat(node.att.scroll);
- if (scroll != null) spr.scrollFactor.set(scroll, scroll);
+ if (scroll.isNotNull()) spr.scrollFactor.set(scroll, scroll);
} else {
if (node.has.scrollx) {
var scroll:Null = Std.parseFloat(node.att.scrollx);
- if (scroll != null) spr.scrollFactor.x = scroll;
+ if (scroll.isNotNull()) spr.scrollFactor.x = scroll;
}
if (node.has.scrolly) {
var scroll:Null = Std.parseFloat(node.att.scrolly);
- if (scroll != null) spr.scrollFactor.y = scroll;
+ if (scroll.isNotNull()) spr.scrollFactor.y = scroll;
}
}
if (node.has.skewx) {
var skew:Null = Std.parseFloat(node.att.skewx);
- if (skew != null) spr.skew.x = skew;
+ if (skew.isNotNull()) spr.skew.x = skew;
}
if (node.has.skewy) {
var skew:Null = Std.parseFloat(node.att.skewy);
- if (skew != null) spr.skew.y = skew;
+ if (skew.isNotNull()) spr.skew.y = skew;
}
if (node.has.antialiasing) spr.antialiasing = node.att.antialiasing == "true";
if (node.has.scale) {
var scale:Null = Std.parseFloat(node.att.scale);
- if (scale != null) spr.scale.set(scale, scale);
+ if (scale.isNotNull()) spr.scale.set(scale, scale);
+ }
+ if (node.has.scalex) {
+ var scale:Null = Std.parseFloat(node.att.scalex);
+ if (scale.isNotNull()) spr.scale.x = scale;
+ }
+ if (node.has.scaley) {
+ var scale:Null = Std.parseFloat(node.att.scaley);
+ if (scale.isNotNull()) spr.scale.y = scale;
}
if (node.has.updateHitbox && node.att.updateHitbox == "true") spr.updateHitbox();
- spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
+ if(node.has.zoomfactor)
+ spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
if (node.has.alpha)
spr.alpha = Std.parseFloat(node.getAtt("alpha")).getDefault(spr.alpha);
- for(anim in node.nodes.anim)
- addXMLAnimation(spr, anim);
+ if (node.has.playOnCountdown)
+ spr.skipNegativeBeats = node.att.playOnCountdown == "true";
+ if (node.has.beatInterval)
+ spr.beatInterval = Std.parseInt(node.att.beatInterval);
+ if (node.has.beatOffset)
+ spr.beatOffset = Std.parseInt(node.att.beatOffset);
+
+ if(node.hasNode.anim) {
+ for(anim in node.nodes.anim)
+ addXMLAnimation(spr, anim);
+ } else {
+ if (spr.frames != null && spr.frames.frames != null) {
+ addAnimToSprite(spr, {
+ name: "idle",
+ anim: null,
+ fps: 24,
+ loop: spr.spriteAnimType == LOOP,
+ animType: spr.spriteAnimType,
+ x: 0,
+ y: 0,
+ indices: [for(i in 0...spr.frames.frames.length) i],
+ forced: (node.has.forced && node.att.forced == "true") || (!node.has.forced && spr.spriteAnimType == BEAT)
+ });
+ }
+ }
return spr;
}
@@ -133,16 +165,18 @@ class XMLUtil {
animType: animType,
x: 0,
y: 0,
- indices: []
+ indices: [],
+ forced: false,
};
if (anim.has.name) animData.name = anim.att.name;
if (anim.has.type) animData.animType = XMLAnimType.fromString(anim.att.type, animData.animType);
if (anim.has.anim) animData.anim = anim.att.anim;
- if (anim.has.fps) animData.fps = Std.parseFloat(anim.att.fps);
- if (anim.has.x) animData.x = Std.parseFloat(anim.att.x);
- if (anim.has.y) animData.y = Std.parseFloat(anim.att.y);
+ if (anim.has.fps) animData.fps = Std.parseFloat(anim.att.fps).getDefault(animData.fps);
+ if (anim.has.x) animData.x = Std.parseFloat(anim.att.x).getDefault(animData.x);
+ if (anim.has.y) animData.y = Std.parseFloat(anim.att.y).getDefault(animData.y);
if (anim.has.loop) animData.loop = anim.att.loop == "true";
+ if (anim.has.forced) animData.forced = anim.att.forced == "true";
if (anim.has.indices) {
var indicesSplit = anim.att.indices.split(",");
for(indice in indicesSplit) {
@@ -161,24 +195,30 @@ class XMLUtil {
*/
public static function addXMLAnimation(sprite:FlxSprite, anim:Access, loop:Bool = false):ErrorCode {
var animType:XMLAnimType = NONE;
- if (sprite is FunkinSprite)
+ if (sprite is FunkinSprite) {
animType = cast(sprite, FunkinSprite).spriteAnimType;
+ }
return addAnimToSprite(sprite, extractAnimFromXML(anim, animType, loop));
}
public static function addAnimToSprite(sprite:FlxSprite, animData:AnimData):ErrorCode {
- if (animData.name != null && animData.anim != null) {
+ if (animData.name != null) {
if (animData.fps <= 0 #if web || animData.fps == null #end) animData.fps = 24;
if (sprite is FunkinSprite && cast(sprite, FunkinSprite).animateAtlas != null) {
var animateAnim = cast(sprite, FunkinSprite).animateAtlas.anim;
+ if(animData.anim == null)
+ return MISSING_PROPERTY;
+
if (animData.indices.length > 0)
animateAnim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
else
animateAnim.addBySymbol(animData.name, animData.anim, animData.fps, animData.loop);
} else {
- if (animData.indices.length > 0)
+ if (animData.anim == null && animData.indices.length > 0)
+ sprite.animation.add(animData.name, animData.indices, animData.fps, animData.loop);
+ else if (animData.indices.length > 0)
sprite.animation.addByIndices(animData.name, animData.anim, animData.indices, "", animData.fps, animData.loop);
else
sprite.animation.addByPrefix(animData.name, animData.anim, animData.fps, animData.loop);
@@ -191,9 +231,12 @@ class XMLUtil {
var xmlSpr = cast(sprite, FunkinSprite);
switch(animData.animType) {
case BEAT:
- xmlSpr.beatAnims.push(animData.name);
+ xmlSpr.beatAnims.push({
+ name: animData.name,
+ forced: animData.forced.getDefault(false)
+ });
case LOOP:
- xmlSpr.animation.play(animData.name);
+ xmlSpr.animation.play(animData.name, animData.forced.getDefault(false));
default:
// nothing
}
@@ -219,6 +262,12 @@ typedef AnimData = {
var y:Float;
var indices:Array;
var animType:XMLAnimType;
+ var ?forced:Bool;
+}
+
+typedef BeatAnim = {
+ var name:String;
+ var forced:Bool;
}
interface IXMLEvents {
diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx
index 5646b612..6566f5d3 100644
--- a/source/funkin/game/GameOverSubstate.hx
+++ b/source/funkin/game/GameOverSubstate.hx
@@ -110,6 +110,7 @@ class GameOverSubstate extends MusicBeatSubstate
if (controls.BACK)
{
+ PlayState.resetSongInfos();
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
FlxG.sound.music = null;
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index 4bec15b2..d08b8d4b 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -89,6 +89,10 @@ class PlayState extends MusicBeatState
*/
public var strumLines:FlxTypedGroup = new FlxTypedGroup();
+ /**
+ * Death counter on current week (or song if from freeplay).
+ */
+ public static var deathCounter:Int = 0;
/**
* Game Over Song. (assets/music/gameOver.ogg)
*/
@@ -365,11 +369,14 @@ class PlayState extends MusicBeatState
* Whenever the game is currently in a cutscene or not.
*/
public var inCutscene:Bool = false;
-
/**
* Whenever the game should play the cutscenes. Defaults to whenever the game is currently in Story Mode or not.
*/
public var playCutscenes:Bool = isStoryMode;
+ /**
+ * Whenever the game has already played a specific cutscene for the current song. Check `startCutscene` for more details.
+ */
+ public static var seenCutscene:Bool = false;
/**
* Cutscene script path.
*/
@@ -447,6 +454,7 @@ class PlayState extends MusicBeatState
public var hitWindow:Float = Options.hitWindow; // is calculated in create(), is safeFrames in milliseconds
@:noCompletion @:dox(hide) private var _startCountdownCalled:Bool = false;
+ @:noCompletion @:dox(hide) private var _endSongCalled:Bool = false;
@:dox(hide)
var __vocalOffsetViolation:Float = 0;
@@ -746,11 +754,15 @@ class PlayState extends MusicBeatState
}
@:dox(hide) public override function createPost() {
- startCutscene("", cutscene);
+ startCutscene("", cutscene, null, true);
super.createPost();
updateDiscordPresence();
+ // Make icons appear in the correct spot during cutscenes
+ healthBar.update(0);
+ updateIconPositions();
+
__updateNote_event = EventManager.get(NoteUpdateEvent);
scripts.call("postCreate");
@@ -768,10 +780,15 @@ class PlayState extends MusicBeatState
* @param prefix Custom prefix. Using `midsong-` will require you to for example rename your video cutscene to `songs/song/midsong-cutscene.mp4` instead of `songs/song/cutscene.mp4`
* @param cutsceneScriptPath Optional: Custom script path.
* @param callback Callback called after the cutscene ended. If equals to `null`, `startCountdown` will be called.
+ * @param checkSeen Bool that by default is false, if true and `seenCutscene` is also true, it won't play the cutscene but directly call `callback` (PS: `seenCutscene` becomes true if the cutscene gets played and `checkSeen` was true)
*/
- public function startCutscene(prefix:String = "", ?cutsceneScriptPath:String, ?callback:Void->Void) {
- if (callback == null)
- callback = startCountdown;
+ public function startCutscene(prefix:String = "", ?cutsceneScriptPath:String, ?callback:Void->Void, checkSeen:Bool = false) {
+ if (callback == null) callback = startCountdown;
+ if (checkSeen && seenCutscene) {
+ callback();
+ return;
+ }
+
if (cutsceneScriptPath == null)
cutsceneScriptPath = Paths.script('songs/${SONG.meta.name.toLowerCase()}/${prefix}cutscene');
@@ -781,28 +798,25 @@ class PlayState extends MusicBeatState
var videoCutsceneAlt = Paths.file('songs/${PlayState.SONG.meta.name.toLowerCase()}/${prefix}cutscene.mp4');
var dialogue = Paths.file('songs/${PlayState.SONG.meta.name.toLowerCase()}/${prefix}dialogue.xml');
persistentUpdate = true;
+ var toCall:Void->Void = function() {
+ if(checkSeen) seenCutscene = true;
+ callback();
+ }
+
if (cutsceneScriptPath != null && Assets.exists(cutsceneScriptPath)) {
- openSubState(new ScriptedCutscene(cutsceneScriptPath, function() {
- callback();
- }));
+ openSubState(new ScriptedCutscene(cutsceneScriptPath, toCall));
} else if (Assets.exists(dialogue)) {
MusicBeatState.skipTransIn = true;
- openSubState(new DialogueCutscene(dialogue, function() {
- callback();
- }));
+ openSubState(new DialogueCutscene(dialogue, toCall));
} else if (Assets.exists(videoCutsceneAlt)) {
MusicBeatState.skipTransIn = true;
persistentUpdate = false;
- openSubState(new VideoCutscene(videoCutsceneAlt, function() {
- callback();
- }));
+ openSubState(new VideoCutscene(videoCutsceneAlt, toCall));
persistentDraw = false;
} else if (Assets.exists(videoCutscene)) {
MusicBeatState.skipTransIn = true;
persistentUpdate = false;
- openSubState(new VideoCutscene(videoCutscene, function() {
- callback();
- }));
+ openSubState(new VideoCutscene(videoCutscene, toCall));
persistentDraw = false;
} else
callback();
@@ -857,6 +871,7 @@ class PlayState extends MusicBeatState
sprite.scale.set(event.scale, event.scale);
sprite.updateHitbox();
sprite.screenCenter();
+ sprite.antialiasing = event.antialiasing;
add(sprite);
tween = FlxTween.tween(sprite, {y: sprite.y + 100, alpha: 0}, Conductor.crochet / 1000, {
ease: FlxEase.cubeInOut,
@@ -931,6 +946,11 @@ class PlayState extends MusicBeatState
Note.__customNoteTypeExists = [];
}
+ public static function resetSongInfos() {
+ deathCounter = 0;
+ seenCutscene = false;
+ }
+
@:dox(hide) private function generateSong(?songData:ChartData):Void
{
if (songData == null) songData = SONG;
@@ -1100,6 +1120,18 @@ class PlayState extends MusicBeatState
updateDiscordPresence();
}
+ function updateIconPositions() {
+ var iconOffset:Int = 26;
+
+ iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0)) - iconOffset);
+ iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0))) - (iconP2.width - iconOffset);
+
+ health = FlxMath.bound(health, 0, maxHealth);
+
+ iconP1.health = healthBar.percent / 100;
+ iconP2.health = 1 - (healthBar.percent / 100);
+ }
+
@:dox(hide)
override public function update(elapsed:Float)
{
@@ -1145,15 +1177,7 @@ class PlayState extends MusicBeatState
iconP1.updateHitbox();
iconP2.updateHitbox();
- var iconOffset:Int = 26;
-
- iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0)) - iconOffset);
- iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0))) - (iconP2.width - iconOffset);
-
- health = FlxMath.bound(health, 0, maxHealth);
-
- iconP1.health = healthBar.percent / 100;
- iconP2.health = 1 - (healthBar.percent / 100);
+ updateIconPositions();
if (startingSong)
{
@@ -1359,6 +1383,7 @@ class PlayState extends MusicBeatState
}
startCutscene("end-", endCutscene, nextSong);
+ resetSongInfos();
}
private static inline function getSongChanges():Array {
diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx
index 099a86a8..a1202664 100644
--- a/source/funkin/game/Stage.hx
+++ b/source/funkin/game/Stage.hx
@@ -78,7 +78,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
case "sprite" | "spr" | "sparrow":
if (!node.has.sprite || !node.has.name) continue;
- var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, BEAT);
+ var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, LOOP);
if (!node.has.zoomfactor && PlayState.instance != null)
spr.initialZoom = PlayState.instance.defaultCamZoom;
@@ -90,8 +90,8 @@ class Stage extends FlxBasic implements IBeatReceiver {
if ( !node.has.name || !node.has.width || !node.has.height) continue;
var spr = new FlxSprite(
- (node.has.x) ? Std.parseFloat(node.att.x) : 0,
- (node.has.y) ? Std.parseFloat(node.att.y) : 0
+ (node.has.x) ? Std.parseFloat(node.att.x).getDefault(0) : 0,
+ (node.has.y) ? Std.parseFloat(node.att.y).getDefault(0) : 0
);
(node.name == "solid" ? spr.makeSolid : spr.makeGraphic)(
diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx
index f46c14e6..af3a5f31 100644
--- a/source/funkin/game/StrumLine.hx
+++ b/source/funkin/game/StrumLine.hx
@@ -305,7 +305,9 @@ class StrumLine extends FlxTypedGroup {
if(data.scrollSpeed != null)
babyArrow.scrollSpeed = data.scrollSpeed;
- var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix));
+ var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
+ event.__doAnimation = !MusicBeatState.skipTransIn;
+ event = PlayState.instance.scripts.event("onStrumCreation", event);
if (!event.cancelled) {
babyArrow.frames = Paths.getFrames(event.sprite);
diff --git a/source/funkin/game/cutscenes/ScriptedCutscene.hx b/source/funkin/game/cutscenes/ScriptedCutscene.hx
index b17639eb..522ad668 100644
--- a/source/funkin/game/cutscenes/ScriptedCutscene.hx
+++ b/source/funkin/game/cutscenes/ScriptedCutscene.hx
@@ -23,7 +23,7 @@ class ScriptedCutscene extends Cutscene {
public override function create() {
super.create();
- trace("fuck");
+ trace("fuck you");
script.call("create");
if (Std.isOfType(script, DummyScript)) {
Logs.trace('Could not find script for scripted cutscene at ${scriptPath}', ERROR, RED);
diff --git a/source/funkin/menus/GitarooPause.hx b/source/funkin/menus/GitarooPause.hx
index ac65da6a..fc569c85 100644
--- a/source/funkin/menus/GitarooPause.hx
+++ b/source/funkin/menus/GitarooPause.hx
@@ -61,6 +61,7 @@ class GitarooPause extends MusicBeatState
}
else
{
+ PlayState.resetSongInfos();
FlxG.switchState(new MainMenuState());
}
}
diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx
index f81319e6..64b31a48 100644
--- a/source/funkin/menus/PauseSubState.hx
+++ b/source/funkin/menus/PauseSubState.hx
@@ -72,15 +72,17 @@ class PauseSubState extends MusicBeatSubstate
add(bg);
var levelInfo:FlxText = new FlxText(20, 15, 0, PlayState.SONG.meta.displayName, 32);
- var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, PlayState.difficulty.toUpperCase(), 32);
- var multiplayerText:FlxText = new FlxText(20, 15 + 32 + 32, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32);
+ var levelDifficulty:FlxText = new FlxText(20, 15, 0, PlayState.difficulty.toUpperCase(), 32);
+ var deathCounter:FlxText = new FlxText(20, 15, 0, "Blue balled: " + PlayState.deathCounter, 32);
+ var multiplayerText:FlxText = new FlxText(20, 15, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32);
- for(k=>label in [levelInfo, levelDifficulty, multiplayerText]) {
+ for(k=>label in [levelInfo, levelDifficulty, deathCounter, multiplayerText]) {
label.scrollFactor.set();
label.setFormat(Paths.font('vcr.ttf'), 32);
label.updateHitbox();
label.alpha = 0;
label.x = FlxG.width - (label.width + 20);
+ label.y = 15 + (32 * k);
FlxTween.tween(label, {alpha: 1, y: label.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3 * (k+1)});
add(label);
}
@@ -156,6 +158,7 @@ class PauseSubState extends MusicBeatSubstate
case "Exit to charter":
FlxG.switchState(new funkin.editors.charter.Charter(PlayState.SONG.meta.name, PlayState.difficulty, false));
case "Exit to menu":
+ PlayState.resetSongInfos();
CoolUtil.playMenuSong();
FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState());
}
diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx
index 3716b43f..705758e0 100644
--- a/source/funkin/menus/StoryMenuState.hx
+++ b/source/funkin/menus/StoryMenuState.hx
@@ -75,6 +75,7 @@ class StoryMenuState extends MusicBeatState {
arrow.animation.addByPrefix('idle', 'arrow $dir');
arrow.animation.addByPrefix('press', 'arrow push $dir', 24, false);
arrow.animation.play('idle');
+ arrow.antialiasing = true;
add(arrow);
}
rightArrow.x -= rightArrow.width;
diff --git a/source/funkin/menus/credits/CreditsCodename.hx b/source/funkin/menus/credits/CreditsCodename.hx
index 42b8b4e7..491413c9 100644
--- a/source/funkin/menus/credits/CreditsCodename.hx
+++ b/source/funkin/menus/credits/CreditsCodename.hx
@@ -1,11 +1,13 @@
package funkin.menus.credits;
import funkin.backend.system.github.GitHub;
-import funkin.options.type.PortraitOption;
+import funkin.options.type.GithubIconOption;
using StringTools;
class CreditsCodename extends funkin.options.OptionsScreen {
+ public var error:Bool = false;
+
public override function new()
{
super("Codename Engine", "All the contributors of the engine! - Press RESET to update the list (One reset per 2 minutes).");
@@ -21,17 +23,16 @@ class CreditsCodename extends funkin.options.OptionsScreen {
super.update(elapsed);
}
- var error:Bool = false;
public function checkUpdate():Bool {
var curTime:Float = Date.now().getTime();
- if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex_isDumb
+ if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits
Options.lastUpdated = curTime;
error = false;
//Main.execAsync(function() {
var idk = GitHub.getContributors("FNF-CNE-Devs", "CodenameEngine", function(e) {
error = true;
- var errMsg:String = ~/\d+.\d+.\d+.\d+/.replace(e.message, "[Your IP]"); // Removing sensitive stuff - Nex_isDumb
+ var errMsg:String = ~/\d+.\d+.\d+.\d+/.replace(e.message, "[Your IP]"); // Removing sensitive stuff
errMsg = 'Error while trying to download contributors list:\n$errMsg';
Logs.traceColored([Logs.logText(errMsg.replace('\n', ' '), RED)], ERROR);
@@ -39,7 +40,7 @@ class CreditsCodename extends funkin.options.OptionsScreen {
});
//});
if(error) return false;
-
+
Options.contributors = idk;
trace('List Updated!');
return true;
@@ -49,7 +50,7 @@ class CreditsCodename extends funkin.options.OptionsScreen {
//if (curSelected > Options.contributors.length - 1) changeSelection(-(curSelected - (Options.contributors.length - 1)));
if (curSelected > Options.contributors.length - 1) curSelected = Options.contributors.length - 1;
changeSelection(0, true);
-
+
while (members.length > 0) {
members[0].destroy();
remove(members[0], true);
@@ -58,12 +59,10 @@ class CreditsCodename extends funkin.options.OptionsScreen {
var totalContributions = 0;
for(c in Options.contributors) totalContributions += c.contributions;
for(c in Options.contributors) {
- var opt:PortraitOption = new PortraitOption(
- c.login,
- 'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account',
- function() CoolUtil.openURL(c.html_url)
+ var opt:GithubIconOption = new GithubIconOption(
+ c,
+ 'Total Contributions: ${c.contributions} / ${totalContributions} (${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%) - Select to open GitHub account'
);
- if(!error) opt.loadFromGithub(c);
add(opt);
}
}
diff --git a/source/funkin/menus/credits/CreditsMain.hx b/source/funkin/menus/credits/CreditsMain.hx
index 775593c9..f82d33db 100644
--- a/source/funkin/menus/credits/CreditsMain.hx
+++ b/source/funkin/menus/credits/CreditsMain.hx
@@ -1,5 +1,6 @@
package funkin.menus.credits;
+import funkin.backend.system.github.GitHub;
import funkin.options.OptionsScreen;
import funkin.options.type.*;
import funkin.options.TreeMenu;
@@ -27,7 +28,7 @@ class CreditsMain extends TreeMenu {
} catch(e) {
Logs.trace('Error while parsing credits.xml: ${Std.string(e)}', ERROR);
}
-
+
if (access != null)
for(c in parseCreditsFromXML(access, source))
selectables.push(c);
@@ -51,24 +52,45 @@ class CreditsMain extends TreeMenu {
var credsMenus:Array = [];
for(node in xml.elements) {
- if (!node.has.name) {
- Logs.trace("A credit node requires a name attribute.", WARNING);
- continue;
- }
- var name = node.getAtt("name");
var desc = node.getAtt("desc").getDefault("No Description");
- switch(node.name) {
- case "credit":
- credsMenus.push(new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
- node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
- FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96
- ));
+ if (node.name == "github") {
+ if (!node.has.user) {
+ Logs.trace("A github node requires a user attribute.", WARNING);
+ continue;
+ }
- case "menu":
- credsMenus.push(new TextOption(name + " >", desc, function() {
- optionsTree.add(new OptionsScreen(name, desc, parseCreditsFromXML(node, source)));
- }));
+ var username = node.getAtt("user");
+ var user = { // Kind of forcing - Nex_isDumb
+ login: username,
+ html_url: 'https://github.com/$username',
+ avatar_url: 'https://github.com/$username.png'
+ };
+
+ credsMenus.push(new GithubIconOption(user, desc, null,
+ node.has.customName ? node.att.customName : null, node.has.size ? Std.parseInt(node.att.size) : 96,
+ node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
+ ));
+ } else {
+ if (!node.has.name) {
+ Logs.trace("A credit node requires a name attribute.", WARNING);
+ continue;
+ }
+ var name = node.getAtt("name");
+
+ switch(node.name) {
+ case "credit":
+ credsMenus.push(new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
+ node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
+ FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96,
+ node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
+ ));
+
+ case "menu":
+ credsMenus.push(new TextOption(name + " >", desc, function() {
+ optionsTree.add(new OptionsScreen(name, desc, parseCreditsFromXML(node, source)));
+ }));
+ }
}
}
diff --git a/source/funkin/options/Options.hx b/source/funkin/options/Options.hx
index 988aac6a..ccfb498c 100644
--- a/source/funkin/options/Options.hx
+++ b/source/funkin/options/Options.hx
@@ -27,6 +27,7 @@ class Options
public static var antialiasing:Bool = true;
public static var volume:Float = 1;
public static var week6PixelPerfect:Bool = true;
+ public static var gameplayShaders:Bool = true;
public static var colorHealthBar:Bool = true;
public static var lowMemoryMode:Bool = false;
public static var betaUpdates:Bool = false;
@@ -54,7 +55,9 @@ class Options
public static var contributors:Array = [];
public static var lastUpdated:Null;
- // CHARTER
+ /**
+ * CHARTER
+ */
public static var charterMetronomeEnabled:Bool = false;
public static var charterShowSections:Bool = true;
public static var charterShowBeats:Bool = true;
diff --git a/source/funkin/options/categories/AppearanceOptions.hx b/source/funkin/options/categories/AppearanceOptions.hx
index 60fa4535..155179ef 100644
--- a/source/funkin/options/categories/AppearanceOptions.hx
+++ b/source/funkin/options/categories/AppearanceOptions.hx
@@ -23,6 +23,10 @@ class AppearanceOptions extends OptionsScreen {
"Pixel Perfect Effect",
"If checked, Week 6 will have a pixel perfect effect to it enabled, aligning every pixel on the screen.",
"week6PixelPerfect"));
+ add(new Checkbox(
+ "Gameplay Shaders",
+ "If unchecked, gameplay shaders (visual effects like Thorns's Chromatic Aberration) wont be loaded; this may be helpful on weak devices.",
+ "gameplayShaders"));
add(new Checkbox(
"Flashing Menu",
"If unchecked, will disable menu flashing when you select an option in the Main Menu, and other flashes will be slower.",
diff --git a/source/funkin/options/type/GithubIconOption.hx b/source/funkin/options/type/GithubIconOption.hx
new file mode 100644
index 00000000..91ea1604
--- /dev/null
+++ b/source/funkin/options/type/GithubIconOption.hx
@@ -0,0 +1,103 @@
+package funkin.options.type;
+
+import openfl.display.BitmapData;
+import flixel.graphics.FlxGraphic;
+import funkin.backend.shaders.CustomShader;
+import funkin.backend.system.github.GitHub;
+import flixel.util.FlxColor;
+
+class GithubIconOption extends TextOption
+{
+ public var user(default, null):Dynamic; // Can possibly be GitHubUser or GitHubContributor - Nex_isDumb
+ public var icon:GithubUserIcon = null;
+ public var usePortrait(default, set) = true;
+
+ public function set_usePortrait(value:Bool)
+ {
+ if (icon == null) return usePortrait = false;
+ icon.shader = (value ? new CustomShader('engine/circleProfilePicture') : null);
+ return usePortrait = value;
+ }
+
+ public function new(user:Dynamic, desc:String, ?callback:Void->Void, ?customName:String, size:Int = 96, usePortrait:Bool = true) {
+ super(customName == null ? user.login : customName, desc, callback == null ? function() CoolUtil.openURL(user.html_url) : callback);
+ this.user = user;
+ this.icon = new GithubUserIcon(user, size);
+ this.usePortrait = usePortrait;
+ add(icon);
+ }
+}
+
+class GithubUserIcon extends FlxSprite
+{
+ private var loading:Bool = false;
+ private var user:Dynamic;
+ private var size:Int;
+
+ public override function new(user:Dynamic, size:Int = 96) {
+ this.user = user;
+ this.size = size;
+ super();
+ makeGraphic(size, size, FlxColor.TRANSPARENT);
+ antialiasing = true;
+ }
+
+ final mutex = new sys.thread.Mutex();
+ override function drawComplex(camera:FlxCamera):Void { // Making the image downlaod only if the player actually sees it on the screeeeen - Nex_isDumb
+ if(!loading) {
+ loading = true;
+ Main.execAsync(function() {
+ var key:String = 'GITHUB-USER:${user.login}';
+ var bmap:Dynamic = FlxG.bitmap.get(key);
+
+ if(bmap == null) {
+ trace('Downloading avatar: ${user.login}');
+ var unfLink:Bool = StringTools.endsWith(user.avatar_url, '.png');
+ var planB:Bool = true;
+
+ var bytes = null;
+ if(unfLink) {
+ try bytes = GitHub.__requestBytesOnGitHubServers('${user.avatar_url}?size=$size')
+ catch(e) Logs.traceColored([Logs.logText('Failed to download github pfp for ${user.login}: ${CoolUtil.removeIP(e.message)} - (Retrying using the api..)', RED)], ERROR);
+
+ if(bytes != null) {
+ bmap = BitmapData.fromBytes(bytes);
+ planB = false;
+ }
+ }
+
+ if(planB) {
+ if(unfLink) user = GitHub.getUser(user.login, function(e) Logs.traceColored([Logs.logText('Failed to download github user info for ${user.login}: ${CoolUtil.removeIP(e.message)}', RED)], ERROR)); // Api part - Nex_isDumb
+ try bytes = GitHub.__requestBytesOnGitHubServers('${user.avatar_url}&size=$size')
+ catch(e) Logs.traceColored([Logs.logText('Failed to download github pfp for ${user.login}: ${CoolUtil.removeIP(e.message)}', RED)], ERROR);
+
+ if(bytes != null) bmap = BitmapData.fromBytes(bytes);
+ }
+
+ if(bmap != null) try {
+ mutex.acquire(); // Avoiding critical section - Nex_isDumb
+ var leGraphic:FlxGraphic = FlxG.bitmap.add(bmap, false, key);
+ leGraphic.persist = true;
+ updateDaFunni(leGraphic);
+ bmap = null;
+ mutex.release();
+ } catch(e) {
+ Logs.traceColored([Logs.logText('Failed to update the pfp for ${user.login}: ${e.message}', RED)], ERROR);
+ }
+ } else {
+ mutex.acquire();
+ updateDaFunni(bmap);
+ mutex.release();
+ }
+ });
+ }
+ super.drawComplex(camera);
+ }
+
+ public inline function updateDaFunni(graphic:FlxGraphic) {
+ loadGraphic(graphic);
+ this.setUnstretchedGraphicSize(size, size, false);
+ updateHitbox();
+ x += 90 - width;
+ }
+}
\ No newline at end of file
diff --git a/source/funkin/options/type/OptionType.hx b/source/funkin/options/type/OptionType.hx
index 67b5785c..7a7d4077 100644
--- a/source/funkin/options/type/OptionType.hx
+++ b/source/funkin/options/type/OptionType.hx
@@ -24,5 +24,4 @@ class OptionType extends FlxSpriteGroup {
super.update(elapsed);
alpha = (selected ? 1 : 0.6);
}
-}
-
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/source/funkin/options/type/PortraitOption.hx b/source/funkin/options/type/PortraitOption.hx
index 08876035..da5dbb60 100644
--- a/source/funkin/options/type/PortraitOption.hx
+++ b/source/funkin/options/type/PortraitOption.hx
@@ -1,24 +1,21 @@
package funkin.options.type;
-import openfl.display.BitmapData;
import flixel.graphics.FlxGraphic;
import funkin.backend.shaders.CustomShader;
-import funkin.backend.system.github.GitHubContributor;
-import funkin.backend.system.github.GitHub;
class PortraitOption extends TextOption {
public var portrait:FlxSprite = null;
- public function new(name:String, desc:String, callback:Void->Void, ?graphic:FlxGraphic, size:Int = 96) {
+ public function new(name:String, desc:String, callback:Void->Void, ?graphic:FlxGraphic, size:Int = 96, usePortrait:Bool = true) {
super(name, desc, callback);
- if (graphic != null) addPortrait(graphic, size);
+ if (graphic != null) addPortrait(graphic, size, usePortrait);
}
- public function addPortrait(graphic:FlxGraphic, size:Int = 96) {
+ public function addPortrait(graphic:FlxGraphic, size:Int = 96, usePortrait:Bool = true) {
if (portrait == null) {
portrait = new FlxSprite();
portrait.antialiasing = true;
- portrait.shader = new CustomShader('engine/circleProfilePicture');
+ if(usePortrait) portrait.shader = new CustomShader('engine/circleProfilePicture');
add(portrait);
}
portrait.loadGraphic(graphic);
@@ -26,12 +23,4 @@ class PortraitOption extends TextOption {
portrait.updateHitbox();
portrait.setPosition(90 - portrait.width, 0);
}
-
- public function loadFromGithub(user:GitHubContributor, size:Int = 96) {
- //Main.execAsync(function() {
- var bytes = GitHub.__requestBytesOnGitHubServers('${user.avatar_url}&size=$size');
- var bmap = BitmapData.fromBytes(bytes);
- addPortrait(FlxG.bitmap.add(bmap, false, 'GITHUB-USER:${user.login}'), size);
- //});
- }
}
\ No newline at end of file