diff --git a/Project.xml b/Project.xml index 3504b38806..33ea82aee4 100644 --- a/Project.xml +++ b/Project.xml @@ -128,7 +128,7 @@ - + @@ -184,6 +184,8 @@ + + diff --git a/appveyor-linux.yml b/appveyor-linux.yml index e8f76aba93..a6c03fcb38 100644 --- a/appveyor-linux.yml +++ b/appveyor-linux.yml @@ -29,6 +29,7 @@ install: - haxelib git polymod https://github.com/larsiusprime/polymod.git - haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc - haxelib git extension-webm https://github.com/KadeDev/extension-webm + - haxelib git hxvm-luajit https://github.com/KadeDev/hxvm-luajit - haxelib run lime rebuild extension-webm linux - haxelib git linc_luajit https://github.com/AndreiRudenko/linc_luajit.git - haxelib install actuate diff --git a/appveyor-macos.yml b/appveyor-macos.yml index 47c0bcd1b8..57c76afd9d 100644 --- a/appveyor-macos.yml +++ b/appveyor-macos.yml @@ -29,6 +29,7 @@ install: - haxelib git polymod https://github.com/larsiusprime/polymod.git - haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc - haxelib git extension-webm https://github.com/KadeDev/extension-webm + - haxelib git hxvm-luajit https://github.com/KadeDev/hxvm-luajit - haxelib run lime rebuild extension-webm macos - haxelib install linc_luajit - haxelib install actuate diff --git a/appveyor-windows.yml b/appveyor-windows.yml index 58d5d98f9e..16b6d42721 100644 --- a/appveyor-windows.yml +++ b/appveyor-windows.yml @@ -34,6 +34,7 @@ install: - haxelib git polymod https://github.com/larsiusprime/polymod.git - haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc - haxelib git extension-webm https://github.com/KadeDev/extension-webm + - haxelib git hxvm-luajit https://github.com/KadeDev/hxvm-luajit - haxelib run lime rebuild extension-webm windows - haxelib install linc_luajit - haxelib install actuate diff --git a/assets/preload/data/tutorial/modchart.lua b/assets/preload/data/tutorial/modchart.lua index 4db18f0eda..71a33b8a3c 100644 --- a/assets/preload/data/tutorial/modchart.lua +++ b/assets/preload/data/tutorial/modchart.lua @@ -1,13 +1,21 @@ function start(song) -- do nothing - + spinLength = 0 end function update(elapsed) + if difficulty == 2 and curStep > 400 then + if spinLength < 32 then + spinLength = spinLength + 0.2 + end + + local currentBeat = (songPos / 1000)*(bpm/60) - for i=0,7 do - setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i) - setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i) + for i=0,7,1 do + local receptor = _G['receptor_'..i] + receptor.angle = (spinLength / 7) * -math.sin((currentBeat + i*0.25) * math.pi) + receptor.x = receptor.defaultX + spinLength * math.sin((currentBeat + i*0.25) * math.pi) + receptor.y = receptor.defaultY + spinLength * math.cos((currentBeat + i*0.25) * math.pi) end end end @@ -21,9 +29,9 @@ function stepHit(step) -- do nothing end function playerTwoTurn() - tweenCameraZoom(1.3,(crochet * 4) / 1000) + camGame.tweenZoom(camGame,1.3,(crochet * 4) / 1000) end function playerOneTurn() - tweenCameraZoom(1,(crochet * 4) / 1000) + camGame.tweenZoom(camGame,1,(crochet * 4) / 1000) end \ No newline at end of file diff --git a/docs/building.md b/docs/building.md index 806c8f3154..62f29cb69b 100644 --- a/docs/building.md +++ b/docs/building.md @@ -36,13 +36,9 @@ If you are planning to build for Windows, you also need to install **Visual Studio 2019**. While installing it, *don't click on any of the options to install workloads*. Instead, go to the **individual components** tab and choose the following: - MSVC v142 - VS 2019 C++ x64/x86 build tools -- MSVC v141 - VS 2017 C++ x64/x86 build tools - Windows SDK (10.0.17763.0) -- C++ Profiling tools -- C++ CMake tools for windows -- C++ ATL for v142 build tools (x86 & x64) -This will install about 7 GB of crap, but is necessary to build for Windows. +This will install about 4 GB of crap, but is necessary to build for Windows. ### macOS-only dependencies (these are required for building on macOS at all, including html5.) If you are running macOS, you'll need to install Xcode. You can download it from the macOS App Store or from the [Xcode website](https://developer.apple.com/xcode/). diff --git a/docs/changelogs/changelog-1.7.md b/docs/changelogs/changelog-1.7.md new file mode 100644 index 0000000000..43cd0e5167 --- /dev/null +++ b/docs/changelogs/changelog-1.7.md @@ -0,0 +1,29 @@ +# Latest (master) changelog/Changelog + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- 💖 A speed modifier (To use, press shift-left/right in freeplay or the charter. Does not work on modcharts.) + +### Changes +- Relocated all of the stage code into it's own file +- 💖 Completely redid all of modcharting (docs can be found [here](https://github.com/KadeDev/Kade-Engine/wiki)) +- Removed replay functionality due to it being a peice of shit and never working and causing issues and problems all the time. +- 💖 Optimized a lot of code to run better +- 💖 Allowed numpad to be binded as a key +- Optimized rating code to be faster +- Removed debug code from release builds for faster execution +- Binding a key to an already binded key no longer sets the other as null +- When beat quant colors are enabled, your key presses are highlighted in the color you hit instead of the original color. +- Removed beat base idle animations for characters +- Changed beat quant colors to. 4th = red, 8th = blue, green = 12th, purple = 16th+ +- 💖 Changed the editor to work entirely on beats +- Changed the BPM change code to work on beats instead of timestamps +- Removed a lot of unnecessary code. +- Changed **scroll speed** change events to be **based on multipliers instead of constant values** (aka 2 scroll speed would be scrollSpeed * 2 instead of setting it to 2) + +### Bugfixes +- 💖 Fix multiplie crashes with story mode and other weeks in story mode +- 💖 Fix desyncs with bpm changes and section notes in the charter +- Fix snap working in the charter (it's way more accurate now) +- Fixed crashing on a song that has a modchart at the end. diff --git a/docs/changelogs/index.md b/docs/changelogs/index.md index b85d9e07ca..923beb7a79 100644 --- a/docs/changelogs/index.md +++ b/docs/changelogs/index.md @@ -1,6 +1,7 @@ # Changelogs - [Latest](latest) (Contains changes that are not in a release yet) +- [1.7](changelog-1.7) - [1.6.2](changelog-1.6.2) - [1.6.1](changelog-1.6.1) - [1.6](changelog-1.6) diff --git a/source/BackgroundDancer.hx b/source/BackgroundDancer.hx index 99a83dff18..38978c91d1 100644 --- a/source/BackgroundDancer.hx +++ b/source/BackgroundDancer.hx @@ -15,6 +15,8 @@ class BackgroundDancer extends FlxSprite animation.addByIndices('danceRight', 'bg dancer sketch PINK', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); animation.play('danceLeft'); antialiasing = FlxG.save.data.antialiasing; + + } var danceDir:Bool = false; diff --git a/source/Caching.hx b/source/Caching.hx index 9160f8e1d1..2d9f28ff6a 100644 --- a/source/Caching.hx +++ b/source/Caching.hx @@ -152,6 +152,7 @@ class Caching extends MusicBeatState function cache() { + #if !linux trace("LOADING: " + toBeDone + " OBJECTS."); for (i in images) @@ -181,6 +182,7 @@ class Caching extends MusicBeatState trace(Assets.cache.hasBitmapData('GF_assets')); + #end FlxG.switchState(new TitleState()); } diff --git a/source/Character.hx b/source/Character.hx index 542b868813..7e1328065d 100644 --- a/source/Character.hx +++ b/source/Character.hx @@ -382,7 +382,7 @@ class Character extends FlxSprite dance(); - if (isPlayer) + if (isPlayer && frames != null) { flipX = !flipX; diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 39c5c01086..ebad6da9e5 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -44,6 +44,9 @@ import openfl.events.IOErrorEvent; import openfl.media.Sound; import openfl.net.FileReference; import openfl.utils.ByteArray; +#if windows +import Discord.DiscordClient; +#end using StringTools; @@ -65,6 +68,8 @@ class ChartingState extends MusicBeatState public static var lengthInSteps:Float = 0; public static var lengthInBeats:Float = 0; + public var speed = 1.0; + public var beatsShown:Float = 1; // for the zoom factor public var zoomFactor:Float = 0.4; @@ -160,8 +165,26 @@ class ChartingState extends MusicBeatState TimingStruct.clearTimings(); + + + if (PlayState.SONG != null) - _song = PlayState.SONG; + { + if (PlayState.isSM) + _song = Song.conversionChecks(Song.loadFromJsonRAW(File.getContent(PlayState.pathToSm + "/converted.json"))); + else + { + var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-"); + switch (songFormat) { + case 'Dad-Battle': songFormat = 'Dadbattle'; + case 'Philly-Nice': songFormat = 'Philly'; + } + + var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty); + + _song = Song.conversionChecks(Song.loadFromJson(poop, PlayState.SONG.song)); + } + } else { _song = { @@ -265,8 +288,12 @@ class ChartingState extends MusicBeatState lastSeg = seg; } + trace("STRUCTS: " + TimingStruct.AllTimings.length); + recalculateAllSectionTimes(); + + poggers(); trace("Song length in MS: " + FlxG.sound.music.length); @@ -429,32 +456,6 @@ class ChartingState extends MusicBeatState trace("create"); - TimingStruct.clearTimings(); - - var currentIndex = 0; - for (i in _song.eventObjects) - { - if (i.type == "BPM Change") - { - var beat:Float = i.position; - - var endBeat:Float = Math.POSITIVE_INFINITY; - - TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset - - if (currentIndex != 0) - { - 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; - } - - currentIndex++; - } - } super.create(); } @@ -558,8 +559,8 @@ class ChartingState extends MusicBeatState var check_snap:FlxUICheckBox; var listOfEvents:FlxUIDropDownMenu; var currentSelectedEventName:String = ""; - var savedType:String = ""; - var savedValue:String = ""; + var savedType:String = "BPM Change"; + var savedValue:String = "100"; var currentEventPosition:Float = 0; function containsName(name:String, events:Array):Song.Event @@ -652,7 +653,10 @@ class ChartingState extends MusicBeatState } if (pog.type == "BPM Change") + { recalculateAllSectionTimes(); + poggers(); + } regenerateLines(); @@ -743,6 +747,7 @@ class ChartingState extends MusicBeatState trace(i.bpm + " - START: " + i.startBeat + " - END: " + i.endBeat + " - START-TIME: " + i.startTime); recalculateAllSectionTimes(); + poggers(); regenerateLines(); @@ -825,6 +830,7 @@ class ChartingState extends MusicBeatState } recalculateAllSectionTimes(); + poggers(); regenerateLines(); @@ -1182,8 +1188,8 @@ class ChartingState extends MusicBeatState var check_mustHitSection:FlxUICheckBox; var check_changeBPM:FlxUICheckBox; var stepperSectionBPM:FlxUINumericStepper; - var check_p1AltAnim:FlxUICheckBox; - var check_p2AltAnim:FlxUICheckBox; + var check_CPUAltAnim:FlxUICheckBox; + var check_playerAltAnim:FlxUICheckBox; function addSectionUI():Void { @@ -1236,7 +1242,7 @@ class ChartingState extends MusicBeatState } } }); - check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100,null,function() { + check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to Player?", 100,null,function() { var sect = lastUpdatedSection; trace(sect); @@ -1267,11 +1273,11 @@ class ChartingState extends MusicBeatState check_mustHitSection.checked = true; // _song.needsVoices = check_mustHit.checked; - check_p1AltAnim = new FlxUICheckBox(10, 340, null, null, "P1 Alternate Animation", 100); - check_p1AltAnim.name = 'check_p1AltAnim'; + check_CPUAltAnim = new FlxUICheckBox(10, 340, null, null, "CPU Alternate Animation", 100); + check_CPUAltAnim.name = 'check_CPUAltAnim'; - check_p2AltAnim = new FlxUICheckBox(200, 340, null, null, "P2 Alternate Animation", 100); - check_p2AltAnim.name = 'check_p2AltAnim'; + check_playerAltAnim = new FlxUICheckBox(180, 340, null, null, "Player Alternate Animation", 100); + check_playerAltAnim.name = 'check_playerAltAnim'; var refresh = new FlxButton(10, 60, 'Refresh Section', function() { var section = getSectionByTime(Conductor.songPosition); @@ -1280,8 +1286,8 @@ class ChartingState extends MusicBeatState return; check_mustHitSection.checked = section.mustHitSection; - check_p1AltAnim.checked = section.p1AltAnim; - check_p2AltAnim.checked = section.p2AltAnim; + check_CPUAltAnim.checked = section.CPUAltAnim; + check_playerAltAnim.checked = section.playerAltAnim; }); var startSection:FlxButton = new FlxButton(10, 85, "Play Here", function() { @@ -1298,8 +1304,8 @@ class ChartingState extends MusicBeatState //tab_group_section.add(stepperCopy); //tab_group_section.add(stepperCopyLabel); tab_group_section.add(check_mustHitSection); - tab_group_section.add(check_p1AltAnim); - tab_group_section.add(check_p2AltAnim); + tab_group_section.add(check_CPUAltAnim); + tab_group_section.add(check_playerAltAnim); //tab_group_section.add(copyButton); tab_group_section.add(clearSectionButton); tab_group_section.add(swapSection); @@ -1403,12 +1409,12 @@ class ChartingState extends MusicBeatState { trace("new strum " + strum + " - at section " + section); // alright we're in this section lets paste the note here. - var newData = [strum,i[1],i[2]]; + var newData = [strum,i[1],i[2],i[3],i[4]]; ii.sectionNotes.push(newData); var thing = ii.sectionNotes[ii.sectionNotes.length - 1]; - var note:Note = new Note(strum, Math.floor(i[1] % 4),null,false,true); + var note:Note = new Note(strum, Math.floor(i[1] % 4),null,false,true,i[3], i[4]); note.rawNoteData = i[1]; note.sustainLength = i[2]; note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); @@ -1466,6 +1472,21 @@ class ChartingState extends MusicBeatState FlxG.sound.playMusic(Paths.inst(daSong), 0.6); #end + if (PlayState.isSM) + _song = Song.conversionChecks(Song.loadFromJsonRAW(File.getContent(PlayState.pathToSm + "/converted.json"))); + else + { + var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-"); + switch (songFormat) { + case 'Dad-Battle': songFormat = 'Dadbattle'; + case 'Philly-Nice': songFormat = 'Philly'; + } + + var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty); + + _song = Song.conversionChecks(Song.loadFromJson(poop, PlayState.SONG.song)); + } + // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER #if sys if (PlayState.isSM) @@ -1516,10 +1537,10 @@ class ChartingState extends MusicBeatState var label = check.getLabel().text; switch (label) { - case "P1 Alternate Animation": - getSectionByTime(Conductor.songPosition).p1AltAnim = check.checked; - case "P2 Alternate Animation": - getSectionByTime(Conductor.songPosition).p2AltAnim = check.checked; + case "CPU Alternate Animation": + getSectionByTime(Conductor.songPosition).CPUAltAnim = check.checked; + case "Player Alternate Animation": + getSectionByTime(Conductor.songPosition).playerAltAnim = check.checked; } } else if (id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) @@ -1549,7 +1570,54 @@ class ChartingState extends MusicBeatState if (_song.eventObjects[0].type != "BPM Change") Application.current.window.alert("i'm crying, first event isn't a bpm change. fuck you"); else + { _song.eventObjects[0].value = nums.value; + regenerateLines(); + } + + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + trace(i.type); + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + 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; + } + + currentIndex++; + } + } + trace("BPM CHANGES:"); + + for (i in TimingStruct.AllTimings) + trace(i.bpm + " - START: " + i.startBeat + " - END: " + i.endBeat + " - START-TIME: " + i.startTime); + + recalculateAllSectionTimes(); + + regenerateLines(); + + poggers(); + case 'note_susLength': if (curSelectedNote == null) return; @@ -1596,7 +1664,73 @@ class ChartingState extends MusicBeatState return getSectionByTime(Conductor.songPosition).lengthInSteps; }*/ - + function poggers() + { + var notes = []; + + for(section in _song.notes) + { + + var removed = []; + + for(note in section.sectionNotes) + { + // commit suicide + var old = note[0]; + note[0] = TimingStruct.getTimeFromBeat(note[4]); + note[2] = TimingStruct.getTimeFromBeat(TimingStruct.getBeatFromTime(note[2])); + if (note[0] < section.startTime) + { + notes.push(note); + removed.push(note); + } + if (note[0] > section.endTime) + { + notes.push(note); + removed.push(note); + } + } + + for(i in removed) + { + section.sectionNotes.remove(i); + } + } + + for(section in _song.notes) + { + + var saveRemove = []; + + for(i in notes) + { + if (i[0] >= section.startTime && i[0] < section.endTime) + { + saveRemove.push(i); + section.sectionNotes.push(i); + } + } + + for(i in saveRemove) + notes.remove(i); + } + + for(i in curRenderedNotes) + { + i.strumTime = TimingStruct.getTimeFromBeat(i.beat); + i.y = Math.floor(getYfromStrum(i.strumTime) * zoomFactor); + i.sustainLength = TimingStruct.getTimeFromBeat(TimingStruct.getBeatFromTime(i.sustainLength)); + if (i.noteCharterObject != null) + { + i.noteCharterObject.y = i.y + 40; + i.noteCharterObject.makeGraphic(8,Math.floor((getYfromStrum(i.strumTime + i.sustainLength) * zoomFactor) - i.y),FlxColor.WHITE); + } + + } + + trace("FUCK YOU BITCH FUCKER CUCK SUCK BITCH " + _song.notes.length); + } + function stepStartTime(step):Float { @@ -1656,6 +1790,10 @@ class ChartingState extends MusicBeatState override function update(elapsed:Float) { updateHeads(); + + #if windows + DiscordClient.changePresence("Chart Editor", null, null, true); + #end for(i in sectionRenderes) { @@ -1674,6 +1812,26 @@ class ChartingState extends MusicBeatState shownNotes = []; + if (FlxG.sound.music != null) + { + if (FlxG.sound.music.playing) + { + @:privateAccess + { + lime.media.openal.AL.sourcef(FlxG.sound.music._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, speed); + try + { + lime.media.openal.AL.sourcef(vocals._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, speed); + } + catch(e) + { + // trace("failed to pitch vocals (probably cuz they don't exist)"); + } + + } + } + } + for(note in curRenderedNotes) { var diff = note.strumTime - Conductor.songPosition; @@ -1785,7 +1943,7 @@ class ChartingState extends MusicBeatState if (data != null) { - FlxG.sound.music.time = (data.startTime + ((beats - data.startBeat) / (bpm/60)) ) * 1000; + FlxG.sound.music.time = (data.startTime + ((beats - data.startBeat) / (bpm/60))) * 1000; } } else @@ -1799,10 +1957,25 @@ class ChartingState extends MusicBeatState } } - if (FlxG.keys.justPressed.RIGHT && !FlxG.keys.pressed.CONTROL) - goToSection(curSection + 1); - else if (FlxG.keys.justPressed.LEFT && !FlxG.keys.pressed.CONTROL) - goToSection(curSection - 1); + if (FlxG.keys.pressed.SHIFT) + { + if (FlxG.keys.justPressed.RIGHT) + speed += 0.1; + else if (FlxG.keys.justPressed.LEFT) + speed -= 0.1; + + if (speed > 3) + speed = 3; + if (speed <= 0.01) + speed = 0.1; + } + else + { + if (FlxG.keys.justPressed.RIGHT && !FlxG.keys.pressed.CONTROL) + goToSection(curSection + 1); + else if (FlxG.keys.justPressed.LEFT && !FlxG.keys.pressed.CONTROL) + goToSection(curSection - 1); + } if (FlxG.mouse.pressed && FlxG.keys.pressed.CONTROL) { @@ -1897,7 +2070,7 @@ class ChartingState extends MusicBeatState { copiedNotes = []; for(i in selectedBoxes.members) - copiedNotes.push([i.connectedNote.strumTime,i.connectedNote.rawNoteData,i.connectedNote.sustainLength,i.connectedNote.isAlt]); + copiedNotes.push([i.connectedNote.strumTime,i.connectedNote.rawNoteData,i.connectedNote.sustainLength,i.connectedNote.isAlt,i.connectedNote.beat]); var firstNote = copiedNotes[0][0]; @@ -2086,8 +2259,8 @@ class ChartingState extends MusicBeatState { lastUpdatedSection = weird; check_mustHitSection.checked = weird.mustHitSection; - check_p1AltAnim.checked = weird.p1AltAnim; - check_p2AltAnim.checked = weird.p2AltAnim; + check_CPUAltAnim.checked = weird.CPUAltAnim; + check_playerAltAnim.checked = weird.playerAltAnim; } } @@ -2108,7 +2281,9 @@ class ChartingState extends MusicBeatState + "\nCurStep: " + curStep + "\nZoom: " - + HelperFunctions.truncateFloat(zoomFactor,2); + + HelperFunctions.truncateFloat(zoomFactor,2) + + "\nSpeed: " + + HelperFunctions.truncateFloat(speed,1); var left = FlxG.keys.justPressed.ONE; @@ -2126,7 +2301,7 @@ class ChartingState extends MusicBeatState { curRenderedNotes.forEach(function(note:Note) { - if (strumLine.overlaps(note) && pressArray[Math.floor(Math.abs(note.noteData))]) + if (strumLine.overlaps(note) && pressArray[Math.floor(Math.abs(note.rawNoteData))]) { deleteNote(note); delete = true; @@ -2271,7 +2446,19 @@ class ChartingState extends MusicBeatState dummyArrow.x = Math.floor(FlxG.mouse.x / GRID_SIZE) * GRID_SIZE; - dummyArrow.y = (Math.floor(FlxG.mouse.y / (GRID_SIZE / deezNuts.get(snap))) * (GRID_SIZE / deezNuts.get(snap))); + if (doSnapShit) + { + var time = getStrumTime(FlxG.mouse.y / zoomFactor); + + var beat = TimingStruct.getBeatFromTime(time); + var snapped = Math.round(beat * deezNuts.get(snap)) / deezNuts.get(snap); + + dummyArrow.y = getYfromStrum(TimingStruct.getTimeFromBeat(snapped)) * zoomFactor; + } + else + { + dummyArrow.y = FlxG.mouse.y; + } } else { @@ -2303,7 +2490,11 @@ class ChartingState extends MusicBeatState if (FlxG.keys.justPressed.C && !FlxG.keys.pressed.CONTROL) { var sect = _song.notes[curSection]; + + trace(sect); + sect.mustHitSection = !sect.mustHitSection; + check_mustHitSection.checked = sect.mustHitSection; var i = sectionRenderes.members[curSection]; var cachedY = i.icon.y; remove(i.icon); @@ -2561,14 +2752,14 @@ class ChartingState extends MusicBeatState if (sec == null) { check_mustHitSection.checked = true; - check_p1AltAnim.checked = false; - check_p2AltAnim.checked = false; + check_CPUAltAnim.checked = false; + check_playerAltAnim.checked = false; } else { check_mustHitSection.checked = sec.mustHitSection; - check_p1AltAnim.checked = sec.p1AltAnim; - check_p2AltAnim.checked = sec.p2AltAnim; + check_CPUAltAnim.checked = sec.CPUAltAnim; + check_playerAltAnim.checked = sec.playerAltAnim; } } @@ -2638,7 +2829,7 @@ class ChartingState extends MusicBeatState var daStrumTime = i[0]; var daSus = i[2]; - var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true,i[3]); + var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true,i[3], i[4]); note.rawNoteData = daNoteInfo; note.sustainLength = daSus; note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); @@ -2697,8 +2888,8 @@ class ChartingState extends MusicBeatState sectionNotes: [], typeOfSection: 0, altAnim: false, - p1AltAnim: false, - p2AltAnim: false + CPUAltAnim: false, + playerAltAnim: false }; _song.notes.push(sec); @@ -2809,7 +3000,7 @@ class ChartingState extends MusicBeatState updateGrid(); } - private function newSection(lengthInSteps:Int = 16,mustHitSection:Bool = false,p1AltAnim:Bool = true, p2AltAnim:Bool = true):SwagSection + private function newSection(lengthInSteps:Int = 16,mustHitSection:Bool = false,CPUAltAnim:Bool = true, playerAltAnim:Bool = true):SwagSection { var daPos:Float = 0; @@ -2838,8 +3029,8 @@ class ChartingState extends MusicBeatState sectionNotes: [], typeOfSection: 0, altAnim: false, - p1AltAnim: p1AltAnim, - p2AltAnim: p2AltAnim + CPUAltAnim: CPUAltAnim, + playerAltAnim: playerAltAnim }; @@ -2849,28 +3040,10 @@ class ChartingState extends MusicBeatState function recalculateAllSectionTimes() { - /*if (TimingStruct.AllTimings.length > 0) - { - trace("Song length in MS: " + FlxG.sound.music.length); - - for(i in 0...9000000) // REALLY HIGH BEATS just cuz like ig this is the upper limit, I mean ur chart is probably going to run like ass anyways - { - var seg = TimingStruct.getTimingAtBeat(i); - - var time = (i / (seg.bpm / 60)) * 1000; - - if (time > FlxG.sound.music.length) - break; - - lengthInBeats = i; - } - - lengthInSteps = lengthInBeats * 4; + trace("RECALCULATING SECTION TIMES"); - trace('LENGTH IN STEPS ' + lengthInSteps + ' | LENGTH IN BEATS ' + lengthInBeats); - }*/ + var savedNotes:Array = []; - trace("RECALCULATING SECTION TIMES"); for (i in 0..._song.notes.length) // loops through sections { var section = _song.notes[i]; @@ -2889,12 +3062,9 @@ class ChartingState extends MusicBeatState if (i != 0) _song.notes[i - 1].endTime = section.startTime; section.endTime = Math.POSITIVE_INFINITY; - } - once = true; } - var once = false; function shiftNotes(measure:Int=0,step:Int=0,ms:Int = 0):Void @@ -2913,7 +3083,7 @@ class ChartingState extends MusicBeatState } for (daSection1 in 0..._song.notes.length) { - newSong.push(newSection(16,_song.notes[daSection1].mustHitSection,_song.notes[daSection1].p1AltAnim,_song.notes[daSection1].p2AltAnim)); + newSong.push(newSection(16,_song.notes[daSection1].mustHitSection,_song.notes[daSection1].CPUAltAnim,_song.notes[daSection1].playerAltAnim)); } for (daSection in 0...(_song.notes.length)) @@ -2921,8 +3091,8 @@ class ChartingState extends MusicBeatState var aimtosetsection = daSection+Std.int((totaladdsection)); if(aimtosetsection<0) aimtosetsection = 0; newSong[aimtosetsection].mustHitSection = _song.notes[daSection].mustHitSection; - newSong[aimtosetsection].p1AltAnim = _song.notes[daSection].p1AltAnim; - newSong[aimtosetsection].p2AltAnim = _song.notes[daSection].p2AltAnim; + newSong[aimtosetsection].CPUAltAnim = _song.notes[daSection].CPUAltAnim; + newSong[aimtosetsection].playerAltAnim = _song.notes[daSection].playerAltAnim; //trace("section "+daSection); for(daNote in 0...(_song.notes[daSection].sectionNotes.length)) { @@ -2999,9 +3169,9 @@ class ChartingState extends MusicBeatState var noteSus = 0; if (n != null) - section.sectionNotes.push([n.strumTime, n.noteData, n.sustainLength, false]); + section.sectionNotes.push([n.strumTime, n.noteData, n.sustainLength, false, TimingStruct.getBeatFromTime(n.strumTime)]); else - section.sectionNotes.push([noteStrum, noteData, noteSus, false]); + section.sectionNotes.push([noteStrum, noteData, noteSus, false, TimingStruct.getBeatFromTime(noteStrum)]); var thingy = section.sectionNotes[section.sectionNotes.length - 1]; @@ -3011,7 +3181,7 @@ class ChartingState extends MusicBeatState if (n == null) { - var note:Note = new Note(noteStrum, noteData % 4,null,false,true); + var note:Note = new Note(noteStrum, noteData % 4,null,false,true,TimingStruct.getBeatFromTime(noteStrum)); note.rawNoteData = noteData; note.sustainLength = noteSus; note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); @@ -3041,7 +3211,8 @@ class ChartingState extends MusicBeatState } else { - var note:Note = new Note(n.strumTime, n.noteData % 4,null,false,true, n.isAlt); + var note:Note = new Note(n.strumTime, n.noteData % 4,null,false,true, n.isAlt,TimingStruct.getBeatFromTime(n.strumTime)); + note.beat = TimingStruct.getBeatFromTime(n.strumTime); note.rawNoteData = n.noteData; note.sustainLength = noteSus; note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); diff --git a/source/ConvertScore.hx b/source/ConvertScore.hx index 9eba969fef..cd88854a0d 100644 --- a/source/ConvertScore.hx +++ b/source/ConvertScore.hx @@ -2,19 +2,7 @@ class ConvertScore { public static function convertScore(noteDiff:Float):Int { - var daRating:String = Ratings.CalculateRating(noteDiff, 166); - switch(daRating) - { - case 'shit': - return -300; - case 'bad': - return 0; - case 'good': - return 200; - case 'sick': - return 350; - } return 0; } diff --git a/source/DialogueBox.hx b/source/DialogueBox.hx index 07363c6f85..64107f5235 100644 --- a/source/DialogueBox.hx +++ b/source/DialogueBox.hx @@ -1,5 +1,6 @@ package; +import flixel.system.FlxSound; import flixel.FlxG; import flixel.FlxSprite; import flixel.addons.text.FlxTypeText; @@ -34,6 +35,8 @@ class DialogueBox extends FlxSpriteGroup var handSelect:FlxSprite; var bgFade:FlxSprite; + var sound:FlxSound; + public function new(talkingRight:Bool = true, ?dialogueList:Array) { super(); @@ -41,11 +44,15 @@ class DialogueBox extends FlxSpriteGroup switch (PlayState.SONG.song.toLowerCase()) { case 'senpai': - FlxG.sound.playMusic(Paths.music('Lunchbox'), 0); - FlxG.sound.music.fadeIn(1, 0, 0.8); + sound = new FlxSound().loadEmbedded(Paths.music('Lunchbox'),true); + sound.volume = 0; + FlxG.sound.list.add(sound); + sound.fadeIn(1, 0, 0.8); case 'thorns': - FlxG.sound.playMusic(Paths.music('LunchboxScary'), 0); - FlxG.sound.music.fadeIn(1, 0, 0.8); + sound = new FlxSound().loadEmbedded(Paths.music('LunchboxScary'),true); + sound.volume = 0; + FlxG.sound.list.add(sound); + sound.fadeIn(1, 0, 0.8); } bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), 0xFFB3DFd8); @@ -190,8 +197,7 @@ class DialogueBox extends FlxSpriteGroup isEnding = true; if (PlayState.SONG.song.toLowerCase() == 'senpai' || PlayState.SONG.song.toLowerCase() == 'thorns') - FlxG.sound.music.fadeOut(2.2, 0); - + sound.fadeOut(2.2, 0); new FlxTimer().start(0.2, function(tmr:FlxTimer) { box.alpha -= 1 / 5; diff --git a/source/DiffCalc.hx b/source/DiffCalc.hx index 608fb05f3c..91bf3298d0 100644 --- a/source/DiffCalc.hx +++ b/source/DiffCalc.hx @@ -40,9 +40,9 @@ class DiffCalc var gottaHitNote:Bool = i.mustHitSection; if (ii[1] >= 3 && gottaHitNote) - cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); + cleanedNotes.push(new SmallNote(ii[0] / FreeplayState.rate,Math.floor(Math.abs(ii[1])))); if (ii[1] <= 4 && !gottaHitNote) - cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); + cleanedNotes.push(new SmallNote(ii[0] / FreeplayState.rate,Math.floor(Math.abs(ii[1])))); } } diff --git a/source/EtternaFunctions.hx b/source/EtternaFunctions.hx index 9fcfbaea9d..126269a4fa 100644 --- a/source/EtternaFunctions.hx +++ b/source/EtternaFunctions.hx @@ -65,7 +65,7 @@ class EtternaFunctions var max_points = 1.0; var miss_weight = -5.5; var ridic= 5 * ts; - var max_boo_weight = 180 * ts; + var max_boo_weight = 166 * (ts / PlayState.songMultiplier); var ts_pow = 0.75; var zero = 65 * (Math.pow(ts,ts_pow)); var power = 2.5; diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index d4372e07e2..daf1c886bf 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -32,6 +32,9 @@ class FreeplayState extends MusicBeatState public static var songs:Array = []; var selector:FlxText; + + public static var rate:Float = 1.0; + public static var curSelected:Int = 0; public static var curDifficulty:Int = 1; @@ -136,7 +139,7 @@ class FreeplayState extends MusicBeatState { if (file.contains(" ")) FileSystem.rename("assets/sm/" + i + "/" + file,"assets/sm/" + i + "/" + file.replace(" ","_")); - if (file.endsWith(".sm")) + if (file.endsWith(".sm") && !FileSystem.exists("assets/sm/" + i + "/converted.json")) { trace("reading " + file); var file:SMFile = SMFile.loadFile("assets/sm/" + i + "/" + file.replace(" ","_")); @@ -147,6 +150,18 @@ class FreeplayState extends MusicBeatState var song = Song.loadFromJsonRAW(data); songData.set(file.header.TITLE, [song,song,song]); } + else if (FileSystem.exists("assets/sm/" + i + "/converted.json") && file.endsWith(".sm")) + { + trace("reading " + file); + var file:SMFile = SMFile.loadFile("assets/sm/" + i + "/" + file.replace(" ","_")); + trace("Converting " + file.header.TITLE); + var data = file.convertToFNF("assets/sm/" + i + "/converted.json"); + var meta = new SongMetadata(file.header.TITLE, 0, "sm",file,"assets/sm/" + i); + songs.push(meta); + var song = Song.loadFromJsonRAW(File.getContent("assets/sm/" + i + "/converted.json")); + trace("got content lol"); + songData.set(file.header.TITLE, [song,song,song]); + } } } } @@ -210,7 +225,7 @@ class FreeplayState extends MusicBeatState scoreText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT); // scoreText.alignment = RIGHT; - var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 105, 0xFF000000); + var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 135, 0xFF000000); scoreBG.alpha = 0.6; add(scoreBG); @@ -222,9 +237,9 @@ class FreeplayState extends MusicBeatState diffCalcText.font = scoreText.font; add(diffCalcText); - previewtext = new FlxText(scoreText.x, scoreText.y + 94, 0, "" + (KeyBinds.gamepad ? "X" : "SPACE") + " to preview", 24); + previewtext = new FlxText(scoreText.x, scoreText.y + 94, 0, "Rate: " + rate + "x", 24); previewtext.font = scoreText.font; - //add(previewtext); + add(previewtext); comboText = new FlxText(diffText.x + 100, diffText.y, 0, "", 24); comboText.font = diffText.font; @@ -349,10 +364,48 @@ class FreeplayState extends MusicBeatState //if (FlxG.keys.justPressed.SPACE && !openedPreview) //openSubState(new DiffOverview()); - if (FlxG.keys.justPressed.LEFT) - changeDiff(-1); - if (FlxG.keys.justPressed.RIGHT) - changeDiff(1); + if (FlxG.keys.pressed.SHIFT) + { + if (FlxG.keys.justPressed.LEFT) + { + rate -= 0.05; + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + } + if (FlxG.keys.justPressed.RIGHT) + { + rate += 0.05; + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + } + + if (rate > 3) + { + rate = 3; + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + } + else if (rate < 0.5) + { + rate = 0.5; + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + } + + previewtext.text = "Rate: " + rate + "x"; + } + else + { + if (FlxG.keys.justPressed.LEFT) + changeDiff(-1); + if (FlxG.keys.justPressed.RIGHT) + changeDiff(1); + } + + + #if cpp + @:privateAccess + { + if (FlxG.sound.music.playing) + lime.media.openal.AL.sourcef(FlxG.sound.music._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, rate); + } + #end if (controls.BACK) { @@ -398,7 +451,11 @@ class FreeplayState extends MusicBeatState #else PlayState.isSM = false; #end + + PlayState.songMultiplier = rate; + LoadingState.loadAndSwitchState(new PlayState()); + clean(); } } diff --git a/source/GameOverSubstate.hx b/source/GameOverSubstate.hx index 182ce8c79f..798feb170d 100644 --- a/source/GameOverSubstate.hx +++ b/source/GameOverSubstate.hx @@ -16,9 +16,9 @@ class GameOverSubstate extends MusicBeatSubstate public function new(x:Float, y:Float) { - var daStage = PlayState.curStage; + var daStage = PlayState.Stage.curStage; var daBf:String = ''; - switch (PlayState.SONG.player1) + switch (PlayState.boyfriend.curCharacter) { case 'bf-pixel': stageSuffix = '-pixel'; diff --git a/source/HitGraph.hx b/source/HitGraph.hx index 169d823197..4b9ed586b9 100644 --- a/source/HitGraph.hx +++ b/source/HitGraph.hx @@ -38,6 +38,8 @@ class HitGraph extends Sprite public var bitmap:Bitmap; + public var ts:Float; + var _axis:Shape; var _width:Int; var _height:Int; @@ -60,7 +62,7 @@ class HitGraph extends Sprite _axis = new Shape(); _axis.x = _labelWidth + 10; - var ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166; + ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166; var early = createTextField(10,10,FlxColor.WHITE,12); var late = createTextField(10,_height - 20,FlxColor.WHITE,12); @@ -157,35 +159,35 @@ class HitGraph extends Sprite gfx.lineStyle(1, graphColor, 1); gfx.beginFill(0x00FF00); - drawJudgementLine(45); + drawJudgementLine(45 ); gfx.endFill(); gfx.beginFill(0xFF0000); - drawJudgementLine(90); + drawJudgementLine(90 ); gfx.endFill(); gfx.beginFill(0x8b0000); - drawJudgementLine(135); + drawJudgementLine(135 ); gfx.endFill(); gfx.beginFill(0x580000); - drawJudgementLine(166); + drawJudgementLine(166 ); gfx.endFill(); gfx.beginFill(0x00FF00); - drawJudgementLine(-45); + drawJudgementLine(-45 ); gfx.endFill(); gfx.beginFill(0xFF0000); - drawJudgementLine(-90); + drawJudgementLine(-90 ); gfx.endFill(); gfx.beginFill(0x8b0000); - drawJudgementLine(-135); + drawJudgementLine(-135 ); gfx.endFill(); gfx.beginFill(0x580000); - drawJudgementLine(-166); + drawJudgementLine(-166 ); gfx.endFill(); var range:Float = Math.max(maxValue - minValue, maxValue * 0.1); @@ -233,7 +235,7 @@ class HitGraph extends Sprite default: gfx.beginFill(0xFFFFFF); } - var pointY = (-value * _height - 1) + _height; + var pointY = ((-value * _height - 1) + _height); /*if (i == 0) gfx.moveTo(graphX, _axis.y + pointY);*/ diff --git a/source/KadeEngineData.hx b/source/KadeEngineData.hx index 9556ed3daf..2fc7cc5354 100644 --- a/source/KadeEngineData.hx +++ b/source/KadeEngineData.hx @@ -73,7 +73,10 @@ class KadeEngineData if (FlxG.save.data.distractions == null) FlxG.save.data.distractions = true; - if (FlxG.save.data.stepMania == null) + if (FlxG.save.data.colour == null) + FlxG.save.data.colour = true; + + if (FlxG.save.data.stepMania == null) FlxG.save.data.stepMania = false; if (FlxG.save.data.flashing == null) @@ -130,4 +133,4 @@ class KadeEngineData (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap); } -} \ No newline at end of file +} diff --git a/source/KeyBindMenu.hx b/source/KeyBindMenu.hx index e7efdc82ee..12d1a5e35f 100644 --- a/source/KeyBindMenu.hx +++ b/source/KeyBindMenu.hx @@ -180,10 +180,13 @@ class KeyBindMenu extends FlxSubState } case "input": - tempKey = keys[curSelected]; - keys[curSelected] = "?"; - if (KeyBinds.gamepad) + if (KeyBinds.gamepad) { + tempKey = gpKeys[curSelected]; gpKeys[curSelected] = "?"; + } else { + tempKey = keys[curSelected]; + keys[curSelected] = "?"; + } textUpdate(); state = "waiting"; @@ -322,12 +325,15 @@ class KeyBindMenu extends FlxSubState var shouldReturn:Bool = true; var notAllowed:Array = ["START"]; + var swapKey:Int = -1; for(x in 0...gpKeys.length) { var oK = gpKeys[x]; - if(oK == r) + if(oK == r) { + swapKey = x; gpKeys[x] = null; + } if (notAllowed.contains(oK)) { gpKeys[x] = null; @@ -336,7 +342,17 @@ class KeyBindMenu extends FlxSubState } } + if (notAllowed.contains(r)) + { + gpKeys[curSelected] = tempKey; + lastKey = r; + return; + } + if(shouldReturn){ + if (swapKey != -1) { + gpKeys[swapKey] = tempKey; + } gpKeys[curSelected] = r; FlxG.sound.play(Paths.sound('scrollMenu')); } @@ -354,6 +370,7 @@ class KeyBindMenu extends FlxSubState var shouldReturn:Bool = true; var notAllowed:Array = []; + var swapKey:Int = -1; for(x in blacklist){notAllowed.push(x);} @@ -362,8 +379,10 @@ class KeyBindMenu extends FlxSubState for(x in 0...keys.length) { var oK = keys[x]; - if(oK == r) + if(oK == r) { + swapKey = x; keys[x] = null; + } if (notAllowed.contains(oK)) { keys[x] = null; @@ -372,9 +391,9 @@ class KeyBindMenu extends FlxSubState } } - if (r.contains("NUMPAD")) + if (notAllowed.contains(r)) { - keys[curSelected] = null; + keys[curSelected] = tempKey; lastKey = r; return; } @@ -382,6 +401,10 @@ class KeyBindMenu extends FlxSubState lastKey = ""; if(shouldReturn){ + // Swap keys instead of setting the other one as null + if (swapKey != -1) { + keys[swapKey] = tempKey; + } keys[curSelected] = r; FlxG.sound.play(Paths.sound('scrollMenu')); } diff --git a/source/KeyBinds.hx b/source/KeyBinds.hx index b9c704d212..7813db5861 100644 --- a/source/KeyBinds.hx +++ b/source/KeyBinds.hx @@ -35,26 +35,18 @@ class KeyBinds FlxG.save.data.upBind = "W"; trace("No UP"); } - if (StringTools.contains(FlxG.save.data.upBind,"NUMPAD")) - FlxG.save.data.upBind = "W"; if(FlxG.save.data.downBind == null){ FlxG.save.data.downBind = "S"; trace("No DOWN"); } - if (StringTools.contains(FlxG.save.data.downBind,"NUMPAD")) - FlxG.save.data.downBind = "S"; if(FlxG.save.data.leftBind == null){ FlxG.save.data.leftBind = "A"; trace("No LEFT"); } - if (StringTools.contains(FlxG.save.data.leftBind,"NUMPAD")) - FlxG.save.data.leftBind = "A"; if(FlxG.save.data.rightBind == null){ FlxG.save.data.rightBind = "D"; trace("No RIGHT"); } - if (StringTools.contains(FlxG.save.data.rightBind,"NUMPAD")) - FlxG.save.data.rightBind = "D"; if(FlxG.save.data.gpupBind == null){ FlxG.save.data.gpupBind = "DPAD_UP"; diff --git a/source/LuaClass.hx b/source/LuaClass.hx new file mode 100644 index 0000000000..375054d1f4 --- /dev/null +++ b/source/LuaClass.hx @@ -0,0 +1,1789 @@ +import flixel.FlxG; +import llua.Convert; +import llua.Lua; +import llua.State; +import llua.LuaL; +import flixel.util.FlxAxes; +import flixel.FlxSprite; +import lime.app.Application; +import openfl.Lib; +import sys.io.File; +import flash.display.BitmapData; +import sys.FileSystem; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.FlxCamera; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import haxe.DynamicAccess; + +// completely yoinked from andromeda (thats what you get for stealing my callback inputs you fuckers /j) + +typedef LuaProperty = { + var defaultValue:Any; + var getter:(State,Any)->Int; + var setter:State->Int; +} + +class LuaStorage { + public static var ListOfCameras:Array = []; + public static var objectProperties:Map> = []; + public static var objects:Map = []; +} + +class LuaClass { + public var properties:Map = []; + public var methods:MapInt> > = []; + public var className:String = "BaseClass"; + private static var state:State; + public var addToGlobal:Bool=true; + public function Register(l:State){ + Lua.newtable(l); + state=l; + LuaStorage.objectProperties[className]=this.properties; + + var classIdx = Lua.gettop(l); + Lua.pushvalue(l,classIdx); + if(addToGlobal) + Lua.setglobal(l,className); + + for (k in methods.keys()){ + Lua.pushcfunction(l,methods[k]); + Lua.setfield(l,classIdx,k); + } + + LuaL.newmetatable(l,className + "Metatable"); + var mtIdx = Lua.gettop(l); + Lua.pushstring(l, "__index"); + Lua.pushcfunction(l,cpp.Callable.fromStaticFunction(index)); + Lua.settable(l, mtIdx); + + Lua.pushstring(l, "__newindex"); + Lua.pushcfunction(l,cpp.Callable.fromStaticFunction(newindex)); + Lua.settable(l, mtIdx); + + for (k in properties.keys()){ + Lua.pushstring(l,k + "PropertyData"); + Convert.toLua(l,properties[k].defaultValue); + Lua.settable(l,mtIdx); + } + Lua.pushstring(l,"_CLASSNAME"); + Lua.pushstring(l,className); + Lua.settable(l,mtIdx); + + Lua.pushstring(l,"__metatable"); + Lua.pushstring(l,"This metatable is locked."); + Lua.settable(l,mtIdx); + + Lua.setmetatable(l,classIdx); + + }; + + + public static function index(l:StatePointer):Int{ + var l = state; + var index = Lua.tostring(l,-1); + if(Lua.getmetatable(l,-2)!=0){ + var mtIdx = Lua.gettop(l); + Lua.pushstring(l,index + "PropertyData"); + Lua.rawget(l,mtIdx); + var data:Any = Convert.fromLua(l,-1); + if(data!=null){ + Lua.pushstring(l,"_CLASSNAME"); + Lua.rawget(l,mtIdx); + var clName = Lua.tostring(l,-1); + if(LuaStorage.objectProperties[clName]!=null && LuaStorage.objectProperties[clName][index]!=null){ + return LuaStorage.objectProperties[clName][index].getter(l,data); + } + }; + }else{ + // TODO: throw an error! + }; + return 0; + } + + public static function newindex(l:StatePointer):Int{ + var l = state; + var index = Lua.tostring(l,2); + if(Lua.getmetatable(l,1)!=0){ + var mtIdx = Lua.gettop(l); + Lua.pushstring(l,index + "PropertyData"); + Lua.rawget(l,mtIdx); + var data:Any = Convert.fromLua(l,-1); + if(data!=null){ + Lua.pushstring(l,"_CLASSNAME"); + Lua.rawget(l,mtIdx); + var clName = Lua.tostring(l,-1); + if(LuaStorage.objectProperties[clName]!=null && LuaStorage.objectProperties[clName][index]!=null){ + Lua.pop(l,2); + return LuaStorage.objectProperties[clName][index].setter(l); + } + }; + }else{ + // TODO: throw an error! + }; + return 0; + } + + public static function SetProperty(l:State,tableIndex:Int,key:String,value:Any){ + Lua.pushstring(l,key + "PropertyData"); + Convert.toLua(l,value); + Lua.settable(l,tableIndex ); + + Lua.pop(l,2); + } + + public static function DefaultSetter(l:State){ + var key = Lua.tostring(l,2); + + Lua.pushstring(l,key + "PropertyData"); + Lua.pushvalue(l,3); + Lua.settable(l,4); + + Lua.pop(l,2); + }; + public function new(){} +} + +class LuaNote extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + public var note:Note; + public function new(connectedNote:Note, index:Int){ + super(); + className= "note_" + index; + + note = connectedNote; + + properties=[ + "alpha"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.alpha); + return 1; + }, + setter: SetNumProperty + }, + + "angle"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.angle); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + + var angle = Lua.tonumber(l,3); + connectedNote.modAngle = angle; + + LuaClass.DefaultSetter(l); + return 0; + } + }, + + "strumTime"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.strumTime); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + // mf you can't modify this shit + return 0; + } + }, + + "data"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.noteData); + return 1; + }, + setter: SetNumProperty + }, + + "mustPress"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushboolean(l,connectedNote.mustPress); + return 1; + }, + setter: SetNumProperty + }, + + "beat"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.beat); + return 1; + }, + setter: SetNumProperty + }, + + "isSustain"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.rawNoteData); + return 1; + }, + setter: SetNumProperty + }, + + "isParent"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushboolean(l,connectedNote.isParent); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"isParent is read-only."); + return 0; + } + }, + + "getParent"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushstring(l,"note_" + connectedNote.parent.luaID); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"getParent is read-only."); + return 0; + } + }, + + "getChildren"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.newtable(l); + + for(i in 0...connectedNote.children.length) + { + var note = connectedNote.children[i]; + Lua.pushstring(l,"note_" + note.luaID); + Lua.rawseti(l, -2, i); + } + + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"getChildren is read-only."); + return 0; + } + }, + + "getSpotInline"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.spotInLine); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"spot in line is read-only."); + return 0; + } + }, + + "x"=> { + defaultValue: connectedNote.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.x); + return 1; + }, + setter: SetNumProperty + }, + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + } + }, + + "tweenAlpha"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAlphaC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAlpha is read-only."); + return 0; + } + }, + + "tweenAngle"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAngleC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAngle is read-only."); + return 0; + } + }, + + + "y"=> { + defaultValue: connectedNote.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedNote.y); + return 1; + }, + setter: SetNumProperty + } + + ]; + } + + + private static function findNote(time:Float,data:Int) + { + + for(i in PlayState.instance.notes) + { + if (i.strumTime == time && i.noteData == data) + { + return i; + } + } + return null; + } + + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"strumTime"); + var time = Lua.tonumber(state,-1); + Lua.getfield(state,1,"data"); + var data = Lua.tonumber(state,-1); + + var note = findNote(time,Math.floor(data)); + + if (note == null) + { + LuaL.error(state,"Failure to tween (couldn't find note " + time + ")"); + return 0; + + } + + FlxTween.tween(note,{x: xp,y:yp},time); + + return 0; + } + + private static function tweenAngle(l:StatePointer):Int{ + // 1 = self + // 2 = angle + // 3 = time + var nangle = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"strumTime"); + var time = Lua.tonumber(state,-1); + Lua.getfield(state,1,"data"); + var data = Lua.tonumber(state,-1); + + var note = findNote(time,Math.floor(data)); + + if (note == null) + { + LuaL.error(state,"Failure to tween (couldn't find note " + time + ")"); + return 0; + + } + + FlxTween.tween(note,{modAngle: nangle},time); + + return 0; + } + + private static function tweenAlpha(l:StatePointer):Int{ + // 1 = self + // 2 = alpha + // 3 = time + var nalpha = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"strumTime"); + var time = Lua.tonumber(state,-1); + Lua.getfield(state,1,"data"); + var data = Lua.tonumber(state,-1); + + var note = findNote(time,Math.floor(data)); + + if (note == null) + { + LuaL.error(state,"Failure to tween (couldn't find note " + time + ")"); + return 0; + + } + FlxTween.tween(note,{alpha: nalpha},time); + + return 0; + } + + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + private static var tweenAngleC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAngle); + private static var tweenAlphaC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAlpha); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + note.modifiedByLua = true; + Reflect.setProperty(note,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + } + } + + class LuaReceptor extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + public var sprite:StaticArrow; + public function new(connectedSprite:StaticArrow, name:String){ + super(); + var defaultY = connectedSprite.y; + var defaultX = connectedSprite.x; + var defaultAngle = connectedSprite.angle; + + sprite = connectedSprite; + + className= name; + + properties=[ + "alpha"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.alpha); + return 1; + }, + setter: SetNumProperty + }, + + "id"=>{ + defaultValue: name , + getter: function(l:State,data:Any):Int{ + Lua.pushstring(l,name); + return 1; + }, + setter: SetNumProperty + }, + + "angle"=>{ + defaultValue: 0 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.angle); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + + var angle = Lua.tonumber(l,3); + connectedSprite.modAngle = angle; + + LuaClass.DefaultSetter(l); + return 0; + } + }, + + "x"=> { + defaultValue: connectedSprite.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.x); + return 1; + }, + setter: SetNumProperty + }, + + + "y"=> { + defaultValue: connectedSprite.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.y); + return 1; + }, + setter: SetNumProperty + }, + + "defaultAngle"=>{ + defaultValue: defaultAngle , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,defaultAngle); + return 1; + }, + setter: SetNumProperty + }, + + "defaultX"=> { + defaultValue: defaultX, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,defaultX); + return 1; + }, + setter: SetNumProperty + }, + + + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + } + }, + + "tweenAlpha"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAlphaC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAlpha is read-only."); + return 0; + } + }, + + "tweenAngle"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAngleC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAngle is read-only."); + return 0; + } + }, + + + "defaultY"=> { + defaultValue: defaultY, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,defaultY); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + return 0; + } + } + + ]; + } + + private static function findReceptor(index:Int) + { + for(i in 0...PlayState.strumLineNotes.length) + { + if (index == i) + { + return PlayState.strumLineNotes.members[i]; + } + } + return null; + } + + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"id"); + var index = Std.parseInt(Lua.tostring(state,-1).split('_')[1]); + + var receptor = findReceptor(index); + + if (receptor == null) + { + LuaL.error(state,"Failure to tween (couldn't find receptor " + index + ")"); + return 0; + } + + FlxTween.tween(receptor,{x: xp,y:yp},time); + + return 0; + } + + private static function tweenAngle(l:StatePointer):Int{ + // 1 = self + // 2 = angle + // 3 = time + var nangle = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Std.parseInt(Lua.tostring(state,-1).split('_')[1]); + + var receptor = findReceptor(index); + + if (receptor == null) + { + LuaL.error(state,"Failure to tween (couldn't find receptor " + index + ")"); + return 0; + } + + FlxTween.tween(receptor,{modAngle: nangle},time); + + return 0; + } + + private static function tweenAlpha(l:StatePointer):Int{ + // 1 = self + // 2 = alpha + // 3 = time + var nalpha = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Std.parseInt(Lua.tostring(state,-1).split('_')[1]); + + var receptor = findReceptor(index); + + if (receptor == null) + { + LuaL.error(state,"Failure to tween (couldn't find receptor " + index + ")"); + return 0; + } + + FlxTween.tween(receptor,{alpha: nalpha},time); + + return 0; + } + + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + private static var tweenAngleC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAngle); + private static var tweenAlphaC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAlpha); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + + sprite.modifiedByLua = true; + + Reflect.setProperty(sprite,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + trace("Registered " + className); + } + } + + class LuaCamera extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + public var cam:FlxCamera; + + public function new(connectedCamera:FlxCamera, name:String){ + super(); + cam = connectedCamera; + + className= name; + + properties=[ + "alpha"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCamera.alpha); + return 1; + }, + setter: SetNumProperty + }, + + "angle"=>{ + defaultValue: 0 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCamera.angle); + return 1; + }, + setter: SetNumProperty + }, + + "x"=> { + defaultValue: connectedCamera.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCamera.x); + return 1; + }, + setter: SetNumProperty + }, + + + "y"=> { + defaultValue: connectedCamera.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCamera.y); + return 1; + }, + setter: SetNumProperty + }, + + "id"=> { + defaultValue: className, + getter: function(l:State,data:Any):Int{ + Lua.pushstring(l,className); + return 1; + }, + setter: SetNumProperty + }, + + "tweenZoom"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenZoomC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenZoom is read-only."); + return 0; + } + }, + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + } + }, + + "tweenAlpha"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAlphaC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAlpha is read-only."); + return 0; + } + }, + + "tweenAngle"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAngleC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAngle is read-only."); + return 0; + } + }, + ]; + + LuaStorage.ListOfCameras.push(this); + } + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + Reflect.setProperty(cam,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + private static function tweenZoom(l:StatePointer):Int{ + // 1 = self + // 2 = zoom + // 3 = time + var nzoom = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var camera:FlxCamera = null; + + for(i in LuaStorage.ListOfCameras) + { + if (i.className == index) + { + camera = i.cam; + } + } + + if (camera == null) + { + LuaL.error(state,"Failure to tween (couldn't find camera " + index + ")"); + return 0; + } + + FlxTween.tween(camera,{zoom: nzoom},time); + + return 0; + } + + private static var tweenZoomC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenZoom); + + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var camera:FlxCamera = null; + + for(i in LuaStorage.ListOfCameras) + { + if (i.className == index) + camera = i.cam; + } + + if (camera == null) + { + LuaL.error(state,"Failure to tween (couldn't find camera " + index + ")"); + return 0; + } + + FlxTween.tween(camera,{x: xp,y:yp},time); + + return 0; + } + + private static function tweenAngle(l:StatePointer):Int{ + // 1 = self + // 2 = angle + // 3 = time + var nangle = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var camera:FlxCamera = null; + + for(i in LuaStorage.ListOfCameras) + { + if (i.className == index) + camera = i.cam; + } + + if (camera == null) + { + LuaL.error(state,"Failure to tween (couldn't find camera " + index + ")"); + return 0; + } + + FlxTween.tween(camera,{modAngle: nangle},time); + + return 0; + } + + private static function tweenAlpha(l:StatePointer):Int{ + // 1 = self + // 2 = alpha + // 3 = time + var nalpha = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var camera:FlxCamera = null; + + for(i in LuaStorage.ListOfCameras) + { + if (i.className == index) + camera = i.cam; + } + + if (camera == null) + { + LuaL.error(state,"Failure to tween (couldn't find camera " + index + ")"); + return 0; + } + + FlxTween.tween(camera,{alpha: nalpha},time); + + return 0; + } + + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + private static var tweenAngleC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAngle); + private static var tweenAlphaC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAlpha); + + override function Register(l:State){ + state=l; + super.Register(l); + trace("Registered " + className); + } + + } + + class LuaCharacter extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + public var char:Character; + public var isPlayer:Bool = false; + + public static var ListOfCharacters:Array = []; + + public function new(connectedCharacter:Character, name:String){ + super(); + className= name; + + char = connectedCharacter; + + isPlayer = char.isPlayer; + + properties=[ + "alpha"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCharacter.alpha); + return 1; + }, + setter: SetNumProperty + }, + + "angle"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCharacter.angle); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + + var angle = Lua.tonumber(l,3); + connectedCharacter.angle = angle; + + LuaClass.DefaultSetter(l); + return 0; + } + }, + + "x"=> { + defaultValue: connectedCharacter.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCharacter.x); + return 1; + }, + setter: SetNumProperty + }, + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + } + }, + + "id"=>{ + defaultValue: name , + getter: function(l:State,data:Any):Int{ + Lua.pushstring(l,name); + return 1; + }, + setter: SetNumProperty + }, + + "tweenAlpha"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAlphaC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAlpha is read-only."); + return 0; + } + }, + + "tweenAngle"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAngleC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAngle is read-only."); + return 0; + } + }, + + "changeCharacter"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,changeCharacterC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"changeCharacter is read-only."); + return 0; + } + }, + + "playAnim"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,playAnimC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"playAnim is read-only."); + return 0; + } + }, + + "y"=> { + defaultValue: connectedCharacter.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedCharacter.y); + return 1; + }, + setter: SetNumProperty + } + + ]; + + ListOfCharacters.push(this); + } + + + private static function findNote(time:Float,data:Int) + { + + for(i in PlayState.instance.notes) + { + if (i.strumTime == time && i.noteData == data) + { + return i; + } + } + return null; + } + + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var char:Character = null; + + for(i in ListOfCharacters) + { + if (i.className == index) + char = i.char; + } + + if (char == null) + { + LuaL.error(state,"Failure to tween (couldn't find character " + index + ")"); + return 0; + } + + FlxTween.tween(char,{x: xp,y:yp},time); + + return 0; + } + + private static function tweenAngle(l:StatePointer):Int{ + // 1 = self + // 2 = angle + // 3 = time + var nangle = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var char:Character = null; + + for(i in ListOfCharacters) + { + if (i.className == index) + char = i.char; + } + + if (char == null) + { + LuaL.error(state,"Failure to tween (couldn't find character " + index + ")"); + return 0; + } + + FlxTween.tween(char,{angle: nangle},time); + + return 0; + } + + private static function tweenAlpha(l:StatePointer):Int{ + // 1 = self + // 2 = alpha + // 3 = time + var nalpha = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var char:Character = null; + + for(i in ListOfCharacters) + { + if (i.className == index) + char = i.char; + } + + if (char == null) + { + LuaL.error(state,"Failure to tween (couldn't find character " + index + ")"); + return 0; + } + + FlxTween.tween(char,{alpha: nalpha},time); + + return 0; + } + + private static function changeCharacter(l:StatePointer):Int{ + // 1 = self + // 2 = newName + // 3 = x + // 4 = y + var newName = LuaL.checkstring(state,2); + var x = LuaL.checknumber(state,3); + var y = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var char:Character = null; + var property:LuaCharacter = null; + + for(i in ListOfCharacters) + { + if (i.className == index) + { + char = i.char; + property = i; + } + } + + trace("fuck " + char); + + if (char == null) + { + LuaL.error(state,"Failure to tween (couldn't find character " + index + ")"); + return 0; + } + + + PlayState.instance.remove(char); + + PlayState.dad = new Character(x,y,newName,char.isPlayer); + + property.char = PlayState.dad; + + PlayState.instance.add(PlayState.dad); + + return 0; + } + + private static function playAnim(l:StatePointer):Int{ + // 1 = self + // 2 = animation + var anim = LuaL.checkstring(state,2); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var char:Character = null; + + for(i in ListOfCharacters) + { + if (i.className == index) + { + char = i.char; + } + } + + if (char == null) + { + LuaL.error(state,"Failure to tween (couldn't find character " + index + ")"); + return 0; + } + + char.playAnim(anim); + + return 0; + } + + private static var playAnimC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(playAnim); + private static var changeCharacterC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(changeCharacter); + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + private static var tweenAngleC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAngle); + private static var tweenAlphaC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAlpha); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + Reflect.setProperty(char,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + } + } + + class LuaSprite extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + public var sprite:FlxSprite; + + public static var ListOfSprites:Array = []; + + public function new(connectedSprite:FlxSprite, name:String){ + super(); + className= name; + + properties=[ + "alpha"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.alpha); + return 1; + }, + setter: SetNumProperty + }, + + "angle"=>{ + defaultValue: 1 , + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.angle); + return 1; + }, + setter: function(l:State):Int{ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + + var angle = Lua.tonumber(l,3); + connectedSprite.angle = angle; + + LuaClass.DefaultSetter(l); + return 0; + } + }, + + "x"=> { + defaultValue: connectedSprite.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.x); + return 1; + }, + setter: SetNumProperty + }, + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + } + }, + + "id"=>{ + defaultValue: name , + getter: function(l:State,data:Any):Int{ + Lua.pushstring(l,name); + return 1; + }, + setter: SetNumProperty + }, + + "tweenAlpha"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAlphaC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAlpha is read-only."); + return 0; + } + }, + + "tweenAngle"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenAngleC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenAngle is read-only."); + return 0; + } + }, + + "destroy"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,destroyC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"destroy is read-only."); + return 0; + } + }, + + "y"=> { + defaultValue: connectedSprite.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,connectedSprite.y); + return 1; + }, + setter: SetNumProperty + } + + ]; + + ListOfSprites.push(this); + } + + + private static function findNote(time:Float,data:Int) + { + + for(i in PlayState.instance.notes) + { + if (i.strumTime == time && i.noteData == data) + { + return i; + } + } + return null; + } + + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var sprite:FlxSprite = null; + + for(i in ListOfSprites) + { + if (i.className == index) + sprite = i.sprite; + } + + if (sprite == null) + { + LuaL.error(state,"Failure to tween (couldn't find sprite " + index + ")"); + return 0; + } + + FlxTween.tween(sprite,{x: xp,y:yp},time); + + return 0; + } + + private static function tweenAngle(l:StatePointer):Int{ + // 1 = self + // 2 = angle + // 3 = time + var nangle = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var sprite:FlxSprite = null; + + for(i in ListOfSprites) + { + if (i.className == index) + sprite = i.sprite; + } + + if (sprite == null) + { + LuaL.error(state,"Failure to tween (couldn't find sprite " + index + ")"); + return 0; + } + + FlxTween.tween(sprite,{angle: nangle},time); + + return 0; + } + + private static function tweenAlpha(l:StatePointer):Int{ + // 1 = self + // 2 = alpha + // 3 = time + var nalpha = LuaL.checknumber(state,2); + var time = LuaL.checknumber(state,3); + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var sprite:FlxSprite = null; + + for(i in ListOfSprites) + { + if (i.className == index) + sprite = i.sprite; + } + + if (sprite == null) + { + LuaL.error(state,"Failure to tween (couldn't find sprite " + index + ")"); + return 0; + } + + FlxTween.tween(sprite,{alpha: nalpha},time); + + return 0; + } + + + private static function destroy(l:StatePointer):Int{ + // 1 = self + + Lua.getfield(state,1,"id"); + var index = Lua.tostring(state,-1); + + var sprite:FlxSprite = null; + + for(i in ListOfSprites) + { + if (i.className == index) + sprite = i.sprite; + } + + if (sprite == null) + { + LuaL.error(state,"Failure to tween (couldn't find sprite " + index + ")"); + return 0; + } + + PlayState.instance.remove(sprite); + sprite.destroy(); + + return 0; + } + + private static var destroyC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(destroy); + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + private static var tweenAngleC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAngle); + private static var tweenAlphaC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenAlpha); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + Reflect.setProperty(sprite,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + } + } + + class LuaWindow extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + + public function new(){ + super(); + className= "Window"; + + properties=[ + "x"=> { + defaultValue: Application.current.window.x, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,Application.current.window.x); + return 1; + }, + setter: SetNumProperty + }, + + "y"=> { + defaultValue: Application.current.window.y, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,Application.current.window.y); + return 1; + }, + setter: SetNumProperty + }, + + + "width"=> { + defaultValue: Application.current.window.width, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,Application.current.window.width); + return 1; + }, + setter: SetNumProperty + }, + + "height"=> { + defaultValue: Application.current.window.height, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,Application.current.window.height); + return 1; + }, + setter: SetNumProperty + }, + + "tweenPos"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,tweenPosC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"tweenPos is read-only."); + return 0; + }, + + }, + ]; + + } + private static function tweenPos(l:StatePointer):Int{ + // 1 = self + // 2 = x + // 3 = y + // 4 = time + var xp = LuaL.checknumber(state,2); + var yp = LuaL.checknumber(state,3); + var time = LuaL.checknumber(state,4); + + FlxTween.tween(Application.current.window,{x: xp,y:yp},time); + + return 0; + } + + + private static var tweenPosC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(tweenPos); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + Reflect.setProperty(Application.current.window,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + } + } + + class LuaGame extends LuaClass { // again, stolen from andromeda but improved a lot for better thinking interoperability (I made that up) + private static var state:State; + + public function new(){ + super(); + className= "Game"; + + properties=[ + + "health"=> { + defaultValue: PlayState.instance.health, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,PlayState.instance.health); + return 1; + }, + setter: function(l:State):Int{ + PlayState.instance.health = Lua.tonumber(l,3); + return 0; + }, + }, + + "accuracy"=> { + defaultValue: PlayState.instance.accuracy, + getter: function(l:State,data:Any):Int{ + Lua.pushnumber(l,PlayState.instance.accuracy); + return 1; + }, + setter: SetNumProperty + }, + "changeStage"=>{ + defaultValue:0, + getter:function(l:State,data:Any){ + Lua.pushcfunction(l,changeStageC); + return 1; + }, + setter:function(l:State){ + LuaL.error(l,"changeStage is read-only."); + return 0; + }, + } + ]; + + } + + private static function changeStage(l:StatePointer):Int{ + // 1 = self + // 2 = stage + var stageName = LuaL.checkstring(state,2); + + for (i in PlayState.Stage.toAdd) + { + PlayState.instance.remove(i); + } + + PlayState.Stage = new Stage(stageName); + + for (i in PlayState.Stage.toAdd) + { + PlayState.instance.add(i); + } + + return 0; + } + + + private static var changeStageC:cpp.CallableInt> = cpp.Callable.fromStaticFunction(changeStage); + + private function SetNumProperty(l:State){ + // 1 = self + // 2 = key + // 3 = value + // 4 = metatable + if(Lua.type(l,3)!=Lua.LUA_TNUMBER){ + LuaL.error(l,"invalid argument #3 (number expected, got " + Lua.typename(l,Lua.type(l,3)) + ")"); + return 0; + } + Reflect.setProperty(Application.current.window,Lua.tostring(l,2),Lua.tonumber(l,3)); + return 0; + } + + override function Register(l:State){ + state=l; + super.Register(l); + } + } \ No newline at end of file diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index a1f39f8056..e4e91664e2 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.2" + nightly; + public static var kadeEngineVer:String = "1.7" + nightly; public static var gameVer:String = "0.2.7.1"; var magenta:FlxSprite; diff --git a/source/ModchartState.hx b/source/ModchartState.hx index 58215604f0..4339c3b70d 100644 --- a/source/ModchartState.hx +++ b/source/ModchartState.hx @@ -1,6 +1,11 @@ // this file is for modchart things, this is to declutter playstate.hx // Lua +import LuaClass.LuaGame; +import LuaClass.LuaWindow; +import LuaClass.LuaSprite; +import LuaClass.LuaCamera; +import LuaClass.LuaReceptor; import openfl.display3D.textures.VideoTexture; import flixel.graphics.FlxGraphic; import flixel.graphics.frames.FlxAtlasFrames; @@ -41,15 +46,14 @@ class ModchartState var p = Lua.tostring(lua,result); var e = getLuaErrorMessage(lua); + Lua.tostring(lua,-1); + if (e != null) { - if (p != null) - { - Application.current.window.alert("LUA ERROR:\n" + p + "\nhaxe things: " + e,"Kade Engine Modcharts"); - lua = null; - LoadingState.loadAndSwitchState(new MainMenuState()); - } - // trace('err: ' + e); + if (e != "attempt to call a nil value") + { + trace(StringTools.replace(e,"c++","haxe function")); + } } if( result == null) { return null; @@ -343,6 +347,9 @@ class ModchartState } } #end + + new LuaSprite(sprite,toBeCalled).Register(lua); + return toBeCalled; } @@ -356,599 +363,142 @@ class ModchartState // LUA SHIT - function new() + function new(? isStoryMode = true) { - trace('opening a lua state (because we are cool :))'); - lua = LuaL.newstate(); - LuaL.openlibs(lua); - trace("Lua version: " + Lua.version()); - trace("LuaJIT version: " + Lua.versionJIT()); - Lua.init_callbacks(lua); - - //shaders = new Array(); - - // pre lowercasing the song name (new) - var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase(); - switch (songLowercase) { - case 'dad-battle': songLowercase = 'dadbattle'; - case 'philly-nice': songLowercase = 'philly'; - } - - 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) - { - Application.current.window.alert("LUA COMPILE ERROR:\n" + Lua.tostring(lua,result),"Kade Engine Modcharts"); - lua = null; - LoadingState.loadAndSwitchState(new MainMenuState()); - } - - // get some fukin globals up in here bois - - setVar("difficulty", PlayState.storyDifficulty); - setVar("bpm", Conductor.bpm); - setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed); - setVar("fpsCap", FlxG.save.data.fpsCap); - setVar("downscroll", FlxG.save.data.downscroll); - setVar("flashing", FlxG.save.data.flashing); - setVar("distractions", FlxG.save.data.distractions); - - setVar("curStep", 0); - setVar("curBeat", 0); - setVar("crochet", Conductor.stepCrochet); - setVar("safeZoneOffset", Conductor.safeZoneOffset); - - setVar("hudZoom", PlayState.instance.camHUD.zoom); - setVar("cameraZoom", FlxG.camera.zoom); - - setVar("cameraAngle", FlxG.camera.angle); - setVar("camHudAngle", PlayState.instance.camHUD.angle); - - setVar("followXOffset",0); - setVar("followYOffset",0); - - setVar("showOnlyStrums", false); - setVar("strumLine1Visible", true); - setVar("strumLine2Visible", true); - - setVar("screenWidth",FlxG.width); - setVar("screenHeight",FlxG.height); - setVar("windowWidth",FlxG.width); - setVar("windowHeight",FlxG.height); - setVar("hudWidth", PlayState.instance.camHUD.width); - setVar("hudHeight", PlayState.instance.camHUD.height); - - setVar("mustHit", false); - - setVar("strumLineY", PlayState.instance.strumLine.y); - - // callbacks - - // sprites - - Lua_helper.add_callback(lua,"makeSprite", makeLuaSprite); - - Lua_helper.add_callback(lua,"changeDadCharacter", changeDadCharacter); - - Lua_helper.add_callback(lua,"changeBoyfriendCharacter", changeBoyfriendCharacter); - - 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 - - Lua_helper.add_callback(lua,"destroySprite", function(id:String) { - var sprite = luaSprites.get(id); - if (sprite == null) - return false; - PlayState.instance.removeObject(sprite); - return true; - }); - - // hud/camera - - Lua_helper.add_callback(lua,"initBackgroundVideo", function(videoName:String) { - trace('playing assets/videos/' + videoName + '.webm'); - PlayState.instance.backgroundVideo("assets/videos/" + videoName + ".webm"); - }); - - Lua_helper.add_callback(lua,"pauseVideo", function() { - if (!GlobalVideo.get().paused) - GlobalVideo.get().pause(); - }); - - Lua_helper.add_callback(lua,"resumeVideo", function() { - if (GlobalVideo.get().paused) - GlobalVideo.get().pause(); - }); - - Lua_helper.add_callback(lua,"restartVideo", function() { - GlobalVideo.get().restart(); - }); - - Lua_helper.add_callback(lua,"getVideoSpriteX", function() { - return PlayState.instance.videoSprite.x; - }); - - Lua_helper.add_callback(lua,"getVideoSpriteY", function() { - return PlayState.instance.videoSprite.y; - }); - - Lua_helper.add_callback(lua,"setVideoSpritePos", function(x:Int,y:Int) { - PlayState.instance.videoSprite.setPosition(x,y); - }); - - Lua_helper.add_callback(lua,"setVideoSpriteScale", function(scale:Float) { - PlayState.instance.videoSprite.setGraphicSize(Std.int(PlayState.instance.videoSprite.width * scale)); - }); - - Lua_helper.add_callback(lua,"setHudAngle", function (x:Float) { - PlayState.instance.camHUD.angle = x; - }); - - Lua_helper.add_callback(lua,"setHealth", function (heal:Float) { - PlayState.instance.health = heal; - }); - - Lua_helper.add_callback(lua,"setHudPosition", function (x:Int, y:Int) { - PlayState.instance.camHUD.x = x; - PlayState.instance.camHUD.y = y; - }); - - Lua_helper.add_callback(lua,"getHudX", function () { - return PlayState.instance.camHUD.x; - }); - - Lua_helper.add_callback(lua,"getHudY", function () { - return PlayState.instance.camHUD.y; - }); - - Lua_helper.add_callback(lua,"setCamPosition", function (x:Int, y:Int) { - FlxG.camera.x = x; - FlxG.camera.y = y; - }); - - Lua_helper.add_callback(lua,"getCameraX", function () { - return FlxG.camera.x; - }); - - Lua_helper.add_callback(lua,"getCameraY", function () { - return FlxG.camera.y; - }); - - Lua_helper.add_callback(lua,"setCamZoom", function(zoomAmount:Float) { - FlxG.camera.zoom = zoomAmount; - }); - - Lua_helper.add_callback(lua,"setHudZoom", function(zoomAmount:Float) { - PlayState.instance.camHUD.zoom = zoomAmount; - }); - - // strumline - - Lua_helper.add_callback(lua, "setStrumlineY", function(y:Float) - { - PlayState.instance.strumLine.y = y; - }); - - // actors - - Lua_helper.add_callback(lua,"getRenderedNotes", function() { - return PlayState.instance.notes.length; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteX", function(id:Int) { - return PlayState.instance.notes.members[id].x; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteY", function(id:Int) { - return PlayState.instance.notes.members[id].y; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteType", function(id:Int) { - return PlayState.instance.notes.members[id].noteData; - }); - - Lua_helper.add_callback(lua,"isSustain", function(id:Int) { - return PlayState.instance.notes.members[id].isSustainNote; - }); - - Lua_helper.add_callback(lua,"isParentSustain", function(id:Int) { - return PlayState.instance.notes.members[id].prevNote.isSustainNote; - }); - - - Lua_helper.add_callback(lua,"getRenderedNoteParentX", function(id:Int) { - return PlayState.instance.notes.members[id].prevNote.x; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteParentY", function(id:Int) { - return PlayState.instance.notes.members[id].prevNote.y; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteHit", function(id:Int) { - return PlayState.instance.notes.members[id].mustPress; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteCalcX", function(id:Int) { - if (PlayState.instance.notes.members[id].mustPress) - return PlayState.playerStrums.members[Math.floor(Math.abs(PlayState.instance.notes.members[id].noteData))].x; - return PlayState.strumLineNotes.members[Math.floor(Math.abs(PlayState.instance.notes.members[id].noteData))].x; - }); - - Lua_helper.add_callback(lua,"anyNotes", function() { - return PlayState.instance.notes.members.length != 0; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteStrumtime", function(id:Int) { - return PlayState.instance.notes.members[id].strumTime; - }); - - Lua_helper.add_callback(lua,"getRenderedNoteScaleX", function(id:Int) { - return PlayState.instance.notes.members[id].scale.x; - }); - - Lua_helper.add_callback(lua,"setRenderedNotePos", function(x:Float,y:Float, id:Int) { - if (PlayState.instance.notes.members[id] == null) - throw('error! you cannot set a rendered notes position when it doesnt exist! ID: ' + id); - else - { - PlayState.instance.notes.members[id].modifiedByLua = true; - PlayState.instance.notes.members[id].x = x; - PlayState.instance.notes.members[id].y = y; - } - }); - - Lua_helper.add_callback(lua,"setRenderedNoteAlpha", function(alpha:Float, id:Int) { - PlayState.instance.notes.members[id].modifiedByLua = true; - PlayState.instance.notes.members[id].alpha = alpha; - }); - - Lua_helper.add_callback(lua,"setRenderedNoteScale", function(scale:Float, id:Int) { - PlayState.instance.notes.members[id].modifiedByLua = true; - PlayState.instance.notes.members[id].setGraphicSize(Std.int(PlayState.instance.notes.members[id].width * scale)); - }); - - Lua_helper.add_callback(lua,"setRenderedNoteScale", function(scaleX:Int, scaleY:Int, id:Int) { - PlayState.instance.notes.members[id].modifiedByLua = true; - PlayState.instance.notes.members[id].setGraphicSize(scaleX,scaleY); - }); - - Lua_helper.add_callback(lua,"getRenderedNoteWidth", function(id:Int) { - return PlayState.instance.notes.members[id].width; - }); - - - Lua_helper.add_callback(lua,"setRenderedNoteAngle", function(angle:Float, id:Int) { - PlayState.instance.notes.members[id].modifiedByLua = true; - PlayState.instance.notes.members[id].angle = angle; - }); - - Lua_helper.add_callback(lua,"setActorX", function(x:Int,id:String) { - getActorByName(id).x = x; - }); - - Lua_helper.add_callback(lua,"setActorAccelerationX", function(x:Int,id:String) { - getActorByName(id).acceleration.x = x; - }); - - Lua_helper.add_callback(lua,"setActorDragX", function(x:Int,id:String) { - getActorByName(id).drag.x = x; - }); - - Lua_helper.add_callback(lua,"setActorVelocityX", function(x:Int,id:String) { - getActorByName(id).velocity.x = x; - }); - - Lua_helper.add_callback(lua,"playActorAnimation", function(id:String,anim:String,force:Bool = false,reverse:Bool = false) { - getActorByName(id).playAnim(anim, force, reverse); - }); - - Lua_helper.add_callback(lua,"setActorAlpha", function(alpha:Float,id:String) { - getActorByName(id).alpha = alpha; - }); - - Lua_helper.add_callback(lua,"setActorY", function(y:Int,id:String) { - getActorByName(id).y = y; - }); - - Lua_helper.add_callback(lua,"setActorAccelerationY", function(y:Int,id:String) { - getActorByName(id).acceleration.y = y; - }); - - Lua_helper.add_callback(lua,"setActorDragY", function(y:Int,id:String) { - getActorByName(id).drag.y = y; - }); - - Lua_helper.add_callback(lua,"setActorVelocityY", function(y:Int,id:String) { - getActorByName(id).velocity.y = y; - }); - - Lua_helper.add_callback(lua,"setActorAngle", function(angle:Int,id:String) { - getActorByName(id).angle = angle; - }); - - Lua_helper.add_callback(lua,"setActorScale", function(scale:Float,id:String) { - getActorByName(id).setGraphicSize(Std.int(getActorByName(id).width * scale)); - }); - - Lua_helper.add_callback(lua, "setActorScaleXY", function(scaleX:Float, scaleY:Float, id:String) - { - getActorByName(id).setGraphicSize(Std.int(getActorByName(id).width * scaleX), Std.int(getActorByName(id).height * scaleY)); - }); - - Lua_helper.add_callback(lua, "setActorFlipX", function(flip:Bool, id:String) - { - getActorByName(id).flipX = flip; - }); - - Lua_helper.add_callback(lua, "setActorFlipY", function(flip:Bool, id:String) - { - getActorByName(id).flipY = flip; - }); - - Lua_helper.add_callback(lua,"getActorWidth", function (id:String) { - return getActorByName(id).width; - }); - - Lua_helper.add_callback(lua,"getActorHeight", function (id:String) { - return getActorByName(id).height; - }); - - Lua_helper.add_callback(lua,"getActorAlpha", function(id:String) { - return getActorByName(id).alpha; - }); - - Lua_helper.add_callback(lua,"getActorAngle", function(id:String) { - return getActorByName(id).angle; - }); - - Lua_helper.add_callback(lua,"getActorX", function (id:String) { - return getActorByName(id).x; - }); - - Lua_helper.add_callback(lua,"getActorY", function (id:String) { - return getActorByName(id).y; - }); - - Lua_helper.add_callback(lua,"setWindowPos",function(x:Int,y:Int) { - Application.current.window.x = x; - Application.current.window.y = y; - }); - - Lua_helper.add_callback(lua,"getWindowX",function() { - return Application.current.window.x; - }); - - Lua_helper.add_callback(lua,"getWindowY",function() { - return Application.current.window.y; - }); - - Lua_helper.add_callback(lua,"resizeWindow",function(Width:Int,Height:Int) { - Application.current.window.resize(Width,Height); - }); - - Lua_helper.add_callback(lua,"getScreenWidth",function() { - return Application.current.window.display.currentMode.width; - }); - - Lua_helper.add_callback(lua,"getScreenHeight",function() { - return Application.current.window.display.currentMode.height; - }); - - Lua_helper.add_callback(lua,"getWindowWidth",function() { - return Application.current.window.width; - }); - - Lua_helper.add_callback(lua,"getWindowHeight",function() { - return Application.current.window.height; - }); - - - // tweens - - Lua_helper.add_callback(lua,"tweenCameraPos", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraAngle", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraZoom", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudPos", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudAngle", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudZoom", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPos", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosXAngle", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosYAngle", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenAngle", function(id:String, toAngle:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraPosOut", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraAngleOut", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraZoomOut", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudPosOut", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudAngleOut", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudZoomOut", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosOut", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosXAngleOut", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosYAngleOut", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenAngleOut", function(id:String, toAngle:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraPosIn", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraAngleIn", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenCameraZoomIn", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudPosIn", function(toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudAngleIn", function(toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenHudZoomIn", function(toZoom:Float, time:Float, onComplete:String) { - FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosIn", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosXAngleIn", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenPosYAngleIn", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenAngleIn", function(id:String, toAngle:Int, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenFadeIn", function(id:String, toAlpha:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - Lua_helper.add_callback(lua,"tweenFadeOut", function(id:String, toAlpha:Float, time:Float, onComplete:String) { - FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}}); - }); - - //forgot and accidentally commit to master branch - // shader - - /*Lua_helper.add_callback(lua,"createShader", function(frag:String,vert:String) { - var shader:LuaShader = new LuaShader(frag,vert); - - trace(shader.glFragmentSource); - - shaders.push(shader); - // if theres 1 shader we want to say theres 0 since 0 index and length returns a 1 index. - return shaders.length == 1 ? 0 : shaders.length; - }); - - - Lua_helper.add_callback(lua,"setFilterHud", function(shaderIndex:Int) { - PlayState.instance.camHUD.setFilters([new ShaderFilter(shaders[shaderIndex])]); - }); - - Lua_helper.add_callback(lua,"setFilterCam", function(shaderIndex:Int) { - FlxG.camera.setFilters([new ShaderFilter(shaders[shaderIndex])]); - });*/ - - // default strums - - for (i in 0...PlayState.strumLineNotes.length) { - var member = PlayState.strumLineNotes.members[i]; - trace(PlayState.strumLineNotes.members[i].x + " " + PlayState.strumLineNotes.members[i].y + " " + PlayState.strumLineNotes.members[i].angle + " | strum" + i); - //setVar("strum" + i + "X", Math.floor(member.x)); - setVar("defaultStrum" + i + "X", Math.floor(member.x)); - //setVar("strum" + i + "Y", Math.floor(member.y)); - setVar("defaultStrum" + i + "Y", Math.floor(member.y)); - //setVar("strum" + i + "Angle", Math.floor(member.angle)); - setVar("defaultStrum" + i + "Angle", Math.floor(member.angle)); - trace("Adding strum" + i); - } + trace('opening a lua state (because we are cool :))'); + lua = LuaL.newstate(); + LuaL.openlibs(lua); + trace("Lua version: " + Lua.version()); + trace("LuaJIT version: " + Lua.versionJIT()); + Lua.init_callbacks(lua); + + // shaders = new Array(); + + // pre lowercasing the song name (new) + var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase(); + switch (songLowercase) + { + case 'dad-battle': + songLowercase = 'dadbattle'; + case 'philly-nice': + songLowercase = 'philly'; + } + + 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) + { + Application.current.window.alert("LUA COMPILE ERROR:\n" + Lua.tostring(lua, result), "Kade Engine Modcharts"); + FlxG.switchState(new FreeplayState()); + return; + } + + // get some fukin globals up in here bois + + setVar("difficulty", PlayState.storyDifficulty); + setVar("bpm", Conductor.bpm); + setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed); + setVar("fpsCap", FlxG.save.data.fpsCap); + setVar("downscroll", FlxG.save.data.downscroll); + setVar("flashing", FlxG.save.data.flashing); + setVar("distractions", FlxG.save.data.distractions); + setVar("colour", FlxG.save.data.colour); + + setVar("curStep", 0); + setVar("curBeat", 0); + setVar("crochet", Conductor.stepCrochet); + setVar("safeZoneOffset", Conductor.safeZoneOffset); + + setVar("hudZoom", PlayState.instance.camHUD.zoom); + setVar("cameraZoom", FlxG.camera.zoom); + + setVar("cameraAngle", FlxG.camera.angle); + setVar("camHudAngle", PlayState.instance.camHUD.angle); + + setVar("followXOffset", 0); + setVar("followYOffset", 0); + + setVar("showOnlyStrums", false); + setVar("strumLine1Visible", true); + setVar("strumLine2Visible", true); + + setVar("screenWidth", FlxG.width); + setVar("screenHeight", FlxG.height); + setVar("windowWidth", FlxG.width); + setVar("windowHeight", FlxG.height); + setVar("hudWidth", PlayState.instance.camHUD.width); + setVar("hudHeight", PlayState.instance.camHUD.height); + + setVar("mustHit", false); + + setVar("strumLineY", PlayState.instance.strumLine.y); + + // callbacks + + Lua_helper.add_callback(lua, "makeSprite", makeLuaSprite); + + // sprites + + 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, "setStrumlineY", function(y:Float) + { + PlayState.instance.strumLine.y = y; + }); + + Lua_helper.add_callback(lua, "getNumberOfNotes", function(y:Float) + { + return PlayState.instance.notes.members.length; + }); + + for (i in 0...PlayState.strumLineNotes.length) + { + var member = PlayState.strumLineNotes.members[i]; + new LuaReceptor(member, "receptor_" + i).Register(lua); + } + + new LuaGame().Register(lua); + + new LuaWindow().Register(lua); } public function executeState(name,args:Array) @@ -956,9 +506,9 @@ class ModchartState return Lua.tostring(lua,callLua(name, args)); } - public static function createModchartState():ModchartState + public static function createModchartState(? isStoryMode = true):ModchartState { - return new ModchartState(); + return new ModchartState(isStoryMode); } } #end diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index 5575771693..75f36a9d0c 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -107,8 +107,8 @@ class MusicBeatState extends FlxUIState var step = ((60 / data.bpm) * 1000) / 4; var startInMS = (data.startTime * 1000); - curDecimalBeat = data.startBeat + (((Conductor.songPosition/1000) - data.startTime) * (data.bpm / 60)); - var ste:Int = Math.floor(data.startStep + ((Conductor.songPosition - startInMS) / step)); + 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) @@ -132,8 +132,8 @@ class MusicBeatState extends FlxUIState } else { - curDecimalBeat = (Conductor.songPosition / 1000) * (Conductor.bpm/60); - var nextStep:Int = Math.floor(Conductor.songPosition / Conductor.stepCrochet); + curDecimalBeat = (((Conductor.songPosition / 1000))) * (Conductor.bpm/60); + var nextStep:Int = Math.floor((Conductor.songPosition) / Conductor.stepCrochet); if (nextStep >= 0) { if (nextStep > curStep) diff --git a/source/Note.hx b/source/Note.hx index e42b218ba4..e6bb8e1fdb 100644 --- a/source/Note.hx +++ b/source/Note.hx @@ -35,6 +35,8 @@ class Note extends FlxSprite public var originColor:Int = 0; // The sustain note's original note's color public var noteSection:Int = 0; + public var luaID:Int = 0; + public var isAlt:Bool = false; public var noteCharterObject:FlxSprite; @@ -43,6 +45,8 @@ class Note extends FlxSprite public var noteYOff:Int = 0; + public var beat:Float = 0; + public static var swagWidth:Float = 160 * 0.7; public static var PURP_NOTE:Int = 0; public static var GREEN_NOTE:Int = 2; @@ -53,9 +57,10 @@ class Note extends FlxSprite public var modAngle:Float = 0; // The angle set by modcharts public var localAngle:Float = 0; // The angle to be edited inside Note.hx + public var originAngle:Float = 0; // The angle the OG note of the sus note had (?) public var dataColor:Array = ['purple', 'blue', 'green', 'red']; - public var quantityColor:Array = [RED_NOTE, 2, BLUE_NOTE, 2, PURP_NOTE, 2, BLUE_NOTE, 2]; + public var quantityColor:Array = [RED_NOTE, 2, BLUE_NOTE, 2, PURP_NOTE, 2, GREEN_NOTE, 2]; public var arrowAngles:Array = [180, 90, 270, 0]; public var isParent:Bool = false; @@ -65,13 +70,15 @@ class Note extends FlxSprite public var children:Array = []; - public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false, ?inCharter:Bool = false, ?isAlt:Bool = false) + public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false, ?inCharter:Bool = false, ?isAlt:Bool = false, ?bet:Float = 0) { super(); if (prevNote == null) prevNote = this; + beat = bet; + this.isAlt = isAlt; this.prevNote = prevNote; @@ -95,9 +102,9 @@ class Note extends FlxSprite rStrumTime = strumTime; } else - rStrumTime = (strumTime - FlxG.save.data.offset + PlayState.songOffset); + rStrumTime = strumTime; #else - rStrumTime = (strumTime - FlxG.save.data.offset + PlayState.songOffset); + rStrumTime = strumTime; #end } @@ -105,9 +112,12 @@ class Note extends FlxSprite if (this.strumTime < 0 ) this.strumTime = 0; + if (!inCharter) + y += FlxG.save.data.offset + PlayState.songOffset; + this.noteData = noteData; - var daStage:String = PlayState.curStage; + var daStage:String = PlayState.Stage.curStage; //defaults if no noteStyle was found in chart var noteTypeCheck:String = 'normal'; @@ -147,9 +157,7 @@ class Note extends FlxSprite animation.add(dataColor[i] + 'holdend', [i + 4]); // Tails } - var widthSize = Std.int(PlayState.curStage.startsWith('school') ? (width * PlayState.daPixelZoom) : (isSustainNote ? (width * (PlayState.daPixelZoom - 1.5)) : (width * PlayState.daPixelZoom))); - - setGraphicSize(widthSize); + setGraphicSize(Std.int(width * PlayState.daPixelZoom)); updateHitbox(); default: frames = Paths.getSparrowAtlas('NOTE_assets'); @@ -172,22 +180,32 @@ class Note extends FlxSprite animation.play(dataColor[noteData] + 'Scroll'); originColor = noteData; // The note's origin color will be checked by its sustain notes - if (FlxG.save.data.stepMania && !isSustainNote) + if (FlxG.save.data.stepMania && !isSustainNote && !PlayState.instance.executeModchart) { - var strumCheck:Float = rStrumTime; + var col:Int = 0; - // I give up on fluctuating bpms. something has to be subtracted from strumCheck to make them look right but idk what. - // I'd use the note's section's start time but neither the note's section nor its start time are accessible by themselves - //strumCheck -= ??? + var beatRow = Math.round(beat * 48); - var ind:Int = Std.int(Math.round(strumCheck / (Conductor.stepCrochet / 2))); + // STOLEN ETTERNA CODE (IN 2002) + + if (beatRow % (192 / 4) == 0) + col = quantityColor[0]; + else if (beatRow % (192 / 8) == 0) + col = quantityColor[2]; + else if (beatRow % (192 / 12) == 0) + col = quantityColor[4]; + else if (beatRow % (192 / 16) == 0) + col = quantityColor[6]; + else if (beatRow % (192 / 24) == 0) + col = quantityColor[4]; + else if (beatRow % (192 / 32) == 0) + col = quantityColor[4]; - var col:Int = 0; - col = quantityColor[ind % 8]; // Set the color depending on the beats animation.play(dataColor[col] + 'Scroll'); localAngle -= arrowAngles[col]; localAngle += arrowAngles[noteData]; + originAngle = localAngle; originColor = col; } @@ -199,7 +217,10 @@ class Note extends FlxSprite if (FlxG.save.data.downscroll && sustainNote) flipY = true; - var stepHeight = (0.45 * Conductor.stepCrochet * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? PlayState.SONG.speed : PlayStateChangeables.scrollSpeed, 2)); + + var stepHeight = (((0.45 * Conductor.stepCrochet)) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? PlayState.SONG.speed : PlayStateChangeables.scrollSpeed, 2)); + + // we can't divide step height cuz if we do uh it'll fucking lag the shit out of the game if (isSustainNote && prevNote != null) { @@ -209,6 +230,7 @@ class Note extends FlxSprite x += width / 2; originColor = prevNote.originColor; + originAngle = prevNote.originAngle; animation.play(dataColor[originColor] + 'holdend'); // This works both for normal colors and quantization colors updateHitbox(); @@ -225,6 +247,7 @@ class Note extends FlxSprite prevNote.animation.play(dataColor[prevNote.originColor] + 'hold'); prevNote.updateHitbox(); + prevNote.scale.y *= (stepHeight + 1) / prevNote.height; // + 1 so that there's no odd gaps as the notes scroll prevNote.updateHitbox(); prevNote.noteYOff = Math.round(-prevNote.offset.y); @@ -239,7 +262,10 @@ class Note extends FlxSprite override function update(elapsed:Float) { super.update(elapsed); - angle = modAngle + localAngle; + if (!modifiedByLua) + angle = modAngle + localAngle; + else + angle = modAngle; if (!modifiedByLua) { @@ -253,22 +279,22 @@ class Note extends FlxSprite { if (isSustainNote) { - if (strumTime - Conductor.songPosition <= ((166 * Conductor.timeScale) * 0.5) - && strumTime - Conductor.songPosition >= (-166 * Conductor.timeScale)) + if (strumTime - Conductor.songPosition <= ((166 * Conductor.timeScale) * PlayState.songMultiplier * 0.5) + && strumTime - Conductor.songPosition >=((-166 * Conductor.timeScale) * PlayState.songMultiplier)) canBeHit = true; else canBeHit = false; } else { - if (strumTime - Conductor.songPosition <= (166 * Conductor.timeScale) - && strumTime - Conductor.songPosition >= (-166 * Conductor.timeScale)) + if (strumTime - Conductor.songPosition <= ((166 * Conductor.timeScale) * PlayState.songMultiplier) + && strumTime - Conductor.songPosition >= ((-166 * Conductor.timeScale) * PlayState.songMultiplier)) canBeHit = true; else canBeHit = false; } - if (strumTime - Conductor.songPosition < -166 && !wasGoodHit) - tooLate = true; + /*if (strumTime - Conductor.songPosition < (-166 * Conductor.timeScale) && !wasGoodHit) + tooLate = true;*/ } else { diff --git a/source/Options.hx b/source/Options.hx index 0248a8d4a3..5ac14f4d66 100644 --- a/source/Options.hx +++ b/source/Options.hx @@ -267,6 +267,26 @@ class DistractionsAndEffectsOption extends Option } } +class Colour extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + FlxG.save.data.colour = !FlxG.save.data.colour; + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return "Color Health Bar By Character " + (!FlxG.save.data.colour ? "off" : "on"); + } +} + class StepManiaOption extends Option { public function new(desc:String) @@ -933,6 +953,7 @@ class ResetSettings extends Option FlxG.save.data.watermark = null; FlxG.save.data.ghost = null; FlxG.save.data.distractions = null; + FlxG.save.data.colour = null; FlxG.save.data.stepMania = null; FlxG.save.data.flashing = null; FlxG.save.data.resetButton = null; diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx index 440df091b7..d4d5e19748 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu.hx @@ -47,6 +47,7 @@ class OptionsMenu extends MusicBeatState new StepManiaOption("Sets the colors of the arrows depending on quantization instead of direction."), new AccuracyOption("Display accuracy information on the info bar."), new SongPositionOption("Show the song's current position as a scrolling bar."), + new Colour("The color behind icons now fit with their theme. (e.g. Pico = green)"), new NPSDisplayOption("Shows your current Notes Per Second on the info bar."), new RainbowFPSOption("Make the FPS Counter flicker through rainbow colors."), new CpuStrums("Toggle the CPU's strumline lighting up when it hits a note."), @@ -67,7 +68,7 @@ class OptionsMenu extends MusicBeatState new OptionCategory("Saves and Data", [ #if desktop - new ReplayOption("View saved song replays."), + //new ReplayOption("View saved song replays."), #end new ResetScoreOption("Reset your score on all songs and weeks. This is irreversible!"), new LockWeeksOption("Reset your story mode progress. This is irreversible!"), diff --git a/source/PlayState.hx b/source/PlayState.hx index 3acdc32af1..b8f8241f5f 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1,6 +1,10 @@ package; +import LuaClass.LuaCamera; +import LuaClass.LuaCharacter; +import lime.media.openal.AL; +import LuaClass.LuaNote; import Song.Event; import openfl.media.Sound; #if sys @@ -79,11 +83,11 @@ import sys.FileSystem; using StringTools; + class PlayState extends MusicBeatState { public static var instance:PlayState = null; - public static var curStage:String = ''; public static var SONG:SwagSong; public static var isStoryMode:Bool = false; public static var storyWeek:Int = 0; @@ -100,6 +104,8 @@ class PlayState extends MusicBeatState public var visibleCombos:Array = []; + public var visibleNotes:Array = []; + public static var songPosBar:FlxBar; public static var rep:Replay; @@ -108,8 +114,6 @@ class PlayState extends MusicBeatState public static var noteBools:Array = [false, false, false, false]; - var halloweenLevel:Bool = false; - var songLength:Float = 0; var kadeEngineWatermark:FlxText; @@ -147,9 +151,9 @@ class PlayState extends MusicBeatState private static var prevCamFollow:FlxObject; - public static var strumLineNotes:FlxTypedGroup = null; - public static var playerStrums:FlxTypedGroup = null; - public static var cpuStrums:FlxTypedGroup = null; + public static var strumLineNotes:FlxTypedGroup = null; + public static var playerStrums:FlxTypedGroup = null; + public static var cpuStrums:FlxTypedGroup = null; private var camZooming:Bool = false; private var curSong:String = ""; @@ -197,29 +201,19 @@ class PlayState extends MusicBeatState var notesHitArray:Array = []; var currentFrames:Int = 0; - var idleToBeat:Bool = true; // change if bf and dad would idle to the beat of the song + var idleToBeat:Bool = false; // change if bf and dad would idle to the beat of the song var idleBeat:Int = 2; // how frequently bf and dad would play their idle animation(1 - every beat, 2 - every 2 beats and so on) public var dialogue:Array = ['dad:blah blah blah', 'bf:coolswag']; - var halloweenBG:FlxSprite; - var isHalloween:Bool = false; - - var phillyCityLights:FlxTypedGroup; - var phillyTrain:FlxSprite; - var trainSound:FlxSound; + public static var trainSound:FlxSound; - var limo:FlxSprite; - var grpLimoDancers:FlxTypedGroup; - var fastCar:FlxSprite; var songName:FlxText; - var upperBoppers:FlxSprite; - var bottomBoppers:FlxSprite; - var santa:FlxSprite; + + public var currentSection:SwagSection; var fc:Bool = true; - var bgGirls:BackgroundGirls; var wiggleShit:WiggleEffect = new WiggleEffect(); var talking:Bool = true; @@ -232,8 +226,6 @@ class PlayState extends MusicBeatState public static var campaignScore:Int = 0; - var defaultCamZoom:Float = 1.05; - public static var daPixelZoom:Float = 6; public static var theFunne:Bool = true; @@ -242,6 +234,10 @@ class PlayState extends MusicBeatState var inCutscene:Bool = false; var usedTimeTravel:Bool = false; + public var randomVar = false; + + public static var Stage:Stage; + public static var repPresses:Int = 0; public static var repReleases:Int = 0; @@ -266,7 +262,7 @@ class PlayState extends MusicBeatState public static var highestCombo:Int = 0; - private var executeModchart = false; + public var executeModchart = false; // Animation common suffixes private var dataSuffix:Array = ['LEFT', 'DOWN', 'UP', 'RIGHT']; @@ -288,10 +284,14 @@ class PlayState extends MusicBeatState override public function create() { - FlxG.mouse.visible = false; instance = this; + previousRate = songMultiplier - 0.05; + + if (previousRate < 1.00) + previousRate = 1; + if (FlxG.save.data.fpsCap > 290) (cast(Lib.current.getChildAt(0), Main)).setFPSCap(800); @@ -342,6 +342,10 @@ class PlayState extends MusicBeatState trace('Mod chart: ' + executeModchart + " - " + Paths.lua(songLowercase + "/modchart")); + + if (executeModchart) + songMultiplier = 1; + #if windows // Making difficulty text for Discord Rich Presence. storyDifficultyText = CoolUtil.difficultyFromInt(storyDifficulty); @@ -372,8 +376,6 @@ class PlayState extends MusicBeatState // String for when the game is paused detailsPausedText = "Paused - " + detailsText; - curStage = ""; - // Updating Discord Rich Presence. DiscordClient.changePresence(detailsText + " " @@ -417,11 +419,12 @@ class PlayState extends MusicBeatState Conductor.mapBPMChanges(SONG); Conductor.changeBPM(SONG.bpm); + Conductor.bpm = SONG.bpm; + if (SONG.eventObjects == null) { SONG.eventObjects = [new Song.Event("Init BPM",0,SONG.bpm,"BPM Change")]; } - TimingStruct.clearTimings(); @@ -434,7 +437,9 @@ class PlayState extends MusicBeatState var endBeat:Float = Math.POSITIVE_INFINITY; - TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset + var bpm = i.value; + + TimingStruct.addTiming(beat,bpm,endBeat, 0); // offset in this case = start time since we don't have a offset if (currentIndex != 0) { @@ -448,8 +453,11 @@ class PlayState extends MusicBeatState } } + + recalculateAllSectionTimes(); + trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + PlayStateChangeables.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + PlayStateChangeables.botPlay); @@ -457,7 +465,7 @@ class PlayState extends MusicBeatState { //if the song has dialogue, so we don't accidentally try to load a nonexistant file and crash the game case 'senpai' | 'roses' | 'thorns': - dialogue = CoolUtil.coolTextFile(Paths.txt('data/' + songLowercase + '/dialogue')); + dialogue = CoolUtil.coolTextFile(Paths.txt('data/$songLowercase/dialogue')); } // defaults if no stage was found in chart @@ -499,373 +507,9 @@ class PlayState extends MusicBeatState stageCheck = SONG.stage; } - if (!PlayStateChangeables.Optimize) - { - switch (stageCheck) - { - case 'halloween': - { - curStage = 'spooky'; - halloweenLevel = true; - - var hallowTex = Paths.getSparrowAtlas('halloween_bg', 'week2'); - - halloweenBG = new FlxSprite(-200, -100); - halloweenBG.frames = hallowTex; - halloweenBG.animation.addByPrefix('idle', 'halloweem bg0'); - halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false); - halloweenBG.animation.play('idle'); - halloweenBG.antialiasing = FlxG.save.data.antialiasing; - add(halloweenBG); - - isHalloween = true; - } - case 'philly': - { - curStage = 'philly'; - - var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky', 'week3')); - bg.scrollFactor.set(0.1, 0.1); - add(bg); - - var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city', 'week3')); - city.scrollFactor.set(0.3, 0.3); - city.setGraphicSize(Std.int(city.width * 0.85)); - city.updateHitbox(); - add(city); - - phillyCityLights = new FlxTypedGroup(); - if (FlxG.save.data.distractions) - { - add(phillyCityLights); - } - - for (i in 0...5) - { - var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i, 'week3')); - light.scrollFactor.set(0.3, 0.3); - light.visible = false; - light.setGraphicSize(Std.int(light.width * 0.85)); - light.updateHitbox(); - light.antialiasing = FlxG.save.data.antialiasing; - phillyCityLights.add(light); - } - - var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain', 'week3')); - add(streetBehind); - - phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train', 'week3')); - if (FlxG.save.data.distractions) - { - add(phillyTrain); - } - - trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes', 'week3')); - FlxG.sound.list.add(trainSound); - - // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png); - - var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street', 'week3')); - add(street); - } - case 'limo': - { - curStage = 'limo'; - defaultCamZoom = 0.90; - - var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset', 'week4')); - skyBG.scrollFactor.set(0.1, 0.1); - skyBG.antialiasing = FlxG.save.data.antialiasing; - add(skyBG); - - var bgLimo:FlxSprite = new FlxSprite(-200, 480); - bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo', 'week4'); - bgLimo.animation.addByPrefix('drive', "background limo pink", 24); - bgLimo.animation.play('drive'); - bgLimo.scrollFactor.set(0.4, 0.4); - bgLimo.antialiasing = FlxG.save.data.antialiasing; - add(bgLimo); - if (FlxG.save.data.distractions) - { - grpLimoDancers = new FlxTypedGroup(); - add(grpLimoDancers); - - for (i in 0...5) - { - var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400); - dancer.scrollFactor.set(0.4, 0.4); - grpLimoDancers.add(dancer); - } - } - - var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay', 'week4')); - overlayShit.alpha = 0.5; - // add(overlayShit); - - // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED); - - // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]); - - // overlayShit.shader = shaderBullshit; - - var limoTex = Paths.getSparrowAtlas('limo/limoDrive', 'week4'); - - limo = new FlxSprite(-120, 550); - limo.frames = limoTex; - limo.animation.addByPrefix('drive', "Limo stage", 24); - limo.animation.play('drive'); - limo.antialiasing = FlxG.save.data.antialiasing; - - fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol', 'week4')); - fastCar.antialiasing = FlxG.save.data.antialiasing; - // add(limo); - } - case 'mall': - { - curStage = 'mall'; - - defaultCamZoom = 0.80; - - var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls', 'week5')); - bg.antialiasing = FlxG.save.data.antialiasing; - bg.scrollFactor.set(0.2, 0.2); - bg.active = false; - bg.setGraphicSize(Std.int(bg.width * 0.8)); - bg.updateHitbox(); - add(bg); - - upperBoppers = new FlxSprite(-240, -90); - upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop', 'week5'); - upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false); - upperBoppers.antialiasing = FlxG.save.data.antialiasing; - upperBoppers.scrollFactor.set(0.33, 0.33); - upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85)); - upperBoppers.updateHitbox(); - if (FlxG.save.data.distractions) - { - add(upperBoppers); - } - - var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator', 'week5')); - bgEscalator.antialiasing = FlxG.save.data.antialiasing; - bgEscalator.scrollFactor.set(0.3, 0.3); - bgEscalator.active = false; - bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9)); - bgEscalator.updateHitbox(); - add(bgEscalator); - - var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree', 'week5')); - tree.antialiasing = FlxG.save.data.antialiasing; - tree.scrollFactor.set(0.40, 0.40); - add(tree); - - bottomBoppers = new FlxSprite(-300, 140); - bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop', 'week5'); - bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false); - bottomBoppers.antialiasing = FlxG.save.data.antialiasing; - bottomBoppers.scrollFactor.set(0.9, 0.9); - bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1)); - bottomBoppers.updateHitbox(); - if (FlxG.save.data.distractions) - { - add(bottomBoppers); - } - - var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow', 'week5')); - fgSnow.active = false; - fgSnow.antialiasing = FlxG.save.data.antialiasing; - add(fgSnow); - - santa = new FlxSprite(-840, 150); - santa.frames = Paths.getSparrowAtlas('christmas/santa', 'week5'); - santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false); - santa.antialiasing = FlxG.save.data.antialiasing; - if (FlxG.save.data.distractions) - { - add(santa); - } - } - case 'mallEvil': - { - curStage = 'mallEvil'; - var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG', 'week5')); - bg.antialiasing = FlxG.save.data.antialiasing; - bg.scrollFactor.set(0.2, 0.2); - bg.active = false; - bg.setGraphicSize(Std.int(bg.width * 0.8)); - bg.updateHitbox(); - add(bg); - - var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree', 'week5')); - evilTree.antialiasing = FlxG.save.data.antialiasing; - evilTree.scrollFactor.set(0.2, 0.2); - add(evilTree); - - var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow", 'week5')); - evilSnow.antialiasing = FlxG.save.data.antialiasing; - add(evilSnow); - } - case 'school': - { - curStage = 'school'; - - // defaultCamZoom = 0.9; - - var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky', 'week6')); - bgSky.scrollFactor.set(0.1, 0.1); - add(bgSky); - - var repositionShit = -200; - - var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool', 'week6')); - bgSchool.scrollFactor.set(0.6, 0.90); - add(bgSchool); - - var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet', 'week6')); - bgStreet.scrollFactor.set(0.95, 0.95); - add(bgStreet); - - var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack', 'week6')); - fgTrees.scrollFactor.set(0.9, 0.9); - add(fgTrees); - - var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800); - var treetex = Paths.getPackerAtlas('weeb/weebTrees', 'week6'); - bgTrees.frames = treetex; - bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12); - bgTrees.animation.play('treeLoop'); - bgTrees.scrollFactor.set(0.85, 0.85); - add(bgTrees); - - var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40); - treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals', 'week6'); - treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true); - treeLeaves.animation.play('leaves'); - treeLeaves.scrollFactor.set(0.85, 0.85); - add(treeLeaves); - - var widShit = Std.int(bgSky.width * 6); - - bgSky.setGraphicSize(widShit); - bgSchool.setGraphicSize(widShit); - bgStreet.setGraphicSize(widShit); - bgTrees.setGraphicSize(Std.int(widShit * 1.4)); - fgTrees.setGraphicSize(Std.int(widShit * 0.8)); - treeLeaves.setGraphicSize(widShit); - - fgTrees.updateHitbox(); - bgSky.updateHitbox(); - bgSchool.updateHitbox(); - bgStreet.updateHitbox(); - bgTrees.updateHitbox(); - treeLeaves.updateHitbox(); - - bgGirls = new BackgroundGirls(-100, 190); - bgGirls.scrollFactor.set(0.9, 0.9); - - if (songLowercase == 'roses') - { - if (FlxG.save.data.distractions) - { - bgGirls.getScared(); - } - } - - bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); - bgGirls.updateHitbox(); - if (FlxG.save.data.distractions) - { - add(bgGirls); - } - } - case 'schoolEvil': - { - curStage = 'schoolEvil'; - - if (!PlayStateChangeables.Optimize) - { - var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); - var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); - } + if (isStoryMode) + songMultiplier = 1; - var posX = 400; - var posY = 200; - - var bg:FlxSprite = new FlxSprite(posX, posY); - bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool', 'week6'); - bg.animation.addByPrefix('idle', 'background 2', 24); - bg.animation.play('idle'); - bg.scrollFactor.set(0.8, 0.9); - bg.scale.set(6, 6); - add(bg); - - /* - var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG')); - bg.scale.set(6, 6); - // bg.setGraphicSize(Std.int(bg.width * 6)); - // bg.updateHitbox(); - add(bg); - var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG')); - fg.scale.set(6, 6); - // fg.setGraphicSize(Std.int(fg.width * 6)); - // fg.updateHitbox(); - add(fg); - wiggleShit.effectType = WiggleEffectType.DREAMY; - wiggleShit.waveAmplitude = 0.01; - wiggleShit.waveFrequency = 60; - wiggleShit.waveSpeed = 0.8; - */ - - // bg.shader = wiggleShit.shader; - // fg.shader = wiggleShit.shader; - - /* - var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]); - var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]); - // Using scale since setGraphicSize() doesnt work??? - waveSprite.scale.set(6, 6); - waveSpriteFG.scale.set(6, 6); - waveSprite.setPosition(posX, posY); - waveSpriteFG.setPosition(posX, posY); - waveSprite.scrollFactor.set(0.7, 0.8); - waveSpriteFG.scrollFactor.set(0.9, 0.8); - // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6)); - // waveSprite.updateHitbox(); - // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6)); - // waveSpriteFG.updateHitbox(); - add(waveSprite); - add(waveSpriteFG); - */ - } - default: - { - defaultCamZoom = 0.9; - curStage = 'stage'; - var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); - bg.antialiasing = FlxG.save.data.antialiasing; - bg.scrollFactor.set(0.9, 0.9); - bg.active = false; - add(bg); - - var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); - stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); - stageFront.updateHitbox(); - stageFront.antialiasing = FlxG.save.data.antialiasing; - stageFront.scrollFactor.set(0.9, 0.9); - stageFront.active = false; - add(stageFront); - - var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); - stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); - stageCurtains.updateHitbox(); - stageCurtains.antialiasing = FlxG.save.data.antialiasing; - stageCurtains.scrollFactor.set(1.3, 1.3); - stageCurtains.active = false; - - add(stageCurtains); - } - } - } // defaults if no gf was found in chart var gfCheck:String = 'gf'; @@ -886,27 +530,67 @@ class PlayState extends MusicBeatState gfCheck = SONG.gfVersion; } - var curGf:String = ''; - switch (gfCheck) + gf = new Character(400, 130, gfCheck); + + if (gf.frames == null) { - case 'gf-car': - curGf = 'gf-car'; - case 'gf-christmas': - curGf = 'gf-christmas'; - case 'gf-pixel': - curGf = 'gf-pixel'; - default: - curGf = 'gf'; + #if debug + FlxG.log.warn(["Couldn't load gf: " + gfCheck + ". Loading default gf"]); + #end + gf = new Character(770, 450, 'gf'); } - gf = new Character(400, 130, curGf); - gf.scrollFactor.set(0.95, 0.95); + boyfriend = new Boyfriend(770, 450, SONG.player1); + + if (boyfriend.frames == null) + { + #if debug + FlxG.log.warn(["Couldn't load boyfriend: " + SONG.player1 + ". Loading default boyfriend"]); + #end + boyfriend = new Boyfriend(770, 450, 'bf'); + } dad = new Character(100, 100, SONG.player2); + if (dad.frames == null) + { + #if debug + FlxG.log.warn(["Couldn't load opponent: " + SONG.player2 + ". Loading default opponent"]); + #end + dad = new Character(100, 100, 'dad'); + } + + if (!PlayStateChangeables.Optimize) + { + Stage = new Stage(SONG.stage); + for (i in Stage.toAdd) + { + add(i); + } + for (index => array in Stage.layInFront) + { + switch (index) + { + case 0: + add(gf); + gf.scrollFactor.set(0.95, 0.95); + for (bg in array) + add(bg); + case 1: + add(dad); + for (bg in array) + add(bg); + case 2: + add(boyfriend); + for (bg in array) + add(bg); + } + } + } + var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y); - switch (SONG.player2) + switch (dad.curCharacter) { case 'gf': dad.setPosition(gf.x, gf.y); @@ -957,10 +641,8 @@ class PlayState extends MusicBeatState camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); } - boyfriend = new Boyfriend(770, 450, SONG.player1); - // REPOSITIONING PER STAGE - switch (curStage) + switch (Stage.curStage) { case 'limo': boyfriend.y -= 220; @@ -968,7 +650,6 @@ class PlayState extends MusicBeatState if (FlxG.save.data.distractions) { resetFastCar(); - add(fastCar); } case 'mall': @@ -989,18 +670,6 @@ class PlayState extends MusicBeatState gf.y += 300; } - if (!PlayStateChangeables.Optimize) - { - add(gf); - - // Shitty layering but whatev it works LOL - if (curStage == 'limo') - add(limo); - - add(dad); - add(boyfriend); - } - if (loadRep) { FlxG.watch.addQuick('rep rpesses', repPresses); @@ -1016,11 +685,16 @@ class PlayState extends MusicBeatState trace("SF CALC: " + Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); - var doof:DialogueBox = new DialogueBox(false, dialogue); - // doof.x += 70; - // doof.y = FlxG.height * 0.5; - doof.scrollFactor.set(); - doof.finishThing = startCountdown; + var doof = null; + + if (isStoryMode) + { + doof = new DialogueBox(false, dialogue); + // doof.x += 70; + // doof.y = FlxG.height * 0.5; + doof.scrollFactor.set(); + doof.finishThing = startCountdown; + } Conductor.songPosition = -5000; @@ -1030,11 +704,11 @@ class PlayState extends MusicBeatState if (PlayStateChangeables.useDownscroll) strumLine.y = FlxG.height - 165; - strumLineNotes = new FlxTypedGroup(); + strumLineNotes = new FlxTypedGroup(); add(strumLineNotes); - playerStrums = new FlxTypedGroup(); - cpuStrums = new FlxTypedGroup(); + playerStrums = new FlxTypedGroup(); + cpuStrums = new FlxTypedGroup(); generateStaticArrows(0); generateStaticArrows(1); @@ -1048,22 +722,34 @@ class PlayState extends MusicBeatState generateSong(SONG.song); - for(i in unspawnNotes) + #if cpp + // pre lowercasing the song name (startCountdown) + var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase(); + switch (songLowercase) { - var dunceNote:Note = i; - notes.add(dunceNote); - if (executeModchart) - { - if (!dunceNote.isSustainNote) - dunceNote.cameras = [camNotes]; - else - dunceNote.cameras = [camSustains]; - } - else + case 'dad-battle': + songLowercase = 'dadbattle'; + case 'philly-nice': + songLowercase = 'philly'; + } + if (executeModchart) + { + luaModchart = ModchartState.createModchartState(isStoryMode); + luaModchart.executeState('start', [songLowercase]); + } + #end + + if (executeModchart) { - dunceNote.cameras = [camHUD]; + new LuaCamera(camGame,"camGame").Register(ModchartState.lua); + new LuaCamera(camHUD,"camHUD").Register(ModchartState.lua); + new LuaCamera(camSustains,"camSustains").Register(ModchartState.lua); + new LuaCamera(camSustains,"camNotes").Register(ModchartState.lua); + new LuaCharacter(dad,"dad").Register(ModchartState.lua); + new LuaCharacter(gf,"gf").Register(ModchartState.lua); + new LuaCharacter(boyfriend,"boyfriend").Register(ModchartState.lua); } - } + var index = 0; if (startTime != 0) { @@ -1080,22 +766,22 @@ class PlayState extends MusicBeatState { if (dunceNote.mustPress) dunceNote.y = (playerStrums.members[Math.floor(Math.abs(dunceNote.noteData))].y - + 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2)) - dunceNote.noteYOff; else dunceNote.y = (strumLineNotes.members[Math.floor(Math.abs(dunceNote.noteData))].y - + 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2)) - dunceNote.noteYOff; } else { if (dunceNote.mustPress) dunceNote.y = (playerStrums.members[Math.floor(Math.abs(dunceNote.noteData))].y - - 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2)) + dunceNote.noteYOff; else dunceNote.y = (strumLineNotes.members[Math.floor(Math.abs(dunceNote.noteData))].y - - 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2)) + dunceNote.noteYOff; } } @@ -1123,7 +809,7 @@ class PlayState extends MusicBeatState FlxG.camera.follow(camFollow, LOCKON, 0.04 * (30 / (cast(Lib.current.getChildAt(0), Main)).getFPS())); // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height); - FlxG.camera.zoom = defaultCamZoom; + FlxG.camera.zoom = Stage.camZoom; FlxG.camera.focusOn(camFollow.getPosition()); FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height); @@ -1164,8 +850,29 @@ class PlayState extends MusicBeatState healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this, 'health', 0, 2); healthBar.scrollFactor.set(); - healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33); - // healthBar + if(FlxG.save.data.colour) + { + switch (SONG.player2) + { + case 'gf': + healthBar.createFilledBar(0xFFFF0000, 0xFF0097C4); + case 'dad' | 'mom-car' | 'parents-christmas': + healthBar.createFilledBar(0xFF5A07F5, 0xFF0097C4); + case 'spooky': + healthBar.createFilledBar(0xFFF57E07, 0xFF0097C4); + case 'monster-christmas' | 'monster': + healthBar.createFilledBar(0xFFF5DD07, 0xFF0097C4); + case 'pico': + healthBar.createFilledBar(0xFF52B514, 0xFF0097C4); + case 'senpai' | 'senpai-angry': + healthBar.createFilledBar(0xFFF76D6D, 0xFF0097C4); + case 'spirit': + healthBar.createFilledBar(0xFFAD0505, 0xFF0097C4); + } + } + else + healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33); + // healthBar add(healthBar); // Add Kade Engine watermark @@ -1214,11 +921,11 @@ class PlayState extends MusicBeatState if (PlayStateChangeables.botPlay && !loadRep) add(botPlayState); - iconP1 = new HealthIcon(SONG.player1, true); + iconP1 = new HealthIcon(boyfriend.curCharacter, true); iconP1.y = healthBar.y - (iconP1.height / 2); add(iconP1); - iconP2 = new HealthIcon(SONG.player2, false); + iconP2 = new HealthIcon(dad.curCharacter, false); iconP2.y = healthBar.y - (iconP2.height / 2); add(iconP2); @@ -1229,7 +936,8 @@ class PlayState extends MusicBeatState iconP1.cameras = [camHUD]; iconP2.cameras = [camHUD]; scoreTxt.cameras = [camHUD]; - doof.cameras = [camHUD]; + if (isStoryMode) + doof.cameras = [camHUD]; if (FlxG.save.data.songPosition) { songPosBG.cameras = [camHUD]; @@ -1267,11 +975,11 @@ class PlayState extends MusicBeatState FlxG.camera.focusOn(camFollow.getPosition()); FlxG.camera.zoom = 1.5; - new FlxTimer().start(0.8, function(tmr:FlxTimer) + new FlxTimer().start(1, function(tmr:FlxTimer) { camHUD.visible = true; remove(blackScreen); - FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, { + FlxTween.tween(FlxG.camera, {zoom: Stage.camZoom}, 2.5, { ease: FlxEase.quadInOut, onComplete: function(twn:FlxTween) { @@ -1288,12 +996,16 @@ class PlayState extends MusicBeatState case 'thorns': schoolIntro(doof); default: - startCountdown(); + new FlxTimer().start(1, function(timer) { + startCountdown(); + }); } } else { - startCountdown(); + new FlxTimer().start(1, function(timer) { + startCountdown(); + }); } if (!loadRep) @@ -1391,7 +1103,6 @@ class PlayState extends MusicBeatState var startTimer:FlxTimer; var perfectMode:Bool = false; - var luaWiggles:Array = []; #if cpp @@ -1408,23 +1119,6 @@ class PlayState extends MusicBeatState - #if cpp - // pre lowercasing the song name (startCountdown) - var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase(); - switch (songLowercase) - { - case 'dad-battle': - songLowercase = 'dadbattle'; - case 'philly-nice': - songLowercase = 'philly'; - } - if (executeModchart) - { - luaModchart = ModchartState.createModchartState(); - luaModchart.executeState('start', [songLowercase]); - } - #end - talking = false; startedCountdown = true; Conductor.songPosition = 0; @@ -1516,10 +1210,9 @@ class PlayState extends MusicBeatState } swagCounter += 1; - // generateSong('fresh'); }, 5); } - + var previousFrameTime:Int = 0; var lastReportedPlayheadPosition:Int = 0; var songTime:Float = 0; @@ -1539,7 +1232,7 @@ class PlayState extends MusicBeatState private function releaseInput(evt:KeyboardEvent):Void // handles releases { @:privateAccess - var key = FlxKey.toStringMap.get(Keyboard.__convertKeyCode(evt.keyCode)); + var key = FlxKey.toStringMap.get(evt.keyCode); var binds:Array = [ FlxG.save.data.leftBind, @@ -1588,7 +1281,7 @@ class PlayState extends MusicBeatState // this makes it work for special characters @:privateAccess - var key = FlxKey.toStringMap.get(Keyboard.__convertKeyCode(evt.keyCode)); + var key = FlxKey.toStringMap.get(evt.keyCode); var binds:Array = [ FlxG.save.data.leftBind, @@ -1636,6 +1329,8 @@ class PlayState extends MusicBeatState if (i.noteData == data) dataNotes.push(i); + trace("notes able to hit for " + key.toString() + " " + dataNotes.length); + if (dataNotes.length != 0) { var coolNote = null; @@ -1661,9 +1356,9 @@ class PlayState extends MusicBeatState var note = dataNotes[i]; - if (!note.isSustainNote && (note.strumTime - coolNote.strumTime) < 2) + if (!note.isSustainNote && (note.strumTime / songMultiplier - coolNote.strumTime / songMultiplier) < 2) { - trace('found a stacked/really close note ' + (note.strumTime - coolNote.strumTime)); + trace('found a stacked/really close note ' + (note.strumTime / songMultiplier - coolNote.strumTime / songMultiplier)); // just fuckin remove it since it's a stacked note and shouldn't be there note.kill(); notes.remove(note, true); @@ -1673,10 +1368,10 @@ class PlayState extends MusicBeatState } goodNoteHit(coolNote); - var noteDiff:Float = -(coolNote.strumTime - Conductor.songPosition); + var noteDiff:Float = -(coolNote.strumTime / songMultiplier - Conductor.songPosition / songMultiplier); ana.hit = true; - ana.hitJudge = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); - ana.nearestNote = [coolNote.strumTime, coolNote.noteData, coolNote.sustainLength]; + ana.hitJudge = Ratings.judgeNote(coolNote); + ana.nearestNote = [coolNote.strumTime / songMultiplier, coolNote.noteData, coolNote.sustainLength]; } else if (!FlxG.save.data.ghost && songStarted) { @@ -1690,6 +1385,12 @@ class PlayState extends MusicBeatState var songStarted = false; + public var doAnything = false; + + + public static var songMultiplier = 1.0; + public var previousRate = songMultiplier; + function startSong():Void { startingSong = false; @@ -1700,6 +1401,7 @@ class PlayState extends MusicBeatState FlxG.sound.music.play(); vocals.play(); + // Song check real quick switch (curSong) { @@ -1712,6 +1414,9 @@ class PlayState extends MusicBeatState if (useVideo) GlobalVideo.get().resume(); + if (executeModchart) + luaModchart.executeState("songStart",[null]); + #if windows // Updating Discord Rich Presence (with Time Left) DiscordClient.changePresence(detailsText @@ -1730,10 +1435,46 @@ class PlayState extends MusicBeatState #end FlxG.sound.music.time = startTime; - vocals.time = startTime; + if (vocals != null) + vocals.time = startTime; Conductor.songPosition = startTime; startTime = 0; + + + /*@:privateAccess + { + var aux = AL.createAux(); + var fx = AL.createEffect(); + AL.effectf(fx,AL.PITCH,songMultiplier); + AL.auxi(aux, AL.EFFECTSLOT_EFFECT, fx); + var instSource = FlxG.sound.music._channel.__source; + + var backend:lime._internal.backend.native.NativeAudioSource = instSource.__backend; + + AL.source3i(backend.handle, AL.AUXILIARY_SEND_FILTER, aux, 1, AL.FILTER_NULL); + if (vocals != null) + { + var vocalSource = vocals._channel.__source; + + backend = vocalSource.__backend; + AL.source3i(backend.handle, AL.AUXILIARY_SEND_FILTER, aux, 1, AL.FILTER_NULL); + } + + trace("pitched to " + songMultiplier); + }*/ + + #if cpp + @:privateAccess + { + lime.media.openal.AL.sourcef(FlxG.sound.music._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); + if (vocals.playing) + lime.media.openal.AL.sourcef(vocals._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); + + } + trace("pitched inst and vocals to " + songMultiplier); + #end + for(i in 0...unspawnNotes.length) if (unspawnNotes[i].strumTime < startTime) unspawnNotes.remove(unspawnNotes[i]); @@ -1778,6 +1519,7 @@ class PlayState extends MusicBeatState FlxG.sound.playMusic(sound); } else + FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); #else FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); @@ -1786,9 +1528,19 @@ class PlayState extends MusicBeatState FlxG.sound.music.onComplete = endSong; FlxG.sound.music.pause(); + + if (SONG.needsVoices) + FlxG.sound.cache(Paths.voices(PlayState.SONG.song)); + if (!PlayState.isSM) + FlxG.sound.cache(Paths.inst(PlayState.SONG.song)); + + // Song duration in a float, useful for the time left feature - songLength = FlxG.sound.music.length; + songLength = FlxG.sound.music.length / 1000; + + Conductor.crochet = ((60 / (SONG.bpm) * 1000)) / songMultiplier; + Conductor.stepCrochet = Conductor.crochet / 4; if (FlxG.save.data.songPosition) { @@ -1806,8 +1558,7 @@ class PlayState extends MusicBeatState songPosBar = new FlxBar(songPosBG.x + 4, songPosBG.y + 4, LEFT_TO_RIGHT, Std.int(songPosBG.width - 8), Std.int(songPosBG.height - 8), this, - 'songPositionBar', 0, songLength - - 1000); + 'songPositionBar', 0, 100); songPosBar.numDivisions = 1000; songPosBar.scrollFactor.set(); songPosBar.createFilledBar(FlxColor.GRAY, FlxColor.LIME); @@ -1883,17 +1634,18 @@ class PlayState extends MusicBeatState for (songNotes in section.sectionNotes) { - var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset + songOffset; + var daStrumTime:Float = songNotes[0] - FlxG.save.data.offset - songOffset; if (daStrumTime < 0) daStrumTime = 0; var daNoteData:Int = Std.int(songNotes[1] % 4); - var gottaHitNote:Bool = section.mustHitSection; + var gottaHitNote:Bool = true; - if (songNotes[1] > 3) - { - gottaHitNote = !section.mustHitSection; - } + if (songNotes[1] > 3 && section.mustHitSection) + gottaHitNote = false; + else if (songNotes[1] < 4 && !section.mustHitSection) + gottaHitNote = false; + var oldNote:Note; if (unspawnNotes.length > 0) @@ -1901,12 +1653,12 @@ class PlayState extends MusicBeatState else oldNote = null; - var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); + var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote,false,false,false,songNotes[4]); if (!gottaHitNote && PlayStateChangeables.Optimize) continue; - swagNote.sustainLength = songNotes[2]; + swagNote.sustainLength = TimingStruct.getTimeFromBeat((TimingStruct.getBeatFromTime(songNotes[2]))); swagNote.scrollFactor.set(0, 0); var susLength:Float = swagNote.sustainLength; @@ -1961,6 +1713,7 @@ class PlayState extends MusicBeatState generatedMusic = true; } + function sortByShit(Obj1:Note, Obj2:Note):Int { return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); @@ -1971,7 +1724,7 @@ class PlayState extends MusicBeatState for (i in 0...4) { // FlxG.log.add(i); - var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y); + var babyArrow:StaticArrow = new StaticArrow(0, strumLine.y); // defaults if no noteStyle was found in chart var noteTypeCheck:String = 'normal'; @@ -2005,28 +1758,14 @@ class PlayState extends MusicBeatState babyArrow.updateHitbox(); babyArrow.antialiasing = false; - switch (Math.abs(i)) + babyArrow.x += Note.swagWidth * i; + babyArrow.animation.add('static', [i]); + babyArrow.animation.add('pressed', [4 + i, 8 + i], 12, false); + babyArrow.animation.add('confirm', [12 + i, 16 + i], 24, false); + + for (j in 0...4) { - case 2: - babyArrow.x += Note.swagWidth * 2; - babyArrow.animation.add('static', [2]); - babyArrow.animation.add('pressed', [6, 10], 12, false); - babyArrow.animation.add('confirm', [14, 18], 12, false); - case 3: - babyArrow.x += Note.swagWidth * 3; - babyArrow.animation.add('static', [3]); - babyArrow.animation.add('pressed', [7, 11], 12, false); - babyArrow.animation.add('confirm', [15, 19], 24, false); - case 1: - babyArrow.x += Note.swagWidth * 1; - babyArrow.animation.add('static', [1]); - babyArrow.animation.add('pressed', [5, 9], 12, false); - babyArrow.animation.add('confirm', [13, 17], 24, false); - case 0: - babyArrow.x += Note.swagWidth * 0; - babyArrow.animation.add('static', [0]); - babyArrow.animation.add('pressed', [4, 8], 12, false); - babyArrow.animation.add('confirm', [12, 16], 24, false); + babyArrow.animation.add('dirCon' + j, [12 + j, 16 + j], 24, false); } default: @@ -2034,6 +1773,7 @@ class PlayState extends MusicBeatState for (j in 0...4) { babyArrow.animation.addByPrefix(dataColor[j], 'arrow' + dataSuffix[j]); + babyArrow.animation.addByPrefix('dirCon' + j, dataSuffix[j].toLowerCase() + ' confirm', 24, false); } var lowerDir:String = dataSuffix[i].toLowerCase(); @@ -2069,7 +1809,7 @@ class PlayState extends MusicBeatState playerStrums.add(babyArrow); } - babyArrow.animation.play('static'); + babyArrow.playAnim('static'); babyArrow.x += 50; babyArrow.x += ((FlxG.width / 2) * player); @@ -2116,7 +1856,7 @@ class PlayState extends MusicBeatState + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), - "Acc: " + "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore @@ -2178,9 +1918,17 @@ class PlayState extends MusicBeatState FlxG.sound.music.play(); Conductor.songPosition = FlxG.sound.music.time; - vocals.time = Conductor.songPosition; + vocals.time = FlxG.sound.music.time; vocals.play(); + @:privateAccess + { + lime.media.openal.AL.sourcef(FlxG.sound.music._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); + if (vocals.playing) + lime.media.openal.AL.sourcef(vocals._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); + + } + #if windows DiscordClient.changePresence(detailsText + " " @@ -2215,64 +1963,151 @@ class PlayState extends MusicBeatState public var pastScrollChanges:Array = []; + + var currentLuaIndex = 0; + override public function update(elapsed:Float) { #if !debug perfectMode = false; #end - if (generatedMusic) + + if (unspawnNotes[0] != null) { - for(i in notes) + + if (unspawnNotes[0].strumTime - Conductor.songPosition < 14000 * songMultiplier) { - var diff = i.strumTime - Conductor.songPosition; - if (diff < 2650 && diff >= -2650) + var dunceNote:Note = unspawnNotes[0]; + notes.add(dunceNote); + + if (executeModchart) { - i.active = true; - i.visible = true; + new LuaNote(dunceNote,currentLuaIndex); + dunceNote.luaID = currentLuaIndex; + } + + if (executeModchart) + { + if (!dunceNote.isSustainNote) + dunceNote.cameras = [camNotes]; + else + dunceNote.cameras = [camSustains]; } else { - i.active = false; - i.visible = false; + dunceNote.cameras = [camHUD]; } + + var index:Int = unspawnNotes.indexOf(dunceNote); + unspawnNotes.splice(index, 1); + currentLuaIndex++; } } - - var timingSeg = TimingStruct.getTimingAtTimestamp(Conductor.songPosition); - - if (timingSeg != null) + #if cpp + if (FlxG.sound.music.playing) + @:privateAccess { - - var timingSegBpm = timingSeg.bpm; - - if (timingSegBpm != Conductor.bpm) - { - trace("BPM CHANGE to " + timingSegBpm); - Conductor.changeBPM(timingSegBpm, false); - } - - } + lime.media.openal.AL.sourcef(FlxG.sound.music._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); + if (vocals.playing) + lime.media.openal.AL.sourcef(vocals._channel.__source.__backend.handle, lime.media.openal.AL.PITCH, songMultiplier); - var newScroll = PlayStateChangeables.scrollSpeed; + } + #end - for(i in SONG.eventObjects) - { - switch(i.type) + if (generatedMusic) { - case "Scroll Speed Change": - if (i.position <= curDecimalBeat && !pastScrollChanges.contains(i)) + if (songStarted && !endingSong) + { + // Song ends abruptly on slow rate even with second condition being deleted, + // and if it's deleted on songs like cocoa then it would end without finishing instrumental fully, + // so no reason to delete it at all + if (notes.length == 0 && FlxG.sound.music.length - Conductor.songPosition <= 100) { - pastScrollChanges.push(i); - trace("SCROLL SPEED CHANGE to " + i.value); - newScroll = i.value; + endSong(); } + } } - } - PlayStateChangeables.scrollSpeed = newScroll; + + if (updateFrame == 4) + { + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in SONG.eventObjects) + { + if (i.type == "BPM Change") + { + var beat:Float = i.position; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + var bpm = i.value; + + TimingStruct.addTiming(beat,bpm,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + 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; + } + + currentIndex++; + } + } + + updateFrame++; + } + else if (updateFrame != 5) + updateFrame++; + + + if (FlxG.sound.music.playing) + { + + var timingSeg = TimingStruct.getTimingAtBeat(curDecimalBeat); + + if (timingSeg != null) + { + + var timingSegBpm = timingSeg.bpm; + + if (timingSegBpm != Conductor.bpm) + { + trace("BPM CHANGE to " + timingSegBpm); + Conductor.changeBPM(timingSegBpm, false); + Conductor.crochet = ((60 / (timingSegBpm) * 1000)) / songMultiplier; + Conductor.stepCrochet = Conductor.crochet / 4; + } + + } + + var newScroll = 1.0; + + for(i in SONG.eventObjects) + { + switch(i.type) + { + case "Scroll Speed Change": + if (i.position <= curDecimalBeat && !pastScrollChanges.contains(i)) + { + pastScrollChanges.push(i); + trace("SCROLL SPEED CHANGE to " + i.value); + newScroll = i.value; + } + } + } + + if (newScroll != 0) + PlayStateChangeables.scrollSpeed *= newScroll; + } if (PlayStateChangeables.botPlay && FlxG.keys.justPressed.ONE) camHUD.visible = !camHUD.visible; @@ -2295,6 +2130,7 @@ class PlayState extends MusicBeatState luaModchart.setVar('hudZoom', camHUD.zoom); luaModchart.setVar('curBeat', HelperFunctions.truncateFloat(curDecimalBeat,3)); luaModchart.setVar('cameraZoom', FlxG.camera.zoom); + luaModchart.executeState('update', [elapsed]); for (key => value in luaModchart.luaWiggles) @@ -2303,6 +2139,8 @@ class PlayState extends MusicBeatState value.update(elapsed); } + PlayStateChangeables.useDownscroll = luaModchart.getVar("downscroll","bool"); + /*for (i in 0...strumLineNotes.length) { var member = strumLineNotes.members[i]; member.x = luaModchart.getVar("strum" + i + "X", "float"); @@ -2375,7 +2213,7 @@ class PlayState extends MusicBeatState if (FlxG.keys.justPressed.NINE) iconP1.swapOldIcon(); - switch (curStage) + switch (Stage.curStage) { case 'philly': if (trainMoving && !PlayStateChangeables.Optimize) @@ -2391,9 +2229,6 @@ class PlayState extends MusicBeatState // phillyCityLights.members[curLight].alpha -= (Conductor.crochet / 1000) * FlxG.elapsed; } - super.update(elapsed); - - scoreTxt.text = Ratings.CalculateRanking(songScore, songScoreDef, nps, maxNPS, accuracy); var lengthInPx = scoreTxt.textField.length * scoreTxt.frameHeight; // bad way but does more or less a better job @@ -2418,6 +2253,7 @@ class PlayState extends MusicBeatState if (FlxG.keys.justPressed.SEVEN && songStarted) { + songMultiplier = 1; if (useVideo) { GlobalVideo.get().stop(); @@ -2429,9 +2265,6 @@ class PlayState extends MusicBeatState removedVideo = true; } cannotDie = true; - #if windows - DiscordClient.changePresence("Chart Editor", null, null, true); - #end FlxG.switchState(new ChartingState()); clean(); @@ -2487,7 +2320,46 @@ class PlayState extends MusicBeatState removedVideo = true; } - FlxG.switchState(new AnimationDebug(SONG.player2)); + FlxG.switchState(new AnimationDebug(dad.curCharacter)); + clean(); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); + #if cpp + if (luaModchart != null) + { + luaModchart.die(); + luaModchart = null; + } + #end + } + + if (FlxG.keys.justPressed.EIGHT && songStarted) + { + paused = true; + if (useVideo) + { + GlobalVideo.get().stop(); + remove(videoSprite); + FlxG.stage.window.onFocusOut.remove(focusOut); + FlxG.stage.window.onFocusIn.remove(focusIn); + removedVideo = true; + } + new FlxTimer().start(0.3, function(tmr:FlxTimer) + { + for (bg in Stage.toAdd) + { + remove(bg); + } + for (array in Stage.layInFront) + { + for (bg in array) + remove(bg); + } + remove(boyfriend); + remove(dad); + remove(gf); + }); + FlxG.switchState(new StagePositioningDebug(SONG.stage, gf.curCharacter, boyfriend.curCharacter, dad.curCharacter)); clean(); FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); @@ -2502,7 +2374,7 @@ class PlayState extends MusicBeatState if (FlxG.keys.justPressed.ZERO) { - FlxG.switchState(new AnimationDebug(SONG.player1)); + FlxG.switchState(new AnimationDebug(boyfriend.curCharacter)); clean(); FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); @@ -2515,7 +2387,7 @@ class PlayState extends MusicBeatState #end } - if(FlxG.keys.justPressed.TWO) { //Go 10 seconds into the future, credit: Shadow Mario#9396 + if(FlxG.keys.justPressed.TWO && songStarted) { //Go 10 seconds into the future, credit: Shadow Mario#9396 if (!usedTimeTravel && Conductor.songPosition + 10000 < FlxG.sound.music.length) { usedTimeTravel = true; @@ -2560,12 +2432,14 @@ class PlayState extends MusicBeatState else { // Conductor.songPosition = FlxG.sound.music.time; - Conductor.songPosition += FlxG.elapsed * 1000; + Conductor.songPosition = FlxG.sound.music.time; /*@:privateAccess { FlxG.sound.music._channel. }*/ - songPositionBar = Conductor.songPosition; + songPositionBar = (Conductor.songPosition - songLength) / 1000; + + currentSection = getSectionByTime(Conductor.songPosition); if (!paused) { @@ -2585,22 +2459,19 @@ class PlayState extends MusicBeatState // Conductor.lastSongPos = FlxG.sound.music.time; } - if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) + if (generatedMusic && currentSection != null) { closestNotes = []; notes.forEachAlive(function(daNote:Note) { - if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit) + if (daNote.canBeHit && daNote.mustPress && !daNote.wasGoodHit) closestNotes.push(daNote); }); // Collect notes that can be hit closestNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); - if (closestNotes.length != 0) - FlxG.watch.addQuick("Current Note",closestNotes[0].strumTime - Conductor.songPosition); - // Make sure Girlfriend cheers only for certain songs if (allowedToHeadbang) { @@ -2711,10 +2582,10 @@ class PlayState extends MusicBeatState #if cpp if (luaModchart != null) - luaModchart.setVar("mustHit", PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection); + luaModchart.setVar("mustHit", currentSection.mustHitSection); #end - if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) + if (camFollow.x != dad.getMidpoint().x + 150 && !currentSection.mustHitSection) { var offsetX = 0; var offsetY = 0; @@ -2742,7 +2613,7 @@ class PlayState extends MusicBeatState } } - if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) + if (currentSection.mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) { var offsetX = 0; var offsetY = 0; @@ -2760,7 +2631,7 @@ class PlayState extends MusicBeatState luaModchart.executeState('playerOneTurn', []); #end - switch (curStage) + switch (Stage.curStage) { case 'limo': camFollow.x = boyfriend.getMidpoint().x - 300; @@ -2776,8 +2647,14 @@ class PlayState extends MusicBeatState } } - if (camZooming) + if (camZooming && Conductor.bpm < 320) { + + if (Conductor.bpm > 320) // if we don't do this it'll be really annoying + { + camZooming = false; + } + if (FlxG.save.data.zoom < 0.8) FlxG.save.data.zoom = 0.8; @@ -2786,7 +2663,7 @@ class PlayState extends MusicBeatState if (!executeModchart) { - FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); + FlxG.camera.zoom = FlxMath.lerp(Stage.camZoom, FlxG.camera.zoom, 0.95); camHUD.zoom = FlxMath.lerp(FlxG.save.data.zoom, camHUD.zoom, 0.95); camNotes.zoom = camHUD.zoom; @@ -2794,7 +2671,7 @@ class PlayState extends MusicBeatState } else { - FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); + FlxG.camera.zoom = FlxMath.lerp(Stage.camZoom, FlxG.camera.zoom, 0.95); camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); camNotes.zoom = camHUD.zoom; @@ -2803,8 +2680,6 @@ class PlayState extends MusicBeatState } FlxG.watch.addQuick("curBPM", Conductor.bpm); - FlxG.watch.addQuick("Closest Note", (unspawnNotes.length != 0 ? unspawnNotes[0].strumTime - Conductor.songPosition : "No note")); - FlxG.watch.addQuick("beatShit", curBeat); FlxG.watch.addQuick("stepShit", curStep); @@ -2851,7 +2726,14 @@ class PlayState extends MusicBeatState vocals.stop(); FlxG.sound.music.stop(); - openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + if (FlxG.save.data.InstantRespawn) + { + FlxG.switchState(new PlayState()); + } + else + { + openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + } #if windows // Game Over doesn't get his own variable because it's only used here @@ -2868,7 +2750,7 @@ class PlayState extends MusicBeatState + " | Misses: " + misses, iconRPC); #end - + // God i love futabu!! so fucking much (From: McChomk) // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); } else @@ -2886,8 +2768,15 @@ class PlayState extends MusicBeatState vocals.stop(); FlxG.sound.music.stop(); - - openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + + if (FlxG.save.data.InstantRespawn) + { + FlxG.switchState(new PlayState()); + } + else + { + openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + } #if windows // Game Over doesn't get his own variable because it's only used here @@ -2918,41 +2807,34 @@ class PlayState extends MusicBeatState { // instead of doing stupid y > FlxG.height // we be men and actually calculate the time :) - if (daNote.tooLate) - { - daNote.active = false; - daNote.visible = false; - } - else - { - daNote.visible = true; - daNote.active = true; - } if (!daNote.modifiedByLua) { if (PlayStateChangeables.useDownscroll) { + if (daNote.mustPress) + { daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, - 2)) - daNote.noteYOff; + + 0.45 * ((Conductor.songPosition - daNote.strumTime) / songMultiplier) * + (FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2) )) + - daNote.noteYOff; + } else daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, - 2)) - daNote.noteYOff; + + 0.45 * ((Conductor.songPosition - daNote.strumTime) / songMultiplier) * (FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2))) - daNote.noteYOff; if (daNote.isSustainNote) { // Remember = minus makes notes go up, plus makes them go down if (daNote.animation.curAnim.name.endsWith('end') && daNote.prevNote != null) daNote.y += daNote.prevNote.height; - else - daNote.y += daNote.height / 2; // If not in botplay, only clip sustain notes when properly hit, botplay gets to clip it everytime if (!PlayStateChangeables.botPlay) { - if ((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit || holdArray[Math.floor(Math.abs(daNote.noteData))] && !daNote.tooLate) + if ((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit || holdArray[Math.floor(Math.abs(daNote.noteData))]) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= (strumLine.y + Note.swagWidth / 2)) { // Clip to strumline @@ -2981,19 +2863,18 @@ class PlayState extends MusicBeatState { if (daNote.mustPress) daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, - 2)) + daNote.noteYOff; + - 0.45 * ((Conductor.songPosition - daNote.strumTime) / songMultiplier) * (FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2))) + daNote.noteYOff; else daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, - 2)) + daNote.noteYOff; + - 0.45 * ((Conductor.songPosition - daNote.strumTime) / songMultiplier) * (FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2))) + daNote.noteYOff; if (daNote.isSustainNote) { - daNote.y -= daNote.height / 2; if (!PlayStateChangeables.botPlay) { - if ((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit || holdArray[Math.floor(Math.abs(daNote.noteData))] && !daNote.tooLate) + if ((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit || holdArray[Math.floor(Math.abs(daNote.noteData))]) && daNote.y + daNote.offset.y * daNote.scale.y <= (strumLine.y + Note.swagWidth / 2)) { // Clip to strumline @@ -3027,9 +2908,9 @@ class PlayState extends MusicBeatState var altAnim:String = ""; - if (SONG.notes[Math.floor(curStep / 16)] != null) + if (currentSection != null) { - if (SONG.notes[Math.floor(curStep / 16)].p1AltAnim) + if (currentSection.CPUAltAnim) altAnim = '-alt'; } @@ -3049,12 +2930,10 @@ class PlayState extends MusicBeatState if (FlxG.save.data.cpuStrums) { - cpuStrums.forEach(function(spr:FlxSprite) + cpuStrums.forEach(function(spr:StaticArrow) { - if (Math.abs(daNote.noteData) == spr.ID) - { - spr.animation.play('confirm', true); - } + pressArrow(spr, spr.ID, daNote); + /* if (spr.animation.curAnim.name == 'confirm' && SONG.noteStyle != 'pixel') { spr.centerOffsets(); @@ -3063,6 +2942,7 @@ class PlayState extends MusicBeatState } else spr.centerOffsets(); + */ }); } @@ -3084,12 +2964,10 @@ class PlayState extends MusicBeatState if (FlxG.save.data.cpuStrums) { - cpuStrums.forEach(function(spr:FlxSprite) + cpuStrums.forEach(function(spr:StaticArrow) { - if (Math.abs(daNote.noteData) == spr.ID) - { - spr.animation.play('confirm', true); - } + pressArrow(spr, spr.ID, daNote); + /* if (spr.animation.curAnim.name == 'confirm' && SONG.noteStyle != 'pixel') { spr.centerOffsets(); @@ -3098,6 +2976,7 @@ class PlayState extends MusicBeatState } else spr.centerOffsets(); + */ }); } @@ -3123,26 +3002,26 @@ class PlayState extends MusicBeatState daNote.visible = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].visible; daNote.x = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].x; if (!daNote.isSustainNote) - daNote.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle; + daNote.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].modAngle; if (daNote.sustainActive) { if (executeModchart) daNote.alpha = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].alpha; } - daNote.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle; + daNote.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].modAngle; } else if (!daNote.wasGoodHit && !daNote.modifiedByLua) { daNote.visible = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].visible; daNote.x = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].x; if (!daNote.isSustainNote) - daNote.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle; + daNote.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].modAngle; if (daNote.sustainActive) { if (executeModchart) daNote.alpha = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].alpha; } - daNote.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle; + daNote.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].modAngle; } if (daNote.isSustainNote) @@ -3162,9 +3041,9 @@ class PlayState extends MusicBeatState notes.remove(daNote, true); daNote.destroy(); } - else if ((daNote.mustPress && daNote.tooLate && !PlayStateChangeables.useDownscroll || daNote.mustPress && daNote.tooLate + else if ((daNote.mustPress && !PlayStateChangeables.useDownscroll || daNote.mustPress && PlayStateChangeables.useDownscroll) - && daNote.mustPress) + && daNote.mustPress && daNote.strumTime / songMultiplier - Conductor.songPosition / songMultiplier < -(166 * Conductor.timeScale) && songStarted) { if (daNote.isSustainNote && daNote.wasGoodHit) { @@ -3202,7 +3081,7 @@ class PlayState extends MusicBeatState && daNote.sustainActive && daNote.spotInLine != daNote.parent.children.length) { - health -= 0.2; // give a health punishment for failing a LN + //health -= 0.05; // give a health punishment for failing a LN trace("hold fell over at " + daNote.spotInLine); for (i in daNote.parent.children) { @@ -3213,7 +3092,8 @@ class PlayState extends MusicBeatState misses++; updateAccuracy(); } - else + else if (!daNote.wasGoodHit + && !daNote.isSustainNote) { health -= 0.15; } @@ -3234,7 +3114,7 @@ class PlayState extends MusicBeatState noteMiss(daNote.noteData, daNote); } - if (daNote.isParent) + if (daNote.isParent && daNote.visible) { health -= 0.15; // give a health punishment for failing a LN trace("hold fell over at the start"); @@ -3242,7 +3122,6 @@ class PlayState extends MusicBeatState { i.alpha = 0.3; i.sustainActive = false; - trace(i.alpha); } } else @@ -3252,19 +3131,19 @@ class PlayState extends MusicBeatState && daNote.sustainActive && daNote.spotInLine != daNote.parent.children.length) { - health -= 0.25; // give a health punishment for failing a LN + //health -= 0.05; // give a health punishment for failing a LN trace("hold fell over at " + daNote.spotInLine); for (i in daNote.parent.children) { i.alpha = 0.3; i.sustainActive = false; - trace(i.alpha); } if (daNote.parent.wasGoodHit) misses++; updateAccuracy(); } - else + else if (!daNote.wasGoodHit + && !daNote.isSustainNote) { health -= 0.15; } @@ -3281,22 +3160,22 @@ class PlayState extends MusicBeatState if (FlxG.save.data.cpuStrums) { - cpuStrums.forEach(function(spr:FlxSprite) + cpuStrums.forEach(function(spr:StaticArrow) { if (spr.animation.finished) { - spr.animation.play('static'); + spr.playAnim('static'); spr.centerOffsets(); } }); if (PlayStateChangeables.botPlay) { - playerStrums.forEach(function(spr:FlxSprite) + playerStrums.forEach(function(spr:StaticArrow) { if (spr.animation.finished) { - spr.animation.play('static'); - spr.centerOffsets(); + spr.playAnim('static'); + //spr.centerOffsets(); } }); } @@ -3309,8 +3188,56 @@ class PlayState extends MusicBeatState if (FlxG.keys.justPressed.ONE) endSong(); #end + + super.update(elapsed); } + public function getSectionByTime(ms:Float):SwagSection + { + + for (i in SONG.notes) + { + var start = TimingStruct.getTimeFromBeat((TimingStruct.getBeatFromTime(i.startTime))); + var end = TimingStruct.getTimeFromBeat((TimingStruct.getBeatFromTime(i.endTime))); + + + if (ms >= start && ms < end) + { + return i; + } + } + + + return null; + } + + function recalculateAllSectionTimes() + { + + trace("RECALCULATING SECTION TIMES"); + + for (i in 0...SONG.notes.length) // loops through sections + { + var section = SONG.notes[i]; + + var currentBeat = 4 * i; + + var currentSeg = TimingStruct.getTimingAtBeat(currentBeat); + + if (currentSeg == null) + return; + + var start:Float = (currentBeat - currentSeg.startBeat) / ((currentSeg.bpm) / 60); + + section.startTime = (currentSeg.startTime + start) * 1000; + + if (i != 0) + SONG.notes[i - 1].endTime = section.startTime; + section.endTime = Math.POSITIVE_INFINITY; + } + } + + function endSong():Void { endingSong = true; @@ -3501,6 +3428,28 @@ class PlayState extends MusicBeatState var hits:Array = []; var offsetTest:Float = 0; + public function getRatesScore(rate:Float, score:Float):Float + { + var rateX:Float = 1; + var lastScore:Float = score; + var pr = rate - 0.05; + if (pr < 1.00) + pr = 1; + + while(rateX <= pr) + { + if (rateX > pr) + break; + lastScore = score + ((lastScore * rateX) * 0.022); + rateX += 0.05; + } + + var actualScore = Math.round(score + (Math.floor((lastScore * pr)) * 0.022)); + + return actualScore; + } + + var timeShown = 0; var currentTimingShown:FlxText = null; @@ -3561,13 +3510,15 @@ class PlayState extends MusicBeatState sicks++; } + if (songMultiplier >= 1.05) + score = getRatesScore(songMultiplier, score); + // trace('Wife accuracy loss: ' + wife + ' | Rating: ' + daRating + ' | Score: ' + score + ' | Weight: ' + (1 - wife)); if (daRating != 'shit' || daRating != 'bad') { songScore += Math.round(score); - songScoreDef += Math.round(ConvertScore.convertScore(noteDiff)); /* if (combo > 60) daRating = 'sick'; @@ -3602,7 +3553,7 @@ class PlayState extends MusicBeatState rating.velocity.y -= FlxG.random.int(140, 175); rating.velocity.x -= FlxG.random.int(0, 10); - var msTiming = HelperFunctions.truncateFloat(noteDiff, 3); + var msTiming = HelperFunctions.truncateFloat(noteDiff / songMultiplier, 3); if (PlayStateChangeables.botPlay && !loadRep) msTiming = 0; @@ -3865,7 +3816,6 @@ class PlayState extends MusicBeatState { if (daNote.isSustainNote && daNote.canBeHit && daNote.mustPress && holdArray[daNote.noteData] && daNote.sustainActive) { - trace(daNote.sustainActive); goodNoteHit(daNote); } }); @@ -3885,7 +3835,7 @@ class PlayState extends MusicBeatState notes.forEachAlive(function(daNote:Note) { - if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit && !directionsAccounted[daNote.noteData]) + if (daNote.canBeHit && daNote.mustPress && !daNote.wasGoodHit && !directionsAccounted[daNote.noteData]) { if (directionList.contains(daNote.noteData)) { @@ -3949,7 +3899,7 @@ class PlayState extends MusicBeatState scoreTxt.color = FlxColor.WHITE; var noteDiff:Float = -(coolNote.strumTime - Conductor.songPosition); anas[coolNote.noteData].hit = true; - anas[coolNote.noteData].hitJudge = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); + anas[coolNote.noteData].hitJudge = Ratings.judgeNote(coolNote); anas[coolNote.noteData].nearestNote = [coolNote.strumTime, coolNote.noteData, coolNote.sustainLength]; goodNoteHit(coolNote); } @@ -3977,9 +3927,9 @@ class PlayState extends MusicBeatState if (PlayStateChangeables.botPlay) notes.forEachAlive(function(daNote:Note) { - var diff = -(daNote.strumTime - Conductor.songPosition); + var diff = -(daNote.strumTime / songMultiplier - Conductor.songPosition / songMultiplier ); - daNote.rating = Ratings.CalculateRating(diff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); + daNote.rating = Ratings.judgeNote(daNote); if (daNote.mustPress && daNote.rating == "sick" || (diff > 0 && daNote.mustPress)) { // Force good note hit regardless if it's too late to hit it or not as a fail safe @@ -3991,21 +3941,36 @@ class PlayState extends MusicBeatState if (n != null) { goodNoteHit(daNote); - boyfriend.holdTimer = daNote.sustainLength; + boyfriend.holdTimer = 0; + if (FlxG.save.data.cpuStrums) + { + playerStrums.forEach(function(spr:StaticArrow) + { + pressArrow(spr, spr.ID, daNote); + /* + if (spr.animation.curAnim.name == 'confirm' && SONG.noteStyle != 'pixel') + { + spr.centerOffsets(); + spr.offset.x -= 13; + spr.offset.y -= 13; + } + else + spr.centerOffsets(); + */ + }); + } } } else { goodNoteHit(daNote); - boyfriend.holdTimer = daNote.sustainLength; + boyfriend.holdTimer = 0; if (FlxG.save.data.cpuStrums) { - playerStrums.forEach(function(spr:FlxSprite) + playerStrums.forEach(function(spr:StaticArrow) { - if (Math.abs(daNote.noteData) == spr.ID) - { - spr.animation.play('confirm', true); - } + pressArrow(spr, spr.ID, daNote); + /* if (spr.animation.curAnim.name == 'confirm' && SONG.noteStyle != 'pixel') { spr.centerOffsets(); @@ -4014,6 +3979,7 @@ class PlayState extends MusicBeatState } else spr.centerOffsets(); + */ }); } } @@ -4028,21 +3994,12 @@ class PlayState extends MusicBeatState if (!PlayStateChangeables.botPlay) { - playerStrums.forEach(function(spr:FlxSprite) + playerStrums.forEach(function(spr:StaticArrow) { - if (keys[spr.ID] && spr.animation.curAnim.name != 'confirm' && spr.animation.curAnim.name != 'pressed') - spr.animation.play('pressed', false); + if (keys[spr.ID] && spr.animation.curAnim.name != 'confirm' && spr.animation.curAnim.name != 'pressed' && !spr.animation.curAnim.name.startsWith('dirCon')) + spr.playAnim('pressed', false); if (!keys[spr.ID]) - spr.animation.play('static', false); - - if (spr.animation.curAnim.name == 'confirm' && SONG.noteStyle != 'pixel') - { - spr.centerOffsets(); - spr.offset.x -= 13; - spr.offset.y -= 13; - } - else - spr.centerOffsets(); + spr.playAnim('static', false); }); } } @@ -4178,7 +4135,7 @@ class PlayState extends MusicBeatState daNote.strumTime, 0, direction, - 166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166 + -(166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166) ]); saveJudge.push("miss"); } @@ -4189,7 +4146,7 @@ class PlayState extends MusicBeatState Conductor.songPosition, 0, direction, - 166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166 + -(166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166) ]); saveJudge.push("miss"); } @@ -4215,6 +4172,7 @@ class PlayState extends MusicBeatState // FlxG.log.add('played imss note'); } + // Hole switch statement replaced with a single line :) boyfriend.playAnim('sing' + dataSuffix[direction] + 'miss', true); @@ -4252,6 +4210,8 @@ class PlayState extends MusicBeatState totalPlayed += 1; accuracy = Math.max(0, totalNotesHit / totalPlayed * 100); accuracyDefault = Math.max(0, totalNotesHitDefault / totalPlayed * 100); + + scoreTxt.text = Ratings.CalculateRanking(songScore, songScoreDef, nps, maxNPS, accuracy); } function getKeyPresses(note:Note):Int @@ -4260,7 +4220,7 @@ class PlayState extends MusicBeatState notes.forEachAlive(function(daNote:Note) { - if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate) + if (daNote.canBeHit && daNote.mustPress) { possibleNotes.push(daNote); possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); @@ -4280,7 +4240,7 @@ class PlayState extends MusicBeatState { var noteDiff:Float = -(note.strumTime - Conductor.songPosition); - note.rating = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); + note.rating = Ratings.judgeNote(note); /* if (loadRep) { @@ -4327,7 +4287,8 @@ class PlayState extends MusicBeatState if (mashing != 0) mashing = 0; - var noteDiff:Float = -(note.strumTime - Conductor.songPosition); + var noteDiff:Float = -(note.strumTime - Conductor.songPosition ); + if (loadRep) { @@ -4335,7 +4296,7 @@ class PlayState extends MusicBeatState note.rating = rep.replay.songJudgements[findByTimeIndex(note.strumTime)]; } else - note.rating = Ratings.CalculateRating(noteDiff); + note.rating = Ratings.judgeNote(note); if (note.rating == "miss") return; @@ -4358,8 +4319,6 @@ class PlayState extends MusicBeatState popUpScore(note); combo += 1; } - else - totalNotesHit += 1; var altAnim:String = ""; if (note.isAlt) @@ -4386,12 +4345,9 @@ class PlayState extends MusicBeatState if (!PlayStateChangeables.botPlay) { - playerStrums.forEach(function(spr:FlxSprite) + playerStrums.forEach(function(spr:StaticArrow) { - if (Math.abs(note.noteData) == spr.ID) - { - spr.animation.play('confirm', true); - } + pressArrow(spr, spr.ID, note); }); } @@ -4405,17 +4361,33 @@ class PlayState extends MusicBeatState { note.wasGoodHit = true; } - - updateAccuracy(); + if (!note.isSustainNote) + updateAccuracy(); } } + function pressArrow(spr:StaticArrow, idCheck:Int, daNote:Note) + { + if (Math.abs(daNote.noteData) == idCheck) + { + if (!FlxG.save.data.stepMania) + { + spr.playAnim('confirm', true); + } + else + { + spr.playAnim('dirCon' + daNote.originColor, true); + spr.localAngle = daNote.originAngle; + } + } + } var fastCarCanDrive:Bool = true; function resetFastCar():Void { if (FlxG.save.data.distractions) { + var fastCar = Stage.swagBacks['fastCar']; fastCar.x = -12600; fastCar.y = FlxG.random.int(140, 250); fastCar.velocity.x = 0; @@ -4429,7 +4401,7 @@ class PlayState extends MusicBeatState { FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7); - fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; + Stage.swagBacks['fastCar'].velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; fastCarCanDrive = false; new FlxTimer().start(2, function(tmr:FlxTimer) { @@ -4469,6 +4441,7 @@ class PlayState extends MusicBeatState if (startedMoving) { + var phillyTrain = Stage.swagBacks['phillyTrain']; phillyTrain.x -= 400; if (phillyTrain.x < -2000 && !trainFinishing) @@ -4491,7 +4464,7 @@ class PlayState extends MusicBeatState if (FlxG.save.data.distractions) { gf.playAnim('hairFall'); - phillyTrain.x = FlxG.width + 200; + Stage.swagBacks['phillyTrain'].x = FlxG.width + 200; trainMoving = false; // trainSound.stop(); // trainSound.time = 0; @@ -4504,7 +4477,7 @@ class PlayState extends MusicBeatState function lightningStrikeShit():Void { FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2)); - halloweenBG.animation.play('lightning'); + Stage.swagBacks['halloweenBG'].animation.play('lightning'); lightningStrikeBeat = curBeat; lightningOffset = FlxG.random.int(8, 24); @@ -4523,38 +4496,41 @@ class PlayState extends MusicBeatState resyncVocals(); } + for (step in Stage.slowBacks.keys()) + { + if (step == curStep) + { + if (Stage.hideLastBG) + { + for (bg in Stage.swagBacks) + { + if (!Stage.slowBacks[step].contains(bg)) + FlxTween.tween(bg, {alpha: 0}, Stage.tweenDuration); + } + for (bg in Stage.slowBacks[step]) + { + FlxTween.tween(bg, {alpha: 1}, Stage.tweenDuration); + } + } + else + { + for (bg in Stage.slowBacks[step]) + bg.visible = !bg.visible; + } + } + } + #if cpp if (executeModchart && luaModchart != null) { luaModchart.setVar('curStep', curStep); luaModchart.executeState('stepHit', [curStep]); } - #end - // yes this updates every step. - // yes this is bad - // but i'm doing it to update misses and accuracy - #if windows - // Song duration in a float, useful for the time left feature - songLength = FlxG.sound.music.length; - // Updating Discord Rich Presence (with Time Left) - DiscordClient.changePresence(detailsText - + " " - + SONG.song - + " (" - + storyDifficultyText - + ") " - + Ratings.GenerateLetterRank(accuracy), - "Acc: " - + HelperFunctions.truncateFloat(accuracy, 2) - + "% | Score: " - + songScore - + " | Misses: " - + misses, iconRPC, true, - songLength - - Conductor.songPosition); + #end + } var lightningStrikeBeat:Int = 0; @@ -4576,9 +4552,9 @@ class PlayState extends MusicBeatState } #end - if (curSong == 'Tutorial' && dad.curCharacter == 'gf' && SONG.notes[Math.floor(curStep / 16)] != null) + if (curSong == 'Tutorial' && dad.curCharacter == 'gf' && currentSection != null) { - if (SONG.notes[Math.floor(curStep / 16)].mustHitSection) + if (currentSection.mustHitSection) dad.dance(); else { @@ -4589,7 +4565,7 @@ class PlayState extends MusicBeatState } } - if (SONG.notes[Math.floor(curStep / 16)] != null) + if (currentSection != null) { // else // Conductor.changeBPM(SONG.bpm); @@ -4597,124 +4573,257 @@ class PlayState extends MusicBeatState // Dad doesnt interupt his own notes if ((!dad.animation.curAnim.name.startsWith("sing")) && dad.curCharacter != 'gf') if ((curBeat % idleBeat == 0 || !idleToBeat) || dad.curCharacter == "spooky") - dad.dance(idleToBeat, SONG.notes[Math.floor(curStep / 16)].p1AltAnim); + dad.dance(idleToBeat, currentSection.CPUAltAnim); } // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); wiggleShit.update(Conductor.crochet); - if (FlxG.save.data.camzoom) + if (FlxG.save.data.camzoom && Conductor.bpm < 340) { // HARDCODING FOR MILF ZOOMS! if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; + FlxG.camera.zoom += 0.015 / songMultiplier; + camHUD.zoom += 0.03 / songMultiplier; } if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; + FlxG.camera.zoom += 0.015 / songMultiplier; + camHUD.zoom += 0.03 / songMultiplier; } } - - iconP1.setGraphicSize(Std.int(iconP1.width + 30)); - iconP2.setGraphicSize(Std.int(iconP2.width + 30)); - - iconP1.updateHitbox(); - iconP2.updateHitbox(); - - if (curBeat % gfSpeed == 0) + if (Conductor.bpm < 340) { - gf.dance(); - } + iconP1.setGraphicSize(Std.int(iconP1.width + 30)); + iconP2.setGraphicSize(Std.int(iconP2.width + 30)); - if (!boyfriend.animation.curAnim.name.startsWith("sing") && (curBeat % idleBeat == 0 || !idleToBeat)) + iconP1.updateHitbox(); + iconP2.updateHitbox(); + } + else { - boyfriend.playAnim('idle' + ((SONG.notes[Math.floor(curStep / 16)].p2AltAnim && boyfriend.animation.getByName('idle-alt') != null) ? '-alt' : ''), idleToBeat); + + iconP1.setGraphicSize(Std.int(iconP1.width + 4)); + iconP2.setGraphicSize(Std.int(iconP2.width + 4)); + + iconP1.updateHitbox(); + iconP2.updateHitbox(); } - /*if (!dad.animation.curAnim.name.startsWith("sing")) + if (!endingSong && currentSection != null) { - dad.dance(); - }*/ + if (curBeat % gfSpeed == 0) + { + gf.dance(); + } - if (curBeat % 8 == 7 && curSong == 'Bopeebo') - { - boyfriend.playAnim('hey', true); - } + if (!boyfriend.animation.curAnim.name.startsWith("sing") && (curBeat % idleBeat == 0 || !idleToBeat)) + { + boyfriend.playAnim('idle' + ((currentSection.playerAltAnim && boyfriend.animation.getByName('idle-alt') != null) ? '-alt' : ''), idleToBeat); + } - if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48) - { - boyfriend.playAnim('hey', true); - dad.playAnim('cheer', true); - } + /*if (!dad.animation.curAnim.name.startsWith("sing")) + { + dad.dance(); + }*/ - switch (curStage) - { - case 'school': - if (FlxG.save.data.distractions) - { - bgGirls.dance(); - } + if (curBeat % 8 == 7 && curSong == 'Bopeebo') + { + boyfriend.playAnim('hey', true); + } - case 'mall': + if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48) + { + boyfriend.playAnim('hey', true); + dad.playAnim('cheer', true); + } + + switch (Stage.curStage) + { + case 'school': + if (FlxG.save.data.distractions && Stage.swagBacks['bgGirls'] != null) + { + Stage.swagBacks['bgGirls'].dance(); + } + + case 'mall': + if (FlxG.save.data.distractions) + { + for (bg in Stage.animatedBacks) + bg.animation.play('idle'); + } + + case 'limo': + if (FlxG.save.data.distractions) + { + Stage.swagGroup['grpLimoDancers'].forEach(function(dancer:BackgroundDancer) + { + dancer.dance(); + }); + + if (FlxG.random.bool(10) && fastCarCanDrive) + fastCarDrive(); + } + case "philly": + if (FlxG.save.data.distractions) + { + if (!trainMoving) + trainCooldown += 1; + + if (curBeat % 4 == 0) + { + var phillyCityLights = Stage.swagGroup['phillyCityLights']; + phillyCityLights.forEach(function(light:FlxSprite) + { + light.visible = false; + }); + + curLight = FlxG.random.int(0, phillyCityLights.length - 1); + + phillyCityLights.members[curLight].visible = true; + // phillyCityLights.members[curLight].alpha = 1; + } + } + + if (curBeat % 8 == 4 && FlxG.random.bool(Conductor.bpm > 320 ? 150 : 30) && !trainMoving && trainCooldown > 8) + { + if (FlxG.save.data.distractions) + { + trainCooldown = FlxG.random.int(-4, 0); + trainStart(); + } + } + } + + if (Stage.halloweenLevel && FlxG.random.bool(Conductor.bpm > 320 ? 100 : 10) && curBeat > lightningStrikeBeat + lightningOffset) + { if (FlxG.save.data.distractions) { - upperBoppers.animation.play('bop', true); - bottomBoppers.animation.play('bop', true); - santa.animation.play('idle', true); + lightningStrikeShit(); } + } + } + } - case 'limo': - if (FlxG.save.data.distractions) + public var cleanedSong:SwagSong; + + function poggers(?cleanTheSong = false) + { + var notes = []; + + if (cleanTheSong) + { + cleanedSong = SONG; + + for(section in cleanedSong.notes) { - grpLimoDancers.forEach(function(dancer:BackgroundDancer) + + var removed = []; + + for(note in section.sectionNotes) { - dancer.dance(); - }); - - if (FlxG.random.bool(10) && fastCarCanDrive) - fastCarDrive(); + // commit suicide + var old = note[0]; + if (note[0] < section.startTime) + { + notes.push(note); + removed.push(note); + } + if (note[0] > section.endTime) + { + notes.push(note); + removed.push(note); + } + } + + for(i in removed) + { + section.sectionNotes.remove(i); + } } - case "philly": - if (FlxG.save.data.distractions) + + for(section in cleanedSong.notes) { - if (!trainMoving) - trainCooldown += 1; - - if (curBeat % 4 == 0) + + var saveRemove = []; + + for(i in notes) { - phillyCityLights.forEach(function(light:FlxSprite) + if (i[0] >= section.startTime && i[0] < section.endTime) { - light.visible = false; - }); + saveRemove.push(i); + section.sectionNotes.push(i); + } + } + + for(i in saveRemove) + notes.remove(i); + } + - curLight = FlxG.random.int(0, phillyCityLights.length - 1); - phillyCityLights.members[curLight].visible = true; - // phillyCityLights.members[curLight].alpha = 1; + trace("FUCK YOU BITCH FUCKER CUCK SUCK BITCH " + cleanedSong.notes.length); + + + SONG = cleanedSong; + } + else + { + + for(section in SONG.notes) + { + + var removed = []; + + for(note in section.sectionNotes) + { + // commit suicide + var old = note[0]; + if (note[0] < section.startTime) + { + notes.push(note); + removed.push(note); + } + if (note[0] > section.endTime) + { + notes.push(note); + removed.push(note); + } + } + + for(i in removed) + { + section.sectionNotes.remove(i); } } - - if (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) + + for(section in SONG.notes) { - if (FlxG.save.data.distractions) + + var saveRemove = []; + + for(i in notes) { - trainCooldown = FlxG.random.int(-4, 0); - trainStart(); + if (i[0] >= section.startTime && i[0] < section.endTime) + { + saveRemove.push(i); + section.sectionNotes.push(i); + } } + + for(i in saveRemove) + notes.remove(i); } - } + - if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset) - { - if (FlxG.save.data.distractions) - { - lightningStrikeShit(); + + trace("FUCK YOU BITCH FUCKER CUCK SUCK BITCH " + cleanedSong.notes.length); + + + SONG = cleanedSong; } } - } var curLight:Int = 0; } diff --git a/source/Ratings.hx b/source/Ratings.hx index 495efb932f..92150f50d9 100644 --- a/source/Ratings.hx +++ b/source/Ratings.hx @@ -92,45 +92,31 @@ class Ratings return ranking; } - public static function CalculateRating(noteDiff:Float, ?customSafeZone:Float):String // Generate a judgement through some timing shit - { - - var customTimeScale = Conductor.timeScale; - - if (customSafeZone != null) - customTimeScale = customSafeZone / 166; - - // trace(customTimeScale + ' vs ' + Conductor.timeScale); - - // I HATE THIS IF CONDITION - // IF LEMON SEES THIS I'M SORRY :( - - // trace('Hit Info\nDifference: ' + noteDiff + '\nZone: ' + Conductor.safeZoneOffset * 1.5 + "\nTS: " + customTimeScale + "\nLate: " + 155 * customTimeScale); - - var rating = checkRating(noteDiff,customTimeScale); - - - return rating; - } + public static var timingWindows = [166,135,90,45]; - public static function checkRating(ms:Float, ts:Float) + public static function judgeNote(note:Note) { - var rating = "shit"; - if (ms <= 166 * ts && ms >= 135 * ts) - rating = "shit"; - if (ms < 135 * ts && ms >= 90 * ts) - rating = "bad"; - if (ms < 90 * ts && ms >= 45 * ts) - rating = "good"; - if (ms < 45 * ts && ms >= -45 * ts) - rating = "sick"; - if (ms > -90 * ts && ms <= -45 * ts) - rating = "good"; - if (ms > -135 * ts && ms <= -90 * ts) - rating = "bad"; - if (ms > -166 * ts && ms <= -135 * ts) - rating = "shit"; - return rating; + var diff = Math.abs(note.strumTime - Conductor.songPosition); + for(index in 0...timingWindows.length) // based on 4 timing windows, will break with anything else + { + var time = timingWindows[index]; + var nextTime = index + 1 > timingWindows.length - 1 ? 0 : timingWindows[index + 1]; + if (diff < time * PlayState.songMultiplier && diff >= nextTime * PlayState.songMultiplier) + { + switch(index) + { + case 0: // shit + return "shit"; + case 1: // bad + return "bad"; + case 2: // good + return "good"; + case 3: // sick + return "sick"; + } + } + } + return "shit"; } public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,maxNPS:Int,accuracy:Float):String @@ -144,4 +130,5 @@ class Ratings " | Accuracy:" + (PlayStateChangeables.botPlay && !PlayState.loadRep ? "N/A" : HelperFunctions.truncateFloat(accuracy, 2) + " %") + // Accuracy " | " + GenerateLetterRank(accuracy) : "") : ""); // Letter Rank } + } diff --git a/source/ResultsScreen.hx b/source/ResultsScreen.hx index 66b5569197..df7700877f 100644 --- a/source/ResultsScreen.hx +++ b/source/ResultsScreen.hx @@ -88,7 +88,7 @@ class ResultsScreen extends FlxSubState var bads = PlayState.isStoryMode ? PlayState.campaignBads : PlayState.bads; var shits = PlayState.isStoryMode ? PlayState.campaignShits : PlayState.shits; - comboText = new FlxText(20,-75,0,'Judgements:\nSicks - ${sicks}\nGoods - ${goods}\nBads - ${bads}\n\nCombo Breaks: ${(PlayState.isStoryMode ? PlayState.campaignMisses : PlayState.misses)}\nHighest Combo: ${PlayState.highestCombo + 1}\nScore: ${PlayState.instance.songScore}\nAccuracy: ${HelperFunctions.truncateFloat(PlayState.instance.accuracy,2)}%\n\n${Ratings.GenerateLetterRank(PlayState.instance.accuracy)}\n\n${!PlayState.loadRep ? "F1 - View replay\nF2 - Replay song" : ""} + comboText = new FlxText(20,-75,0,'Judgements:\nSicks - ${sicks}\nGoods - ${goods}\nBads - ${bads}\n\nCombo Breaks: ${(PlayState.isStoryMode ? PlayState.campaignMisses : PlayState.misses)}\nHighest Combo: ${PlayState.highestCombo + 1}\nScore: ${PlayState.instance.songScore}\nAccuracy: ${HelperFunctions.truncateFloat(PlayState.instance.accuracy,2)}%\n\n${Ratings.GenerateLetterRank(PlayState.instance.accuracy)}\nRate: ${PlayState.songMultiplier}x\n\n${!PlayState.loadRep ? "\nF1 - Replay song" : ""} '); comboText.size = 28; comboText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1); @@ -147,7 +147,7 @@ class ResultsScreen extends FlxSubState if (diff != (166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166)) mean += diff; if (obj[1] != -1) - graph.addToHistory(diff, judge, obj3); + graph.addToHistory(diff / PlayState.songMultiplier, judge, obj3 / PlayState.songMultiplier); } if (sicks == Math.POSITIVE_INFINITY || sicks == Math.NaN) @@ -222,77 +222,6 @@ class ResultsScreen extends FlxSubState } if (FlxG.keys.justPressed.F1 && !PlayState.loadRep) - { - trace(PlayState.rep.path); - PlayState.rep = Replay.LoadReplay(PlayState.rep.path); - - PlayState.loadRep = true; - PlayState.isSM = PlayState.rep.replay.sm; - - var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-"); - switch (songFormat) { - case 'Dad-Battle': songFormat = 'Dadbattle'; - case 'Philly-Nice': songFormat = 'Philly'; - // Replay v1.0 support - case 'dad-battle': songFormat = 'Dadbattle'; - case 'philly-nice': songFormat = 'Philly'; - } - - var songHighscore = StringTools.replace(PlayState.SONG.song, " ", "-"); - switch (songHighscore) { - case 'Dad-Battle': songHighscore = 'Dadbattle'; - case 'Philly-Nice': songHighscore = 'Philly'; - } - - #if !switch - Highscore.saveScore(songHighscore, Math.round(PlayState.instance.songScore), PlayState.storyDifficulty); - Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(PlayState.instance.accuracy),PlayState.storyDifficulty); - #end - - #if sys - if (PlayState.rep.replay.sm) - if (!FileSystem.exists(StringTools.replace(PlayState.rep.replay.chartPath,"converted.json",""))) - { - Application.current.window.alert("The SM file in this replay does not exist!","SM Replays"); - return; - } - #end - - var poop = ""; - - #if sys - if (PlayState.isSM) - { - poop = File.getContent(PlayState.rep.replay.chartPath); - try - { - PlayState.sm = SMFile.loadFile(PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm"); - } - catch(e:Exception) - { - Application.current.window.alert("Make sure that the SM file is called " + PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm!\nAs I couldn't read it.","SM Replays"); - return; - } - } - else - poop = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); - #else - poop = Highscore.formatSong(PlayState.rep.replay.songName, PlayState.rep.replay.songDiff); - #end - - music.fadeOut(0.3); - - if (PlayState.isSM) - PlayState.SONG = Song.conversionChecks(Song.loadFromJsonRAW(poop)); - else - PlayState.SONG = Song.conversionChecks(Song.loadFromJson(poop, PlayState.rep.replay.songName)); - PlayState.isStoryMode = false; - PlayState.storyDifficulty = PlayState.rep.replay.songDiff; - LoadingState.loadAndSwitchState(new PlayState()); - PlayState.instance.clean(); - } - - if (FlxG.keys.justPressed.F2 && !PlayState.loadRep) { PlayState.rep = null; @@ -309,20 +238,9 @@ class ResultsScreen extends FlxSubState Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(PlayState.instance.accuracy),PlayState.storyDifficulty); #end - var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-"); - switch (songFormat) { - case 'Dad-Battle': songFormat = 'Dadbattle'; - case 'Philly-Nice': songFormat = 'Philly'; - case 'dad-battle': songFormat = 'Dadbattle'; - case 'philly-nice': songFormat = 'Philly'; - } - - var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty); - if (music != null) music.fadeOut(0.3); - PlayState.SONG = Song.loadFromJson(poop, PlayState.SONG.song); PlayState.isStoryMode = false; PlayState.storyDifficulty = PlayState.storyDifficulty; LoadingState.loadAndSwitchState(new PlayState()); diff --git a/source/Section.hx b/source/Section.hx index cd17e25289..1e92e87334 100644 --- a/source/Section.hx +++ b/source/Section.hx @@ -11,8 +11,8 @@ typedef SwagSection = var bpm:Float; var changeBPM:Bool; var altAnim:Bool; - var p1AltAnim:Bool; - var p2AltAnim:Bool; + var CPUAltAnim:Bool; + var playerAltAnim:Bool; } class Section diff --git a/source/Song.hx b/source/Song.hx index a0cbecb5b0..cc858003d7 100644 --- a/source/Song.hx +++ b/source/Song.hx @@ -43,6 +43,7 @@ typedef SwagSong = class Song { + public static var latestChart:String = "KE1"; public var chartVersion:String; public var song:String; public var notes:Array; @@ -63,6 +64,7 @@ class Song this.notes = notes; this.bpm = bpm; } + public static function loadFromJsonRAW(rawJson:String) { @@ -74,6 +76,7 @@ class Song return parseJSONshit(rawJson); } + public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong { @@ -137,6 +140,41 @@ class Song song.eventObjects = convertedStuff; + if (song.noteStyle == null) + song.noteStyle = "normal"; + + if (song.gfVersion == null) + song.gfVersion = "gf"; + + + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in song.eventObjects) + { + if (i.type == "BPM Change") + { + var beat:Float = i.position; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + 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; + } + + currentIndex++; + } + } + + for(i in song.notes) { var currentBeat = 4 * index; @@ -157,13 +195,21 @@ class Song for(ii in i.sectionNotes) { - if (ii[3] == null) + if (song.chartVersion == null) + { ii[3] = false; + ii[4] = TimingStruct.getBeatFromTime(ii[0]); + } + + if (ii[3] == 0) + ii[3] == false; } index++; } + song.chartVersion = latestChart; + return song; } @@ -178,7 +224,7 @@ class Song for (section in swagShit.notes) { if (section.altAnim) - section.p1AltAnim = section.altAnim; + section.CPUAltAnim = section.altAnim; } return swagShit; diff --git a/source/Stage.hx b/source/Stage.hx new file mode 100644 index 0000000000..ba7efe23aa --- /dev/null +++ b/source/Stage.hx @@ -0,0 +1,430 @@ +package; + +import flixel.FlxSprite; +import flixel.FlxG; +import flixel.FlxBasic; +import flixel.group.FlxGroup; +import flixel.system.FlxSound; +import flixel.addons.effects.chainable.FlxWaveEffect; + +class Stage +{ + public var curStage:String = ''; + public var halloweenLevel:Bool = false; + public var camZoom:Float; + public var hideLastBG:Bool = false; // True = hide last BG and show ones from slowBacks on certain step, False = Toggle Visibility of BGs from SlowBacks on certain step + public var tweenDuration:Float = 2; // How long will it tween hiding/showing BGs, variable above must be set to True for tween to activate + public var toAdd:Array = []; // Add BGs on stage startup, load BG in by using "toAdd.push(bgVar);" + // Layering algorithm for noobs: Everything loads by the method of "On Top", example: You load wall first(Every other added BG layers on it), then you load road(comes on top of wall and doesn't clip through it), then loading street lights(comes on top of wall and road) + public var swagBacks:Map = []; // Store BGs here to use them later in PlayState or when slowBacks activate + public var swagGroup:Map> = []; //Store Groups + public var animatedBacks:Array = []; // Store animated backgrounds and make them play animation(Animation must be named Idle!! Else use swagGroup) + public var layInFront:Array> = [[], [], []]; // BG layering, format: first [0] - in front of GF, second [1] - in front of opponent, third [2] - in front of boyfriend(and techincally also opponent since Haxe layering moment) + public var slowBacks:Map> = []; // Change/add/remove backgrounds mid song! Format: "slowBacks[StepToBeActivated] = [Sprites,To,Be,Changed,Or,Added];" + + public function new(daStage:String) + { + this.curStage = daStage; + camZoom = 1.05; // Don't change zoom here, unless you want to change zoom of every stage that doesn't have custom one + halloweenLevel = false; + + switch(daStage) + { + case 'halloween': + { + halloweenLevel = true; + + var hallowTex = Paths.getSparrowAtlas('halloween_bg', 'week2'); + + var halloweenBG = new FlxSprite(-200, -100); + halloweenBG.frames = hallowTex; + halloweenBG.animation.addByPrefix('idle', 'halloweem bg0'); + halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false); + halloweenBG.animation.play('idle'); + halloweenBG.antialiasing = FlxG.save.data.antialiasing; + swagBacks['halloweenBG'] = halloweenBG; + toAdd.push(halloweenBG); + } + case 'philly': + { + + var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky', 'week3')); + bg.scrollFactor.set(0.1, 0.1); + swagBacks['bg'] = bg; + toAdd.push(bg); + + var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city', 'week3')); + city.scrollFactor.set(0.3, 0.3); + city.setGraphicSize(Std.int(city.width * 0.85)); + city.updateHitbox(); + swagBacks['city'] = city; + toAdd.push(city); + + var phillyCityLights = new FlxTypedGroup(); + if (FlxG.save.data.distractions) + { + swagGroup['phillyCityLights'] = phillyCityLights; + toAdd.push(phillyCityLights); + } + + for (i in 0...5) + { + var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i, 'week3')); + light.scrollFactor.set(0.3, 0.3); + light.visible = false; + light.setGraphicSize(Std.int(light.width * 0.85)); + light.updateHitbox(); + light.antialiasing = FlxG.save.data.antialiasing; + phillyCityLights.add(light); + } + + var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain', 'week3')); + swagBacks['streetBehind'] = streetBehind; + toAdd.push(streetBehind); + + var phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train', 'week3')); + if (FlxG.save.data.distractions) + { + swagBacks['phillyTrain'] = phillyTrain; + toAdd.push(phillyTrain); + } + + PlayState.trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes', 'week3')); + FlxG.sound.list.add(PlayState.trainSound); + + // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png); + + var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street', 'week3')); + swagBacks['street'] = street; + toAdd.push(street); + } + case 'limo': + { + camZoom = 0.90; + + var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset', 'week4')); + skyBG.scrollFactor.set(0.1, 0.1); + skyBG.antialiasing = FlxG.save.data.antialiasing; + swagBacks['skyBG'] = skyBG; + toAdd.push(skyBG); + + var bgLimo:FlxSprite = new FlxSprite(-200, 480); + bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo', 'week4'); + bgLimo.animation.addByPrefix('drive', "background limo pink", 24); + bgLimo.animation.play('drive'); + bgLimo.scrollFactor.set(0.4, 0.4); + bgLimo.antialiasing = FlxG.save.data.antialiasing; + swagBacks['bgLimo'] = bgLimo; + toAdd.push(bgLimo); + + var fastCar:FlxSprite; + fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol', 'week4')); + fastCar.antialiasing = FlxG.save.data.antialiasing; + + if (FlxG.save.data.distractions) + { + var grpLimoDancers = new FlxTypedGroup(); + swagGroup['grpLimoDancers'] = grpLimoDancers; + toAdd.push(grpLimoDancers); + + for (i in 0...5) + { + var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400); + dancer.scrollFactor.set(0.4, 0.4); + grpLimoDancers.add(dancer); + } + + swagBacks['fastCar'] = fastCar; + layInFront[2].push(fastCar); + } + + var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay', 'week4')); + overlayShit.alpha = 0.5; + // add(overlayShit); + + // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED); + + // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]); + + // overlayShit.shader = shaderBullshit; + + var limoTex = Paths.getSparrowAtlas('limo/limoDrive', 'week4'); + + var limo = new FlxSprite(-120, 550); + limo.frames = limoTex; + limo.animation.addByPrefix('drive', "Limo stage", 24); + limo.animation.play('drive'); + limo.antialiasing = FlxG.save.data.antialiasing; + layInFront[0].push(limo); + swagBacks['limo'] = limo; + + // Testing + // + // hideLastBG = true; + // slowBacks[40] = [limo]; + // slowBacks[120] = [limo, bgLimo, skyBG, fastCar]; + } + case 'mall': + { + camZoom = 0.80; + + var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls', 'week5')); + bg.antialiasing = FlxG.save.data.antialiasing; + bg.scrollFactor.set(0.2, 0.2); + bg.active = false; + bg.setGraphicSize(Std.int(bg.width * 0.8)); + bg.updateHitbox(); + swagBacks['bg'] = bg; + toAdd.push(bg); + + var upperBoppers = new FlxSprite(-240, -90); + upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop', 'week5'); + upperBoppers.animation.addByPrefix('idle', "Upper Crowd Bob", 24, false); + upperBoppers.antialiasing = FlxG.save.data.antialiasing; + upperBoppers.scrollFactor.set(0.33, 0.33); + upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85)); + upperBoppers.updateHitbox(); + if (FlxG.save.data.distractions) + { + swagBacks['upperBoppers'] = upperBoppers; + toAdd.push(upperBoppers); + animatedBacks.push(upperBoppers); + } + + var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator', 'week5')); + bgEscalator.antialiasing = FlxG.save.data.antialiasing; + bgEscalator.scrollFactor.set(0.3, 0.3); + bgEscalator.active = false; + bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9)); + bgEscalator.updateHitbox(); + swagBacks['bgEscalator'] = bgEscalator; + toAdd.push(bgEscalator); + + var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree', 'week5')); + tree.antialiasing = FlxG.save.data.antialiasing; + tree.scrollFactor.set(0.40, 0.40); + swagBacks['tree'] = tree; + toAdd.push(tree); + + var bottomBoppers = new FlxSprite(-300, 140); + bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop', 'week5'); + bottomBoppers.animation.addByPrefix('idle', 'Bottom Level Boppers', 24, false); + bottomBoppers.antialiasing = FlxG.save.data.antialiasing; + bottomBoppers.scrollFactor.set(0.9, 0.9); + bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1)); + bottomBoppers.updateHitbox(); + if (FlxG.save.data.distractions) + { + swagBacks['bottomBoppers'] = bottomBoppers; + toAdd.push(bottomBoppers); + animatedBacks.push(bottomBoppers); + } + + var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow', 'week5')); + fgSnow.active = false; + fgSnow.antialiasing = FlxG.save.data.antialiasing; + swagBacks['fgSnow'] = fgSnow; + toAdd.push(fgSnow); + + var santa = new FlxSprite(-840, 150); + santa.frames = Paths.getSparrowAtlas('christmas/santa', 'week5'); + santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false); + santa.antialiasing = FlxG.save.data.antialiasing; + if (FlxG.save.data.distractions) + { + swagBacks['santa'] = santa; + toAdd.push(santa); + animatedBacks.push(santa); + } + } + case 'mallEvil': + { + var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG', 'week5')); + bg.antialiasing = FlxG.save.data.antialiasing; + bg.scrollFactor.set(0.2, 0.2); + bg.active = false; + bg.setGraphicSize(Std.int(bg.width * 0.8)); + bg.updateHitbox(); + swagBacks['bg'] = bg; + toAdd.push(bg); + + var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree', 'week5')); + evilTree.antialiasing = FlxG.save.data.antialiasing; + evilTree.scrollFactor.set(0.2, 0.2); + swagBacks['evilTree'] = evilTree; + toAdd.push(evilTree); + + var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow", 'week5')); + evilSnow.antialiasing = FlxG.save.data.antialiasing; + swagBacks['evilSnow'] = evilSnow; + toAdd.push(evilSnow); + } + case 'school': + { + // defaultCamZoom = 0.9; + + var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky', 'week6')); + bgSky.scrollFactor.set(0.1, 0.1); + swagBacks['bgSky'] = bgSky; + toAdd.push(bgSky); + + var repositionShit = -200; + + var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool', 'week6')); + bgSchool.scrollFactor.set(0.6, 0.90); + swagBacks['bgSchool'] = bgSchool; + toAdd.push(bgSchool); + + var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet', 'week6')); + bgStreet.scrollFactor.set(0.95, 0.95); + swagBacks['bgStreet'] = bgStreet; + toAdd.push(bgStreet); + + var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack', 'week6')); + fgTrees.scrollFactor.set(0.9, 0.9); + swagBacks['fgTrees'] = fgTrees; + toAdd.push(fgTrees); + + var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800); + var treetex = Paths.getPackerAtlas('weeb/weebTrees', 'week6'); + bgTrees.frames = treetex; + bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12); + bgTrees.animation.play('treeLoop'); + bgTrees.scrollFactor.set(0.85, 0.85); + swagBacks['bgTrees'] = bgTrees; + toAdd.push(bgTrees); + + var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40); + treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals', 'week6'); + treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true); + treeLeaves.animation.play('leaves'); + treeLeaves.scrollFactor.set(0.85, 0.85); + swagBacks['treeLeaves'] = treeLeaves; + toAdd.push(treeLeaves); + + var widShit = Std.int(bgSky.width * 6); + + bgSky.setGraphicSize(widShit); + bgSchool.setGraphicSize(widShit); + bgStreet.setGraphicSize(widShit); + bgTrees.setGraphicSize(Std.int(widShit * 1.4)); + fgTrees.setGraphicSize(Std.int(widShit * 0.8)); + treeLeaves.setGraphicSize(widShit); + + fgTrees.updateHitbox(); + bgSky.updateHitbox(); + bgSchool.updateHitbox(); + bgStreet.updateHitbox(); + bgTrees.updateHitbox(); + treeLeaves.updateHitbox(); + + var bgGirls = new BackgroundGirls(-100, 190); + bgGirls.scrollFactor.set(0.9, 0.9); + + if (PlayState.SONG.song.toLowerCase() == 'roses') + { + if (FlxG.save.data.distractions) + { + bgGirls.getScared(); + } + } + + bgGirls.setGraphicSize(Std.int(bgGirls.width * PlayState.daPixelZoom)); + bgGirls.updateHitbox(); + if (FlxG.save.data.distractions) + { + swagBacks['bgGirls'] = bgGirls; + toAdd.push(bgGirls); + } + } + case 'schoolEvil': + { + if (!PlayStateChangeables.Optimize) + { + var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); + var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); + } + + var posX = 400; + var posY = 200; + + var bg:FlxSprite = new FlxSprite(posX, posY); + bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool', 'week6'); + bg.animation.addByPrefix('idle', 'background 2', 24); + bg.animation.play('idle'); + bg.scrollFactor.set(0.8, 0.9); + bg.scale.set(6, 6); + swagBacks['bg'] = bg; + toAdd.push(bg); + + /* + var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG')); + bg.scale.set(6, 6); + // bg.setGraphicSize(Std.int(bg.width * 6)); + // bg.updateHitbox(); + add(bg); + var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG')); + fg.scale.set(6, 6); + // fg.setGraphicSize(Std.int(fg.width * 6)); + // fg.updateHitbox(); + add(fg); + wiggleShit.effectType = WiggleEffectType.DREAMY; + wiggleShit.waveAmplitude = 0.01; + wiggleShit.waveFrequency = 60; + wiggleShit.waveSpeed = 0.8; + */ + + // bg.shader = wiggleShit.shader; + // fg.shader = wiggleShit.shader; + + /* + var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]); + var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]); + // Using scale since setGraphicSize() doesnt work??? + waveSprite.scale.set(6, 6); + waveSpriteFG.scale.set(6, 6); + waveSprite.setPosition(posX, posY); + waveSpriteFG.setPosition(posX, posY); + waveSprite.scrollFactor.set(0.7, 0.8); + waveSpriteFG.scrollFactor.set(0.9, 0.8); + // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6)); + // waveSprite.updateHitbox(); + // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6)); + // waveSpriteFG.updateHitbox(); + add(waveSprite); + add(waveSpriteFG); + */ + } + default: + { + camZoom = 0.9; + curStage = 'stage'; + var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); + bg.antialiasing = FlxG.save.data.antialiasing; + bg.scrollFactor.set(0.9, 0.9); + bg.active = false; + swagBacks['bg'] = bg; + toAdd.push(bg); + + var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); + stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); + stageFront.updateHitbox(); + stageFront.antialiasing = FlxG.save.data.antialiasing; + stageFront.scrollFactor.set(0.9, 0.9); + stageFront.active = false; + swagBacks['stageFront'] = stageFront; + toAdd.push(stageFront); + + var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); + stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); + stageCurtains.updateHitbox(); + stageCurtains.antialiasing = FlxG.save.data.antialiasing; + stageCurtains.scrollFactor.set(1.3, 1.3); + stageCurtains.active = false; + + swagBacks['stageCurtains'] = stageCurtains; + toAdd.push(stageCurtains); + } + } + } +} \ No newline at end of file diff --git a/source/StagePositioningDebug.hx b/source/StagePositioningDebug.hx new file mode 100644 index 0000000000..e34099ede6 --- /dev/null +++ b/source/StagePositioningDebug.hx @@ -0,0 +1,182 @@ +package; + +import flixel.FlxState; +import flixel.FlxG; +import flixel.FlxObject; +import flixel.group.FlxGroup; +import flixel.text.FlxText; +import flixel.FlxCamera; +import flixel.FlxSprite; + +class StagePositioningDebug extends FlxState +{ + public var daStage:String; + public var daBf:String; + public var daGf:String; + public var opponent:String; + + var gf:Character; + var boyfriend:Boyfriend; + var dad:Character; + var Stage:Stage; + var camFollow:FlxObject; + var posText:FlxText; + var curChar:FlxSprite; + var curCharIndex:Int = 0; + var curCharString:String; + var curChars:Array; + var dragging:Bool = false; + var oldMousePosX:Int; + var oldMousePosY:Int; + var camHUD:FlxCamera; + var camGame:FlxCamera; + + public function new(daStage:String = 'stage', daGf:String = 'gf', daBf:String = 'bf', opponent:String = 'dad') + { + super(); + this.daStage = daStage; + this.daGf = daGf; + this.daBf = daBf; + this.opponent = opponent; + curCharString = daGf; + } + + override function create() + { + FlxG.sound.music.stop(); + FlxG.mouse.visible = true; + + Stage = PlayState.Stage; + + gf = PlayState.gf; + boyfriend = PlayState.boyfriend; + dad = PlayState.dad; + curChars = [gf, boyfriend, dad]; + curChar = curChars[curCharIndex]; + + for (i in Stage.toAdd) + { + add(i); + } + + for (index => array in Stage.layInFront) + { + switch (index) + { + case 0: + add(gf); + for (bg in array) + add(bg); + case 1: + add(dad); + for (bg in array) + add(bg); + case 2: + add(boyfriend); + for (bg in array) + add(bg); + } + } + + camFollow = new FlxObject(0, 0, 2, 2); + camFollow.screenCenter(); + add(camFollow); + + camHUD = new FlxCamera(); + camHUD.bgColor.alpha = 0; + camGame = new FlxCamera(); + camGame.zoom = 0.7; + FlxG.cameras.add(camGame); + FlxG.cameras.add(camHUD); + FlxCamera.defaultCameras = [camGame]; + camGame.follow(camFollow); + + posText = new FlxText(0, 0); + posText.size = 26; + posText.scrollFactor.set(); + posText.cameras = [camHUD]; + add(posText); + } + + override public function update(elapsed:Float) + { + if (FlxG.keys.justPressed.E) + camGame.zoom += 0.1; + if (FlxG.keys.justPressed.Q) + { + if (camGame.zoom > 0.11) // me when floating point error + camGame.zoom -= 0.1; + } + FlxG.watch.addQuick('Camera Zoom', camGame.zoom); + + if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L) + { + if (FlxG.keys.pressed.I) + camFollow.velocity.y = -90; + else if (FlxG.keys.pressed.K) + camFollow.velocity.y = 90; + else + camFollow.velocity.y = 0; + + if (FlxG.keys.pressed.J) + camFollow.velocity.x = -90; + else if (FlxG.keys.pressed.L) + camFollow.velocity.x = 90; + else + camFollow.velocity.x = 0; + } + else + { + camFollow.velocity.set(); + } + + if (FlxG.keys.justPressed.SPACE) + { + ++curCharIndex; + if (curCharIndex >= curChars.length) + { + curChar = curChars[0]; + curCharIndex = 0; + } + else + curChar = curChars[curCharIndex]; + switch (curCharIndex) + { + case 0: + curCharString = daGf; + case 1: + curCharString = daBf; + case 2: + curCharString = opponent; + } + } + + if (FlxG.mouse.pressed && curChar.pixelsOverlapPoint(FlxG.mouse.getPosition()) && !dragging) + { + dragging = true; + updateMousePos(); + } + + if (dragging && FlxG.mouse.justMoved) + { + curChar.setPosition(-(oldMousePosX - FlxG.mouse.x) + curChar.x, -(oldMousePosY - FlxG.mouse.y) + curChar.y); + updateMousePos(); + } + + if (dragging && FlxG.mouse.justReleased || FlxG.keys.justPressed.TAB) + dragging = false; + + posText.text = (curCharString + " X: " + curChar.x + " Y: " + curChar.y); + + if (FlxG.keys.justPressed.ESCAPE) + FlxG.switchState(new MainMenuState()); + + super.update(elapsed); + } + + public function updateMousePos() + { + oldMousePosX = FlxG.mouse.x; + oldMousePosY = FlxG.mouse.y; + } +} \ No newline at end of file diff --git a/source/StaticArrow.hx b/source/StaticArrow.hx new file mode 100644 index 0000000000..a5d54ab53a --- /dev/null +++ b/source/StaticArrow.hx @@ -0,0 +1,54 @@ +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.animation.FlxBaseAnimation; +import flixel.graphics.frames.FlxAtlasFrames; + +using StringTools; + +class StaticArrow extends FlxSprite +{ + public var modifiedByLua:Bool = false; + public var modAngle:Float = 0; // The angle set by modcharts + public var localAngle:Float = 0; // The angle to be edited inside here + + public function new(xx:Float, yy:Float) + { + x = xx; + y = yy; + super(x, y); + updateHitbox(); + } + + override function update(elapsed:Float) + { + if (!modifiedByLua) + angle = localAngle + modAngle; + else + angle = modAngle; + super.update(elapsed); + + if (FlxG.keys.justPressed.THREE) + { + localAngle += 10; + } + } + + public function playAnim(AnimName:String, ?force:Bool = false):Void + { + animation.play(AnimName, force); + + if (!AnimName.startsWith('dirCon')) + { + localAngle = 0; + } + updateHitbox(); + offset.set(frameWidth / 2, frameHeight / 2); + + offset.x -= 54; + offset.y -= 56; + + angle = localAngle + modAngle; + } +} diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index e046ed64e6..6fb80d217b 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -352,7 +352,7 @@ class StoryMenuState extends MusicBeatState PlayState.storyPlaylist = weekData()[curWeek]; PlayState.isStoryMode = true; selectedWeek = true; - + PlayState.songMultiplier = 1; PlayState.storyDifficulty = curDifficulty; diff --git a/source/TimingStruct.hx b/source/TimingStruct.hx index d1301c1880..1e933e43f6 100644 --- a/source/TimingStruct.hx +++ b/source/TimingStruct.hx @@ -4,12 +4,12 @@ class TimingStruct { public static var AllTimings:Array = []; - public var bpm:Float = 0; + public var bpm:Float = 0; // idk what does this do - public var startBeat:Float = 0; - public var startStep:Int = 0; - public var endBeat:Float = Math.POSITIVE_INFINITY; - public var startTime:Float = 0; + public var startBeat:Float = 0; // BEATS + public var startStep:Int = 0; // BAD MEASUREMENTS + public var endBeat:Float = Math.POSITIVE_INFINITY; // BEATS + public var startTime:Float = 0; // SECONDS public var length:Float = Math.POSITIVE_INFINITY; // in beats @@ -24,6 +24,29 @@ class TimingStruct AllTimings.push(pog); } + public static function getBeatFromTime(time:Float) + { + var beat = -1.0; + var seg = TimingStruct.getTimingAtTimestamp(time); + + if (seg != null) + beat = seg.startBeat + (((time / 1000) - seg.startTime) * (seg.bpm / 60)); + + return beat; + } + + public static function getTimeFromBeat(beat:Float) + { + var time = -1.0; + var seg = TimingStruct.getTimingAtBeat(beat); + + if (seg != null) + time = seg.startTime + ((beat - seg.startBeat) / (seg.bpm / 60)); + + return time * 1000; + } + + public function new(startBeat:Float,bpm:Float,endBeat:Float, offset:Float) { this.bpm = bpm; @@ -40,7 +63,6 @@ class TimingStruct if (msTime >= i.startTime * 1000 && msTime < (i.startTime + i.length) * 1000) return i; } - trace('Apparently ' + msTime + ' is out of any segs'); return null; } diff --git a/source/smTools/SMFile.hx b/source/smTools/SMFile.hx index 145ccb032d..d5b81be271 100644 --- a/source/smTools/SMFile.hx +++ b/source/smTools/SMFile.hx @@ -134,7 +134,8 @@ class SMFile noteStyle: 'normal', stage: 'stage', speed: 1.0, - validScore: false + validScore: false, + chartVersion: "", }; // lets check if the sm loading was valid @@ -244,16 +245,16 @@ class SMFile switch(numba) { case 1: // normal - section.sectionNotes.push([rowTime,lane ,0]); + section.sectionNotes.push([rowTime,lane ,0,0, currentBeat]); case 2: // held head - heldNotes[lane] = [rowTime,lane,0]; + heldNotes[lane] = [rowTime,lane,0,0, currentBeat]; case 3: // held tail var data = heldNotes[lane]; var timeDiff = rowTime - data[0]; - section.sectionNotes.push([data[0],lane,timeDiff]); + section.sectionNotes.push([data[0],lane,timeDiff,0, data[4]]); heldNotes[index] = []; case 4: // roll head - heldNotes[lane] = [rowTime,lane,0]; + heldNotes[lane] = [rowTime,lane,0,0, currentBeat]; } index++; } @@ -327,6 +328,8 @@ class SMFile // save da song + song.chartVersion = Song.latestChart; + var json = { "song": song }; diff --git a/version.downloadMe b/version.downloadMe index 93bbd4b397..ab531e921b 100644 --- a/version.downloadMe +++ b/version.downloadMe @@ -1,8 +1,8 @@ -1.6.2; -- Added the ability to select and modify notes in the editor -- Added copy and paste (with ctrl z support) while selecting notes -- Optimized gameplay -- Optimized the chart editor (less lag on longer songs, and faster load times) -- Fixed stutter at the start of a song -- Fixed scroll speed changes so they work when more then one of them exist -- Modcharts now work on Linux! \ No newline at end of file +1.7; +- A speed modifier +- Completely redid all of the modcharting api +- Optimized a lot of code to run better +- Allowed numpad to be binded as a key +- Changed the editor to work entirely on beats +- Fix multiplie crashes with story mode and other weeks in story mode +- Fix desyncs with bpm changes and section notes in the charter \ No newline at end of file