diff --git a/Project.xml b/Project.xml index 1eace03..86cd7c8 100644 --- a/Project.xml +++ b/Project.xml @@ -7,6 +7,8 @@ + + diff --git a/assets/preload/images/campaign_menu_UI_assets.xml b/assets/preload/images/campaign_menu_UI_assets.xml index f35ead1..ed6ed76 100644 --- a/assets/preload/images/campaign_menu_UI_assets.xml +++ b/assets/preload/images/campaign_menu_UI_assets.xml @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/assets/preload/images/iconGrid.png b/assets/preload/images/iconGrid.png deleted file mode 100644 index 876010a..0000000 Binary files a/assets/preload/images/iconGrid.png and /dev/null differ diff --git a/assets/preload/images/icons/icon-bf-old.png b/assets/preload/images/icons/icon-bf-old.png new file mode 100644 index 0000000..7d47aa0 Binary files /dev/null and b/assets/preload/images/icons/icon-bf-old.png differ diff --git a/assets/preload/images/icons/icon-bf-pixel.png b/assets/preload/images/icons/icon-bf-pixel.png new file mode 100644 index 0000000..661ea7f Binary files /dev/null and b/assets/preload/images/icons/icon-bf-pixel.png differ diff --git a/assets/preload/images/icons/icon-bf.png b/assets/preload/images/icons/icon-bf.png new file mode 100644 index 0000000..fc27bdd Binary files /dev/null and b/assets/preload/images/icons/icon-bf.png differ diff --git a/assets/preload/images/icons/icon-dad.png b/assets/preload/images/icons/icon-dad.png new file mode 100644 index 0000000..f068dd1 Binary files /dev/null and b/assets/preload/images/icons/icon-dad.png differ diff --git a/assets/preload/images/icons/icon-face.png b/assets/preload/images/icons/icon-face.png new file mode 100644 index 0000000..65dc76c Binary files /dev/null and b/assets/preload/images/icons/icon-face.png differ diff --git a/assets/preload/images/icons/icon-gf.png b/assets/preload/images/icons/icon-gf.png new file mode 100644 index 0000000..48de50f Binary files /dev/null and b/assets/preload/images/icons/icon-gf.png differ diff --git a/assets/preload/images/icons/icon-mom.png b/assets/preload/images/icons/icon-mom.png new file mode 100644 index 0000000..4eb9984 Binary files /dev/null and b/assets/preload/images/icons/icon-mom.png differ diff --git a/assets/preload/images/icons/icon-monster.png b/assets/preload/images/icons/icon-monster.png new file mode 100644 index 0000000..c9e05d0 Binary files /dev/null and b/assets/preload/images/icons/icon-monster.png differ diff --git a/assets/preload/images/icons/icon-parents.png b/assets/preload/images/icons/icon-parents.png new file mode 100644 index 0000000..5d820c5 Binary files /dev/null and b/assets/preload/images/icons/icon-parents.png differ diff --git a/assets/preload/images/icons/icon-pico.png b/assets/preload/images/icons/icon-pico.png new file mode 100644 index 0000000..8a36a61 Binary files /dev/null and b/assets/preload/images/icons/icon-pico.png differ diff --git a/assets/preload/images/icons/icon-senpai.png b/assets/preload/images/icons/icon-senpai.png new file mode 100644 index 0000000..bc294eb Binary files /dev/null and b/assets/preload/images/icons/icon-senpai.png differ diff --git a/assets/preload/images/icons/icon-sm.png b/assets/preload/images/icons/icon-sm.png new file mode 100644 index 0000000..16cdc0e Binary files /dev/null and b/assets/preload/images/icons/icon-sm.png differ diff --git a/assets/preload/images/icons/icon-spirit.png b/assets/preload/images/icons/icon-spirit.png new file mode 100644 index 0000000..441c48b Binary files /dev/null and b/assets/preload/images/icons/icon-spirit.png differ diff --git a/assets/preload/images/icons/icon-spooky.png b/assets/preload/images/icons/icon-spooky.png new file mode 100644 index 0000000..bbfe340 Binary files /dev/null and b/assets/preload/images/icons/icon-spooky.png differ diff --git a/assets/preload/images/icons/icon-tankman.png b/assets/preload/images/icons/icon-tankman.png new file mode 100644 index 0000000..25a2ed3 Binary files /dev/null and b/assets/preload/images/icons/icon-tankman.png differ diff --git a/assets/preload/images/stepmania-icon.png b/assets/preload/images/stepmania-icon.png deleted file mode 100644 index 023353b..0000000 Binary files a/assets/preload/images/stepmania-icon.png and /dev/null differ diff --git a/docs/changelogs/changelog-1.6.1.md b/docs/changelogs/changelog-1.6.1.md new file mode 100644 index 0000000..42d16a3 --- /dev/null +++ b/docs/changelogs/changelog-1.6.1.md @@ -0,0 +1,20 @@ +# Latest (master) changelog/Changelog for 1.0.0 + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- The ability to hide the grid in the editor (for faster load times) +- 💖 Wiggle Shader for Lua Modcharts + +### Changes +- Sort replays by the newest one +- Cleaned up code +- SM Files can now have modcharts +- 💖 Optimized the editor +- 💖 Fixed HTML5 Delta Timings + +### Bugfixes +- 💖 Steps actually exist now +- Fixed Decimal BPM Changes +- Fixes some hard locks +- It's a lot harder to crash in freeplay now \ No newline at end of file diff --git a/docs/changelogs/index.md b/docs/changelogs/index.md index 38dc1b7..a34c60e 100644 --- a/docs/changelogs/index.md +++ b/docs/changelogs/index.md @@ -1,6 +1,9 @@ # Changelogs - [Latest](latest) (Contains changes that are not in a release yet) +- [1.6.1](changelog-1.6.1) +- [1.6](changelog-1.6) +- [1.5.4](changelog-1.5.4) - [1.5.3](changelog-1.5.3) - [1.5.2](changelog-1.5.2) - [1.5.1](changelog-1.5.1) diff --git a/source/Character.hx b/source/Character.hx index 2f15c00..da801e1 100644 --- a/source/Character.hx +++ b/source/Character.hx @@ -348,7 +348,7 @@ class Character extends FlxSprite antialiasing = false; case 'spirit': - frames = Paths.getPackerAtlas('spirit','shared',true); + frames = Paths.getPackerAtlas('spirit','shared',false); animation.addByPrefix('idle', "idle spirit_", 24, false); animation.addByPrefix('singUP', "up_", 24, false); animation.addByPrefix('singRIGHT', "right_", 24, false); @@ -408,9 +408,9 @@ class Character extends FlxSprite } } - public function loadOffsetFile(character:String) + public function loadOffsetFile(character:String, library:String = 'shared') { - var offset:Array = CoolUtil.coolTextFile(Paths.txt('images/characters/' + character + "Offsets", 'shared')); + var offset:Array = CoolUtil.coolTextFile(Paths.txt('images/characters/' + character + "Offsets", library)); for (i in 0...offset.length) { diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 5237e1e..6357545 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -243,6 +243,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -418,6 +420,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -611,6 +615,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -639,7 +645,7 @@ class ChartingState extends MusicBeatState var eventPos = new FlxUIInputText(150,100,80,""); var eventAdd = new FlxButton(95,155,"Add Event", function() { - var pog:Song.Event = new Song.Event("New Event " + HelperFunctions.truncateFloat(curDecimalBeat, 3),HelperFunctions.truncateFloat(curDecimalBeat, 3),_song.bpm + "","BPM Change"); + var pog:Song.Event = new Song.Event("New Event " + HelperFunctions.truncateFloat(curDecimalBeat, 3),HelperFunctions.truncateFloat(curDecimalBeat, 3),_song.bpm,"BPM Change"); trace("adding " + pog.name); @@ -654,13 +660,13 @@ class ChartingState extends MusicBeatState eventName.text = pog.name; eventType.selectedLabel = pog.type; - eventValue.text = pog.value; + eventValue.text = pog.value + ""; eventPos.text = pog.position + ""; currentSelectedEventName = pog.name; currentEventPosition = pog.position; savedType = pog.type; - savedValue = pog.value; + savedValue = pog.value + ""; var listofnames = []; @@ -696,6 +702,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -738,13 +746,13 @@ class ChartingState extends MusicBeatState eventName.text = firstEvent.name; eventType.selectedLabel = firstEvent.type; - eventValue.text = firstEvent.value; + eventValue.text = firstEvent.value + ""; eventPos.text = firstEvent.position + ""; currentSelectedEventName = firstEvent.name; currentEventPosition = firstEvent.position; savedType = firstEvent.type; - savedValue = firstEvent.value; + savedValue = firstEvent.value + ''; var listofnames = []; @@ -780,6 +788,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -839,7 +849,7 @@ class ChartingState extends MusicBeatState trace("bruh"); eventType.selectedLabel = firstEventObject.type; trace("bruh"); - eventValue.text = firstEventObject.value; + eventValue.text = firstEventObject.value + ""; trace("bruh"); currentSelectedEventName = firstEventObject.name; trace("bruh"); @@ -859,7 +869,7 @@ class ChartingState extends MusicBeatState trace('selecting ' + name + ' found: ' + event); eventName.text = event.name; - eventValue.text = event.value; + eventValue.text = event.value + ""; eventPos.text = event.position + ""; eventType.selectedLabel = event.type; currentSelectedEventName = event.name; @@ -1162,14 +1172,6 @@ class ChartingState extends MusicBeatState }); var clearSectionButton:FlxButton = new FlxButton(10, 150, "Clear Section", clearSection); - var startSection:FlxButton = new FlxButton(10, 85, "Play Here", function() { - PlayState.SONG = _song; - FlxG.sound.music.stop(); - if (!PlayState.isSM) - vocals.stop(); - PlayState.startTime = lastUpdatedSection.startTime; - LoadingState.loadAndSwitchState(new PlayState()); - }); var swapSection:FlxButton = new FlxButton(10, 170, "Swap Section", function() { @@ -1242,7 +1244,6 @@ class ChartingState extends MusicBeatState tab_group_section.add(copyButton); tab_group_section.add(clearSectionButton); tab_group_section.add(swapSection); - tab_group_section.add(startSection); UI_box.addGroup(tab_group_section); } @@ -1491,6 +1492,36 @@ class ChartingState extends MusicBeatState { updateHeads(); + for(i in sectionRenderes) + { + var diff = i.y - strumLine.y; + if (diff < 4000 && diff >= -4000) + { + i.active = true; + i.visible = true; + } + else + { + i.active = false; + i.visible = false; + } + } + + for(i in curRenderedNotes) + { + var diff = i.y - strumLine.y; + if (diff < 4000 && diff >= -4000) + { + i.active = true; + i.visible = true; + } + else + { + i.active = false; + i.visible = false; + } + } + var doInput = true; for (i in Typeables) @@ -1599,6 +1630,8 @@ class ChartingState extends MusicBeatState var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -1692,6 +1725,8 @@ class ChartingState extends MusicBeatState + currentBPM + "\nCurBeat: " + HelperFunctions.truncateFloat(curDecimalBeat,3) + + "\nCurStep: " + + curStep + "\nZoom: " + zoomFactor; diff --git a/source/DiffCalc.hx b/source/DiffCalc.hx index 5022cb8..608fb05 100644 --- a/source/DiffCalc.hx +++ b/source/DiffCalc.hx @@ -23,7 +23,6 @@ class DiffCalc public static function CalculateDiff(song:SwagSong, ?accuracy:Float = .93) { - trace('calcuilafjwaf'); // cleaned notes var cleanedNotes:Array = []; @@ -38,14 +37,16 @@ class DiffCalc { for (ii in i.sectionNotes) // notes { - if (ii[1] > 3 && !i.mustHitSection) + var gottaHitNote:Bool = i.mustHitSection; + + if (ii[1] >= 3 && gottaHitNote) cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); - else if (ii[1] < 4 && i.mustHitSection) + if (ii[1] <= 4 && !gottaHitNote) cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); } } - trace(cleanedNotes.length + " - playable notes"); + trace('calcuilafjwaf ' + cleanedNotes.length); var handOne:Array = []; var handTwo:Array = []; @@ -369,4 +370,4 @@ class DiffCalc diffVector[i] = (fuck + floatZero) / 2; } } -} \ No newline at end of file +} diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index dc27df6..96d0c30 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -1,4 +1,5 @@ package; +import lime.app.Application; import openfl.utils.Future; import openfl.media.Sound; import flixel.system.FlxSound; @@ -77,7 +78,6 @@ class FreeplayState extends MusicBeatState { var data:Array = initSonglist[i].split(':'); var meta = new SongMetadata(data[0], Std.parseInt(data[2]), data[1]); - songs.push(meta); var format = StringTools.replace(meta.songName, " ", "-"); switch (format) { case 'Dad-Battle': format = 'Dadbattle'; @@ -85,11 +85,40 @@ class FreeplayState extends MusicBeatState } var diffs = []; - FreeplayState.loadDiff(0,format,meta.songName,diffs); - FreeplayState.loadDiff(1,format,meta.songName,diffs); - FreeplayState.loadDiff(2,format,meta.songName,diffs); + var diffsThatExist = []; + + + #if sys + if (FileSystem.exists('assets/data/${format}/${format}-hard.json')) + diffsThatExist.push("Hard"); + if (FileSystem.exists('assets/data/${format}/${format}-easy.json')) + diffsThatExist.push("Easy"); + if (FileSystem.exists('assets/data/${format}/${format}.json')) + diffsThatExist.push("Normal"); + + if (diffsThatExist.length == 0) + { + Application.current.window.alert("No difficulties found for chart, skipping.",meta.songName + " Chart"); + continue; + } + #else + diffsThatExist = ["Easy","Normal","Hard"]; + #end + if (diffsThatExist.contains("Easy")) + FreeplayState.loadDiff(0,format,meta.songName,diffs); + if (diffsThatExist.contains("Normal")) + FreeplayState.loadDiff(1,format,meta.songName,diffs); + if (diffsThatExist.contains("Hard")) + FreeplayState.loadDiff(2,format,meta.songName,diffs); + + meta.diffs = diffsThatExist; + + if (diffsThatExist.length != 3) + trace("I ONLY FOUND " + diffsThatExist); + FreeplayState.songData.set(meta.songName,diffs); trace('loaded diffs for ' + meta.songName); + songs.push(meta); } @@ -376,6 +405,9 @@ class FreeplayState extends MusicBeatState function changeDiff(change:Int = 0) { + if (!songs[curSelected].diffs.contains(CoolUtil.difficultyFromInt(curDifficulty + change))) + return; + curDifficulty += change; if (curDifficulty < 0) @@ -417,6 +449,19 @@ class FreeplayState extends MusicBeatState if (curSelected >= songs.length) curSelected = 0; + if (songs[curSelected].diffs.length != 3) + { + switch(songs[curSelected].diffs[0]) + { + case "Easy": + curDifficulty = 0; + case "Normal": + curDifficulty = 1; + case "Hard": + curDifficulty = 2; + } + } + // selector.y = (70 * curSelected) + 30; // adjusting the highscore song name to be compatible (changeSelection) @@ -501,6 +546,8 @@ class SongMetadata #end public var songCharacter:String = ""; + public var diffs = []; + #if sys public function new(song:String, week:Int, songCharacter:String, ?sm:SMFile = null, ?path:String = "") { diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx index ec24910..8104468 100644 --- a/source/HealthIcon.hx +++ b/source/HealthIcon.hx @@ -3,59 +3,58 @@ package; import flixel.FlxG; import flixel.FlxSprite; +using StringTools; + class HealthIcon extends FlxSprite { + public var char:String = 'bf'; + public var isPlayer:Bool = false; + public var isOldIcon:Bool = false; + /** * Used for FreeplayState! If you use it elsewhere, prob gonna annoying */ public var sprTracker:FlxSprite; - public function new(char:String = 'bf', isPlayer:Bool = false) + public function new(?char:String = "bf", ?isPlayer:Bool = false) { super(); - if(FlxG.save.data.antialiasing) + this.char = char; + this.isPlayer = isPlayer; + + isPlayer = isOldIcon = false; + + if (FlxG.save.data.antialiasing) + { + switch(char) { - antialiasing = true; + case 'bf-pixel' | 'senpai' | 'senpai-angry' | 'spirit' | 'gf-pixel': + antialiasing = false; + default: + antialiasing = true; } - if (char == 'sm') - { - loadGraphic(Paths.image("stepmania-icon")); - return; - } - loadGraphic(Paths.image('iconGrid'), true, 150, 150); - animation.add('bf', [0, 1], 0, false, isPlayer); - animation.add('bf-car', [0, 1], 0, false, isPlayer); - animation.add('bf-christmas', [0, 1], 0, false, isPlayer); - animation.add('bf-pixel', [21, 21], 0, false, isPlayer); - animation.add('spooky', [2, 3], 0, false, isPlayer); - animation.add('pico', [4, 5], 0, false, isPlayer); - animation.add('mom', [6, 7], 0, false, isPlayer); - animation.add('mom-car', [6, 7], 0, false, isPlayer); - animation.add('tankman', [8, 9], 0, false, isPlayer); - animation.add('face', [10, 11], 0, false, isPlayer); - animation.add('dad', [12, 13], 0, false, isPlayer); - animation.add('senpai', [22, 22], 0, false, isPlayer); - animation.add('senpai-angry', [22, 22], 0, false, isPlayer); - animation.add('spirit', [23, 23], 0, false, isPlayer); - animation.add('bf-old', [14, 15], 0, false, isPlayer); - animation.add('gf', [16], 0, false, isPlayer); - animation.add('gf-christmas', [16], 0, false, isPlayer); - animation.add('gf-pixel', [16], 0, false, isPlayer); - animation.add('parents-christmas', [17, 18], 0, false, isPlayer); - animation.add('monster', [19, 20], 0, false, isPlayer); - animation.add('monster-christmas', [19, 20], 0, false, isPlayer); - animation.play(char); - - switch(char) - { - case 'bf-pixel' | 'senpai' | 'senpai-angry' | 'spirit' | 'gf-pixel': - antialiasing = false; } + changeIcon(char); scrollFactor.set(); } + public function swapOldIcon() + { + (isOldIcon = !isOldIcon) ? changeIcon("bf-old") : changeIcon(char); + } + + public function changeIcon(char:String) + { + if (char != 'bf-pixel' && char != 'bf-old') + char = char.split("-")[0]; + + loadGraphic(Paths.image('icons/icon-' + char), true, 150, 150); + animation.add(char, [0, 1], 0, false, isPlayer); + animation.play(char); + } + override function update(elapsed:Float) { super.update(elapsed); diff --git a/source/KadeEngineData.hx b/source/KadeEngineData.hx index 89039ff..eb0b876 100644 --- a/source/KadeEngineData.hx +++ b/source/KadeEngineData.hx @@ -109,6 +109,9 @@ class KadeEngineData if (FlxG.save.data.cacheImages == null) FlxG.save.data.cacheImages = false; + if (FlxG.save.data.editor == null) + FlxG.save.data.editor = true; + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; KeyBinds.gamepad = gamepad != null; diff --git a/source/LoadReplayState.hx b/source/LoadReplayState.hx index 135c5ae..3688a6b 100644 --- a/source/LoadReplayState.hx +++ b/source/LoadReplayState.hx @@ -44,7 +44,7 @@ class LoadReplayState extends MusicBeatState #end trace(controlsStrings); - controlsStrings.sort(Reflect.compare); + controlsStrings.sort(sortByDate); addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']); addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky']); @@ -106,6 +106,13 @@ class LoadReplayState extends MusicBeatState super.create(); } + function sortByDate(a:String, b:String) { + var aTime = Std.parseFloat(a.split("time")[1])/1000; + var bTime = Std.parseFloat(b.split("time")[1])/1000; + + return Std.int(bTime - aTime); // Newest first + } + public function getWeekNumbFromSong(songName:String):Int { var week:Int = 0; diff --git a/source/Main.hx b/source/Main.hx index 788ba61..f17cec3 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -78,6 +78,10 @@ class Main extends Sprite gameHeight = Math.ceil(stageHeight / zoom); } + #if !cpp + framerate = 60; + #end + #if cpp initialState = Caching; game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen); diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 2d676ae..543421b 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -40,7 +40,7 @@ class MainMenuState extends MusicBeatState public static var nightly:String = ""; - public static var kadeEngineVer:String = "1.6" + nightly; + public static var kadeEngineVer:String = "1.6.1" + nightly; public static var gameVer:String = "0.2.7.1"; var magenta:FlxSprite; diff --git a/source/ModchartShader.hx b/source/ModchartShader.hx new file mode 100644 index 0000000..9077d22 --- /dev/null +++ b/source/ModchartShader.hx @@ -0,0 +1,74 @@ +import flixel.system.FlxAssets.FlxShader; + +class ModchartShader extends FlxShader +{ + public var vertexHeader = "attribute float openfl_Alpha; + attribute vec4 openfl_ColorMultiplier; + attribute vec4 openfl_ColorOffset; + attribute vec4 openfl_Position; + attribute vec2 openfl_TextureCoord; + varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform mat4 openfl_Matrix; + uniform bool openfl_HasColorTransform; + uniform vec2 openfl_TextureSize;"; + public var vertexBody = "openfl_Alphav = openfl_Alpha; + openfl_TextureCoordv = openfl_TextureCoord; + if (openfl_HasColorTransform) { + openfl_ColorMultiplierv = openfl_ColorMultiplier; + openfl_ColorOffsetv = openfl_ColorOffset / 255.0; + } + gl_Position = openfl_Matrix * openfl_Position;"; + public var vertexSource = "#pragma header + void main(void) { + #pragma body + }"; + public var fragmentHeader = "varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform bool openfl_HasColorTransform; + uniform sampler2D openfl_Texture; + uniform vec2 openfl_TextureSize;"; + public var fragmentBody = "vec4 color = texture2D (openfl_Texture, openfl_TextureCoordv); + if (color.a == 0.0) { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } else if (openfl_HasColorTransform) { + color = vec4 (color.rgb / color.a, color.a); + mat4 colorMultiplier = mat4 (0); + colorMultiplier[0][0] = openfl_ColorMultiplierv.x; + colorMultiplier[1][1] = openfl_ColorMultiplierv.y; + colorMultiplier[2][2] = openfl_ColorMultiplierv.z; + colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w; + color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); + if (color.a > 0.0) { + gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + } else { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } + } else { + gl_FragColor = color * openfl_Alphav; + }"; + + public function new(frag:String,?vert:String = "") + { + if (vert != "") + glVertexSource = vert; + glFragmentSource = frag; + + if (glVertexSource != null) + { + glVertexSource = StringTools.replace(glVertexSource, "#pragma header", vertexHeader); + glVertexSource = StringTools.replace(glVertexSource, "#pragma body", vertexBody); + } + + if (glVertexSource != null) + { + glFragmentSource = StringTools.replace(glFragmentSource, "#pragma header", fragmentHeader); + glFragmentSource = StringTools.replace(glFragmentSource, "#pragma body", fragmentBody); + } + super(); + } +} \ No newline at end of file diff --git a/source/ModchartState.hx b/source/ModchartState.hx index 571edbf..311ae08 100644 --- a/source/ModchartState.hx +++ b/source/ModchartState.hx @@ -241,7 +241,7 @@ class ModchartState PlayState.instance.removeObject(PlayState.dad); PlayState.dad = new Character(olddadx, olddady, id); PlayState.instance.addObject(PlayState.dad); - PlayState.instance.iconP2.animation.play(id); + PlayState.instance.iconP2.changeIcon(id); } function changeBoyfriendCharacter(id:String) @@ -250,7 +250,7 @@ class ModchartState PlayState.instance.removeObject(PlayState.boyfriend); PlayState.boyfriend = new Boyfriend(oldboyfriendx, oldboyfriendy, id); PlayState.instance.addObject(PlayState.boyfriend); - PlayState.instance.iconP1.animation.play(id); + PlayState.instance.iconP1.changeIcon(id); } function makeAnimatedLuaSprite(spritePath:String,names:Array,prefixes:Array,startAnim:String, id:String) @@ -297,7 +297,12 @@ class ModchartState case 'philly-nice': songLowercase = 'philly'; } - var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png"); + var path = Sys.getCwd() + "assets/data/" + songLowercase + '/'; + + if (PlayState.isSM) + path = PlayState.pathToSm + "/"; + + var data:BitmapData = BitmapData.fromFile(path + spritePath + ".png"); var sprite:FlxSprite = new FlxSprite(0,0); var imgWidth:Float = FlxG.width / data.width; @@ -347,6 +352,8 @@ class ModchartState lua = null; } + public var luaWiggles:Map = new Map(); + // LUA SHIT function new() @@ -367,7 +374,11 @@ class ModchartState case 'philly-nice': songLowercase = 'philly'; } - var result = LuaL.dofile(lua, Paths.lua(songLowercase + "/modchart")); // execute le file + var path = Paths.lua(songLowercase + "/modchart"); + if (PlayState.isSM) + path = PlayState.pathToSm + "/modchart.lua"; + + var result = LuaL.dofile(lua, path); // execute le file if (result != 0) { @@ -427,6 +438,41 @@ class ModchartState Lua_helper.add_callback(lua,"getProperty", getPropertyByName); + Lua_helper.add_callback(lua,"setNoteWiggle", function(wiggleId) { + PlayState.instance.camNotes.setFilters([new ShaderFilter(luaWiggles.get(wiggleId).shader)]); + }); + + Lua_helper.add_callback(lua,"setSustainWiggle", function(wiggleId) { + PlayState.instance.camSustains.setFilters([new ShaderFilter(luaWiggles.get(wiggleId).shader)]); + }); + + Lua_helper.add_callback(lua,"createWiggle", function(freq:Float,amplitude:Float,speed:Float) { + var wiggle = new WiggleEffect(); + wiggle.waveAmplitude = amplitude; + wiggle.waveSpeed = speed; + wiggle.waveFrequency = freq; + + var id = Lambda.count(luaWiggles) + 1 + ""; + + luaWiggles.set(id,wiggle); + return id; + }); + + Lua_helper.add_callback(lua,"setWiggleTime", function(wiggleId:String,time:Float) { + var wiggle = luaWiggles.get(wiggleId); + + wiggle.shader.uTime.value = [time]; + }); + + + Lua_helper.add_callback(lua,"setWiggleAmplitude", function(wiggleId:String,amp:Float) { + var wiggle = luaWiggles.get(wiggleId); + + wiggle.waveAmplitude = amp; + }); + + + // Lua_helper.add_callback(lua,"makeAnimatedSprite", makeAnimatedLuaSprite); // this one is still in development diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index 7a3bde8..dec5264 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -49,7 +49,7 @@ class MusicBeatState extends FlxUIState override function update(elapsed:Float) { //everyStep(); - var nextStep:Int = updateCurStep(); + /*var nextStep:Int = updateCurStep(); if (nextStep >= 0) { @@ -69,7 +69,7 @@ class MusicBeatState extends FlxUIState updateBeat(); stepHit(); } - } + }*/ if (Conductor.songPosition < 0) curDecimalBeat = 0; @@ -83,17 +83,62 @@ class MusicBeatState extends FlxUIState Conductor.crochet = ((60 / data.bpm) * 1000); - var percent = (Conductor.songPosition - (data.startTime * 1000)) / (data.length * 1000); + var step = ((60 / data.bpm) * 1000) / 4; + var startInMS = (data.startTime * 1000); + + + var percent = (Conductor.songPosition - startInMS) / (data.length * 1000); curDecimalBeat = data.startBeat + (((Conductor.songPosition/1000) - data.startTime) * (data.bpm / 60)); + var ste:Int = Math.floor(data.startStep + ((Conductor.songPosition - startInMS) / step)); + if (ste >= 0) + { + if (ste > curStep) + { + for (i in curStep...ste) + { + curStep++; + updateBeat(); + stepHit(); + } + } + else if (ste < curStep) + { + //Song reset? + curStep = ste; + updateBeat(); + stepHit(); + } + } } else { curDecimalBeat = (Conductor.songPosition / 1000) * (Conductor.bpm/60); + var nextStep:Int = Math.floor(Conductor.songPosition / Conductor.stepCrochet); + if (nextStep >= 0) + { + if (nextStep > curStep) + { + for (i in curStep...nextStep) + { + curStep++; + updateBeat(); + stepHit(); + } + } + else if (nextStep < curStep) + { + //Song reset? + curStep = nextStep; + updateBeat(); + stepHit(); + } + } Conductor.crochet = ((60 / Conductor.bpm) * 1000); } } + if (FlxG.save.data.fpsRain && skippedFrames >= 6) { if (currentColor >= array.length) diff --git a/source/Options.hx b/source/Options.hx index 37403ff..0a7f8ef 100644 --- a/source/Options.hx +++ b/source/Options.hx @@ -142,6 +142,29 @@ class GraphicLoading extends Option } +class EditorRes extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + + public override function press():Bool + { + FlxG.save.data.editor = !FlxG.save.data.editor; + + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return FlxG.save.data.editor ? "Show Editor Grid" : "Do not Show Editor Grid"; + } + +} + class DownscrollOption extends Option { public function new(desc:String) @@ -801,6 +824,7 @@ class LockWeeksOption extends Option } FlxG.save.data.weekUnlocked = 1; StoryMenuState.weekUnlocked = [true, true]; + confirm = false; trace('Weeks Locked'); display = updateDisplay(); return true; @@ -871,6 +895,8 @@ class ResetSettings extends Option FlxG.save.data.weekUnlocked = null; FlxG.save.data.newInput = null; FlxG.save.data.downscroll = null; + FlxG.save.data.antialiasing = null; + FlxG.save.data.missSounds = null; FlxG.save.data.dfjk = null; FlxG.save.data.accuracyDisplay = null; FlxG.save.data.offset = null; @@ -886,6 +912,7 @@ class ResetSettings extends Option FlxG.save.data.watermark = null; FlxG.save.data.ghost = null; FlxG.save.data.distractions = null; + FlxG.save.data.stepMania = null; FlxG.save.data.flashing = null; FlxG.save.data.resetButton = null; FlxG.save.data.botplay = null; @@ -893,7 +920,12 @@ class ResetSettings extends Option FlxG.save.data.strumline = null; FlxG.save.data.customStrumLine = null; FlxG.save.data.camzoom = null; - FlxG.save.data.stepMania = null; + FlxG.save.data.scoreScreen = null; + FlxG.save.data.inputShow = null; + FlxG.save.data.optimize = null; + FlxG.save.data.cacheImages = null; + FlxG.save.data.editor = null; + KadeEngineData.initSave(); confirm = false; trace('All settings have been reset'); diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx index 495219b..87a6b56 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu.hx @@ -40,6 +40,7 @@ class OptionsMenu extends MusicBeatState new CustomizeGameplay("Drag and drop gameplay modules to your prefered positions!") ]), new OptionCategory("Appearance", [ + new EditorRes("Not showing the editor grid will greatly increase editor performance"), new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay."), new CamZoomOption("Toggle the camera zoom in-game."), new StepManiaOption("Sets the colors of the arrows depending on quantization instead of direction."), @@ -124,6 +125,8 @@ class OptionsMenu extends MusicBeatState FlxTween.tween(versionShit,{y: FlxG.height - 18},2,{ease: FlxEase.elasticInOut}); FlxTween.tween(blackBorder,{y: FlxG.height - 18},2, {ease: FlxEase.elasticInOut}); + + changeSelection(); super.create(); } diff --git a/source/Paths.hx b/source/Paths.hx index 69adc31..8c8f184 100644 --- a/source/Paths.hx +++ b/source/Paths.hx @@ -164,7 +164,7 @@ class Paths if (isCharacter) if (usecahce) #if cpp - return FlxAtlasFrames.fromSpriteSheetPacker(imageCached(key), file('images/$key.txt', library)); + return FlxAtlasFrames.fromSpriteSheetPacker(imageCached(key), file('images/characters/$key.txt', library)); #else return null; #end diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index e6b68af..747c7cb 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -205,7 +205,7 @@ class PauseSubState extends MusicBeatSubstate } #end - if (controls.ACCEPT) + if (controls.ACCEPT && !FlxG.keys.pressed.ALT) { var daSelected:String = menuItems[curSelected]; diff --git a/source/PlayState.hx b/source/PlayState.hx index 487ca7a..e14b145 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1,5 +1,6 @@ package; + import Song.Event; import openfl.media.Sound; #if sys @@ -178,6 +179,8 @@ class PlayState extends MusicBeatState public var iconP1:HealthIcon; // making these public again because i may be stupid public var iconP2:HealthIcon; // what could go wrong? public var camHUD:FlxCamera; + public var camSustains:FlxCamera; + public var camNotes:FlxCamera; private var camGame:FlxCamera; public var cannotDie = false; @@ -323,6 +326,8 @@ class PlayState extends MusicBeatState #if windows executeModchart = FileSystem.exists(Paths.lua(songLowercase + "/modchart")); + if (isSM) + executeModchart = FileSystem.exists(pathToSm + "/modchart.lua"); if (executeModchart) PlayStateChangeables.Optimize = false; #end @@ -382,9 +387,15 @@ class PlayState extends MusicBeatState camGame = new FlxCamera(); camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; + camSustains = new FlxCamera(); + camSustains.bgColor.alpha = 0; + camNotes = new FlxCamera(); + camNotes.bgColor.alpha = 0; FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD); + FlxG.cameras.add(camSustains); + FlxG.cameras.add(camNotes); FlxCamera.defaultCameras = [camGame]; @@ -2324,13 +2335,14 @@ class PlayState extends MusicBeatState { luaModchart.setVar('songPos', Conductor.songPosition); luaModchart.setVar('hudZoom', camHUD.zoom); + luaModchart.setVar('curBeat', HelperFunctions.truncateFloat(curDecimalBeat,3)); luaModchart.setVar('cameraZoom', FlxG.camera.zoom); luaModchart.executeState('update', [elapsed]); - for (i in luaWiggles) + for (key => value in luaModchart.luaWiggles) { trace('wiggle le gaming'); - i.update(elapsed); + value.update(elapsed); } /*for (i in 0...strumLineNotes.length) { @@ -2394,12 +2406,7 @@ class PlayState extends MusicBeatState } if (FlxG.keys.justPressed.NINE) - { - if (iconP1.animation.curAnim.name == 'bf-old') - iconP1.animation.play(SONG.player1); - else - iconP1.animation.play('bf-old'); - } + iconP1.swapOldIcon(); switch (curStage) { @@ -2425,7 +2432,7 @@ class PlayState extends MusicBeatState scoreTxt.x = (originalX - (lengthInPx / 2)) + 335; - if (controls.PAUSE && startedCountdown && canPause) + if (controls.PAUSE && startedCountdown && canPause && !cannotDie) { persistentUpdate = false; persistentDraw = true; @@ -2909,6 +2916,10 @@ class PlayState extends MusicBeatState { var dunceNote:Note = unspawnNotes[0]; notes.add(dunceNote); + if (!dunceNote.isSustainNote) + dunceNote.cameras = [camNotes]; + else + dunceNote.cameras = [camSustains]; var index:Int = unspawnNotes.indexOf(dunceNote); unspawnNotes.splice(index, 1); @@ -3726,25 +3737,22 @@ class PlayState extends MusicBeatState var holdArray:Array = [controls.LEFT, controls.DOWN, controls.UP, controls.RIGHT]; var pressArray:Array = [controls.LEFT_P, controls.DOWN_P, controls.UP_P, controls.RIGHT_P]; var releaseArray:Array = [controls.LEFT_R, controls.DOWN_R, controls.UP_R, controls.RIGHT_R]; + var keynameArray:Array = ['left', 'down', 'up', 'right']; #if windows if (luaModchart != null) { - if (controls.LEFT_P) - { - luaModchart.executeState('keyPressed', ["left"]); + for (i in 0...pressArray.length) { + if (pressArray[i] == true) { + luaModchart.executeState('keyPressed', [keynameArray[i]]); + } }; - if (controls.DOWN_P) - { - luaModchart.executeState('keyPressed', ["down"]); - }; - if (controls.UP_P) - { - luaModchart.executeState('keyPressed', ["up"]); - }; - if (controls.RIGHT_P) - { - luaModchart.executeState('keyPressed', ["right"]); + + for (i in 0...releaseArray.length) { + if (releaseArray[i] == true) { + luaModchart.executeState('keyReleased', [keynameArray[i]]); + } }; + }; #end @@ -3914,9 +3922,9 @@ class PlayState extends MusicBeatState playerStrums.forEach(function(spr:FlxSprite) { if (keys[spr.ID] && spr.animation.curAnim.name != 'confirm') - spr.animation.play('pressed'); + spr.animation.play('pressed', false); if (!keys[spr.ID]) - spr.animation.play('static'); + spr.animation.play('static', false); if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school')) { @@ -3991,7 +3999,7 @@ class PlayState extends MusicBeatState FlxG.stage.window.onFocusIn.add(focusIn); var ourSource:String = "assets/videos/daWeirdVid/dontDelete.webm"; - WebmPlayer.SKIP_STEP_LIMIT = 90; + //WebmPlayer.SKIP_STEP_LIMIT = 90; var str1:String = "WEBM SHIT"; webmHandler = new WebmHandler(); webmHandler.source(ourSource); @@ -4447,17 +4455,21 @@ class PlayState extends MusicBeatState #if windows if (executeModchart && luaModchart != null) { - luaModchart.setVar('curBeat', curBeat); luaModchart.executeState('beatHit', [curBeat]); } #end if (curSong == 'Tutorial' && dad.curCharacter == 'gf') { - if (curBeat % 2 == 1 && dad.animOffsets.exists('danceLeft')) - dad.playAnim('danceLeft'); - if (curBeat % 2 == 0 && dad.animOffsets.exists('danceRight')) - dad.playAnim('danceRight'); + if (SONG.notes[Math.floor(curStep / 16)].mustHitSection) + dad.dance(); + else + { + if (curBeat == 73 || curBeat % 4 == 0 || curBeat % 4 == 1) + dad.playAnim('danceLeft', true); + else + dad.playAnim('danceRight', true); + } } if (SONG.notes[Math.floor(curStep / 16)] != null) @@ -4467,7 +4479,7 @@ class PlayState extends MusicBeatState // Dad doesnt interupt his own notes if ((SONG.notes[Math.floor(curStep / 16)].mustHitSection || !dad.animation.curAnim.name.startsWith("sing")) && dad.curCharacter != 'gf') - if (curBeat % idleBeat == 0 || dad.curCharacter == "spooky") + if ((curBeat % idleBeat == 0 || !idleToBeat) || dad.curCharacter == "spooky") dad.dance(idleToBeat); } // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); @@ -4500,7 +4512,7 @@ class PlayState extends MusicBeatState gf.dance(); } - if (!boyfriend.animation.curAnim.name.startsWith("sing") && curBeat % idleBeat == 0) + if (!boyfriend.animation.curAnim.name.startsWith("sing") && (curBeat % idleBeat == 0 || !idleToBeat)) { boyfriend.playAnim('idle', idleToBeat); } diff --git a/source/SectionRender.hx b/source/SectionRender.hx index 3410ccb..67cafa8 100644 --- a/source/SectionRender.hx +++ b/source/SectionRender.hx @@ -15,13 +15,14 @@ class SectionRender extends FlxSprite { super(x,y); - makeGraphic(GRID_SIZE * 8, GRID_SIZE * Height,FlxColor.BLACK); + makeGraphic(GRID_SIZE * 8, GRID_SIZE * Height,0xffe7e6e6); var h = GRID_SIZE; if (Math.floor(h) != h) h = GRID_SIZE; - FlxGridOverlay.overlay(this,GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * Height); + if (FlxG.save.data.editor) + FlxGridOverlay.overlay(this,GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * Height); } diff --git a/source/ShaderShader.hx b/source/ShaderShader.hx new file mode 100644 index 0000000..fc19f21 --- /dev/null +++ b/source/ShaderShader.hx @@ -0,0 +1,41 @@ +import flixel.system.FlxAssets; + +class ShaderShader extends FlxShader +{ + @:glFragmentSource(' + #pragma header + uniform float fade; + + varying vec4 color; + varying vec2 textureCoord; + varying vec2 textureSize; + uniform sampler2D sampler0; + + float luma(vec3 color) { + return dot(color, vec3(0.299, 0.587, 0.114)); + } + + vec3 rgb(float r, float g, float b) { + return vec3(r/255.0,g/255.0,b/255.0); + } + + void main() + { + vec2 uv = textureCoord; + + vec3 col = texture2D( sampler0, uv ).rgb; + float bright=floor(luma(col+0.4)*4.0)/4.0; + + vec3 newcol; + if (bright<0.3) newcol = rgb(54.0,87.0,53.0); + else if (bright<0.6) newcol = rgb(128.0,128.0,0.0); + else newcol = rgb(157.0,187.0,97.0); + gl_FragColor = vec4( newcol*(fade)+col*(1.0-fade), 1.0 ) * color; + } + ') + + public function new() + { + super(); + } +} \ No newline at end of file diff --git a/source/Song.hx b/source/Song.hx index abbec7f..e3e3055 100644 --- a/source/Song.hx +++ b/source/Song.hx @@ -11,10 +11,10 @@ class Event { public var name:String; public var position:Float; - public var value:Dynamic; + public var value:Float; public var type:String; - public function new(name:String,pos:Float,value:Dynamic,type:String) + public function new(name:String,pos:Float,value:Float,type:String) { this.name = name; this.position = pos; diff --git a/source/TimingStruct.hx b/source/TimingStruct.hx index 82128a3..d1301c1 100644 --- a/source/TimingStruct.hx +++ b/source/TimingStruct.hx @@ -7,6 +7,7 @@ class TimingStruct public var bpm:Float = 0; public var startBeat:Float = 0; + public var startStep:Int = 0; public var endBeat:Float = Math.POSITIVE_INFINITY; public var startTime:Float = 0; @@ -23,7 +24,7 @@ class TimingStruct AllTimings.push(pog); } - public function new(startBeat,bpm,endBeat:Float, offset:Float) + public function new(startBeat:Float,bpm:Float,endBeat:Float, offset:Float) { this.bpm = bpm; this.startBeat = startBeat; @@ -52,4 +53,4 @@ class TimingStruct } return null; } -} \ No newline at end of file +} diff --git a/source/smTools/SMHeader.hx b/source/smTools/SMHeader.hx index 656b15a..950da4f 100644 --- a/source/smTools/SMHeader.hx +++ b/source/smTools/SMHeader.hx @@ -70,6 +70,8 @@ class SMHeader var data = TimingStruct.AllTimings[currentIndex - 1]; data.endBeat = beat; data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + var step = ((60 / data.bpm) * 1000) / 4; + TimingStruct.AllTimings[currentIndex].startStep = Math.floor(((data.endBeat / (data.bpm / 60)) * 1000) / step); TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; } @@ -106,4 +108,4 @@ class SMHeader } } } -#end \ No newline at end of file +#end diff --git a/version.downloadMe b/version.downloadMe index a061bd3..d49b667 100644 --- a/version.downloadMe +++ b/version.downloadMe @@ -1,8 +1,5 @@ -1.6; -- Full reworked charter -- BPM Changes & Scroll Speed Change Support -- StepMania File Format support -- Pre-loading for characters option -- New Main Menu Remix -- Difficulty Calculator -- Held note rework \ No newline at end of file +1.6.1; +- Wiggle Shader for Lua Modcharts +- Optimized the editor +- Fixed HTML5 Delta Timings +- Steps actually exist now \ No newline at end of file