diff --git a/buildnumber.txt b/buildnumber.txt index 1fc188de..3c2af958 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -525 \ No newline at end of file +526 \ No newline at end of file diff --git a/source/funkin/game/Character.hx b/source/funkin/game/Character.hx index 03bd9544..24b8daf6 100644 --- a/source/funkin/game/Character.hx +++ b/source/funkin/game/Character.hx @@ -66,7 +66,6 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom } public function playSingAnim(direction:Int, suffix:String = "", Reversed:Bool = false, Frame:Int = 0) { - // TODO: Script Events var anims = ["singLEFT", "singDOWN", "singUP", "singRIGHT"]; var event = new DirectionAnimEvent('${anims[direction]}$suffix', direction, suffix, Reversed, Frame); @@ -381,7 +380,6 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom var event = new PlayAnimEvent(AnimName, Force, Reversed, Frame); script.call("onPlayAnim", [event]); - // TODO: Character Scripts if (event.cancelled || event.animName == null) return; diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx index 91817670..514382ab 100644 --- a/source/funkin/game/Note.hx +++ b/source/funkin/game/Note.hx @@ -43,7 +43,7 @@ class Note extends FlxSprite public static var swagWidth:Float = 160 * 0.7; - public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false) + public function new(strumTime:Float, noteData:Int, noteType:Int = 0, mustPress:Bool = true, ?prevNote:Note, ?sustainNote:Bool = false) { super(); diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index a47e97e3..8efc6541 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -338,18 +338,18 @@ class PlayState extends MusicBeatState var swagCounter:Int = 0; + introAssets.set('school', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); + introAssets.set('schoolEvil', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); + + var introSprites:Array = [null, 'ready', "set", "go"]; + var introSounds:Array = ['intro3', 'intro2', "intro1", "introGo"]; + startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer) { dad.dance(); gf.dance(); boyfriend.playAnim('idle'); - var introAssets:Map> = new Map>(); - introAssets.set('default', ['ready', "set", "go"]); - introAssets.set('school', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); - introAssets.set('schoolEvil', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); - - var introAlts:Array = introAssets.get('default'); var altSuffix:String = ""; for (value in introAssets.keys()) @@ -361,73 +361,46 @@ class PlayState extends MusicBeatState } } - // TODO: Cancelable countdown - scripts.call("onCountdown", [swagCounter]); + var event:CountdownEvent = scripts.event("onCountdown", new CountdownEvent( + introSprites[swagCounter], + introSounds[swagCounter], + 1, 0.6, true)); - switch (swagCounter) + var sprite:FlxSprite; + var sound:FlxSound; + var tween:FlxTween; - { - case 0: - FlxG.sound.play(Paths.sound('intro3'), 0.6); - case 1: - var ready:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[0])); - ready.scrollFactor.set(); - ready.updateHitbox(); + if (!event.cancelled) { + if (event.spritePath != null) { + var spr = event.spritePath; + if (!Assets.exists(spr)) spr = Paths.image(spr); - if (curStage.startsWith('school')) - ready.setGraphicSize(Std.int(ready.width * daPixelZoom)); - - ready.screenCenter(); - add(ready); - FlxTween.tween(ready, {y: ready.y += 100, alpha: 0}, Conductor.crochet / 1000, { + sprite = new FlxSprite().loadGraphic(spr); + sprite.scrollFactor.set(); + sprite.updateHitbox(); + sprite.screenCenter(); + add(sprite); + tween = FlxTween.tween(sprite, {y: sprite.y + 100, alpha: 0}, Conductor.crochet / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { - ready.destroy(); + sprite.destroy(); } }); - FlxG.sound.play(Paths.sound('intro2'), 0.6); - case 2: - var set:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[1])); - set.scrollFactor.set(); - - if (curStage.startsWith('school')) - set.setGraphicSize(Std.int(set.width * daPixelZoom)); - - set.screenCenter(); - add(set); - FlxTween.tween(set, {y: set.y += 100, alpha: 0}, Conductor.crochet / 1000, { - ease: FlxEase.cubeInOut, - onComplete: function(twn:FlxTween) - { - set.destroy(); - } - }); - FlxG.sound.play(Paths.sound('intro1'), 0.6); - case 3: - var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[2])); - go.scrollFactor.set(); - - if (curStage.startsWith('school')) - go.setGraphicSize(Std.int(go.width * daPixelZoom)); - - go.updateHitbox(); - - go.screenCenter(); - add(go); - FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, { - ease: FlxEase.cubeInOut, - onComplete: function(twn:FlxTween) - { - go.destroy(); - } - }); - FlxG.sound.play(Paths.sound('introGo'), 0.6); - case 4: + } + if (event.soundPath != null) { + var sfx = event.soundPath; + if (!Assets.exists(sfx)) sfx = Paths.sound(sfx); + sound = FlxG.sound.play(sfx, event.volume); + } } - + event.sprite = sprite; + event.sound = sound; + event.spriteTween = tween; + event.cancelled = false; + + scripts.event("onCountdownPost", event); swagCounter += 1; - // generateSong('fresh'); }, introLength); } @@ -459,96 +432,80 @@ class PlayState extends MusicBeatState public var debugNum:Int = 0; - private function generateSong(dataPath:String):Void + private function generateSong(dataPath:String, ?songData:SwagSong):Void { - // FlxG.log.add(ChartParser.parse()); - - var songData = SONG; + if (songData == null) songData = SONG; Conductor.changeBPM(songData.bpm); curSong = songData.song; + vocals = new FlxSound(); if (SONG.needsVoices) - vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); - else - vocals = new FlxSound(); - + vocals.loadEmbedded(Paths.voices(PlayState.SONG.song)); FlxG.sound.list.add(vocals); notes = new NoteGroup(); add(notes); - var noteData:Array; - - // NEW SHIT - noteData = songData.notes; - + var noteData:Array = songData.notes; var playerCounter:Int = 0; - var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped + for (section in noteData) { - var coolSection:Int = Std.int(section.lengthInSteps / 4); + if (section == null || section.sectionNotes == null) continue; + + // var coolSection:Int = Std.int(section.lengthInSteps / 4); for (songNotes in section.sectionNotes) { + if (songNotes == null) continue; var daStrumTime:Float = songNotes[0]; var daNoteData:Int = Std.int(songNotes[1] % 4); + var daNoteType:Int = Std.int(songNotes[1] / 4); + var gottaHitNote:Bool = songNotes[1] >= 4 ? !section.mustHitSection : section.mustHitSection; - var gottaHitNote:Bool = section.mustHitSection; - - if (songNotes[1] > 3) - { - gottaHitNote = !section.mustHitSection; + if (songNotes.length > 2) { + if (songNotes[3] is Int) + daNoteType = songNotes[3]; + else if (songNotes[3] is String) + daNoteType = addNoteType(songNotes[3]); } - var oldNote:Note; + var swagNote:Note; if (notes.length > 0) - oldNote = notes.members[Std.int(notes.members.length - 1)]; + swagNote = notes.members[Std.int(notes.members.length - 1)]; else - oldNote = null; + swagNote = null; - var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); + swagNote = new Note(daStrumTime, daNoteData, daNoteType, gottaHitNote, swagNote); swagNote.sustainLength = songNotes[2]; swagNote.scrollFactor.set(0, 0); - - var susLength:Float = swagNote.sustainLength; - - susLength = susLength / Conductor.stepCrochet; notes.add(swagNote); + + // calculate sustain length and fix + var susLength:Float = swagNote.sustainLength / Conductor.stepCrochet; if (susLength > 0.75) susLength++; + // create sustains for (susNote in 0...Math.floor(susLength)) { - oldNote = notes.members[Std.int(notes.length - 1)]; - - var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote), daNoteData, oldNote, true); - sustainNote.scrollFactor.set(); - notes.add(sustainNote); - - sustainNote.mustPress = gottaHitNote; - - if (sustainNote.mustPress) - { - sustainNote.x += FlxG.width / 2; // general offset - } + swagNote = new Note(daStrumTime + (Conductor.stepCrochet * susNote), daNoteData, daNoteType, gottaHitNote, swagNote, true); + swagNote.scrollFactor.set(); + notes.add(swagNote); } - - swagNote.mustPress = gottaHitNote; - - if (swagNote.mustPress) - { - swagNote.x += FlxG.width / 2; // general offset - } - else {} } daBeats += 1; } - notes.sort(function(i, n1, n2) {return sortByShit(n1, n2);}); + notes.sortNotes(); generatedMusic = true; } + public function addNoteType(name:String) { + // TODO: add note type by string + return 0; + } function sortByShit(Obj1:Note, Obj2:Note):Int { return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); @@ -857,9 +814,7 @@ class PlayState extends MusicBeatState previousFrameTime = FlxG.game.ticks; if (Math.abs(FlxG.sound.music.time - Conductor.songPosition) > 20) - { resyncVocals(); - } } // Conductor.lastSongPos = FlxG.sound.music.time; diff --git a/source/funkin/scripting/events/CountdownEvent.hx b/source/funkin/scripting/events/CountdownEvent.hx new file mode 100644 index 00000000..05c6ba28 --- /dev/null +++ b/source/funkin/scripting/events/CountdownEvent.hx @@ -0,0 +1,53 @@ +package funkin.scripting.events; + +import flixel.tweens.FlxTween; + +class CountdownEvent extends CancellableEvent { + /** + * At which count the countdown is. Normally goes 0-1-2-3-4 unless `PlayState.instance.introLength` is changed. + */ + public var swagCounter:Int; + /** + * Volume at which the intro countdown sound will play. + */ + public var volume:Float; + /** + * Path of the intro sound that'll be played. + */ + public var soundPath:String; + /** + * Path to the sprite path that'll be shown. + */ + public var spritePath:String; + /** + * Scale of the sprite. + */ + public var scale:Float; + /** + * Whenever antialiasing is enabled or not. + */ + public var antialiasing:Bool; + + + /** + * Created sprite, only available in `onCountdownPost` + */ + public var sprite:FlxSprite; + /** + * Created sound, only available in `onCountdownPost` + */ + public var sound:FlxSound; + /** + * Created tween, only available in `onCountdownPost` + */ + public var tween:FlxTween; + + public function new(spritePath:String, soundPath:String, scale:Float = 1, volume:Float = 1, antialiasing:Bool = true) { + super(); + this.volume = volume; + this.soundPath = soundPath; + this.spritePath = spritePath; + this.scale = scale; + this.antialiasing = antialiasing; + } +} \ No newline at end of file diff --git a/source/scripting/PlayStateScript.hx b/source/scripting/PlayStateScript.hx index 732bf6cd..511d5f38 100644 --- a/source/scripting/PlayStateScript.hx +++ b/source/scripting/PlayStateScript.hx @@ -46,6 +46,18 @@ interface PlayStateScript { */ public function beatHit(curBeat:Int):Void; + /** + * Triggered every countdown. + * @param event Countdown event. + */ + public function onCountdown(event:CountdownEvent):Void; + + /** + * Triggered after every countdown. + * @param event Countdown event. + */ + public function onCountdownPost(event:CountdownEvent):Void; + /** * Triggered whenever the player hits a note. * @param note Event object with the note being pressed, the character who pressed it, and functions to alter or cancel the default behaviour.