diff --git a/assets/images/game/notes/default.xml b/assets/images/game/notes/default.xml index d7df312c..587e6821 100644 --- a/assets/images/game/notes/default.xml +++ b/assets/images/game/notes/default.xml @@ -9,10 +9,12 @@ - - - - + + + + + + @@ -20,10 +22,12 @@ + + @@ -50,10 +54,12 @@ - - + + + + diff --git a/assets/songs/test/scripts/modchart.hx b/assets/songs/test/scripts/modchart.hx index c517ed5a..b91a084d 100644 --- a/assets/songs/test/scripts/modchart.hx +++ b/assets/songs/test/scripts/modchart.hx @@ -14,10 +14,22 @@ function postCreate() { } function postUpdate(elapsed) { - // var sin = Math.sin(curBeatFloat * Math.PI / 2); + for(s in strumLines) { + for(i in 0...4) { + var n = s.members[i]; + n.angle = Math.sin(curBeatFloat + (i * 0.45)) * 35; + } + } - // camGame.angle = sin * -15; - - if (curSection != null) - defaultCamZoom = curSection.mustHitSection ? 0.9 : 0.5; + + // for(s in strumLines) { + // for(i in 0...4) { + // var n = s.members[i]; + // n.y = FlxG.height - 200; + // n.angle = 180; + // } + // } + + // if (curSection != null) + // defaultCamZoom = curSection.mustHitSection ? 0.9 : 0.5; } \ No newline at end of file diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx index 3210375d..bbf058fb 100644 --- a/source/funkin/game/Note.hx +++ b/source/funkin/game/Note.hx @@ -119,7 +119,7 @@ class Note extends FlxSprite this.noteData = noteData.id.getDefault(0); var customType = Paths.image('game/notes/${this.noteType}'); - var event = EventManager.get(NoteCreationEvent).recycle(this, strumID, this.noteType, noteTypeID, PlayState.instance.strumLines.indexOf(strumLine), mustPress, + var event = EventManager.get(NoteCreationEvent).recycle(this, strumID, this.noteType, noteTypeID, PlayState.instance.strumLines.members.indexOf(strumLine), mustPress, (this.noteType != null && customTypePathExists(customType)) ? 'game/notes/${this.noteType}' : 'game/notes/default', 0.7, animSuffix); if (PlayState.instance != null) @@ -251,7 +251,11 @@ class Note extends FlxSprite if (!wasGoodHit) return; var t = FlxMath.bound((Conductor.songPosition - strumTime) / (height / (0.45 * FlxMath.roundDecimal(scrollSpeed, 2))), 0, 1); - var swagRect = new FlxRect(0, t * frameHeight, frameWidth, frameHeight); + var swagRect = this.clipRect == null ? new FlxRect() : this.clipRect; + swagRect.x = 0; + swagRect.y = t * frameHeight; + swagRect.width = frameWidth; + swagRect.height = frameHeight; setClipRect(swagRect); } diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index fbaf1709..b2175d04 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -87,7 +87,7 @@ class PlayState extends MusicBeatState /** * Array of all the players in the stage. */ - public var strumLines:Array = []; + public var strumLines:FlxTypedGroup = new FlxTypedGroup(); /** * Game Over Song. (assets/music/gameOver.ogg) @@ -618,11 +618,12 @@ class PlayState extends MusicBeatState var strLine = new StrumLine(chars, strOffset, strumLine.type == 2 || (!coopMode && !((strumLine.type == 1 && !opponentMode) || (strumLine.type == 0 && opponentMode))), strumLine.type != 1, coopMode ? (strumLine.type == 1 ? controlsP1 : controlsP2) : controls); strLine.cameras = [camHUD]; strLine.data = strumLine; - strumLines.push(strLine); - if (strumLine.visible != false) - add(strLine); + strLine.visible = (strumLine.visible != false); + strumLines.add(strLine); } + add(strumLines); + splashHandler = new SplashHandler(); add(splashHandler); @@ -1114,11 +1115,11 @@ class PlayState extends MusicBeatState while(events.length > 0 && events[0].time <= Conductor.songPosition) executeEvent(events.shift()); - if (generatedMusic && strumLines[curCameraTarget] != null) + if (generatedMusic && strumLines.members[curCameraTarget] != null) { var pos = FlxPoint.get(); var r = 0; - for(c in strumLines[curCameraTarget].characters) { + for(c in strumLines.members[curCameraTarget].characters) { if (c == null) continue; var cpos = c.getCameraPosition(); pos.x += cpos.x; @@ -1130,7 +1131,7 @@ class PlayState extends MusicBeatState pos.x /= r; pos.y /= r; - var event = scripts.event("onCameraMove", EventManager.get(CamMoveEvent).recycle(pos, strumLines[curCameraTarget], r)); + var event = scripts.event("onCameraMove", EventManager.get(CamMoveEvent).recycle(pos, strumLines.members[curCameraTarget], r)); if (!event.cancelled) camFollow.setPosition(pos.x, pos.y); } @@ -1181,7 +1182,7 @@ class PlayState extends MusicBeatState // automatically handled by conductor case ALT_ANIM_TOGGLE: if (event.params[0] is Int && event.params[1] is Bool) { - var strLine = strumLines[event.params[0]]; + var strLine = strumLines.members[event.params[0]]; if (strLine != null) strLine.altAnim = cast event.params[1]; } @@ -1322,74 +1323,10 @@ class PlayState extends MusicBeatState MusicBeatState.skipTransOut = true; } - var __funcsToExec:ArrayVoid> = []; - var __pressed:Array = []; - var __justPressed:Array = []; - var __justReleased:Array = []; - private function keyShit():Void + private inline function keyShit():Void { - for(id=>p in strumLines) { - p.updateNotes(); - - if (p.cpu) continue; - - __funcsToExec = [null, null]; - __pressed.clear(); - __justPressed.clear(); - __justReleased.clear(); - - __pressed.pushGroup(p.controls.NOTE_LEFT, p.controls.NOTE_DOWN, p.controls.NOTE_UP, p.controls.NOTE_RIGHT); - __justPressed.pushGroup(p.controls.NOTE_LEFT_P, p.controls.NOTE_DOWN_P, p.controls.NOTE_UP_P, p.controls.NOTE_RIGHT_P); - __justReleased.pushGroup(p.controls.NOTE_LEFT_R, p.controls.NOTE_DOWN_R, p.controls.NOTE_UP_R, p.controls.NOTE_RIGHT_R); - - var event = scripts.event("onKeyShit", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, p, id)); - if (event.cancelled) return; - - __pressed = CoolUtil.getDefault(event.pressed, []); - __justPressed = CoolUtil.getDefault(event.justPressed, []); - __justReleased = CoolUtil.getDefault(event.justReleased, []); - - - if (__pressed.contains(true)) { - for(c in p.characters) - if (c.lastAnimContext != DANCE) - c.__lockAnimThisFrame = true; - - __funcsToExec[0] = function(note:Note) { - if (__pressed[note.strumID] && note.isSustainNote && note.canBeHit && !note.wasGoodHit) { - goodNoteHit(p, note); - } - }; - } - - var notePerStrum = [for(_ in 0...4) null]; - if (__justPressed.contains(true)) { - __funcsToExec[1] = function(note:Note) { - if (__justPressed[note.strumID] && !note.isSustainNote && !note.wasGoodHit && note.canBeHit) { - if (notePerStrum[note.strumID] == null) notePerStrum[note.strumID] = note; - else if (Math.abs(notePerStrum[note.strumID].strumTime - note.strumTime) <= 2) p.deleteNote(note); - else if (note.strumTime < notePerStrum[note.strumID].strumTime) notePerStrum[note.strumID] = note; - } - }; - } - - if (__funcsToExec.length > 0) { - p.notes.forEachAlive(function(note:Note) { - for(e in __funcsToExec) if (e != null) e(note); - }); - } - - if (!p.ghostTapping) for(k=>pr in __justPressed) if (pr && notePerStrum[k] == null) { - // FUCK YOU - noteMiss(p, null, k, id); - } - for(e in notePerStrum) if (e != null) goodNoteHit(p, e); - - p.forEach(function(str:Strum) { - str.updatePlayerInput(__pressed[str.ID], __justPressed[str.ID], __justReleased[str.ID]); - }); - scripts.call("onPostKeyShit"); - } + for(id=>p in strumLines.members) + p.updateInput(id); } /** @@ -1400,11 +1337,11 @@ class PlayState extends MusicBeatState */ public function noteMiss(strumLine:StrumLine, note:Note, ?direction:Int, ?player:Int):Void { - var playerID:Null = note == null ? player : strumLines.indexOf(strumLine); + var playerID:Null = note == null ? player : strumLines.members.indexOf(strumLine); var directionID:Null = note == null ? direction : note.strumID; if (playerID == null || directionID == null) return; - var event:NoteHitEvent = scripts.event("onPlayerMiss", EventManager.get(NoteHitEvent).recycle(true, false, false, note, strumLines[playerID].characters, true, note != null ? note.noteType : null, "", "", "", directionID, -10, 0, -0.04, "shit")); + var event:NoteHitEvent = scripts.event("onPlayerMiss", EventManager.get(NoteHitEvent).recycle(true, false, false, note, strumLines.members[playerID].characters, true, note != null ? note.noteType : null, "", "", "", directionID, -10, 0, -0.04, "shit")); strumLine.onMiss.dispatch(event); if (event.cancelled) return; @@ -1647,44 +1584,44 @@ class PlayState extends MusicBeatState return cpuStrums = s; private function get_boyfriend():Character { - if (strumLines != null && strumLines[1] != null) - return strumLines[1].characters[0]; + if (strumLines != null && strumLines.members[1] != null) + return strumLines.members[1].characters[0]; return null; } private function set_boyfriend(bf:Character):Character { - if (strumLines != null && strumLines[1] != null) - strumLines[1].characters = [bf]; + if (strumLines != null && strumLines.members[1] != null) + strumLines.members[1].characters = [bf]; return bf; } private function get_dad():Character { - if (strumLines != null && strumLines[0] != null) - return strumLines[0].characters[0]; + if (strumLines != null && strumLines.members[0] != null) + return strumLines.members[0].characters[0]; return null; } private function set_dad(dad:Character):Character { - if (strumLines != null && strumLines[0] != null) - strumLines[0].characters = [dad]; + if (strumLines != null && strumLines.members[0] != null) + strumLines.members[0].characters = [dad]; return dad; } private function get_gf():Character { - if (strumLines != null && strumLines[2] != null) - return strumLines[2].characters[0]; + if (strumLines != null && strumLines.members[2] != null) + return strumLines.members[2].characters[0]; return null; } private function set_gf(gf:Character):Character { - if (strumLines != null && strumLines[2] != null) - strumLines[2].characters = [gf]; + if (strumLines != null && strumLines.members[2] != null) + strumLines.members[2].characters = [gf]; return gf; } private inline function get_cpuStrums():StrumLine - return strumLines[0]; + return strumLines.members[0]; private inline function get_playerStrums():StrumLine - return strumLines[1]; + return strumLines.members[1]; private inline function get_gfSpeed():Int - return (strumLines[2] != null && strumLines[2].characters[0] != null) ? strumLines[2].characters[0].danceInterval : 1; + return (strumLines.members[2] != null && strumLines.members[2].characters[0] != null) ? strumLines.members[2].characters[0].danceInterval : 1; private inline function set_gfSpeed(v:Int):Int { - if (strumLines[2] != null && strumLines[2].characters[0] != null) - strumLines[2].characters[0].danceInterval = v; + if (strumLines.members[2] != null && strumLines.members[2].characters[0] != null) + strumLines.members[2].characters[0].danceInterval = v; return v; } diff --git a/source/funkin/game/Strum.hx b/source/funkin/game/Strum.hx index f06d6b82..1e3b3d99 100644 --- a/source/funkin/game/Strum.hx +++ b/source/funkin/game/Strum.hx @@ -51,8 +51,12 @@ class Strum extends FlxSprite { daNote.__noteAngle = getNotesAngle(daNote); daNote.angle = daNote.isSustainNote ? daNote.__noteAngle : angle; + updateNotePos(daNote); + } + + private inline function updateNotePos(daNote:Note) { if (daNote.strumRelativePos) { - daNote.setPosition((Note.swagWidth - daNote.width) / 2, (daNote.strumTime - Conductor.songPosition) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2))); + daNote.setPosition((this.width - daNote.width) / 2, (daNote.strumTime - Conductor.songPosition) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2))); if (daNote.isSustainNote) daNote.y += N_WIDTHDIV2; } else { var offset = FlxPoint.get(0, (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(getScrollSpeed(daNote), 2))); @@ -104,8 +108,6 @@ class Strum extends FlxSprite { case null: playAnim("static"); } - centerOffsets(); - centerOrigin(); } public inline function press(time:Float) { @@ -114,7 +116,6 @@ class Strum extends FlxSprite { } public function playAnim(anim:String, force:Bool = true) { - var oldAnim = animation.curAnim; animation.play(anim, force); centerOffsets(); centerOrigin(); diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx index d8ab2b16..3d959738 100644 --- a/source/funkin/game/StrumLine.hx +++ b/source/funkin/game/StrumLine.hx @@ -27,6 +27,12 @@ class StrumLine extends FlxTypedGroup { * `strumLine.onNoteUpdate.add(function(e:NoteUpdateEvent) {});` */ public var onNoteUpdate:FlxTypedSignalVoid> = new FlxTypedSignalVoid>(); + /** + * Signal that triggers whenever a note is being updated. Similar to onNoteUpdate, except strumline specific. + * To add a listener, do + * `strumLine.onNoteUpdate.add(function(e:NoteUpdateEvent) {});` + */ + public var onNoteDelete:FlxTypedSignalVoid> = new FlxTypedSignalVoid>(); /** * Array containing all of the characters "attached" to those strums. */ @@ -112,7 +118,7 @@ class StrumLine extends FlxTypedGroup { notes.draw(); } - public function updateNotes() { + public inline function updateNotes() { notes.forEach(updateNote); } @@ -121,7 +127,7 @@ class StrumLine extends FlxTypedGroup { __updateNote_strum = members[daNote.noteData]; if (__updateNote_strum == null) return; - PlayState.instance.scripts.event("onNoteUpdate", PlayState.instance.__updateNote_event.recycle(daNote, FlxG.elapsed, __updateNote_strum)); + PlayState.instance.__updateNote_event.recycle(daNote, FlxG.elapsed, __updateNote_strum); onNoteUpdate.dispatch(PlayState.instance.__updateNote_event); if (PlayState.instance.__updateNote_event.cancelled) return; @@ -133,7 +139,7 @@ class StrumLine extends FlxTypedGroup { daNote.tooLate = true; } - if (PlayState.instance.__updateNote_event.__autoCPUHit && cpu && !daNote.wasGoodHit && daNote.strumTime < Conductor.songPosition) PlayState.instance.goodNoteHit(this, daNote); + if (cpu && PlayState.instance.__updateNote_event.__autoCPUHit && !daNote.wasGoodHit && daNote.strumTime < Conductor.songPosition) PlayState.instance.goodNoteHit(this, daNote); if (daNote.wasGoodHit && daNote.isSustainNote && daNote.strumTime + (daNote.sustainLength) < Conductor.songPosition) { deleteNote(daNote); @@ -149,9 +155,78 @@ class StrumLine extends FlxTypedGroup { if (PlayState.instance.__updateNote_event.strum == null) return; if (PlayState.instance.__updateNote_event.__reposNote) PlayState.instance.__updateNote_event.strum.updateNotePosition(daNote); - PlayState.instance.__updateNote_event.strum.updateSustain(daNote); + if (daNote.isSustainNote) + daNote.updateSustain(PlayState.instance.__updateNote_event.strum); + } - PlayState.instance.scripts.event("onNotePostUpdate", PlayState.instance.__updateNote_event); + var __funcsToExec:ArrayVoid> = []; + var __pressed:Array = []; + var __justPressed:Array = []; + var __justReleased:Array = []; + var __notePerStrum:Array = []; + + function __inputProcessPressed(note:Note) { + if (__pressed[note.strumID] && note.isSustainNote && note.canBeHit && !note.wasGoodHit) { + PlayState.instance.goodNoteHit(this, note); + } + } + function __inputProcessJustPressed(note:Note) { + if (__justPressed[note.strumID] && !note.isSustainNote && !note.wasGoodHit && note.canBeHit) { + if (__notePerStrum[note.strumID] == null) __notePerStrum[note.strumID] = note; + else if (Math.abs(__notePerStrum[note.strumID].strumTime - note.strumTime) <= 2) deleteNote(note); + else if (note.strumTime < __notePerStrum[note.strumID].strumTime) __notePerStrum[note.strumID] = note; + } + } + public function updateInput(id:Int = 0) { + updateNotes(); + + if (cpu) return; + + __funcsToExec.clear(); + __pressed.clear(); + __justPressed.clear(); + __justReleased.clear(); + + __pressed.pushGroup(controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT); + __justPressed.pushGroup(controls.NOTE_LEFT_P, controls.NOTE_DOWN_P, controls.NOTE_UP_P, controls.NOTE_RIGHT_P); + __justReleased.pushGroup(controls.NOTE_LEFT_R, controls.NOTE_DOWN_R, controls.NOTE_UP_R, controls.NOTE_RIGHT_R); + + var event = PlayState.instance.scripts.event("onKeyShit", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, this, id)); + if (event.cancelled) return; + + __pressed = CoolUtil.getDefault(event.pressed, []); + __justPressed = CoolUtil.getDefault(event.justPressed, []); + __justReleased = CoolUtil.getDefault(event.justReleased, []); + + __notePerStrum = [for(_ in 0...4) null]; + + + if (__pressed.contains(true)) { + for(c in characters) + if (c.lastAnimContext != DANCE) + c.__lockAnimThisFrame = true; + + __funcsToExec.push(__inputProcessPressed); + } + if (__justPressed.contains(true)) + __funcsToExec.push(__inputProcessJustPressed); + + if (__funcsToExec.length > 0) { + notes.forEachAlive(function(note:Note) { + for(e in __funcsToExec) if (e != null) e(note); + }); + } + + if (!ghostTapping) for(k=>pr in __justPressed) if (pr && __notePerStrum[k] == null) { + // FUCK YOU + PlayState.instance.noteMiss(this, null, k, ID); + } + for(e in __notePerStrum) if (e != null) PlayState.instance.goodNoteHit(this, e); + + forEach(function(str:Strum) { + str.updatePlayerInput(__pressed[str.ID], __justPressed[str.ID], __justReleased[str.ID]); + }); + PlayState.instance.scripts.call("onPostKeyShit"); } public inline function addHealth(health:Float) @@ -163,7 +238,7 @@ class StrumLine extends FlxTypedGroup { var babyArrow:Strum = new Strum((FlxG.width * strumOffset) + (Note.swagWidth * (i - 2)), PlayState.instance.strumLine.y); babyArrow.ID = i; - var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.indexOf(this), i)); + var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i)); if (!event.cancelled) { babyArrow.frames = Paths.getFrames(event.sprite); @@ -219,7 +294,8 @@ class StrumLine extends FlxTypedGroup { */ public function deleteNote(note:Note) { if (note == null) return; - var event:SimpleNoteEvent = PlayState.instance.scripts.event("onNoteDelete", EventManager.get(SimpleNoteEvent).recycle(note)); + var event:SimpleNoteEvent = EventManager.get(SimpleNoteEvent).recycle(note); + onNoteDelete.dispatch(event); if (!event.cancelled) { note.kill(); notes.remove(note, true);