Compare commits

...
342 Commits
Author SHA1 Message Date
Cameron Taylor 0971a0bb4c music persist fixes for title screen
Create and publish Docker image / build-and-push-image (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (html5) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-in-container (linux) (push) Canceled after 0s
2024-09-30 10:53:27 -04:00
Cameron Taylor 136e7358b1 bump project version 2024-09-30 10:40:19 -04:00
Cameron TaylorandGitHub 84ff83759f Merge pull request #805 from FunkinCrew/bugfix/two-fixes
[PUBLIC PR] Two bug fixes
2024-09-30 10:33:20 -04:00
Cameron TaylorandGitHub 9d3131bc8d Merge branch 'rewrite/master' into bugfix/two-fixes 2024-09-30 10:25:58 -04:00
EliteMasterEric 90f6f80a71 Fix issues with animation offsets breaking on restart on characters with high offstes. 2024-09-29 07:06:11 -04:00
EliteMasterEric e3ed153a7c Add a "persist" argument to FunkinSound to prevent Results music from continuing in Freeplay. 2024-09-29 06:59:49 -04:00
Cameron Taylor 66781181fa Merge branch 'rewrite/master' of github.com:FunkinCrew/Funkin-secret into rewrite/master 2024-09-28 12:37:24 -04:00
Cameron Taylor 93039c3d65 intro text stuff 2024-09-28 12:37:12 -04:00
Cameron TaylorandGitHub a1370157a4 Merge pull request #803 from FunkinCrew/abnormalpoof/stage-prop-flipx
[PUBLIC PR] Add flipX and flipY parameters to Stage props
2024-09-28 12:30:57 -04:00
EliteMasterEric 7ce7d7839e Update stage data version after adding new values. 2024-09-28 09:51:41 -04:00
EliteMasterEric 042dfb7442 Merge branch 'rewrite/master' into abnormalpoof/stage-prop-flipx 2024-09-28 09:18:41 -04:00
Cameron Taylor 7a3d983bba Merge branch 'feature/discord-rpc-resurrected' into rewrite/master 2024-09-27 17:47:59 -04:00
Cameron Taylor ac3e2b2560 discord api mac 2024-09-27 17:45:54 -04:00
Cameron Taylor db0944712d Merge branch 'rewrite/master' into bugfix/mod-dev-fixes 2024-09-27 17:27:59 -04:00
Cameron Taylor fb1b3cc1cd Merge branch 'bugfix/week-7-pico-stress' into rewrite/master 2024-09-27 17:00:54 -04:00
Cameron Taylor 007a32dc9c assets submod 2024-09-27 17:00:31 -04:00
Cameron Taylor 9a57762a9c Merge remote-tracking branch 'origin/bugfix/web-screenshots' into rewrite/master 2024-09-27 16:56:12 -04:00
Cameron TaylorandGitHub 06fee5599c Merge pull request #796 from FunkinCrew/lemz1/completion-fix
[PUBLIC PR] Fix an issue where getting the same rank (but a different clear %) will override the rating
2024-09-27 16:50:53 -04:00
AbnormalPoof cd2b458da2 add flipx and flipy 2024-09-27 15:15:35 -05:00
EliteMasterEric 8a8160dfe7 Update assets submodule 2024-09-27 14:26:46 -04:00
EliteMasterEric 5630e74584 Rework Freeplay variation handling... again. 2024-09-27 14:26:08 -04:00
EliteMasterEric 067f52ca91 Kill intro music when leaving Results state. 2024-09-27 14:25:32 -04:00
EliteMasterEric 2eb5208c46 Hide the pixel icon in the Results screen when there's no matching character 2024-09-27 14:25:17 -04:00
EliteMasterEric b5f3996236 Properly sort difficulties/variations. Validate variation IDs (alphanumeric only) 2024-09-27 12:21:17 -04:00
EliteMasterEric 378179d1f7 Change crash keybind to Ctrl-Alt-Shift-L 2024-09-27 12:20:36 -04:00
EliteMasterEric f1c1e63375 Use more dynamic API version rules for checking mod versions. 2024-09-27 12:19:41 -04:00
EricandGitHub ec749c7157 Merge pull request #3465 from AbnormalPoof/patch-5
chore: Add a link to `credits.json`
2024-09-27 03:56:08 -04:00
EliteMasterEric e321861b9f Fix an issue where animations wouldn't loop properly on AnimateAtlasCharacters. 2024-09-27 03:09:59 -04:00
EliteMasterEric c4ed31b246 Fix a bug where force-ending a song could occasionally try to draw destroyed sprites. 2024-09-27 02:52:01 -04:00
EliteMasterEric 2053f0d691 Fix a missing import in Pico (Blazin) 2024-09-27 02:51:31 -04:00
AbnormalandGitHub ffd76963bd Update README.md 2024-09-26 21:04:23 +00:00
Cameron TaylorandGitHub 4669ac03a9 Merge pull request #795 from FunkinCrew/nebulazorua/classic-camera-fix
[PUBLIC PR] Fix an issue where the Classic FocusCamera event would cause the camera to snap in place
2024-09-25 19:25:45 -04:00
Cameron TaylorandGitHub cb16a8d55e Merge pull request #793 from FunkinCrew/cyn0x8/module-ondestroy-fix
[PUBLIC PR] Fix an issue when interacting with modules during onDestroy()
2024-09-25 19:24:48 -04:00
Cameron TaylorandGitHub e1aa25a249 Merge pull request #791 from FunkinCrew/actions-manual-output
Allow for manual configuration + artifact saving for Github Actions
2024-09-25 19:24:14 -04:00
EliteMasterEric 67126b33fa Suppress some spammy log calls 2024-09-25 10:02:18 -04:00
EliteMasterEric a84ae6069e Fix an issue where Pico wouldn't shoot in Stress 2024-09-25 10:02:11 -04:00
EricandGitHub c3f982b32c Merge pull request #3435 from NotHyper-474/patch/upgrade-example-mods
Chore: Upgrade Example Mods to latest API version
2024-09-25 08:52:55 -04:00
EricandGitHub 67bce85343 Merge branch 'develop' into patch/upgrade-example-mods 2024-09-25 08:51:57 -04:00
EliteMasterEric 998bbb213a Merge branch 'rewrite/master' into nebulazorua/classic-camera-fix 2024-09-25 08:48:20 -04:00
EliteMasterEric 8d02a3f984 A bunch of controls fixes 2024-09-25 08:39:57 -04:00
EricandGitHub 85763813ae Merge branch 'develop' into patch-2 2024-09-25 07:38:14 -04:00
EricandGitHub b29296288e Merge pull request #3438 from TechnikTil/fix-develop-branch
[BUGFIX] Fix develop branch
2024-09-25 06:55:39 -04:00
EliteMasterEric 5693d626b5 Update so that album art works. 2024-09-25 03:58:43 -04:00
EliteMasterEric 84d8c02920 Update art repo 2024-09-25 00:39:37 -04:00
EliteMasterEric ec9b5db210 Create shader for Week 5 once and reuse it rather than recreating it every frame. 2024-09-23 21:41:48 -04:00
Cameron Taylor 7e75308423 capitalization hxCodec 2024-09-23 18:51:48 -04:00
Cameron Taylor 073dbaa023 Merge remote-tracking branch 'origin/bugfix/input-offsets-crash' into rewrite/master 2024-09-23 18:48:22 -04:00
Cameron Taylor f6697f8ddc Merge branch 'bugfix/html5-video-error' into rewrite/master 2024-09-23 18:47:48 -04:00
Cameron Taylor 78d0ad9956 Merge remote-tracking branch 'origin/feature/tracy' into rewrite/master 2024-09-23 17:41:01 -04:00
EliteMasterEric 52f5c24f96 Add frame market support, and enable on demand tracing. 2024-09-23 16:09:34 -04:00
Cameron TaylorandGitHub 252b87c451 Merge pull request #763 from FunkinCrew/feature/tracy
Add Tracy support for performance profiling
2024-09-23 15:03:33 -04:00
EliteMasterEric 0389cd6760 Fix a compile issue on HTML5 with video sprites 2024-09-23 14:45:12 -04:00
Cameron Taylor 29c860ed43 Merge branch 'pico-burp-fix' into rewrite/master 2024-09-23 13:12:00 -04:00
Cameron Taylor a86cfded2a assets submod 2024-09-23 13:11:36 -04:00
Cameron Taylor 3d5482660c Merge branch 'week2-death-fix' into rewrite/master 2024-09-23 13:10:52 -04:00
Cameron Taylor 299f4840cf assets submod 2024-09-23 13:10:44 -04:00
Cameron Taylor 8749372725 Merge remote-tracking branch 'origin/docs/updated-changelog' into rewrite/master 2024-09-23 13:09:52 -04:00
Cameron Taylor 50f65177cb Merge branch 'rewrite/master' into spirit-trail 2024-09-23 13:09:03 -04:00
Cameron Taylor 1c2a403dea Merge branch 'rewrite/master' into kadedev/fix-audio-offsets 2024-09-23 13:07:32 -04:00
FabsTheFabs 84ce43eff7 assets submod 2024-09-23 03:46:14 +01:00
Til Tjardes cca997b724 fix develop branch cuz git is on crack 2024-09-22 17:59:18 -06:00
Hyper_ 298bc9496b Upgrade API versions 2024-09-22 18:05:25 -03:00
FabsTheFabs 2edb318901 assets submod 2024-09-22 20:11:37 +01:00
Cameron TaylorandGitHub 15bce04a50 Merge pull request #783 from FunkinCrew/nothyper474/chart-selection
[PUBLIC PR] Chart Editor: Fi bug where selecting area left of the chart would select the player's left notes
2024-09-22 13:30:32 -04:00
Cameron TaylorandGitHub 5c6d72d8d5 Merge pull request #782 from FunkinCrew/cyn0x8/funkinsound-persist
[PUBLIC PR] If FunkinSound.persist is true, don't destroy it when switching states
2024-09-22 13:30:17 -04:00
Cameron TaylorandGitHub 1937529c1f Merge pull request #779 from FunkinCrew/cutscene-volume-math-fix
proper audio scaling for hxcodec / desktop
2024-09-22 13:29:59 -04:00
EliteMasterEric 0bf1bead03 Fix some issues causing the Input Offsets view to crash on web. 2024-09-22 12:14:15 -04:00
Cameron Taylor 58508755f9 revert extra flxtrail function 2024-09-22 10:57:00 -04:00
lemzandGitHub bcb7bc4cbc Merge branch 'develop' into completion-fix 2024-09-22 16:12:17 +02:00
EliteMasterEric 28d50a4567 Merge branch 'rewrite/master' into nothyper474/chart-selection 2024-09-22 01:10:56 -04:00
EricandGitHub 6a113addca Merge branch 'develop' into bugfix/chart-selection 2024-09-22 01:09:37 -04:00
EliteMasterEric c7238fcfd1 Stop the volume tray from hiding as long as the game is muted 2024-09-22 00:45:30 -04:00
EliteMasterEric 29a7005d8a Fix a bug where you can hear the game a little when setting the volume to 0 ticks 2024-09-22 00:44:57 -04:00
EliteMasterEric d23ae7c55b Merge remote-tracking branch 'public/develop' into docs/updated-changelog 2024-09-21 23:31:25 -04:00
EliteMasterEric d11acfd83b Merge remote-tracking branch 'public/main' into docs/updated-changelog 2024-09-21 23:31:21 -04:00
EricandGitHub 754e2edbeb Merge pull request #3420 from JVNpixels/patch-4
[DOCUMENTATION/BUG-FIX] Fix changelog for v0.5.0
2024-09-21 23:12:57 -04:00
EliteMasterEric 5548fd52f4 Update default mod so it actually loads 2024-09-21 20:33:59 -04:00
EliteMasterEric 6c743b3b89 Remove some spammy trace calls. 2024-09-21 20:33:51 -04:00
Cameron Taylor e978f5df76 fix for spirit's trail 2024-09-21 16:32:44 -04:00
JVN-PixelsandGitHub 3601b50e32 Update CHANGELOG.md 2024-09-21 10:29:08 -07:00
JVN-PixelsandGitHub e535ae4ca6 Change line 12
The songs from Weekend 1 have moved line
2024-09-21 10:19:00 -07:00
JVN-PixelsandGitHub ec8ecc6163 Update CHANGELOG.md 2024-09-21 10:14:09 -07:00
JVN-PixelsandGitHub 01e9888839 Update CHANGELOG.md
Fixes changelog for the 0.5.0 update!
2024-09-21 10:07:41 -07:00
EliteMasterEric 2c73b241e8 Rework offset+vocal sync handling to fix the "Swing Mode" bug 2024-09-21 06:33:47 -04:00
EricandGitHub 3ef238a2f6 Merge pull request #3282 from TechnikTil/playsound-typo
[DOCUMENTATION] playSound Typo in NoteScriptEvent
2024-09-21 05:45:35 -04:00
Cameron Taylor 690f3090b7 proper audio scaling for hxcodec / desktop 2024-09-20 20:11:12 -04:00
Cameron Taylor a41d3033d5 small Assets -> OpenFLAssets fix 2024-09-20 18:20:40 -04:00
Cameron Taylor d02e834460 Merge branch 'rewrite/master' into abnormalpoof/assets-getpath 2024-09-20 18:13:13 -04:00
Cameron Taylor 2a6eadcbff Merge branch 'justkolosaki/char-select-gf' into rewrite/master 2024-09-20 18:11:14 -04:00
Cameron Taylor 78cde16af2 assets submod 2024-09-20 18:10:47 -04:00
Cameron TaylorandGitHub 4946e7f4c7 Merge pull request #765 from FunkinCrew/lethrial/fps-counter-bugfix
[PUBLIC PR] Fix bug where FPS counter would display even if Debug Display option was disabled
2024-09-20 16:52:02 -04:00
Cameron Taylor 8a9b1b4727 Merge branch 'bugfix/cocoa-erect-stacked-note' into rewrite/master 2024-09-20 16:51:39 -04:00
Cameron Taylor 5f64d89d0e assets submod 2024-09-20 16:51:21 -04:00
EliteMasterEric 143ef88e6f Update assets submodule 2024-09-20 03:42:48 -04:00
Cameron Taylor cb4ac352e6 Merge branch 'lemz1/fps-setting' into rewrite/master 2024-09-20 00:29:19 -04:00
Cameron Taylor ccb2e1889f Merge branch 'lemz1/substate-event-dispatch' into rewrite/master 2024-09-20 00:25:53 -04:00
Cameron Taylor 9045ae2d9c assets submod 2024-09-20 00:25:38 -04:00
Cameron TaylorandGitHub e3a13bee8c Merge pull request #773 from FunkinCrew/process-cleanup
close sys.io.Process stuff when we're done with them
2024-09-20 00:24:10 -04:00
Cameron TaylorandGitHub 426bff3bf5 Merge pull request #768 from FunkinCrew/kadedev/addcharacter-type
[PUBLIC PR] Move characterType assignment to Stage.addCharacter
2024-09-20 00:23:53 -04:00
EricandGitHub 249ff69f9f Merge branch 'rewrite/master' into lemz1/fps-setting 2024-09-20 00:05:17 -04:00
Cameron Taylor 4af4c2defc Merge branch 'lemz1/fps-setting' into rewrite/master 2024-09-19 23:56:04 -04:00
Cameron TaylorandGitHub 76bf5df57f Merge branch 'rewrite/master' into lemz1/fps-setting 2024-09-19 23:34:51 -04:00
Cameron TaylorandGitHub c46483722e Merge pull request #767 from FunkinCrew/techniktil/chart-editor-icons
[PUBLIC PR] [FUNK-717] Fix pixel icons in the chart editor
2024-09-19 23:31:40 -04:00
Cameron TaylorandGitHub 69bcd0834e Merge branch 'rewrite/master' into techniktil/chart-editor-icons 2024-09-19 23:31:26 -04:00
Cameron TaylorandGitHub 29e89c8acb Merge branch 'rewrite/master' into actualmandm/char-select-crash 2024-09-19 22:50:18 -04:00
Cameron Taylor 778ce54047 Merge branch 'rewrite/master' of github.com:FunkinCrew/Funkin-secret into rewrite/master 2024-09-19 22:49:59 -04:00
Cameron Taylor 47ed9d7fb2 Merge branch 'rewrite/master' into dombomb64/note-style-scaling 2024-09-19 22:35:16 -04:00
Cameron TaylorandGitHub 00c1428c0f Merge pull request #774 from FunkinCrew/abnormalpoof/opening-urls
[PUBLIC PR] Fix Merch button being missing from the main menu
2024-09-19 22:31:44 -04:00
Cameron TaylorandGitHub 0b908b3cab Merge branch 'rewrite/master' into abnormalpoof/opening-urls 2024-09-19 22:31:12 -04:00
Cameron Taylor 50de041251 Merge branch 'public-release/develop' into rewrite/master 2024-09-19 22:11:05 -04:00
Kade f9186b67a7 less tolerance 2024-09-19 17:00:52 -07:00
Kade a8aeae4f7f do not include offset in vocal (they're offset by inst)
Fix a tiny little issue with vocal resync @ start
2024-09-19 14:26:18 -07:00
Kade 4d73e0cc47 fix some interesting issues with this
redundant trace removal
2024-09-19 14:26:18 -07:00
Kade b03c8a9cf8 Limit the song time to 0 and the songs max length
use the new bool to tell if we should start the song

add a public static bool to countdown: finished
2024-09-19 14:26:18 -07:00
EliteMasterEricandCameron Taylor 3cbba8ba29 Resolve merge issues. 2024-09-19 17:16:31 -04:00
EliteMasterEric bfee63f588 Update hmm.json 2024-09-19 11:15:56 -04:00
EliteMasterEric 35aa8731d0 Better status messages, buttons, updated album art, basic chart editor support 2024-09-19 11:13:05 -04:00
EliteMasterEric 8fd84f9d13 Functioning Discord Rich Presence! 2024-09-19 10:03:16 -04:00
EliteMasterEric 25cafe7550 Resolve merge issues. 2024-09-19 04:22:05 -04:00
EliteMasterEric 7d6fa19ff4 Merge remote-tracking branch 'secret/rewrite/master' into lemz1/substate-event-dispatch 2024-09-19 04:20:24 -04:00
EliteMasterEric 9f0bc2bd52 Refactor char select GF data handling. 2024-09-19 04:16:40 -04:00
EricandGitHub d81e09b1c3 Merge branch 'rewrite/master' into abnormalpoof/opening-urls 2024-09-19 03:46:46 -04:00
EricandGitHub a128afedf7 Merge pull request #772 from FunkinCrew/results-sfx-fix
Results Percentage Sound Spam Fix
2024-09-19 03:24:52 -04:00
Cameron Taylor 472d41a893 close sys.io.Process stuff when we're done with them 2024-09-18 16:15:10 -04:00
Cameron Taylor 215e20cabe Merge remote-tracking branch 'origin/docs/issue-management-actions' into rewrite/master 2024-09-18 15:25:51 -04:00
Cameron Taylor 3c30575727 Merge branch 'kadedev/chart-editor-fixes' into rewrite/master 2024-09-18 15:23:07 -04:00
Cameron Taylor f30c0cff49 Merge branch 'feature/gold-perfect-anim-for-modders' into rewrite/master 2024-09-18 15:20:38 -04:00
Cameron Taylor fc6e194d20 assets submod 2024-09-18 15:20:15 -04:00
Cameron Taylor 35005df32a Merge branch 'feature/pico-character-script' into rewrite/master 2024-09-18 15:17:37 -04:00
Cameron Taylor 62149aea39 assets submod 2024-09-18 15:16:56 -04:00
Cameron TaylorandGitHub fdddfba3be Merge pull request #760 from FunkinCrew/bugfix/pico-mix-highscores
Fix bugs with highscore display in Freeplay (FUNK-714)
2024-09-18 15:14:46 -04:00
Cameron Taylor ab3b976f3c fix rounding for sound results sfx 2024-09-18 15:07:15 -04:00
lemzandGitHub e02bb9b21c Merge branch 'develop' into completion-fix 2024-09-18 18:19:31 +02:00
lemzandGitHub afcb57aaf0 Merge branch 'develop' into substate-dispatch-event-fix 2024-09-18 18:18:57 +02:00
KoloandGitHub 99657da1f9 accidentally also put the save changes oops 2024-09-18 17:46:13 +02:00
KoloandGitHub 3bb981adb0 Update CharSelectGF.hx 2024-09-18 17:32:37 +02:00
KoloandGitHub 50a5304ad4 Update PlayerData.hx 2024-09-18 17:30:23 +02:00
KoloandGitHub a4b59d14bf applySongRank fix
fixes the bug with the percent being overriden when the song has the same letter rank but lower percent (eg. E Rank with 99% being overriden by E Rank with 93%)
2024-09-18 13:40:02 +02:00
EliteMasterEric 9d5cde0bf1 Update assets submodule 2024-09-18 06:48:45 -04:00
EliteMasterEric 5efbff044b Resolve merge issues 2024-09-18 06:32:06 -04:00
EliteMasterEric a469385cdb Resolve merge issues 2024-09-18 06:22:02 -04:00
EricandGitHub 970816592f Merge branch 'develop' into bugfix/charselect-crash 2024-09-18 06:20:44 -04:00
EliteMasterEric ba90a6abe0 Add behavior when setting status: rejected 2024-09-18 06:08:18 -04:00
EliteMasterEric d54dc6179a Add several new Github Actions for issue management 2024-09-18 06:02:13 -04:00
EliteMasterEric b5ed7f40d4 Remove redundant character type assignment 2024-09-18 05:24:57 -04:00
EliteMasterEric b28af79eb3 Fix build issues 2024-09-18 05:18:16 -04:00
EricandGitHub 5f563f0555 Merge branch 'develop' into chart-editor-icon-fix 2024-09-18 05:10:30 -04:00
EliteMasterEric 1beb21e57a Replace all instances of openfl/lime Assets with funkin.Assets 2024-09-18 05:04:32 -04:00
EliteMasterEric b6b2248aa3 Make funkin.Assets and funkin.Paths default imports for all scripts 2024-09-18 05:04:10 -04:00
EliteMasterEric d30fe61ca0 Add a bunch of other functions to funkin.Assets, and add documentation 2024-09-18 05:03:04 -04:00
EliteMasterEric 7b7d5deed5 Tweaks to framerate preference 2024-09-18 03:13:21 -04:00
EliteMasterEric 19e6029fb2 Fix some compilation errors 2024-09-18 03:13:10 -04:00
EliteMasterEric 2a5269c2a7 Disable on demand telemetry 2024-09-18 02:30:48 -04:00
EliteMasterEric f7fb640e52 Copy TracyProfiler from pull request 2024-09-18 02:29:11 -04:00
EliteMasterEric 119148acf0 Define for enabling/disabling log trace 2024-09-18 02:11:31 -04:00
EricandGitHub 598a3bea24 Merge branch 'develop' into fps-setting 2024-09-18 02:09:38 -04:00
EricandGitHub b03d320c12 Merge pull request #3139 from AbnormalPoof/patch-1
chore: Update ScriptedFunkinSprite.hx
2024-09-18 01:58:40 -04:00
EliteMasterEric 61d23b9985 Use branch of HXCPP 2024-09-17 20:56:54 -04:00
EliteMasterEric b70983a0e4 Build arguments for Tracy 2024-09-17 20:50:09 -04:00
Kade de07497ae3 Make addCharacter actually set the characters type 2024-09-17 17:29:12 -07:00
Lethrial ea9dab4b73 Update Main.hx 2024-09-18 00:25:20 +01:00
Michael f2b3f47e73 Disable input in CharSelect until stayFunky plays 2024-09-17 15:57:50 -07:00
dombomb64 6e33cac9ec ...Okay it wasn't that simple 2024-09-17 16:47:16 -04:00
EricandGitHub dab417b391 Merge branch 'rewrite/master' into kadedev/chart-editor-fixes 2024-09-17 16:15:02 -04:00
dombomb64 0706192cbe Fix note scaling with one simple trick! 2024-09-17 13:50:59 -04:00
Cameron Taylor 7fbbc5cf95 save artifacts on html5 and linux? 2024-09-17 04:48:30 -04:00
Cameron Taylor 4939b09fb0 manual build artifacts 2024-09-17 04:43:34 -04:00
AbnormalPoof aae7dcdada fix crash when opening urls 2024-09-16 23:35:23 -05:00
Til Tjardes e6525d0129 stop being on the kickstarter crack me 2024-09-16 20:44:29 -06:00
EricandGitHub 6efdbde8da Merge branch 'develop' into fps-setting 2024-09-16 22:09:54 -04:00
Til Tjardes b7c3f5ac9f Chart Editor Icons are fixed now! 2024-09-16 20:04:04 -06:00
EliteMasterEric 811caf6b70 Suppress a spammy log trace 2024-09-16 21:54:33 -04:00
EliteMasterEric d710318830 Update HaxeUI 2024-09-16 21:54:24 -04:00
EricandGitHub 1fc835494d Merge pull request #3020 from anysad/custom-popups-countdowns
[ENHANCEMENT] Custom Popups and Countdowns
2024-09-16 20:56:26 -04:00
EliteMasterEric 2e9223ec72 Merge remote-tracking branch 'origin/develop' into anysad/custom-popups-countdowns 2024-09-16 20:50:13 -04:00
Kade 9624b57e44 This does fix it now 2024-09-16 17:23:49 -07:00
Kade 7d2b946e9c depreciated screen X/Y to view X/Y 2024-09-16 17:13:14 -07:00
Kade 5a877a14a0 only show last two digits
digit
2024-09-16 17:13:13 -07:00
Kade 535ac0e528 add milliseconds to the playbar in charting state
remove laggy redundant traces

Revert "remove laggy redundant traces"

This reverts commit 204113840473dd5069f5d508d50e15e21104b45a.
2024-09-16 17:13:13 -07:00
EricandGitHub 35b5957715 Merge pull request #3007 from anysad/tutorial-hey-events
[CLEANUP] Softcode Tutorial HEY! events from code to JSON
2024-09-16 19:33:04 -04:00
EliteMasterEric e915b637c5 Merge remote-tracking branch 'origin/develop' into anysad/tutorial-hey-events 2024-09-16 19:09:58 -04:00
EricandGitHub f38a95bbf7 Merge branch 'develop' into fps-setting 2024-09-16 18:59:55 -04:00
EricandGitHub ebfce9f990 Merge pull request #2820 from gamerbross/bugfix/animation-editor
[ENHANCEMENT/BUGFIX] Few animation editor bugfixes and improvements
2024-09-16 18:48:50 -04:00
EricandGitHub 359e4b41e5 Merge branch 'develop' into bugfix/animation-editor 2024-09-16 18:48:33 -04:00
EricandGitHub b0c9365c56 Merge pull request #2942 from FlooferLand/new-settings-items
New settings widgets (Number, Checkbox, Enum)
2024-09-16 18:42:48 -04:00
EricandGitHub 65fddd95bb Merge branch 'develop' into new-settings-items 2024-09-16 18:42:43 -04:00
EricandGitHub f1d3ace247 Merge pull request #2925 from gamerbross/bugfix/character-danceevery
[BUGFIX] Implement `danceEvery` for Characters
2024-09-16 18:42:40 -04:00
EricandGitHub 9e90e67673 Merge branch 'develop' into bugfix/character-danceevery 2024-09-16 18:42:32 -04:00
EricandGitHub 3ce7cd6990 Merge pull request #2903 from AbnormalPoof/develop
[ENHANCEMENT] Enable auto-pause for Video Cutscenes
2024-09-16 18:42:20 -04:00
EricandGitHub d4cd2d031c Merge branch 'develop' into develop 2024-09-16 18:41:33 -04:00
EricandGitHub 081d2d8fd8 Merge pull request #2992 from gamerbross/bugfix/charteditor-liveinput-number-6
[BUGFIX + REFACTOR] ChartEditor Live Input
2024-09-16 18:40:24 -04:00
EricandGitHub 99f4d13e47 Merge branch 'develop' into bugfix/charteditor-liveinput-number-6 2024-09-16 18:40:12 -04:00
EricandGitHub 8cad10263e Merge branch 'develop' into bugfix/animation-editor 2024-09-16 18:37:35 -04:00
EricandGitHub 8470880e4a Merge pull request #2926 from gamerbross/tweak/funkinsound-playonce-return-value
[CODE TWEAK] `FunkinSound.playOnce` return the created sound
2024-09-16 18:36:53 -04:00
EricandGitHub 6bde7c34a0 Merge branch 'develop' into tweak/funkinsound-playonce-return-value 2024-09-16 18:36:45 -04:00
EricandGitHub 3ac10fb45c Merge pull request #2981 from gamerbross/bugfix/forced-sustaintrail-alpha
[BUGFIX] SustainTrail forced alpha
2024-09-16 18:35:31 -04:00
EricandGitHub fb0b277a9c Merge branch 'develop' into bugfix/forced-sustaintrail-alpha 2024-09-16 18:35:17 -04:00
EricandGitHub 519a6f3412 Merge pull request #2873 from JVNpixels/JVNPixels-story-menu-scrolling-fixed
[ENHANCEMENT]: Story Mode Menu Mouse Scrolling
2024-09-16 18:34:58 -04:00
EricandGitHub 27f700dd98 Merge branch 'develop' into JVNPixels-story-menu-scrolling-fixed 2024-09-16 18:34:43 -04:00
EricandGitHub f015976521 Merge pull request #2712 from gamerbross/bugfix/freeplay-difficulty-stack-overflow
[BUGFIX] Song with no "Normal" causes Stack Overflow
2024-09-16 18:34:06 -04:00
EricandGitHub 265039b025 Merge branch 'develop' into bugfix/freeplay-difficulty-stack-overflow 2024-09-16 18:33:57 -04:00
EricandGitHub 8c6cb72d47 Merge pull request #2986 from AppleHair/bugfix/cancel-menu-sound
[BUGFIX] Fixed `cancelMenu` sound not playing after switching state
2024-09-16 18:30:02 -04:00
EricandGitHub b3221c0e3f Merge branch 'develop' into bugfix/cancel-menu-sound 2024-09-16 18:29:51 -04:00
EricandGitHub c7cb03dd1d Merge pull request #2990 from gamerbross/bugfix/f5-reload-chart
[BUGFIX] F5 now reloads the chart in the PlayState
2024-09-16 18:29:39 -04:00
EricandGitHub a7c0512503 Merge branch 'develop' into bugfix/f5-reload-chart 2024-09-16 18:29:33 -04:00
EricandGitHub 74a94d0080 Merge branch 'develop' into bugfix/charteditor-liveinput-number-6 2024-09-16 18:28:22 -04:00
EricandGitHub d214ae1747 Merge pull request #3058 from Burgerballs/fix-sync
Use chart inst offset for song resync + other resync fixes
2024-09-16 18:27:35 -04:00
EricandGitHub 6ee1bddacb Merge branch 'develop' into fix-sync 2024-09-16 18:27:27 -04:00
EricandGitHub 8b96d1bbac Merge pull request #2863 from gamerbross/bugfix/stickers-f5-crash
[BUGFIX] Crash after coming back from stickers and pressing F5
2024-09-16 18:26:42 -04:00
EricandGitHub d4e11f786c Merge branch 'develop' into bugfix/stickers-f5-crash 2024-09-16 18:26:31 -04:00
EricandGitHub 724c415016 Merge pull request #2739 from gamerbross/bugfix/chart-key
[BUGFIX] When pressing chart key while charting, chart gets reset
2024-09-16 18:25:42 -04:00
EricandGitHub 055ae5b932 Merge branch 'develop' into bugfix/chart-key 2024-09-16 18:25:35 -04:00
EricandGitHub 85e9dbb959 Merge pull request #2713 from KarimAkra-Stuff/memory-counter-fix
[BUGFIX] Fixed memory counter displaying negative numbers
2024-09-16 18:25:15 -04:00
EricandGitHub c5060b6eec Merge pull request #2749 from NotHyper-474/path-trace-fix
Fix small oversight in LoadingState
2024-09-16 18:24:42 -04:00
EricandGitHub df77d11896 Merge branch 'develop' into path-trace-fix 2024-09-16 18:24:34 -04:00
EricandGitHub aa2d934f22 Merge pull request #3036 from AppleHair/bugfix/freeplay-infinite-recursion
[BUGFIX] Prevented infinite recursion on freeplay when a song doesn't have the `normal` difficulty
2024-09-16 18:24:22 -04:00
EricandGitHub 3f6ad6f8ad Merge branch 'develop' into bugfix/freeplay-infinite-recursion 2024-09-16 18:24:15 -04:00
EricandGitHub 45efd78931 Merge pull request #3037 from AppleHair/bugfix/valid-vari-story-mode
[BUGFIX] Ensure the variation used for the next song is valid.
2024-09-16 18:23:50 -04:00
EricandGitHub b95e228322 Merge branch 'develop' into bugfix/valid-vari-story-mode 2024-09-16 18:23:39 -04:00
EricandGitHub c9e2e7bef5 Merge pull request #3005 from gamerbross/bugfix/default-face-icon
[BUGFIX] Default health icon (face) not used
2024-09-16 18:23:23 -04:00
EricandGitHub bab4ac4902 Merge branch 'develop' into bugfix/default-face-icon 2024-09-16 18:21:20 -04:00
EricandGitHub b8d1341a21 Merge pull request #2850 from MaybeMaru/constants
Use constants pixels per ms
2024-09-16 18:20:46 -04:00
EricandGitHub 55e0970e4c Merge branch 'develop' into constants 2024-09-16 18:20:35 -04:00
EricandGitHub 82c2d54079 Merge pull request #2567 from gamerbross/bugfix/pause-sticker-zoom
[BUGFIX] Pause Menu and Stickers have same zoom as HUD
2024-09-16 18:20:20 -04:00
EricandGitHub c4b475e86a Merge branch 'develop' into bugfix/pause-sticker-zoom 2024-09-16 18:20:11 -04:00
EricandGitHub 9fddb727b8 Merge pull request #2724 from KarimAkra-Stuff/FlxPartialSound-openfl/polymod-support
[BUGFIX] Fixed Polymod and Mods Support in FlxPartialSound
2024-09-16 18:19:20 -04:00
lemz 224d930ae6 Update PreferencesMenu.hx 2024-09-17 00:17:56 +02:00
EricandGitHub 3b9d400f57 Merge pull request #3328 from FunkinCrew/docs/troubleshooting-update
[DOCS] Update to troubleshooting guide
2024-09-16 18:17:25 -04:00
EliteMasterEric f8d0ddef34 Update troubleshooting guide 2024-09-16 18:17:07 -04:00
lemz 18edadb712 Merge branch 'fps-setting' of https://github.com/lemz1/Funkin into fps-setting 2024-09-17 00:16:33 +02:00
lemz 80fc0cd526 Update Preferences.hx 2024-09-17 00:16:27 +02:00
lemzandGitHub e7674ec31c Merge branch 'develop' into fps-setting 2024-09-17 00:13:49 +02:00
AbnormalandGitHub 0b531c5b21 add getPath 2024-09-16 22:13:16 +00:00
EricandGitHub 8efcd1eae1 Merge pull request #2584 from FunkinCrew/docs/compiling-guide
[DOCS] Update compiling guide with more troubleshooting
2024-09-16 18:12:55 -04:00
EricandGitHub 06485518db Merge branch 'develop' into docs/compiling-guide 2024-09-16 18:12:49 -04:00
EricandGitHub 57523c9439 Merge pull request #3035 from 7oltan/character-path-fix
FIXES CHARACTER PATH ONLY CHECKING IN SHARED
2024-09-16 18:10:25 -04:00
EricandGitHub 42544ee757 Merge branch 'develop' into character-path-fix 2024-09-16 18:10:09 -04:00
Til Tjardes 4be4570c94 Merge branch 'main' of https://github.com/FunkinCrew/Funkin into playsound-typo 2024-09-16 16:08:58 -06:00
lemzandGitHub d0ec26c44a Merge branch 'develop' into completion-fix 2024-09-17 00:08:19 +02:00
lemzandGitHub 8252b2a6b3 Merge branch 'develop' into substate-dispatch-event-fix 2024-09-17 00:07:25 +02:00
EricandGitHub a5ac717677 Merge branch 'develop' into bugfix/freeplay-difficulty-stack-overflow 2024-09-16 18:03:47 -04:00
EricandGitHub ea2e6506c8 Merge pull request #2494 from cyn0x8/flash_fix
consistent flashing
2024-09-16 18:03:18 -04:00
EricandGitHub 1e8d3c715b Merge branch 'develop' into flash_fix 2024-09-16 18:03:05 -04:00
Cameron Taylor 4bc2510d3c Merge remote-tracking branch 'origin/bugfix/pixel-shit-aliasing' into rewrite/master 2024-09-16 17:40:44 -04:00
Cameron Taylor 0574f8b07b Merge remote-tracking branch 'origin/dadbattle-pico-chart-fix' into rewrite/master 2024-09-16 17:31:05 -04:00
Cameron Taylor 11224c5999 Merge remote-tracking branch 'origin/bugfix/song-credits-fixes' into rewrite/master 2024-09-16 17:24:56 -04:00
Cameron Taylor 367e3e9008 priv modules 2024-09-16 17:18:42 -04:00
Cameron Taylor a27c4ae24f pub modules art 2024-09-16 17:14:45 -04:00
Cameron Taylor 1f21e1114b pub modules 2024-09-16 17:12:11 -04:00
EliteMasterEric 16aff6e7c3 Fix bugs with highscore display in Freeplay 2024-09-14 21:37:02 -04:00
EliteMasterEric 9f3af1ab94 Add a separate Gold Perfect animation for modders 2024-09-14 20:56:21 -04:00
EliteMasterEric e23a85682a Update some script files. 2024-09-14 20:26:39 -04:00
EliteMasterEric fd6ca6e267 Remove some spammy log traces. 2024-09-14 20:26:33 -04:00
EliteMasterEric d5c7e4ffdb Fix bug where Pico would become locked on every game restart. 2024-09-14 20:26:19 -04:00
EliteMasterEric 688abb5571 Update example mod's API version so it actually loads. 2024-09-14 20:25:45 -04:00
Til Tjardes 0a8719088d techniktil coming back with another typo lets go 2024-09-14 15:06:03 -06:00
EliteMasterEric df87d677e1 Typo lol 2024-09-14 17:00:41 -04:00
EliteMasterEric 517984d120 Fix a bug where Shit judgement would always display with anti-aliasing. 2024-09-13 18:46:49 -04:00
FabsTheFabs 3fba55a422 assets submod 2024-09-13 21:36:20 +01:00
EliteMasterEric 178389ea0b Fix two song credits 2024-09-12 23:28:43 -04:00
AbnormalandGitHub 16905c8210 Update ScriptedFunkinSprite.hx 2024-09-08 21:48:48 +00:00
lemz 77346696f8 Update MusicBeatSubState.hx 2024-09-07 19:49:08 +02:00
cynandGitHub df266e66d3 dont do that 2024-09-04 19:24:14 -07:00
cynandGitHub 00c7767f8a Update FunkinSound.hx 2024-08-23 20:17:10 -07:00
cynandGitHub c62b53ebe9 Merge branch 'FunkinCrew:main' into flash_fix 2024-08-23 20:09:41 -07:00
Hyper_ d43042fd36 Fix out of bounds note selection 2024-08-05 20:02:23 -03:00
Burgerballs 964f6878c3 Update PlayState.hx 2024-07-23 19:02:09 +01:00
Burgerballs 8778ab1d0e Update PlayState.hx 2024-07-23 18:09:39 +01:00
Burgerballs 59ad15aee4 Merge branch 'develop' of https://github.com/FunkinCrew/Funkin into develop 2024-07-23 18:05:54 +01:00
AppleHairandGitHub c8caeb42de A fix requested by Eric 2024-07-23 11:34:26 +03:00
anysad ba96b11196 hopefully final polish? 2024-07-18 17:56:54 +03:00
anysad ff1ab1eb42 welcome fallback note styles! 2024-07-17 23:19:18 +03:00
AppleHairandGitHub 4d81aa0fe6 [BUGFIX] Ensure the variation used for the next song is valid.
When playing in story mode, `PlayState` assumes all the songs use the same variation, which is usually true, but not guaranteed. This PR makes `PlayState` use the `getFirstValidVariation` method to find the valid variation instead of using the `currentVariation` variable, which might not be valid.
2024-07-17 18:00:07 +03:00
AppleHairandGitHub 691da783fc Updated to extend #2712 2024-07-17 10:20:48 +03:00
AppleHairandGitHub a93cd05aeb Added a comment 2024-07-16 22:36:11 +03:00
anysad ee44981995 you know what, make countdown sprites a little bigger 2024-07-16 22:02:05 +03:00
AppleHairandGitHub 5e1d25e791 [BUGFIX] Prevented infinite recursion on freeplay when a song doesn't have the normal difficulty
Any attempt to create a song without the `normal` difficulty will result in a silent crash when opening freeplay. After some debugging, I discovered that the issue is caused by infinite recursion, which gets triggered at the start of `FreeplaySongData`'s `updateValues`.
2024-07-16 21:17:53 +03:00
anysad f8a0627fd2 goodbye scripts, hello notestyles! 2024-07-16 20:53:12 +03:00
7oltan f8232911cb FIX CHARACTER PATHS ISSUE 2024-07-16 12:52:51 +03:00
anysad aed100df47 how the hell did I miss these? 2024-07-13 23:39:56 +03:00
anysad 9d3c043f8a cache textures at their new locations! 2024-07-13 23:29:26 +03:00
anysad 2547fbb8f4 remove trace 2024-07-13 23:08:16 +03:00
anysad 2993e17278 custom popups and countdowns yay!!! 2024-07-13 22:45:58 +03:00
lemz 0c5815c176 add completion check 2024-07-13 21:27:14 +02:00
AppleHairandGitHub 97e69c6343 Merge branch 'develop' into bugfix/cancel-menu-sound 2024-07-12 18:28:14 +03:00
lemzandGitHub 51c304a6fa Merge branch 'develop' into fps-setting 2024-07-12 06:37:22 +02:00
anysad 47a2cf4e5d Add HEY! song events to Tutorial 2024-07-11 18:12:50 +03:00
anysad a12b0e6ec3 Add HEY! song events to Tutorial 2024-07-11 18:10:45 +03:00
lemzandGitHub 2be22055cc Merge branch 'develop' into fps-setting 2024-07-11 10:25:16 +02:00
gamerbross 2fb55ba3ed Fix default health icon not used 2024-07-11 06:59:22 +02:00
gamerbross 9ad2bb35f9 ChartEditor Live Input Code Refactor + 6 key fix 2024-07-10 01:26:16 +02:00
gamerbrossandGitHub 481f7ab61a Fix F5 chart not reloading 2024-07-10 00:23:06 +02:00
AppleHair 717894300d [BUGFIX] Fixed cancelMenu sound not playing after switching state. 2024-07-09 19:59:31 +03:00
gamerbrossandGitHub f82f0d3b05 Remove SustainTrail forced alpha 2024-07-08 03:17:28 +02:00
lemz 927e37b35b use new numberpreferenceitem 2024-07-02 17:18:46 +02:00
FlooferLand! be5e0aafeb Added getWidth 2024-07-01 14:44:23 +03:00
FlooferLand! 488fc6888f Added new settings items 2024-07-01 14:42:50 +03:00
PixelandGitHub 8e81f6bdf4 Merge branch 'develop' into JVNPixels-story-menu-scrolling-fixed 2024-06-29 17:00:54 -07:00
gamerbrossandGitHub 09c8a2600e Fix null safety compiling 2024-06-29 22:54:25 +02:00
lemzandGitHub 0a7902c4b4 Merge branch 'develop' into fps-setting 2024-06-29 14:27:31 +02:00
gamerbross 02dd7e7264 Implement danceEvery for Characters 2024-06-27 21:05:01 +02:00
gamerbrossandGitHub 91bc63004a FunkinSound.playOnce return sound 2024-06-27 21:00:25 +02:00
lemz f3e04114eb use new offsets 2024-06-25 17:05:15 +02:00
AbnormalPoof ef2885ed0e video cutscene autopause magic 2024-06-24 03:55:59 -05:00
lemz 3b3b9d97ba use different implementation 2024-06-23 21:03:30 +02:00
PixelandGitHub be38ae6c00 Extra newline removal.
Removes the extra line in code.
2024-06-22 19:23:40 -07:00
0589624d11 Update source/funkin/ui/story/StoryMenuState.hx
Co-authored-by: gamerbross <55158797+gamerbross@users.noreply.github.com>
2024-06-21 22:46:07 -07:00
PixelandGitHub dd7a894b51 Update StoryMenuState.hx 2024-06-21 08:42:51 -07:00
gamerbross 73efd963b9 Fix crash after pressing F5 and coming back from stickers 2024-06-20 07:24:36 +02:00
MaybeMaru 250ec840ef Add missing constants 2024-06-18 15:11:00 +02:00
gamerbross ba4677857a Few animation editor bugfixes 2024-06-15 20:23:55 +02:00
lemzandGitHub e3159745fb Merge branch 'develop' into fps-setting 2024-06-13 09:02:27 +02:00
gamerbrossandGitHub b7eaa238e0 Revert camCutscene rename 2024-06-12 00:34:04 +02:00
NotHyper-474 fb71f9087d Fix trace 2024-06-10 23:12:28 -03:00
gamerbross 9618cd2128 Fix chart reset when charting and pressing chart key 2024-06-10 16:53:32 +02:00
lemzandGitHub 9468d95506 Merge branch 'develop' into fps-setting 2024-06-10 12:21:46 +02:00
Karim AkraandGitHub 4997bc27fd remove the library strip 2024-06-09 12:47:17 +03:00
gamerbross 73982fbd60 Fix Stack Overflow if song doesn't have "normal" difficulty 2024-06-09 00:29:55 +02:00
Karim AkraandGitHub 7904a6a20f use Math.fround instead of Math.round 2024-06-09 01:25:21 +03:00
Karim AkraandGitHub ade4aeb3f7 get Float instead of Int in cpp (Float is 64-bit in so it works easier than Int64) 2024-06-09 01:24:02 +03:00
lemzandGitHub e46108fa15 Merge branch 'develop' into fps-setting 2024-06-08 13:03:45 +02:00
lemzandGitHub 7346a46975 Merge branch 'develop' into fps-setting 2024-06-07 20:37:54 +02:00
lemzandGitHub 5baa4c7ef7 Merge branch 'develop' into fps-setting 2024-05-31 11:52:10 +02:00
lemzandGitHub 4ce79cc386 Merge branch 'develop' into fps-setting 2024-05-30 22:23:34 +02:00
lemzandGitHub 11fee0f200 Merge branch 'develop' into fps-setting 2024-05-30 13:54:22 +02:00
lemz 26b357df72 Merge branch 'fps-setting' of https://github.com/lemz1/Funkin into fps-setting 2024-05-30 00:22:18 +02:00
lemz 4a531888b5 Update PreferencesMenu.hx 2024-05-30 00:22:10 +02:00
lemzandGitHub 262bcc4d8b Merge branch 'develop' into fps-setting 2024-05-29 18:45:09 +02:00
lemzandGitHub 088ff3744a Merge branch 'develop' into fps-setting 2024-05-29 07:26:35 +02:00
lemzandGitHub 01b1ce679c Merge branch 'develop' into fps-setting 2024-05-29 06:42:46 +02:00
lemz 267fd0eadc alpha stuff and correct text positioning 2024-05-25 16:30:08 +02:00
lemz 814d72cb3f sounds 2024-05-25 03:06:27 +02:00
lemz b75f6e5853 Update PreferencesMenu.hx 2024-05-25 02:19:11 +02:00
lemz dd6d12de23 rename vars 2024-05-25 01:20:10 +02:00
lemz f86a163692 Merge branch 'develop' into fps-setting 2024-05-25 01:16:34 +02:00
lemz e0fe7cb1eb add fps option 2024-05-25 01:11:34 +02:00
EliteMasterEric 47cbd4b620 Update compiling guide with more troubleshooting 2024-05-21 19:11:10 -04:00
gamerbross 0a6f1abd33 Fix references to camCutscene 2024-05-20 23:52:45 +02:00
gamerbross 92b84168e1 Add camOther to fix zooms on pause and stickers 2024-05-20 02:56:57 +02:00
nebulazorua fae625a795 last commit, if merged, would've likely caused issues if going from tween to classic
should be fixed now?
2024-05-15 20:42:11 +08:00
cynandGitHub c49b66f0e4 flash fix 2024-05-13 11:23:16 -07:00
nebulazorua 3cc7f7407d fix focuscamera CLASSIC breaking zooms and snapping 2024-05-08 21:08:17 +08:00
105 changed files with 1829 additions and 727 deletions
+44
View File
@@ -0,0 +1,44 @@
# Configuration for Label Actions - https://github.com/dessant/label-actions
# Automatically close issues and pull requests when the `status: duplicate` label is applied
'status: duplicate':
issues:
# Post a comment
comment: >
This issue is a duplicate. Please direct all discussion to the original issue.
# Close the issue
close: true
# Remove other status labels
unlabel:
- 'status: pending triage'
# Set a close reason
close-reason: 'not planned'
prs:
# Post a comment
comment: >
This pull request is a duplicate. Please direct all discussion to the original pull request.
# Remove other status labels
unlabel:
- 'status: pending triage'
# Close the pull request
close: true
# Set a close reason
close-reason: 'not planned'
'status: rejected':
issues:
# Close the issue
close: true
# Remove other status labels
unlabel:
- 'status: pending triage'
# Set a close reason
close-reason: 'not planned'
prs:
# Close the pull request
close: true
# Remove other status labels
unlabel:
- 'status: pending triage'
# Set a close reason
close-reason: 'not planned'
+25 -3
View File
@@ -2,6 +2,15 @@ name: Build and Upload nightly game builds
on:
workflow_dispatch:
inputs:
build-defines:
type: string
description: Build defines to use
default: '-DGITHUB_BUILD'
save-artifact:
type: boolean
description: Save the build artifact to Github Actions (sends to itch otherwise)
default: false
push:
paths-ignore:
- '**/Dockerfile'
@@ -53,13 +62,20 @@ jobs:
- name: Build game
if: ${{ matrix.target == 'windows' }}
run: |
haxelib run lime build windows -v -release -DGITHUB_BUILD
haxelib run lime build windows -v -release ${{ github.event.inputs.build-defines }}
timeout-minutes: 120
- name: Build game
if: ${{ matrix.target != 'windows' }}
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times -DGITHUB_BUILD
haxelib run lime build ${{ matrix.target }} -v -release --times ${{ github.event.inputs.build-defines }}
timeout-minutes: 120
- name: Save build artifact to Github Actions
if: ${{ github.event.inputs.save-artifact }}
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.target }}
path: export/release/${{matrix.target}}/bin/
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
@@ -125,9 +141,15 @@ jobs:
- name: Build game
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times -DGITHUB_BUILD
haxelib run lime build ${{ matrix.target }} -v -release --times ${{ github.event.inputs.build-defines }}
timeout-minutes: 120
- name: Save build artifact to Github Actions
if: ${{ github.event.inputs.save-artifact }}
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.target }}
path: export/release/${{matrix.target}}/bin/
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
+29
View File
@@ -0,0 +1,29 @@
# Perform actions when labels are applied to issues, discussions, or pull requests
# See .github/label-actions.yml
name: 'Label Actions'
on:
issues:
types:
- labeled
- unlabeled
pull_request_target:
types:
- labeled
- unlabeled
discussion:
types:
- labeled
- unlabeled
permissions:
contents: read
issues: write
pull-requests: write
discussions: write
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/label-actions@v4
+52
View File
@@ -0,0 +1,52 @@
name: "Issue Labeler"
on:
issues:
types:
- opened
- reopened
- edited
jobs:
# When an issue is opened, perform a similarity check for potential duplicates.
# If some are found, add a label and comment listing the potential duplicate issues.
potential-duplicate:
name: Detect potential duplicate issues
runs-on: ubuntu-latest
steps:
- uses: wow-actions/potential-duplicates@v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Issue title filter work with anymatch https://www.npmjs.com/package/anymatch.
# Any matched issue will stop detection immediately.
# You can specify multi filters in each line.
filter: ''
# Exclude keywords in title before detecting.
exclude: ''
# Label to set, when potential duplicates are detected.
label: 'potential duplicate'
# Get issues with state to compare. Supported state: 'all', 'closed', 'open'.
state: all
# If similarity is higher than this threshold([0,1]), issue will be marked as duplicate.
# Turn this up if the detection is too sensitive
threshold: 0.6
# Reactions to be add to comment when potential duplicates are detected.
# Available reactions: "-1", "+1", "confused", "laugh", "heart", "hooray", "rocket", "eyes"
# reactions: '-1'
# Comment to post when potential duplicates are detected.
comment: >
Potential duplicates: {{#issues}}
- [#{{ number }}] {{ title }} ({{ accuracy }}%)
{{/issues}}
# When an issue is opened, detect if it has an empty body or incomplete issue form.
# If it does, close the issue immediately.
empty-issues:
name: Close empty issues
runs-on: ubuntu-latest
steps:
- name: Run empty issues closer action
uses: rickstaa/empty-issues-closer-action@v1
env:
github_token: ${{ secrets.GITHUB_TOKEN }}
with:
close_comment: Closing this issue because it appears to be empty. Please update the issue for it to be reopened.
open_comment: Reopening this issue because the author provided more information.
@@ -3,6 +3,7 @@ on:
- pull_request_target
jobs:
# Apply labels to pull requests based on which files were edited
labeler:
permissions:
contents: read
@@ -13,6 +14,7 @@ jobs:
uses: actions/labeler@v5
with:
sync-labels: true
# Apply labels to pull requests based on how many lines were edited
changed-lines-count-labeler:
permissions:
contents: read
+2 -2
View File
@@ -1,6 +1,6 @@
[submodule "assets"]
path = assets
url = https://github.com/FunkinCrew/Funkin-Assets-secret
url = https://github.com/FunkinCrew/Funkin-assets-secret
[submodule "art"]
path = art
url = https://github.com/FunkinCrew/Funkin-Art-secret
url = https://github.com/FunkinCrew/Funkin-art-secret
+10
View File
@@ -96,6 +96,11 @@
"target": "windows",
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Debug (Tracy)",
"target": "windows",
"args": ["-debug", "-DFEATURE_DEBUG_TRACY", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Linux / Debug",
"target": "linux",
@@ -106,6 +111,11 @@
"target": "hl",
"args": ["-debug"]
},
{
"label": "Windows / Debug (Discord)",
"target": "windows",
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS", "-DFEATURE_DISCORD_RPC"]
},
{
"label": "Windows / Debug (FlxAnimate Test)",
"target": "windows",
+6 -4
View File
@@ -9,19 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added a new Character Select screen to switch between playable characters in Freeplay
- Modding isn't 100% there but we're working on it!
- Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that)
- The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them
- Added 10 new Pico remixes! Access them by selecting Pico from in the Character Select screen
- The songs from Weekend 1 have moved; you must now switch to Pico via Character Select screen in Freeplay to access them
- Added 11 new Pico remixes! Access them by selecting Pico from in the Character Select screen
- Bopeebo (Pico Mix)
- Fresh (Pico Mix)
- DadBattle (Pico Mix)
- Spookeez (Pico Mix)
- South (Pico Mix)
- Pico (Pico Mix)
- Philly Nice (Pico Mix)
- Blammed (Pico Mix)
- Blammed (Pico Mix)
- Eggnog (Pico Mix)
- Ugh (Pico Mix)
- Guns (Pico Mix)
- Added 1 new Boyfriend remix! Access it by selecting Pico from in the Character Select screen
- Added 1 new Boyfriend remix! Access it by completing Weekend 1 as Pico and then selecting Boyfriend from in the Character Select screen
- Darnell (BF Mix)
- Added 2 new Erect remixes! Access them by switching difficulty on the song
- Cocoa Erect
@@ -39,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- These display on Pico remixes, as well as when playing Weekend 1.
- Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1)
- Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand)
- Implemented new animations for Tankman and Pico
## Changed
- Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo.
- The pixel character icons in the Freeplay menu now display an animation!
+1 -1
View File
@@ -19,7 +19,7 @@ Please check out our [Contributor's guide](./CONTRIBUTORS.md) on how you can act
# Credits and Special Thanks
Full credits can be found in-game, or wherever the credits.json file is.
Full credits can be found in-game, or in the `credits.json` file which is located [here](https://github.com/FunkinCrew/funkin.assets/blob/main/exclude/data/credits.json).
## Programming
- [ninjamuffin99](https://twitter.com/ninja_muffin99) - Lead Programmer
+1 -1
Submodule art updated: 0dee03f11a...fbd3e3df77
+1 -1
Submodule assets updated: bc7009b424...b2404b6b1c
+2 -5
View File
@@ -41,9 +41,6 @@ There are several useful build flags you can add to a build to affect how it wor
- `-DFEATURE_STAGE_EDITOR` to forcibly enable the experimental stage editor.
- `-DFEATURE_GHOST_TAPPING` to forcibly enable an experimental gameplay change to the anti-mash system.
# Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB!
# Troubleshooting
- During the cloning process, you may experience an error along the lines of `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` due to poor connectivity. A common fix is to run ` git config --global http.postBuffer 4096M`.
- Make sure your game directory has an `assets` folder! If it's missing, copy the path to your `funkin` folder and run `cd the\path\you\copied`. Then follow the guide starting from **Step 4**.
- Check that your `assets` folder is not empty! If it is, go back to **Step 4** and follow the guide from there.
- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and following the guide starting from **Step 5**.
If you experience any issues during the compilation process, DO NOT open an issue on GitHub. Instead, check the [Troubleshooting Guide](TROUBLESHOOTING.md) for steps on how to resolve common problems.
+9 -1
View File
@@ -1,4 +1,4 @@
# Troubleshooting Common Issues
# Troubleshooting Common Compilation Issues
- Weird macro error with a very tall call stack: Restart Visual Studio Code
- NOTE: This is caused by Polymod somewhere, and seems to only occur when there is another compile error somewhere in the program. There is a bounty up for it.
@@ -13,3 +13,11 @@
- `LINK : fatal error LNK1201: error writing to program database ''; check for insufficient disk space, invalid path, or insufficient privilege`
- This error occurs if the PDB file located in your `export` folder is in use or exceeds 4 GB. Try deleting the `export` folder and building again from scratch.
- `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)`
- This error can happen during cloning as a result of poor network connectivity. A common fix is to run ` git config --global http.postBuffer 4096M` in your terminal.
- Repository is missing an `assets` folder, or `assets` folder is empty.
- You did not clone the repository correctly! Copy the path to your `funkin` folder and run `cd the\path\you\copied`. Then follow the compilation guide starting from **Step 4**.
- Other compilation issues may be caused by installing bad library versions. Try deleting the `.haxelib` folder and following the guide starting from **Step 5**.
+1 -1
View File
@@ -6,7 +6,7 @@
"name": "EliteMasterEric"
}
],
"api_version": "0.1.0",
"api_version": "0.5.0",
"mod_version": "1.0.0",
"license": "Apache-2.0"
}
+1 -1
View File
@@ -6,7 +6,7 @@
"name": "EliteMasterEric"
}
],
"api_version": "0.1.0",
"api_version": "0.5.0",
"mod_version": "1.0.0",
"license": "Apache-2.0"
}
+13 -20
View File
@@ -7,13 +7,6 @@
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "discord_rpc",
"type": "git",
"dir": null,
"ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5",
"url": "https://github.com/FunkinCrew/linc_discord-rpc"
},
{
"name": "flixel",
"type": "git",
@@ -25,7 +18,7 @@
"name": "flixel-addons",
"type": "git",
"dir": null,
"ref": "9c6fb47968e894eb36bf10e94725cd7640c49281",
"ref": "7424db4e9164ff46f224a7c47de1b732d2542dd7",
"url": "https://github.com/FunkinCrew/flixel-addons"
},
{
@@ -35,13 +28,6 @@
"ref": "951a0103a17bfa55eed86703ce50b4fb0d7590bc",
"url": "https://github.com/FunkinCrew/flixel-text-input"
},
{
"name": "flixel-ui",
"type": "git",
"dir": null,
"ref": "27f1ba626f80a6282fa8a187115e79a4a2133dc2",
"url": "https://github.com/HaxeFlixel/flixel-ui"
},
{
"name": "flxanimate",
"type": "git",
@@ -77,14 +63,14 @@
"name": "haxeui-core",
"type": "git",
"dir": null,
"ref": "22f7c5a8ffca90d4677cffd6e570f53761709fbc",
"ref": "c9d96b168ea2a19274ad7c766ab1a34b57baa793",
"url": "https://github.com/haxeui/haxeui-core"
},
{
"name": "haxeui-flixel",
"type": "git",
"dir": null,
"ref": "28bb710d0ae5d94b5108787593052165be43b980",
"ref": "013b9d4e56bfe9a034e028a8d685f0b274cb73c4",
"url": "https://github.com/haxeui/haxeui-flixel"
},
{
@@ -105,8 +91,8 @@
"name": "hxcpp",
"type": "git",
"dir": null,
"ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1",
"url": "https://github.com/HaxeFoundation/hxcpp"
"ref": "c6bac3d6c7d683f25104296b2f4c50f8c90b8349",
"url": "https://github.com/cortex-engine/hxcpp"
},
{
"name": "hxcpp-debug-server",
@@ -115,6 +101,13 @@
"ref": "147294123f983e35f50a966741474438069a7a8f",
"url": "https://github.com/FunkinCrew/hxcpp-debugger"
},
{
"name": "hxdiscord_rpc",
"type": "git",
"dir": null,
"ref": "82c47ecc1a454b7dd644e4fcac7e91155f176dec",
"url": "https://github.com/FunkinCrew/hxdiscord_rpc"
},
{
"name": "hxjsonast",
"type": "git",
@@ -212,4 +205,4 @@
"url": "https://github.com/fponticelli/thx.semver"
}
]
}
}
+46 -5
View File
@@ -25,7 +25,7 @@ class Project extends HXProject {
* REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES!
* You only have to change it here, the rest of the game will query this value.
*/
static final VERSION:String = "0.5.0";
static final VERSION:String = "0.5.1";
/**
* The game's name. Used as the default window title.
@@ -149,6 +149,21 @@ class Project extends HXProject {
*/
static final FEATURE_DEBUG_FUNCTIONS:FeatureFlag = "FEATURE_DEBUG_FUNCTIONS";
/**
* `-DFEATURE_DEBUG_TRACY`
* If this flag is enabled, the game will have the necessary hooks for the Tracy profiler.
* Only enable this if you're using the correct fork of Haxe to support this.
* @see https://github.com/HaxeFoundation/hxcpp/pull/1153
*/
static final FEATURE_DEBUG_TRACY:FeatureFlag = "FEATURE_DEBUG_TRACY";
/**
* `-DFEATURE_LOG_TRACE`
* If this flag is enabled, the game will print debug traces to the console.
* Disable to improve performance a bunch.
*/
static final FEATURE_LOG_TRACE:FeatureFlag = "FEATURE_LOG_TRACE";
/**
* `-DFEATURE_DISCORD_RPC`
* If this flag is enabled, the game will enable the Discord Remote Procedure Call library.
@@ -199,6 +214,12 @@ class Project extends HXProject {
*/
static final FEATURE_OPEN_URL:FeatureFlag = "FEATURE_OPEN_URL";
/**
* `-DFEATURE_SCREENSHOTS`
* If this flag is enabled, the game will support the screenshots feature.
*/
static final FEATURE_SCREENSHOTS:FeatureFlag = "FEATURE_SCREENSHOTS";
/**
* `-DFEATURE_CHART_EDITOR`
* If this flag is enabled, the Chart Editor will be accessible from the debug menu.
@@ -453,14 +474,14 @@ class Project extends HXProject {
// Should be true on debug builds or if GITHUB_BUILD is enabled.
FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
FEATURE_LOG_TRACE.apply(this, isDebug());
// Should default to true on workspace builds and false on release builds.
REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop());
// Should be true on release, non-tester builds.
// Should be true on desktop, release, non-tester builds.
// We don't want testers to accidentally leak songs to their Discord friends!
// TODO: Re-enable this.
FEATURE_DISCORD_RPC.apply(this, false && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
// Should be true only on web builds.
// Audio context issues only exist there.
@@ -478,6 +499,10 @@ class Project extends HXProject {
// Should be true except on web builds.
// Chart editor doesn't work there.
FEATURE_CHART_EDITOR.apply(this, !isWeb());
// Should be true except on web builds.
// Screenshots doesn't work there.
FEATURE_SCREENSHOTS.apply(this, !isWeb());
}
/**
@@ -516,6 +541,16 @@ class Project extends HXProject {
// Cleaner looking compiler errors.
setHaxedef("message.reporting", "pretty");
if (FEATURE_DEBUG_TRACY.isEnabled(this)) {
setHaxedef("HXCPP_TELEMETRY"); // Enable telemetry
setHaxedef("HXCPP_TRACY"); // Enable Tracy telemetry
setHaxedef("HXCPP_TRACY_MEMORY"); // Track memory allocations
setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable
// setHaxedef("HXCPP_TRACY_INCLUDE_CALLSTACKS"); // Inspect callstacks per zone, inflating telemetry data
setHaxedef("absolute-paths"); // Fix source locations so Tracy can see them
}
}
/**
@@ -618,7 +653,7 @@ class Project extends HXProject {
}
if (FEATURE_DISCORD_RPC.isEnabled(this)) {
addHaxelib('discord_rpc'); // Discord API
addHaxelib('hxdiscord_rpc'); // Discord API
}
if (FEATURE_NEWGROUNDS.isEnabled(this)) {
@@ -941,6 +976,8 @@ class Project extends HXProject {
var commitHash:String = process.stdout.readLine();
var commitHashSplice:String = commitHash.substr(0, 7);
process.close();
return commitHashSplice;
}
@@ -955,6 +992,8 @@ class Project extends HXProject {
var branchName:String = branchProcess.stdout.readLine();
branchProcess.close();
return branchName;
}
@@ -979,6 +1018,8 @@ class Project extends HXProject {
}
}
branchProcess.close();
return output.length > 0;
}
+2 -9
View File
@@ -2,6 +2,7 @@ package;
import flixel.FlxGame;
import flixel.FlxState;
import funkin.Preferences;
import funkin.util.logging.CrashHandler;
import funkin.ui.debug.MemoryCounter;
import funkin.save.Save;
@@ -22,12 +23,6 @@ class Main extends Sprite
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class<FlxState> = funkin.InitState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
#if (web || CHEEMS)
var framerate:Int = 60; // How many frames per second the game should run at.
#else
// TODO: This should probably be in the options menu?
var framerate:Int = 144; // How many frames per second the game should run at.
#end
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
@@ -109,7 +104,7 @@ class Main extends Sprite
// George recommends binding the save before FlxGame is created.
Save.load();
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, framerate, framerate, skipSplash, startFullscreen);
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, Preferences.framerate, Preferences.framerate, skipSplash, startFullscreen);
// FlxG.game._customSoundTray wants just the class, it calls new from
// create() in there, which gets called when it's added to stage
@@ -123,8 +118,6 @@ class Main extends Sprite
game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil());
#end
addChild(fpsCounter);
#if hxcpp_debug_server
trace('hxcpp_debug_server is enabled! You can now connect to the game with a debugger.');
#else
+102
View File
@@ -0,0 +1,102 @@
/*
* Pulled from Tracey profiler PR
* @see https://github.com/HaxeFoundation/haxe/pull/11772
*/
package cpp.vm.tracy;
#if (!HXCPP_TRACY)
#error "This class cannot be used without -D HXCPP_TRACY"
#end
enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8
{
var Number = 0;
var Memory = 1;
var Percentage = 2;
}
@:include('hx/TelemetryTracy.h')
extern class Native_TracyProfiler
{
/**
Mark a frame. Call this at the end of each frame loop.
**/
@:native('::__hxcpp_tracy_framemark')
public static function frameMark():Void;
/**
Print a message into Tracy's log.
**/
@:native('::__hxcpp_tracy_message')
public static function message(_msg:String, ?_color:Int = 0x000000):Void;
/**
Tracy can collect additional information about the profiled application,
which will be available in the trace description.
This can include data such as the source repository revision,
the application’s environment (dev/prod), etc.
**/
@:native('::__hxcpp_tracy_message_app_info')
public static function messageAppInfo(_info:String):Void;
/**
Plot a named value to tracy. This will generate a graph in the profiler for you.
**/
@:native('::__hxcpp_tracy_plot')
public static function plot(_name:String, _val:cpp.Float32):Void;
/**
Configure how values are plotted and displayed.
**/
@:native('::__hxcpp_tracy_plot_config')
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000):Void;
/**
Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI.
**/
@:native('::__hxcpp_tracy_set_thread_name_and_group')
public static function setThreadName(_name:String, ?_groupHint:Int = 1):Void;
/**
Create a custom named scoped zone in your code.
**/
@:native('HXCPP_TRACY_ZONE')
public static function zoneScoped(_name:String):Void;
}
#if (scriptable || cppia)
class Cppia_TracyProfiler
{
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMark)
public static function frameMark()
Native_TracyProfiler.frameMark();
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.message)
public static function message(_msg:String, ?_color:Int = 0x000000)
Native_TracyProfiler.message(_msg, _color);
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.messageAppInfo)
public static function messageAppInfo(_info:String)
Native_TracyProfiler.messageAppInfo(_info);
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plot)
public static function plot(_name:String, _val:Float)
Native_TracyProfiler.plot(_name, _val);
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plotConfig)
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000)
Native_TracyProfiler.plotConfig(_name, _format, _step, _fill, _color);
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.setThreadName)
public static function setThreadName(_name:String, ?_groupHint:Int = 1)
Native_TracyProfiler.setThreadName(_name, _groupHint);
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.zoneScoped)
public static function zoneScoped(_name:String)
Native_TracyProfiler.zoneScoped(_name);
}
typedef TracyProfiler = Cppia_TracyProfiler;
#else
typedef TracyProfiler = Native_TracyProfiler;
#end
+136 -13
View File
@@ -1,38 +1,161 @@
package funkin;
import openfl.utils.Future;
/**
* A wrapper around `openfl.utils.Assets` which disallows access to the harmful functions.
* Later we'll add Funkin-specific caching to this.
*/
class Assets
{
public static function getText(path:String):String
/**
* Get the file system path for an asset
* @param path The asset path to load from, relative to the assets folder
* @return The path to the asset on the file system
*/
public static function getPath(path:String):String
{
return openfl.utils.Assets.getText(path);
}
public static function getMusic(path:String):openfl.media.Sound
{
return openfl.utils.Assets.getMusic(path);
}
public static function getBitmapData(path:String):openfl.display.BitmapData
{
return openfl.utils.Assets.getBitmapData(path);
return openfl.utils.Assets.getPath(path);
}
/**
* Load bytes from an asset
* May cause stutters or throw an error if the asset is not cached
* @param path The asset path to load from
* @return The byte contents of the file
*/
public static function getBytes(path:String):haxe.io.Bytes
{
return openfl.utils.Assets.getBytes(path);
}
/**
* Load bytes from an asset asynchronously
* @param path The asset path to load from
* @return A future which promises to return the byte contents of the file
*/
public static function loadBytes(path:String):Future<openfl.utils.ByteArray>
{
return openfl.utils.Assets.loadBytes(path);
}
/**
* Load text from an asset.
* May cause stutters or throw an error if the asset is not cached
* @param path The asset path to load from
* @return The text contents of the file
*/
public static function getText(path:String):String
{
return openfl.utils.Assets.getText(path);
}
/**
* Load text from an asset asynchronously
* @param path The asset path to load from
* @return A future which promises to return the text contents of the file
*/
public static function loadText(path:String):Future<String>
{
return openfl.utils.Assets.loadText(path);
}
/**
* Load a Sound file from an asset
* May cause stutters or throw an error if the asset is not cached
* @param path The asset path to load from
* @return The loaded sound
*/
public static function getSound(path:String):openfl.media.Sound
{
return openfl.utils.Assets.getSound(path);
}
/**
* Load a Sound file from an asset asynchronously
* @param path The asset path to load from
* @return A future which promises to return the loaded sound
*/
public static function loadSound(path:String):Future<openfl.media.Sound>
{
return openfl.utils.Assets.loadSound(path);
}
/**
* Load a Sound file from an asset, with optimizations specific to long-duration music
* May cause stutters or throw an error if the asset is not cached
* @param path The asset path to load from
* @return The loaded sound
*/
public static function getMusic(path:String):openfl.media.Sound
{
return openfl.utils.Assets.getMusic(path);
}
/**
* Load a Sound file from an asset asynchronously, with optimizations specific to long-duration music
* @param path The asset path to load from
* @return A future which promises to return the loaded sound
*/
public static function loadMusic(path:String):Future<openfl.media.Sound>
{
return openfl.utils.Assets.loadMusic(path);
}
/**
* Load a Bitmap from an asset
* May cause stutters or throw an error if the asset is not cached
* @param path The asset path to load from
* @return The loaded Bitmap image
*/
public static function getBitmapData(path:String):openfl.display.BitmapData
{
return openfl.utils.Assets.getBitmapData(path);
}
/**
* Load a Bitmap from an asset asynchronously
* @param path The asset path to load from
* @return The future which promises to return the loaded Bitmap image
*/
public static function loadBitmapData(path:String):Future<openfl.display.BitmapData>
{
return openfl.utils.Assets.loadBitmapData(path);
}
/**
* Determines whether the given asset of the given type exists.
* @param path The asset path to check
* @param type The asset type to check
* @return Whether the asset exists
*/
public static function exists(path:String, ?type:openfl.utils.AssetType):Bool
{
return openfl.utils.Assets.exists(path, type);
}
public static function list(type:openfl.utils.AssetType):Array<String>
/**
* Retrieve a list of all assets of the given type
* @param type The asset type to check
* @return A list of asset paths
*/
public static function list(?type:openfl.utils.AssetType):Array<String>
{
return openfl.utils.Assets.list(type);
}
public static function hasLibrary(name:String):Bool
{
return openfl.utils.Assets.hasLibrary(name);
}
public static function getLibrary(name:String):lime.utils.AssetLibrary
{
return openfl.utils.Assets.getLibrary(name);
}
public static function loadLibrary(name:String):Future<openfl.utils.AssetLibrary>
{
return openfl.utils.Assets.loadLibrary(name);
}
}
+23 -3
View File
@@ -275,6 +275,13 @@ class Conductor
return Save.instance.options.audioVisualOffset;
}
public var combinedOffset(get, never):Float;
function get_combinedOffset():Float
{
return instrumentalOffset + audioVisualOffset + inputOffset;
}
/**
* The number of beats in a measure. May be fractional depending on the time signature.
*/
@@ -397,9 +404,12 @@ class Conductor
*/
public function update(?songPos:Float, applyOffsets:Bool = true, forceDispatch:Bool = false)
{
var currentTime:Float = (FlxG.sound.music != null) ? FlxG.sound.music.time : 0.0;
var currentLength:Float = (FlxG.sound.music != null) ? FlxG.sound.music.length : 0.0;
if (songPos == null)
{
songPos = (FlxG.sound.music != null) ? FlxG.sound.music.time : 0.0;
songPos = currentTime;
}
// Take into account instrumental and file format song offsets.
@@ -409,8 +419,17 @@ class Conductor
var oldBeat:Float = this.currentBeat;
var oldStep:Float = this.currentStep;
// If the song is playing, limit the song position to the length of the song or beginning of the song.
if (FlxG.sound.music != null && FlxG.sound.music.playing)
{
this.songPosition = Math.min(currentLength, Math.max(0, songPos));
}
else
{
this.songPosition = songPos;
}
// Set the song position we are at (for purposes of calculating note positions, etc).
this.songPosition = songPos;
currentTimeChange = timeChanges[0];
if (this.songPosition > 0.0)
@@ -430,7 +449,8 @@ class Conductor
else if (currentTimeChange != null && this.songPosition > 0.0)
{
// roundDecimal prevents representing 8 as 7.9999999
this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT) + (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT)
+ (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
this.currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
this.currentMeasureTime = currentStepTime / stepsPerMeasure;
this.currentStep = Math.floor(currentStepTime);
+22 -20
View File
@@ -1,42 +1,42 @@
package funkin;
import funkin.data.freeplay.player.PlayerRegistry;
import funkin.ui.debug.charting.ChartEditorState;
import funkin.ui.transition.LoadingState;
import flixel.FlxState;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
import flixel.addons.transition.TransitionData;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.graphics.FlxGraphic;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.FlxSprite;
import flixel.system.debug.log.LogStyle;
import flixel.util.FlxColor;
import funkin.util.macro.MacroUtil;
import funkin.util.WindowUtil;
import funkin.play.PlayStatePlaylist;
import openfl.display.BitmapData;
import funkin.data.story.level.LevelRegistry;
import funkin.data.notestyle.NoteStyleRegistry;
import funkin.data.freeplay.style.FreeplayStyleRegistry;
import funkin.data.event.SongEventRegistry;
import funkin.data.stage.StageRegistry;
import funkin.data.dialogue.conversation.ConversationRegistry;
import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry;
import funkin.data.dialogue.speaker.SpeakerRegistry;
import funkin.data.freeplay.album.AlbumRegistry;
import funkin.data.freeplay.player.PlayerRegistry;
import funkin.data.freeplay.style.FreeplayStyleRegistry;
import funkin.data.notestyle.NoteStyleRegistry;
import funkin.data.song.SongRegistry;
import funkin.data.event.SongEventRegistry;
import funkin.data.stage.StageRegistry;
import funkin.data.story.level.LevelRegistry;
import funkin.modding.module.ModuleHandler;
import funkin.play.character.CharacterData.CharacterDataParser;
import funkin.play.notes.notekind.NoteKindManager;
import funkin.modding.module.ModuleHandler;
import funkin.play.PlayStatePlaylist;
import funkin.ui.debug.charting.ChartEditorState;
import funkin.ui.title.TitleState;
import funkin.ui.transition.LoadingState;
import funkin.util.CLIUtil;
import funkin.util.CLIUtil.CLIParams;
import funkin.util.macro.MacroUtil;
import funkin.util.TimerUtil;
import funkin.util.TrackerUtil;
import funkin.util.WindowUtil;
import openfl.display.BitmapData;
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
import funkin.api.discord.DiscordClient;
#end
/**
@@ -125,10 +125,10 @@ class InitState extends FlxState
// DISCORD API SETUP
//
#if FEATURE_DISCORD_RPC
DiscordClient.initialize();
DiscordClient.instance.init();
Application.current.onExit.add(function(exitCode) {
DiscordClient.shutdown();
lime.app.Application.current.onExit.add(function(exitCode) {
DiscordClient.instance.shutdown();
});
#end
@@ -148,10 +148,12 @@ class InitState extends FlxState
#if FEATURE_DEBUG_FUNCTIONS
funkin.util.plugins.MemoryGCPlugin.initialize();
#end
#if FEATURE_SCREENSHOTS
funkin.util.plugins.ScreenshotPlugin.initialize();
#end
funkin.util.plugins.EvacuateDebugPlugin.initialize();
funkin.util.plugins.ForceCrashPlugin.initialize();
funkin.util.plugins.ReloadAssetsDebugPlugin.initialize();
funkin.util.plugins.ScreenshotPlugin.initialize();
funkin.util.plugins.VolumePlugin.initialize();
funkin.util.plugins.WatchPlugin.initialize();
+2 -3
View File
@@ -2,7 +2,6 @@ package funkin;
import flixel.graphics.frames.FlxAtlasFrames;
import openfl.utils.AssetType;
import openfl.utils.Assets as OpenFlAssets;
/**
* A core class which handles determining asset paths.
@@ -44,11 +43,11 @@ class Paths
if (currentLevel != null)
{
var levelPath:String = getLibraryPathForce(file, currentLevel);
if (OpenFlAssets.exists(levelPath, type)) return levelPath;
if (Assets.exists(levelPath, type)) return levelPath;
}
var levelPath:String = getLibraryPathForce(file, 'shared');
if (OpenFlAssets.exists(levelPath, type)) return levelPath;
if (Assets.exists(levelPath, type)) return levelPath;
return getPreloadPath(file);
}
+29
View File
@@ -7,6 +7,35 @@ import funkin.save.Save;
*/
class Preferences
{
/**
* FPS
* @default `60`
*/
public static var framerate(get, set):Int;
static function get_framerate():Int
{
#if web
return 60;
#else
return Save?.instance?.options?.framerate ?? 60;
#end
}
static function set_framerate(value:Int):Int
{
#if web
return 60;
#else
var save:Save = Save.instance;
save.options.framerate = value;
save.flush();
FlxG.updateFramerate = value;
FlxG.drawFramerate = value;
return value;
#end
}
/**
* Whether some particularly fowl language is displayed.
* @default `true`
-91
View File
@@ -1,91 +0,0 @@
package funkin.api.discord;
import Sys.sleep;
#if FEATURE_DISCORD_RPC
import discord_rpc.DiscordRpc;
#end
class DiscordClient
{
#if FEATURE_DISCORD_RPC
public function new()
{
trace("Discord Client starting...");
DiscordRpc.start(
{
clientID: "814588678700924999",
onReady: onReady,
onError: onError,
onDisconnected: onDisconnected
});
trace("Discord Client started.");
while (true)
{
DiscordRpc.process();
sleep(2);
// trace("Discord Client Update");
}
DiscordRpc.shutdown();
}
public static function shutdown()
{
DiscordRpc.shutdown();
}
static function onReady()
{
DiscordRpc.presence(
{
details: "In the Menus",
state: null,
largeImageKey: 'icon',
largeImageText: "Friday Night Funkin'"
});
}
static function onError(_code:Int, _message:String)
{
trace('Error! $_code : $_message');
}
static function onDisconnected(_code:Int, _message:String)
{
trace('Disconnected! $_code : $_message');
}
public static function initialize()
{
var DiscordDaemon = sys.thread.Thread.create(() -> {
new DiscordClient();
});
trace("Discord Client initialized");
}
public static function changePresence(details:String, ?state:String, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float)
{
var startTimestamp:Float = if (hasStartTimestamp) Date.now().getTime() else 0;
if (endTimestamp > 0)
{
endTimestamp = startTimestamp + endTimestamp;
}
DiscordRpc.presence(
{
details: details,
state: state,
largeImageKey: 'icon',
largeImageText: "Friday Night Funkin'",
smallImageKey: smallImageKey,
// Obtained times are in milliseconds so they are divided so Discord can use it
startTimestamp: Std.int(startTimestamp / 1000),
endTimestamp: Std.int(endTimestamp / 1000)
});
// trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp');
}
#end
}
+204
View File
@@ -0,0 +1,204 @@
package funkin.api.discord;
#if FEATURE_DISCORD_RPC
import hxdiscord_rpc.Discord;
import hxdiscord_rpc.Types;
import sys.thread.Thread;
class DiscordClient
{
static final CLIENT_ID:String = "816168432860790794";
public static var instance(get, never):DiscordClient;
static var _instance:Null<DiscordClient> = null;
static function get_instance():DiscordClient
{
if (DiscordClient._instance == null) _instance = new DiscordClient();
if (DiscordClient._instance == null) throw "Could not initialize singleton DiscordClient!";
return DiscordClient._instance;
}
var handlers:DiscordEventHandlers;
private function new()
{
trace('[DISCORD] Initializing event handlers...');
handlers = DiscordEventHandlers.create();
handlers.ready = cpp.Function.fromStaticFunction(onReady);
handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected);
handlers.errored = cpp.Function.fromStaticFunction(onError);
}
public function init():Void
{
trace('[DISCORD] Initializing connection...');
// Discord.initialize(CLIENT_ID, handlers, true, null);
Discord.Initialize(CLIENT_ID, cpp.RawPointer.addressOf(handlers), 1, null);
createDaemon();
}
var daemon:Thread = null;
function createDaemon():Void
{
daemon = Thread.create(doDaemonWork);
}
function doDaemonWork():Void
{
while (true)
{
trace('[DISCORD] Performing client update...');
#if DISCORD_DISABLE_IO_THREAD
Discord.updateConnection();
#end
Discord.runCallbacks();
Sys.sleep(2);
}
}
public function shutdown():Void
{
trace('[DISCORD] Shutting down...');
Discord.shutdown();
}
public function setPresence(params:DiscordClientPresenceParams):Void
{
trace('[DISCORD] Updating presence... (${params})');
Discord.updatePresence(buildPresence(params));
}
function buildPresence(params:DiscordClientPresenceParams):DiscordRichPresence
{
var presence = DiscordRichPresence.create();
// Presence should always be playing the game.
presence.type = DiscordActivityType_Playing;
// Text when hovering over the large image. We just leave this as the game name.
presence.largeImageText = "Friday Night Funkin'";
// State should be generally what the person is doing, like "In the Menus" or "Pico (Pico Mix) [Freeplay Hard]"
presence.state = cast(params.state, Null<String>);
// Details should be what the person is specifically doing, including stuff like timestamps (maybe something like "03:24 elapsed").
presence.details = cast(params.details, Null<String>);
// The large image displaying what the user is doing.
// This should probably be album art.
// IMPORTANT NOTE: This can be an asset key uploaded to Discord's developer panel OR any URL you like.
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? "album-volume1";
trace('[DISCORD] largeImageKey: ${presence.largeImageKey}');
// TODO: Make this use the song's album art.
// presence.largeImageKey = "icon";
// presence.largeImageKey = "https://f4.bcbits.com/img/a0746694746_16.jpg";
// The small inset image for what the user is doing.
// This can be the opponent's health icon?
// NOTE: Like largeImageKey, this can be a URL, or an asset key.
presence.smallImageKey = cast(params.smallImageKey, Null<String>);
// NOTE: In previous versions, this showed as "Elapsed", but now shows as playtime and doesn't look good
// presence.startTimestamp = time - 10;
// presence.endTimestamp = time + 30;
final button1:DiscordButton = DiscordButton.create();
button1.label = "Play on Web";
button1.url = Constants.URL_NEWGROUNDS;
presence.buttons[0] = button1;
final button2:DiscordButton = DiscordButton.create();
button2.label = "Download";
button2.url = Constants.URL_ITCH;
presence.buttons[1] = button2;
return presence;
}
// TODO: WHAT THE FUCK get this pointer bullfuckery out of here
private static function onReady(request:cpp.RawConstPointer<DiscordUser>):Void
{
trace('[DISCORD] Client has connected!');
final username:String = request[0].username;
final globalName:String = request[0].username;
final discriminator:Int = Std.parseInt(request[0].discriminator);
if (discriminator != 0)
{
trace('[DISCORD] User: ${username}#${discriminator} (${globalName})');
}
else
{
trace('[DISCORD] User: @${username} (${globalName})');
}
}
private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void
{
trace('[DISCORD] Client has disconnected! ($errorCode) "${cast (message, String)}"');
}
private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void
{
trace('[DISCORD] Client has received an error! ($errorCode) "${cast (message, String)}"');
}
// public var type(get, set):DiscordActivityType;
// public var state(get, set):String;
// public var details(get, set):String;
// public var startTimestamp(get, set):Int;
// public var endTimestamp(get, set):Int;
// public var largeImageKey(get, set):String;
// public var largeImageText(get, set):String;
// public var smallImageKey(get, set):String;
// public var smallImageText(get, set):String;
//
//
// public var partyId(get, set)
// public var partySize(get, set)
// public var partyMax(get, set)
// public var partyPrivacy(get, set)
//
// public var buttons(get, set)
//
// public var matchSecret(get, set)
// public var joinSecret(get, set)
// public var spectateSecret(get, set)
}
typedef DiscordClientPresenceParams =
{
/**
* The first row of text below the game title.
*/
var state:String;
/**
* The second row of text below the game title.
* Use `null` to display no text.
*/
var details:Null<String>;
/**
* A large, 4-row high image to the left of the content.
*/
var ?largeImageKey:String;
/**
* A small, inset image to the bottom right of `largeImageKey`.
*/
var ?smallImageKey:String;
}
#end
+13 -6
View File
@@ -390,7 +390,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
}
else
{
var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true, params.onComplete);
var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true, params.persist ?? false, params.onComplete);
if (music != null)
{
FlxG.sound.music = music;
@@ -430,12 +430,13 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
* @param autoDestroy Whether to destroy this sound when it finishes playing.
* Leave this value set to `false` if you want to re-use this `FunkinSound` instance.
* @param autoPlay Whether to play the sound immediately or wait for a `play()` call.
* @param persist Whether to keep this `FunkinSound` between states, or destroy it.
* @param onComplete Called when the sound finished playing.
* @param onLoad Called when the sound finished loading. Called immediately for succesfully loaded embedded sounds.
* @return A `FunkinSound` object, or `null` if the sound could not be loaded.
*/
public static function load(embeddedSound:FlxSoundAsset, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, autoPlay:Bool = false,
?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
persist:Bool = false, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
{
@:privateAccess
if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS)
@@ -462,7 +463,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
if (autoPlay) sound.play();
sound.volume = volume;
sound.group = FlxG.sound.defaultSoundGroup;
sound.persist = true;
sound.persist = persist;
// Make sure to add the sound to the list.
// If it's already in, it won't get re-added.
@@ -513,7 +514,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
});
soundRequest.future.onComplete(function(partialSound) {
var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad);
var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, false, onComplete, onLoad);
promise.complete(snd);
});
}
@@ -543,18 +544,19 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
*/
public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
{
var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad);
var result:Null<FunkinSound> = FunkinSound.load(key, volume, false, true, true, false, onComplete, onLoad);
return result;
}
/**
* Stop all sounds in the pool and allow them to be recycled.
*/
public static function stopAllAudio(musicToo:Bool = false):Void
public static function stopAllAudio(musicToo:Bool = false, persistToo:Bool = false):Void
{
for (sound in pool)
{
if (sound == null) continue;
if (!persistToo && sound.persist) continue;
if (!musicToo && sound == FlxG.sound.music) continue;
sound.destroy();
}
@@ -628,6 +630,11 @@ typedef FunkinSoundPlayMusicParams =
var ?partialParams:PartialSoundParams;
/**
* Whether the sound should be destroyed on state switches
*/
var ?persist:Bool;
var ?onComplete:Void->Void;
var ?onLoad:Void->Void;
}
@@ -264,12 +264,32 @@ class PlayerCharSelectData
*/
@:optional
public var position:Null<Int>;
/**
* The GF name to assign for this character.
*/
@:optional
public var gf:PlayerCharSelectGFData;
}
typedef PlayerCharSelectGFData =
{
@:optional
public var assetPath:String;
@:optional
public var animInfoPath:String;
@:optional
@:default(false)
public var visualizer:Bool;
}
typedef PlayerResultsData =
{
var music:PlayerResultsMusicData;
var perfectGold:Array<PlayerResultsAnimationData>;
var perfect:Array<PlayerResultsAnimationData>;
var excellent:Array<PlayerResultsAnimationData>;
var great:Array<PlayerResultsAnimationData>;
+4
View File
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.2]
### Added
- Added the ability to specify `flipX` and `flipY` on stage props to horizontally or vertically flip, respectively.
## [1.0.1]
### Added
- Added the ability to specify a hexadecimal color in the `assetPath` field instead of a texture key.
+16
View File
@@ -118,6 +118,22 @@ typedef StageDataProp =
@:default(false)
var isPixel:Bool;
/**
* If set to true, the prop will be flipped horizontally.
* @default false
*/
@:optional
@:default(false)
var flipX:Bool;
/**
* If set to true, the prop will be flipped vertically.
* @default false
*/
@:optional
@:default(false)
var flipY:Bool;
/**
* Either the scale of the prop as a float, or the [w, h] scale as an array of two floats.
* Pro tip: On pixel-art levels, save the sprite small and set this value to 6 or so to save memory.
+2 -2
View File
@@ -11,9 +11,9 @@ class StageRegistry extends BaseRegistry<Stage, StageData>
* Handle breaking changes by incrementing this value
* and adding migration to the `migrateStageData()` function.
*/
public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.0";
public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.2";
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <=1.0.2";
public static var instance(get, never):StageRegistry;
static var _instance:Null<StageRegistry> = null;
+40
View File
@@ -0,0 +1,40 @@
package funkin.effects;
import flixel.addons.effects.FlxTrail;
import funkin.play.stage.Bopper;
import flixel.FlxSprite;
import flixel.system.FlxAssets;
/**
* An offshoot of FlxTrail, but accomodates the way Funkin
* does offsets for characters. example, fixes Spirits trail
*/
class FunkTrail extends FlxTrail
{
/**
* Creates a new FunkTrail effect for a specific FlxSprite.
*
* @param Target The FlxSprite the trail is attached to.
* @param Graphic The image to use for the trailsprites. Optional, uses the sprite's graphic if null.
* @param Length The amount of trailsprites to create.
* @param Delay How often to update the trail. 0 updates every frame.
* @param Alpha The alpha value for the very first trailsprite.
* @param Diff How much lower the alpha of the next trailsprite is.
*/
public function new(Target:FlxSprite, ?Graphic:FlxGraphicAsset, Length:Int = 10, Delay:Int = 3, Alpha:Float = 0.4, Diff:Float = 0.05)
{
super(Target, Graphic, Length, Delay, Alpha, Diff);
}
override public function update(elapsed:Float):Void
{
if (target is Bopper)
{
var targ:Bopper = cast target;
@:privateAccess effectOffset.set((targ.animOffsets[0] - targ.globalOffsets[0]) * targ.scale.x,
(targ.animOffsets[1] - targ.globalOffsets[1]) * targ.scale.y);
}
super.update(elapsed);
}
}
@@ -7,7 +7,6 @@ import flxanimate.frames.FlxAnimateFrames;
import flixel.graphics.frames.FlxFrame;
import flixel.system.FlxAssets.FlxGraphicAsset;
import openfl.display.BitmapData;
import openfl.utils.Assets;
import flixel.math.FlxPoint;
import flxanimate.animate.FlxKeyFrame;
@@ -184,7 +183,7 @@ class FlxAtlasSprite extends FlxAnimate
// Move to the first frame of the animation.
// goToFrameLabel(id);
trace('Playing animation $id');
// trace('Playing animation $id');
if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
{
this.anim.play(id, restart, false, startFrame);
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import funkin.Paths;
import openfl.utils.Assets;
class AdjustColorShader extends FlxRuntimeShader
{
@@ -52,4 +50,9 @@ class AdjustColorShader extends FlxRuntimeShader
return this.contrast;
}
public override function toString():String
{
return 'AdjustColorShader(${this.hue}, ${this.saturation}, ${this.brightness}, ${this.contrast})';
}
}
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import funkin.Paths;
import openfl.utils.Assets;
import openfl.display.BitmapData;
import openfl.display.ShaderInput;
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import funkin.Paths;
import openfl.utils.Assets;
/**
* Note... not actually gaussian!
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import funkin.Paths;
import openfl.utils.Assets;
class Grayscale extends FlxRuntimeShader
{
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import funkin.Paths;
import openfl.utils.Assets;
class HSVShader extends FlxRuntimeShader
{
@@ -1,8 +1,6 @@
package funkin.graphics.shaders;
import flixel.addons.display.FlxRuntimeShader;
import openfl.utils.Assets;
import funkin.Paths;
import flixel.math.FlxPoint;
class MosaicEffect extends FlxRuntimeShader
@@ -2,7 +2,6 @@ package funkin.graphics.shaders;
import openfl.display.BitmapData;
import openfl.display.BlendMode;
import openfl.utils.Assets;
class RuntimeCustomBlendShader extends RuntimePostEffectShader
{
@@ -5,7 +5,6 @@ import openfl.display.BitmapData;
import openfl.display.ShaderParameter;
import openfl.display.ShaderParameterType;
import flixel.util.FlxColor;
import openfl.utils.Assets;
typedef Light =
{
@@ -0,0 +1,34 @@
package funkin.graphics.video;
#if hxCodec
import hxcodec.flixel.FlxVideoSprite;
/**
* Not to be confused with FlxVideo, this is a hxcodec based video class
* We override it simply to correct/control our volume easier.
*/
class FunkinVideoSprite extends FlxVideoSprite
{
public var volume(default, set):Float = 1;
public function new(x:Float = 0, y:Float = 0)
{
super(x, y);
set_volume(1);
}
override public function update(elapsed:Float):Void
{
super.update(elapsed);
set_volume(volume);
}
function set_volume(value:Float):Float
{
volume = value;
bitmap.volume = Std.int((FlxG.sound.muted ? 0 : 1) * (FlxG.sound.logToLinear(FlxG.sound.volume) * 100) * volume);
return volume;
}
}
#end
+1
View File
@@ -3,6 +3,7 @@ package;
#if !macro
// Only import these when we aren't in a macro.
import funkin.util.Constants;
import funkin.Assets;
import funkin.Paths;
import funkin.Preferences;
import flixel.FlxG; // This one in particular causes a compile error if you're using macros.
+60 -18
View File
@@ -59,7 +59,9 @@ class Controls extends FlxActionSet
var _back = new FunkinAction(Action.BACK);
var _pause = new FunkinAction(Action.PAUSE);
var _reset = new FunkinAction(Action.RESET);
#if FEATURE_SCREENSHOTS
var _window_screenshot = new FunkinAction(Action.WINDOW_SCREENSHOT);
#end
var _window_fullscreen = new FunkinAction(Action.WINDOW_FULLSCREEN);
var _freeplay_favorite = new FunkinAction(Action.FREEPLAY_FAVORITE);
var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT);
@@ -67,8 +69,12 @@ class Controls extends FlxActionSet
var _freeplay_char_select = new FunkinAction(Action.FREEPLAY_CHAR_SELECT);
var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE);
var _debug_menu = new FunkinAction(Action.DEBUG_MENU);
#if FEATURE_CHART_EDITOR
var _debug_chart = new FunkinAction(Action.DEBUG_CHART);
#end
#if FEATURE_STAGE_EDITOR
var _debug_stage = new FunkinAction(Action.DEBUG_STAGE);
#end
var _volume_up = new FunkinAction(Action.VOLUME_UP);
var _volume_down = new FunkinAction(Action.VOLUME_DOWN);
var _volume_mute = new FunkinAction(Action.VOLUME_MUTE);
@@ -243,10 +249,12 @@ class Controls extends FlxActionSet
inline function get_WINDOW_FULLSCREEN()
return _window_fullscreen.check();
#if FEATURE_SCREENSHOTS
public var WINDOW_SCREENSHOT(get, never):Bool;
inline function get_WINDOW_SCREENSHOT()
return _window_screenshot.check();
#end
public var FREEPLAY_FAVORITE(get, never):Bool;
@@ -278,15 +286,19 @@ class Controls extends FlxActionSet
inline function get_DEBUG_MENU()
return _debug_menu.check();
#if FEATURE_CHART_EDITOR
public var DEBUG_CHART(get, never):Bool;
inline function get_DEBUG_CHART()
return _debug_chart.check();
#end
#if FEATURE_STAGE_EDITOR
public var DEBUG_STAGE(get, never):Bool;
inline function get_DEBUG_STAGE()
return _debug_stage.check();
#end
public var VOLUME_UP(get, never):Bool;
@@ -319,7 +331,7 @@ class Controls extends FlxActionSet
add(_back);
add(_pause);
add(_reset);
add(_window_screenshot);
#if FEATURE_SCREENSHOTS add(_window_screenshot); #end
add(_window_fullscreen);
add(_freeplay_favorite);
add(_freeplay_left);
@@ -327,8 +339,8 @@ class Controls extends FlxActionSet
add(_freeplay_char_select);
add(_cutscene_advance);
add(_debug_menu);
add(_debug_chart);
add(_debug_stage);
#if FEATURE_CHART_EDITOR add(_debug_chart); #end
#if FEATURE_STAGE_EDITOR add(_debug_stage); #end
add(_volume_up);
add(_volume_down);
add(_volume_mute);
@@ -444,7 +456,7 @@ class Controls extends FlxActionSet
case BACK: _back;
case PAUSE: _pause;
case RESET: _reset;
case WINDOW_SCREENSHOT: _window_screenshot;
#if FEATURE_SCREENSHOTS case WINDOW_SCREENSHOT: _window_screenshot; #end
case WINDOW_FULLSCREEN: _window_fullscreen;
case FREEPLAY_FAVORITE: _freeplay_favorite;
case FREEPLAY_LEFT: _freeplay_left;
@@ -452,8 +464,8 @@ class Controls extends FlxActionSet
case FREEPLAY_CHAR_SELECT: _freeplay_char_select;
case CUTSCENE_ADVANCE: _cutscene_advance;
case DEBUG_MENU: _debug_menu;
case DEBUG_CHART: _debug_chart;
case DEBUG_STAGE: _debug_stage;
#if FEATURE_CHART_EDITOR case DEBUG_CHART: _debug_chart; #end
#if FEATURE_STAGE_EDITOR case DEBUG_STAGE: _debug_stage; #end
case VOLUME_UP: _volume_up;
case VOLUME_DOWN: _volume_down;
case VOLUME_MUTE: _volume_mute;
@@ -516,8 +528,10 @@ class Controls extends FlxActionSet
func(_pause, JUST_PRESSED);
case RESET:
func(_reset, JUST_PRESSED);
#if FEATURE_SCREENSHOTS
case WINDOW_SCREENSHOT:
func(_window_screenshot, JUST_PRESSED);
#end
case WINDOW_FULLSCREEN:
func(_window_fullscreen, JUST_PRESSED);
case FREEPLAY_FAVORITE:
@@ -532,10 +546,14 @@ class Controls extends FlxActionSet
func(_cutscene_advance, JUST_PRESSED);
case DEBUG_MENU:
func(_debug_menu, JUST_PRESSED);
#if FEATURE_CHART_EDITOR
case DEBUG_CHART:
func(_debug_chart, JUST_PRESSED);
#end
#if FEATURE_STAGE_EDITOR
case DEBUG_STAGE:
func(_debug_stage, JUST_PRESSED);
#end
case VOLUME_UP:
func(_volume_up, JUST_PRESSED);
case VOLUME_DOWN:
@@ -744,7 +762,9 @@ class Controls extends FlxActionSet
bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK));
bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE));
bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET));
#if FEATURE_SCREENSHOTS
bindKeys(Control.WINDOW_SCREENSHOT, getDefaultKeybinds(scheme, Control.WINDOW_SCREENSHOT));
#end
bindKeys(Control.WINDOW_FULLSCREEN, getDefaultKeybinds(scheme, Control.WINDOW_FULLSCREEN));
bindKeys(Control.FREEPLAY_FAVORITE, getDefaultKeybinds(scheme, Control.FREEPLAY_FAVORITE));
bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT));
@@ -752,8 +772,12 @@ class Controls extends FlxActionSet
bindKeys(Control.FREEPLAY_CHAR_SELECT, getDefaultKeybinds(scheme, Control.FREEPLAY_CHAR_SELECT));
bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE));
bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU));
#if FEATURE_CHART_EDITOR
bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART));
#end
#if FEATURE_STAGE_EDITOR
bindKeys(Control.DEBUG_STAGE, getDefaultKeybinds(scheme, Control.DEBUG_STAGE));
#end
bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP));
bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN));
bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE));
@@ -781,15 +805,15 @@ class Controls extends FlxActionSet
case Control.PAUSE: return [P, ENTER, ESCAPE];
case Control.RESET: return [R];
case Control.WINDOW_FULLSCREEN: return [F11]; // We use F for other things LOL.
case Control.WINDOW_SCREENSHOT: return [F3];
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return [F3]; #end
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
case Control.CUTSCENE_ADVANCE: return [Z, ENTER];
case Control.DEBUG_MENU: return [GRAVEACCENT];
case Control.DEBUG_CHART: return [];
case Control.DEBUG_STAGE: return [];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
case Control.VOLUME_UP: return [PLUS, NUMPADPLUS];
case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS];
case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO];
@@ -809,7 +833,7 @@ class Controls extends FlxActionSet
case Control.BACK: return [H, X];
case Control.PAUSE: return [ONE];
case Control.RESET: return [R];
case Control.WINDOW_SCREENSHOT: return [F3];
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return [F3]; #end
case Control.WINDOW_FULLSCREEN: return [F11];
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
@@ -817,8 +841,8 @@ class Controls extends FlxActionSet
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
case Control.CUTSCENE_ADVANCE: return [G, Z];
case Control.DEBUG_MENU: return [GRAVEACCENT];
case Control.DEBUG_CHART: return [];
case Control.DEBUG_STAGE: return [];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
case Control.VOLUME_UP: return [PLUS];
case Control.VOLUME_DOWN: return [MINUS];
case Control.VOLUME_MUTE: return [ZERO];
@@ -838,7 +862,7 @@ class Controls extends FlxActionSet
case Control.BACK: return [ESCAPE];
case Control.PAUSE: return [ONE];
case Control.RESET: return [R];
case Control.WINDOW_SCREENSHOT: return [];
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return []; #end
case Control.WINDOW_FULLSCREEN: return [];
case Control.FREEPLAY_FAVORITE: return [];
case Control.FREEPLAY_LEFT: return [];
@@ -846,8 +870,8 @@ class Controls extends FlxActionSet
case Control.FREEPLAY_CHAR_SELECT: return [];
case Control.CUTSCENE_ADVANCE: return [ENTER];
case Control.DEBUG_MENU: return [];
case Control.DEBUG_CHART: return [];
case Control.DEBUG_STAGE: return [];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
case Control.VOLUME_UP: return [NUMPADPLUS];
case Control.VOLUME_DOWN: return [NUMPADMINUS];
case Control.VOLUME_MUTE: return [NUMPADZERO];
@@ -952,7 +976,9 @@ class Controls extends FlxActionSet
Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE),
Control.RESET => getDefaultGamepadBinds(Control.RESET),
Control.WINDOW_FULLSCREEN => getDefaultGamepadBinds(Control.WINDOW_FULLSCREEN),
#if FEATURE_SCREENSHOTS
Control.WINDOW_SCREENSHOT => getDefaultGamepadBinds(Control.WINDOW_SCREENSHOT),
#end
Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE),
Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE),
Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT),
@@ -961,8 +987,12 @@ class Controls extends FlxActionSet
Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN),
Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE),
Control.DEBUG_MENU => getDefaultGamepadBinds(Control.DEBUG_MENU),
#if FEATURE_CHART_EDITOR
Control.DEBUG_CHART => getDefaultGamepadBinds(Control.DEBUG_CHART),
#end
#if FEATURE_STAGE_EDITOR
Control.DEBUG_STAGE => getDefaultGamepadBinds(Control.DEBUG_STAGE),
#end
]);
}
@@ -996,8 +1026,10 @@ class Controls extends FlxActionSet
return [FlxGamepadInputID.BACK]; // Back (i.e. Select)
case Control.WINDOW_FULLSCREEN:
[];
#if FEATURE_SCREENSHOTS
case Control.WINDOW_SCREENSHOT:
[];
#end
case Control.CUTSCENE_ADVANCE:
return [A];
case Control.FREEPLAY_FAVORITE:
@@ -1014,10 +1046,14 @@ class Controls extends FlxActionSet
[];
case Control.DEBUG_MENU:
[];
#if FEATURE_CHART_EDITOR
case Control.DEBUG_CHART:
[];
#end
#if FEATURE_STAGE_EDITOR
case Control.DEBUG_STAGE:
[];
#end
default:
// Fallthrough.
}
@@ -1582,7 +1618,7 @@ enum Control
FREEPLAY_RIGHT;
FREEPLAY_CHAR_SELECT;
// WINDOW
WINDOW_SCREENSHOT;
#if FEATURE_SCREENSHOTS WINDOW_SCREENSHOT; #end
WINDOW_FULLSCREEN;
// VOLUME
VOLUME_UP;
@@ -1590,8 +1626,8 @@ enum Control
VOLUME_MUTE;
// DEBUG
DEBUG_MENU;
DEBUG_CHART;
DEBUG_STAGE;
#if FEATURE_CHART_EDITOR DEBUG_CHART; #end
#if FEATURE_STAGE_EDITOR DEBUG_STAGE; #end
}
enum abstract Action(String) to String from String
@@ -1628,7 +1664,9 @@ enum abstract Action(String) to String from String
var RESET = "reset";
// WINDOW
var WINDOW_FULLSCREEN = "window_fullscreen";
#if FEATURE_SCREENSHOTS
var WINDOW_SCREENSHOT = "window_screenshot";
#end
// CUTSCENE
var CUTSCENE_ADVANCE = "cutscene_advance";
// FREEPLAY
@@ -1642,8 +1680,12 @@ enum abstract Action(String) to String from String
var VOLUME_MUTE = "volume_mute";
// DEBUG
var DEBUG_MENU = "debug_menu";
#if FEATURE_CHART_EDITOR
var DEBUG_CHART = "debug_chart";
#end
#if FEATURE_STAGE_EDITOR
var DEBUG_STAGE = "debug_stage";
#end
}
enum Device
-1
View File
@@ -1,7 +1,6 @@
package funkin.input;
import haxe.ui.backend.flixel.CursorHelper;
import openfl.utils.Assets;
import lime.app.Future;
import openfl.display.BitmapData;
+15 -6
View File
@@ -27,11 +27,18 @@ import polymod.Polymod;
class PolymodHandler
{
/**
* The API version that mods should comply with.
* Indicates which mods are compatible with this version of the game.
* The API version for the current version of the game. Since 0.5.0, we've just made this the game version!
* Minor updates rarely impact mods but major versions often do.
*/
static final API_VERSION:String = "0.5.0"; // Constants.VERSION;
// static final API_VERSION:String = Constants.VERSION;
/**
* The Semantic Versioning rule
* Indicates which mods are compatible with this version of the game.
* Using more complex rules allows mods from older compatible versions to stay functioning,
* while preventing mods made for future versions from being installed.
*/
static final API_VERSION_RULE:String = ">=0.5.0 <0.6.0";
/**
* Where relative to the executable that mods are located.
@@ -131,7 +138,7 @@ class PolymodHandler
// Framework being used to load assets.
framework: OPENFL,
// The current version of our API.
apiVersionRule: API_VERSION,
apiVersionRule: API_VERSION_RULE,
// Call this function any time an error occurs.
errorCallback: PolymodErrorHandler.onPolymodError,
// Enforce semantic version patterns for each mod.
@@ -228,6 +235,8 @@ class PolymodHandler
static function buildImports():Void
{
// Add default imports for common classes.
Polymod.addDefaultImport(funkin.Assets);
Polymod.addDefaultImport(funkin.Paths);
// Add import aliases for certain classes.
// NOTE: Scripted classes are automatically aliased to their parent class.
@@ -258,7 +267,7 @@ class PolymodHandler
Polymod.blacklistImport('cpp.Lib');
// `Unserializer`
// Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages
// Unserializer.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages
Polymod.blacklistImport('Unserializer');
// `lime.system.CFFI`
@@ -336,7 +345,7 @@ class PolymodHandler
var modMetadata:Array<ModMetadata> = Polymod.scan(
{
modRoot: MOD_FOLDER,
apiVersionRule: API_VERSION,
apiVersionRule: API_VERSION_RULE,
fileSystem: modFileSystem,
errorCallback: PolymodErrorHandler.onPolymodError
});
@@ -1,8 +1,8 @@
package funkin.modding.base;
/**
* A script that can be tied to an FlxSprite.
* Create a scripted class that extends FlxSprite to use this.
* A script that can be tied to a FunkinSprite.
* Create a scripted class that extends FunkinSprite to use this.
*/
@:hscriptClass
class ScriptedFunkinSprite extends funkin.graphics.FunkinSprite implements HScriptedClass {}
+1 -1
View File
@@ -103,7 +103,7 @@ class NoteScriptEvent extends ScriptEvent
public var comboCount(default, null):Int;
/**
* Whether to play the record scratch sound (if this eventn type is `NOTE_MISS`).
* Whether to play the record scratch sound (if this event type is `NOTE_MISS`).
*/
public var playSound(default, default):Bool;
@@ -125,7 +125,6 @@ class ModuleHandler
for (key => value in moduleCache)
{
ScriptEventDispatcher.callEvent(value, event);
moduleCache.remove(key);
}
moduleCache.clear();
-1
View File
@@ -11,7 +11,6 @@ import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
import flixel.util.FlxTimer;
import funkin.util.EaseUtil;
import funkin.audio.FunkinSound;
import openfl.utils.Assets;
import funkin.data.notestyle.NoteStyleRegistry;
import funkin.play.notes.notestyle.NoteStyle;
-1
View File
@@ -15,7 +15,6 @@ import funkin.ui.freeplay.FreeplayState;
import funkin.ui.MusicBeatSubState;
import funkin.ui.story.StoryMenuState;
import funkin.util.MathUtil;
import openfl.utils.Assets;
import funkin.effects.RetroCameraFade;
import flixel.math.FlxPoint;
+178 -68
View File
@@ -15,8 +15,8 @@ import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.ui.FlxBar;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import flixel.util.FlxStringUtil;
import flixel.util.FlxTimer;
import funkin.api.newgrounds.NGio;
import funkin.audio.FunkinSound;
import funkin.audio.VoicesGroup;
@@ -44,12 +44,12 @@ import funkin.play.cutscene.dialogue.Conversation;
import funkin.play.cutscene.VanillaCutscenes;
import funkin.play.cutscene.VideoCutscene;
import funkin.play.notes.NoteDirection;
import funkin.play.notes.notekind.NoteKindManager;
import funkin.play.notes.NoteSplash;
import funkin.play.notes.NoteSprite;
import funkin.play.notes.notestyle.NoteStyle;
import funkin.play.notes.Strumline;
import funkin.play.notes.SustainTrail;
import funkin.play.notes.notekind.NoteKindManager;
import funkin.play.scoring.Scoring;
import funkin.play.song.Song;
import funkin.play.stage.Stage;
@@ -68,7 +68,7 @@ import openfl.display.BitmapData;
import openfl.geom.Rectangle;
import openfl.Lib;
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
import funkin.api.discord.DiscordClient;
#end
/**
@@ -447,10 +447,8 @@ class PlayState extends MusicBeatSubState
#if FEATURE_DISCORD_RPC
// Discord RPC variables
var storyDifficultyText:String = '';
var iconRPC:String = '';
var detailsText:String = '';
var detailsPausedText:String = '';
var discordRPCAlbum:String = '';
var discordRPCIcon:String = '';
#end
/**
@@ -687,7 +685,11 @@ class PlayState extends MusicBeatSubState
}
Conductor.instance.mapTimeChanges(currentChart.timeChanges);
Conductor.instance.update((Conductor.instance.beatLengthMs * -5) + startTimestamp);
var pre:Float = (Conductor.instance.beatLengthMs * -5) + startTimestamp;
trace('Attempting to start at ' + pre);
Conductor.instance.update(pre);
// The song is now loaded. We can continue to initialize the play state.
initCameras();
@@ -813,6 +815,7 @@ class PlayState extends MusicBeatSubState
}
else
{
this.remove(currentStage);
FlxG.switchState(() -> new MainMenuState());
}
return false;
@@ -857,7 +860,7 @@ class PlayState extends MusicBeatSubState
// Reset music properly.
if (FlxG.sound.music != null)
{
FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset;
FlxG.sound.music.time = startTimestamp - Conductor.instance.combinedOffset;
FlxG.sound.music.pitch = playbackRate;
FlxG.sound.music.pause();
}
@@ -874,7 +877,7 @@ class PlayState extends MusicBeatSubState
}
}
vocals.pause();
vocals.time = 0;
vocals.time = 0 - Conductor.instance.combinedOffset;
if (FlxG.sound.music != null) FlxG.sound.music.volume = 1;
vocals.volume = 1;
@@ -915,7 +918,11 @@ class PlayState extends MusicBeatSubState
{
// Do NOT apply offsets at this point, because they already got applied the previous frame!
Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false);
if (Conductor.instance.songPosition >= (startTimestamp)) startSong();
if (Conductor.instance.songPosition >= (startTimestamp + Conductor.instance.combinedOffset))
{
trace("started song at " + Conductor.instance.songPosition);
startSong();
}
}
}
else
@@ -957,6 +964,7 @@ class PlayState extends MusicBeatSubState
// It's a reference to Gitaroo Man, which doesn't let you pause the game.
if (!isSubState && event.gitaroo)
{
this.remove(currentStage);
FlxG.switchState(() -> new GitarooPause(
{
targetSong: currentSong,
@@ -984,7 +992,15 @@ class PlayState extends MusicBeatSubState
}
#if FEATURE_DISCORD_RPC
DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
DiscordClient.instance.setPresence(
{
details: 'Paused - ${buildDiscordRPCDetails()}',
state: buildDiscordRPCState(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
#end
}
}
@@ -1073,8 +1089,14 @@ class PlayState extends MusicBeatSubState
}
#if FEATURE_DISCORD_RPC
// Game Over doesn't get his own variable because it's only used here
DiscordClient.changePresence('Game Over - ' + detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
DiscordClient.instance.setPresence(
{
details: 'Game Over - ${buildDiscordRPCDetails()}',
state: buildDiscordRPCState(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
#end
}
else if (isPlayerDying)
@@ -1285,14 +1307,29 @@ class PlayState extends MusicBeatSubState
Countdown.resumeCountdown();
#if FEATURE_DISCORD_RPC
if (startTimer.finished)
if (Conductor.instance.songPosition > 0)
{
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true,
currentSongLengthMs - Conductor.instance.songPosition);
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true,
// currentSongLengthMs - Conductor.instance.songPosition);
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
}
else
{
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC);
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
}
#end
@@ -1318,16 +1355,32 @@ class PlayState extends MusicBeatSubState
#end
#if FEATURE_DISCORD_RPC
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause)
if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause)
{
if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
+ ' ('
+ storyDifficultyText
+ ')', iconRPC, true,
currentSongLengthMs
- Conductor.instance.songPosition);
if (Conductor.instance.songPosition > 0.0)
{
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
}
else
DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
{
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true,
// currentSongLengthMs - Conductor.instance.songPosition);
}
}
#end
@@ -1344,8 +1397,17 @@ class PlayState extends MusicBeatSubState
#end
#if FEATURE_DISCORD_RPC
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText,
currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause)
{
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
}
#end
super.onFocusLost();
@@ -1358,6 +1420,7 @@ class PlayState extends MusicBeatSubState
{
funkin.modding.PolymodHandler.forceReloadAssets();
lastParams.targetSong = SongRegistry.instance.fetchEntry(currentSong.id);
this.remove(currentStage);
LoadingState.loadPlayState(lastParams);
}
@@ -1391,15 +1454,18 @@ class PlayState extends MusicBeatSubState
// activeNotes.sort(SortUtil.byStrumtime, FlxSort.DESCENDING);
}
if (!startingSong
&& FlxG.sound.music != null
&& (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100
|| Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100))
if (FlxG.sound.music != null)
{
trace("VOCALS NEED RESYNC");
if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset));
trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset));
resyncVocals();
var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.combinedOffset));
if (!startingSong && (Math.abs(FlxG.sound.music.time - correctSync) > 5 || Math.abs(vocals.checkSyncError(correctSync)) > 5))
{
trace("VOCALS NEED RESYNC");
if (vocals != null) trace(vocals.checkSyncError(correctSync));
trace(FlxG.sound.music.time);
trace(correctSync);
resyncVocals();
}
}
// Only bop camera if zoom level is below 135%
@@ -1612,7 +1678,7 @@ class PlayState extends MusicBeatSubState
if (girlfriend != null)
{
girlfriend.characterType = CharacterType.GF;
// Don't need to do anything.
}
else if (currentCharacterData.girlfriend != '')
{
@@ -1630,8 +1696,6 @@ class PlayState extends MusicBeatSubState
if (dad != null)
{
dad.characterType = CharacterType.DAD;
//
// OPPONENT HEALTH ICON
//
@@ -1641,6 +1705,11 @@ class PlayState extends MusicBeatSubState
iconP2.zIndex = 850;
add(iconP2);
iconP2.cameras = [camHUD];
#if FEATURE_DISCORD_RPC
discordRPCAlbum = 'album-${currentChart.album}';
discordRPCIcon = 'icon-${currentCharacterData.opponent}';
#end
}
//
@@ -1650,8 +1719,6 @@ class PlayState extends MusicBeatSubState
if (boyfriend != null)
{
boyfriend.characterType = CharacterType.BF;
//
// PLAYER HEALTH ICON
//
@@ -1758,29 +1825,53 @@ class PlayState extends MusicBeatSubState
function initDiscord():Void
{
#if FEATURE_DISCORD_RPC
storyDifficultyText = difficultyString();
iconRPC = currentSong.player2;
// To avoid having duplicate images in Discord assets
switch (iconRPC)
{
case 'senpai-angry':
iconRPC = 'senpai';
case 'monster-christmas':
iconRPC = 'monster';
case 'mom-car':
iconRPC = 'mom';
}
// String that contains the mode defined here so it isn't necessary to call changePresence for each mode
detailsText = isStoryMode ? 'Story Mode: Week $storyWeek' : 'Freeplay';
detailsPausedText = 'Paused - $detailsText';
// Determine the details strings once and reuse them.
// Updating Discord Rich Presence.
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC);
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
#end
}
function buildDiscordRPCDetails():String
{
if (PlayStatePlaylist.isStoryMode)
{
return 'Story Mode: ${PlayStatePlaylist.campaignTitle}';
}
else
{
if (isChartingMode)
{
return 'Chart Editor [Playtest]';
}
else if (isPracticeMode)
{
return 'Freeplay [Practice]';
}
else if (isBotPlayMode)
{
return 'Freeplay [Bot Play]';
}
else
{
return 'Freeplay';
}
}
}
function buildDiscordRPCState():String
{
var discordRPCDifficulty = PlayState.instance.currentDifficulty.replace('-', ' ').toTitleCase();
return '${currentChart.songName} [${discordRPCDifficulty}]';
}
function initPreciseInputs():Void
{
PreciseInputManager.instance.onInputPressed.add(onKeyPress);
@@ -1956,7 +2047,7 @@ class PlayState extends MusicBeatSubState
};
// A negative instrumental offset means the song skips the first few milliseconds of the track.
// This just gets added into the startTimestamp behavior so we don't need to do anything extra.
FlxG.sound.music.play(true, startTimestamp - Conductor.instance.instrumentalOffset);
FlxG.sound.music.play(true, Math.max(0, startTimestamp - Conductor.instance.combinedOffset));
FlxG.sound.music.pitch = playbackRate;
// Prevent the volume from being wrong.
@@ -1968,16 +2059,27 @@ class PlayState extends MusicBeatSubState
vocals.play();
vocals.volume = 1.0;
vocals.pitch = playbackRate;
vocals.time = FlxG.sound.music.time;
// trace('${FlxG.sound.music.time}');
// trace('${vocals.time}');
resyncVocals();
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence (with Time Left)
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, currentSongLengthMs);
DiscordClient.instance.setPresence(
{
state: buildDiscordRPCState(),
details: buildDiscordRPCDetails(),
largeImageKey: discordRPCAlbum,
smallImageKey: discordRPCIcon
});
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true, currentSongLengthMs);
#end
if (startTimestamp > 0)
{
// FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset;
// FlxG.sound.music.time = startTimestamp - Conductor.instance.combinedOffset;
handleSkippedNotes();
}
@@ -1993,7 +2095,9 @@ class PlayState extends MusicBeatSubState
// Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.)
if (!(FlxG.sound.music?.playing ?? false)) return;
var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset;
var timeToPlayAt:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.combinedOffset));
trace('Resyncing vocals to ${timeToPlayAt}');
FlxG.sound.music.pause();
vocals.pause();
@@ -2373,9 +2477,9 @@ class PlayState extends MusicBeatSubState
if (targetNote == null) continue;
// Judge and hit the note.
trace('Hit note! ${targetNote.noteData}');
// trace('Hit note! ${targetNote.noteData}');
goodNoteHit(targetNote, input);
trace('Score: ${songScore}');
// trace('Score: ${songScore}');
notesInDirection.remove(targetNote);
@@ -2566,7 +2670,7 @@ class PlayState extends MusicBeatSubState
*/
function debugKeyShit():Void
{
#if FEATURE_CHART_EDITOR
#if FEATURE_STAGE_EDITOR
// Open the stage editor overlaying the current state.
if (controls.DEBUG_STAGE)
{
@@ -2575,7 +2679,9 @@ class PlayState extends MusicBeatSubState
persistentUpdate = false;
openSubState(new StageOffsetSubState());
}
#end
#if FEATURE_CHART_EDITOR
// Redirect to the chart editor playing the current song.
if (controls.DEBUG_CHART)
{
@@ -2583,11 +2689,13 @@ class PlayState extends MusicBeatSubState
persistentUpdate = false;
if (isChartingMode)
{
// Close the playtest substate.
FlxG.sound.music?.pause();
this.close();
}
else
{
this.remove(currentStage);
FlxG.switchState(() -> new ChartEditorState(
{
targetSongId: currentSong.id,
@@ -2937,6 +3045,7 @@ class PlayState extends MusicBeatSubState
{
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
}
this.remove(currentStage);
LoadingState.loadPlayState(
{
targetSong: targetSong,
@@ -2954,6 +3063,7 @@ class PlayState extends MusicBeatSubState
{
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
}
this.remove(currentStage);
LoadingState.loadPlayState(
{
targetSong: targetSong,
@@ -3177,7 +3287,7 @@ class PlayState extends MusicBeatSubState
/**
* Resets the camera's zoom level and focus point.
*/
public function resetCamera(?resetZoom:Bool = true, ?cancelTweens:Bool = true):Void
public function resetCamera(?resetZoom:Bool = true, ?cancelTweens:Bool = true, ?snap:Bool = true):Void
{
// Cancel camera tweens if any are active.
if (cancelTweens)
@@ -3194,7 +3304,7 @@ class PlayState extends MusicBeatSubState
}
// Snap the camera to the follow point immediately.
FlxG.camera.focusOn(cameraFollowPoint.getPosition());
if (snap) FlxG.camera.focusOn(cameraFollowPoint.getPosition());
}
/**
+34 -3
View File
@@ -74,6 +74,8 @@ class ResultState extends MusicBeatSubState
var playerCharacterId:Null<String>;
var introMusicAudio:Null<FunkinSound>;
var rankBg:FunkinSprite;
final cameraBG:FunkinCamera;
final cameraScroll:FunkinCamera;
@@ -413,7 +415,8 @@ class ResultState extends MusicBeatSubState
if (Assets.exists(introMusic))
{
// Play the intro music.
FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
introMusicAudio = FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
introMusicAudio = null;
FunkinSound.playMusic(getMusicPath(playerCharacter, rank),
{
startingVolume: 1.0,
@@ -472,9 +475,12 @@ class ResultState extends MusicBeatSubState
{
ease: FlxEase.quartOut,
onUpdate: _ -> {
clearPercentLerp = Math.round(clearPercentLerp);
clearPercentCounter.curNumber = Math.round(clearPercentCounter.curNumber);
// Only play the tick sound if the number increased.
if (clearPercentLerp != clearPercentCounter.curNumber)
{
trace('$clearPercentLerp and ${clearPercentCounter.curNumber}');
clearPercentLerp = clearPercentCounter.curNumber;
FunkinSound.playOnce(Paths.sound('scrollMenu'));
}
@@ -724,9 +730,34 @@ class ResultState extends MusicBeatSubState
if (controls.PAUSE)
{
if (FlxG.sound.music != null)
if (introMusicAudio != null) {
@:nullSafety(Off)
introMusicAudio.onComplete = null;
FlxTween.tween(introMusicAudio, {volume: 0}, 0.8, {
onComplete: _ -> {
if (introMusicAudio != null) {
introMusicAudio.stop();
introMusicAudio.destroy();
introMusicAudio = null;
}
}
});
FlxTween.tween(introMusicAudio, {pitch: 3}, 0.1,
{
onComplete: _ -> {
FlxTween.tween(introMusicAudio, {pitch: 0.5}, 0.4);
}
});
}
else if (FlxG.sound.music != null)
{
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8);
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8, {
onComplete: _ -> {
FlxG.sound.music.stop();
FlxG.sound.music.destroy();
}
});
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
{
onComplete: _ -> {
@@ -147,7 +147,7 @@ class AnimateAtlasCharacter extends BaseCharacter
if (getAnimationData() != null && getAnimationData().looped)
{
playAnimation(prefix, true, false);
playAnimation(currentAnimName, true, false);
}
else
{
+11 -12
View File
@@ -233,15 +233,9 @@ class BaseCharacter extends Bopper
*/
public function resetCharacter(resetCamera:Bool = true):Void
{
// Reset the animation offsets. This will modify x and y to be the absolute position of the character.
// this.animOffsets = [0, 0];
// Now we can set the x and y to be their original values without having to account for animOffsets.
// Set the x and y to be their original values.
this.resetPosition();
// Then reapply animOffsets...
// applyAnimationOffsets(getCurrentAnimation());
this.dance(true); // Force to avoid the old animation playing with the wrong offset at the start of the song.
// Make sure we are playing the idle animation
// ...then update the hitbox so that this.width and this.height are correct.
@@ -305,7 +299,7 @@ class BaseCharacter extends Bopper
{
super.onAnimationFinished(animationName);
trace('${characterId} has finished animation: ${animationName}');
// trace('${characterId} has finished animation: ${animationName}');
if ((animationName.endsWith(Constants.ANIMATION_END_SUFFIX) && !animationName.startsWith('idle') && !animationName.startsWith('dance'))
|| animationName.startsWith('combo')
|| animationName.startsWith('drop'))
@@ -323,6 +317,11 @@ class BaseCharacter extends Bopper
this.cameraFocusPoint = new FlxPoint(charCenterX + _data.cameraOffsets[0], charCenterY + _data.cameraOffsets[1]);
}
public function getHealthIconId():String
{
return _data?.healthIcon?.id ?? Constants.DEFAULT_HEALTH_ICON;
}
public function initHealthIcon(isOpponent:Bool):Void
{
if (!isOpponent)
@@ -332,7 +331,7 @@ class BaseCharacter extends Bopper
trace('[WARN] Player 1 health icon not found!');
return;
}
PlayState.instance.iconP1.configure(_data.healthIcon);
PlayState.instance.iconP1.configure(_data?.healthIcon);
PlayState.instance.iconP1.flipX = !PlayState.instance.iconP1.flipX; // BF is looking the other way.
}
else
@@ -342,7 +341,7 @@ class BaseCharacter extends Bopper
trace('[WARN] Player 2 health icon not found!');
return;
}
PlayState.instance.iconP2.configure(_data.healthIcon);
PlayState.instance.iconP2.configure(_data?.healthIcon);
}
}
@@ -402,7 +401,7 @@ class BaseCharacter extends Bopper
FlxG.watch.addQuick('singTimeSec-${characterId}', singTimeSec);
if (holdTimer > singTimeSec && shouldStopSinging)
{
trace('holdTimer reached ${holdTimer}sec (> ${singTimeSec}), stopping sing animation');
// trace('holdTimer reached ${holdTimer}sec (> ${singTimeSec}), stopping sing animation');
holdTimer = 0;
var currentAnimation:String = getCurrentAnimation();
@@ -636,7 +635,7 @@ class BaseCharacter extends Bopper
var anim:String = 'sing${dir.nameUpper}${miss ? 'miss' : ''}${suffix != '' ? '-${suffix}' : ''}';
// restart even if already playing, because the character might sing the same note twice.
trace('Playing ${anim}...');
// trace('Playing ${anim}...');
playAnimation(anim, true);
}
+58 -21
View File
@@ -11,7 +11,7 @@ import funkin.play.character.ScriptedCharacter.ScriptedSparrowCharacter;
import funkin.util.assets.DataAssets;
import funkin.util.VersionUtil;
import haxe.Json;
import openfl.utils.Assets;
import flixel.graphics.frames.FlxFrame;
class CharacterDataParser
{
@@ -281,41 +281,78 @@ class CharacterDataParser
}
/**
* TODO: Hardcode this.
* Returns the idle frame of a character.
*/
public static function getCharPixelIconAsset(char:String):String
public static function getCharPixelIconAsset(char:String):FlxFrame
{
var icon:String = char;
var charPath:String = "freeplay/icons/";
switch (icon)
// FunkinCrew please dont skin me alive for copying pixelated icon and changing it a tiny bit
switch (char)
{
case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf":
icon = "bf";
case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf" | "bf-dark":
charPath += "bfpixel";
case "monster-christmas":
icon = "monster";
charPath += "monsterpixel";
case "mom" | "mom-car":
icon = "mommy";
charPath += "mommypixel";
case "pico-blazin" | "pico-playable" | "pico-speaker":
icon = "pico";
case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen":
icon = "gf";
charPath += "picopixel";
case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen" | "gf-dark":
charPath += "gfpixel";
case "dad":
icon = "daddy";
charPath += "dadpixel";
case "darnell-blazin":
icon = "darnell";
charPath += "darnellpixel";
case "senpai-angry":
icon = "senpai";
charPath += "senpaipixel";
case "spooky-dark":
icon = "spooky";
charPath += "spookypixel";
case "tankman-atlas":
icon = "tankman";
charPath += "tankmanpixel";
case "pico-christmas" | "pico-dark":
charPath += "picopixel";
default:
charPath += '${char}pixel';
}
var path = Paths.image("freeplay/icons/" + icon + "pixel");
if (Assets.exists(path)) return path;
if (!Assets.exists(Paths.image(charPath)))
{
trace('[WARN] Character ${char} has no freeplay icon.');
return null;
}
// TODO: Hardcode some additional behavior or a fallback.
return null;
var isAnimated = Assets.exists(Paths.file('images/$charPath.xml'));
var frame:FlxFrame = null;
if (isAnimated)
{
var frames = Paths.getSparrowAtlas(charPath);
var idleFrame:FlxFrame = frames.frames.find(function(frame:FlxFrame):Bool {
return frame.name.startsWith('idle');
});
if (idleFrame == null)
{
trace('[WARN] Character ${char} has no idle in their freeplay icon.');
return null;
}
// so, haxe.ui.backend.AssetsImpl uses the parent width and height, which makes the image go crazy when rendered
// so this is a work around so that it uses the actual width and height
var imageGraphic = flixel.graphics.FlxGraphic.fromFrame(idleFrame);
var imageFrame = flixel.graphics.frames.FlxImageFrame.fromImage(imageGraphic);
frame = imageFrame.frame;
}
else
{
var imageFrame = flixel.graphics.frames.FlxImageFrame.fromImage(Paths.image(charPath));
frame = imageFrame.frame;
}
return frame;
}
/**
+9 -21
View File
@@ -5,7 +5,6 @@ import flixel.FlxSprite;
import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import funkin.play.character.CharacterData.CharacterDataParser;
import openfl.utils.Assets;
import funkin.graphics.FunkinSprite;
import funkin.util.MathUtil;
@@ -33,7 +32,7 @@ class HealthIcon extends FunkinSprite
* The character this icon is representing.
* Setting this variable will automatically update the graphic.
*/
public var characterId(default, set):Null<String>;
public var characterId(default, set):String = Constants.DEFAULT_HEALTH_ICON;
/**
* Whether this health icon should automatically update its state based on the character's health.
@@ -116,7 +115,7 @@ class HealthIcon extends FunkinSprite
*/
static final POSITION_OFFSET:Int = 26;
public function new(char:String = 'bf', playerId:Int = 0)
public function new(char:Null<String>, playerId:Int = 0)
{
super(0, 0);
this.playerId = playerId;
@@ -131,7 +130,7 @@ class HealthIcon extends FunkinSprite
snapToTargetSize();
}
function set_characterId(value:Null<String>):Null<String>
function set_characterId(value:Null<String>):String
{
if (value == characterId) return value;
@@ -412,20 +411,9 @@ class HealthIcon extends FunkinSprite
}
}
function correctCharacterId(charId:Null<String>):String
function iconExists(charId:String):Bool
{
if (charId == null)
{
return Constants.DEFAULT_HEALTH_ICON;
}
if (!Assets.exists(Paths.image('icons/icon-$charId')))
{
FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!');
return Constants.DEFAULT_HEALTH_ICON;
}
return charId;
return Assets.exists(Paths.image('icons/icon-$charId'));
}
function isNewSpritesheet(charId:String):Bool
@@ -435,11 +423,11 @@ class HealthIcon extends FunkinSprite
function loadCharacter(charId:Null<String>):Void
{
if (charId == null || correctCharacterId(charId) != charId)
if (charId == null || !iconExists(charId))
{
// This will recursively trigger loadCharacter to be called again.
characterId = correctCharacterId(charId);
return;
FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!');
characterId = Constants.DEFAULT_HEALTH_ICON;
charId = characterId;
}
isLegacyStyle = !isNewSpritesheet(charId);
@@ -8,7 +8,6 @@ import funkin.graphics.FunkinSprite;
import funkin.play.PlayState;
import funkin.util.TimerUtil;
import funkin.util.EaseUtil;
import openfl.utils.Assets;
import funkin.data.notestyle.NoteStyleRegistry;
import funkin.play.notes.notestyle.NoteStyle;
@@ -95,7 +94,6 @@ class PopUpStuff extends FlxTypedGroup<FunkinSprite>
if (numScore == null) continue;
numScore.x = (FlxG.width * 0.507) - (36 * daLoop) - 65;
trace('numScore($daLoop) = ${numScore.x}');
numScore.y = (FlxG.camera.height * 0.44);
numScore.x += offsets[0];
+3 -3
View File
@@ -11,7 +11,7 @@ import flixel.util.FlxTimer;
import funkin.graphics.video.FlxVideo;
#end
#if hxCodec
import hxcodec.flixel.FlxVideoSprite;
import funkin.graphics.video.FunkinVideoSprite;
#end
/**
@@ -26,7 +26,7 @@ class VideoCutscene
static var vid:FlxVideo;
#end
#if hxCodec
static var vid:FlxVideoSprite;
static var vid:FunkinVideoSprite;
#end
/**
@@ -138,7 +138,7 @@ class VideoCutscene
static function playVideoNative(filePath:String):Void
{
// Video displays OVER the FlxState.
vid = new FlxVideoSprite(0, 0);
vid = new FunkinVideoSprite(0, 0);
if (vid != null)
{
@@ -127,7 +127,8 @@ class FocusCameraSongEvent extends SongEvent
switch (ease)
{
case 'CLASSIC': // Old-school. No ease. Just set follow point.
PlayState.instance.resetCamera(false, true);
PlayState.instance.resetCamera(false, false, false);
PlayState.instance.cancelCameraFollowTween();
PlayState.instance.cameraFollowPoint.setPosition(targetX, targetY);
case 'INSTANT': // Instant ease. Duration is automatically 0.
PlayState.instance.tweenCameraToPosition(targetX, targetY, 0);
+2 -1
View File
@@ -85,7 +85,8 @@ class StrumlineNote extends FlxSprite
noteStyle.applyStrumlineFrames(this);
noteStyle.applyStrumlineAnimations(this, this.direction);
this.setGraphicSize(Std.int(Strumline.STRUMLINE_SIZE * noteStyle.getStrumlineScale()));
var scale = noteStyle.getStrumlineScale();
this.scale.set(scale, scale);
this.updateHitbox();
noteStyle.applyStrumlineOffsets(this);
+3 -2
View File
@@ -87,6 +87,7 @@ class SustainTrail extends FlxSprite
public var bottomClip:Float = 0.9;
public var isPixel:Bool;
public var noteStyleOffsets:Array<Float>;
var graphicWidth:Float = 0;
var graphicHeight:Float = 0;
@@ -107,6 +108,7 @@ class SustainTrail extends FlxSprite
this.noteDirection = noteDirection;
setupHoldNoteGraphic(noteStyle);
noteStyleOffsets = noteStyle.getHoldNoteOffsets();
indices = new DrawData<Int>(12, true, TRIANGLE_VERTEX_INDICES);
@@ -137,7 +139,6 @@ class SustainTrail extends FlxSprite
zoom = 1.0;
zoom *= noteStyle.fetchHoldNoteScale();
zoom *= 0.7;
// CALCULATE SIZE
graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2
@@ -202,7 +203,7 @@ class SustainTrail extends FlxSprite
{
width = graphicWidth;
height = graphicHeight;
offset.set(0, 0);
offset.set(noteStyleOffsets[0], noteStyleOffsets[1]);
origin.set(width * 0.5, height * 0.5);
}
+126 -106
View File
@@ -34,7 +34,12 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
* The note style to use if this one doesn't have a certain asset.
* This can be recursive, ehe.
*/
final fallback:Null<NoteStyle>;
var fallback(get, never):Null<NoteStyle>;
function get_fallback():Null<NoteStyle> {
if (_data == null || _data.fallback == null) return null;
return NoteStyleRegistry.instance.fetchEntry(_data.fallback);
}
/**
* @param id The ID of the JSON file to parse.
@@ -43,9 +48,6 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
this.id = id;
_data = _fetchData(id);
var fallbackID = _data.fallback;
if (fallbackID != null) this.fallback = NoteStyleRegistry.instance.fetchEntry(fallbackID);
}
/**
@@ -93,7 +95,8 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
buildNoteAnimations(target);
// Set the scale.
target.setGraphicSize(Strumline.STRUMLINE_SIZE * getNoteScale());
var scale = getNoteScale();
target.scale.set(scale, scale);
target.updateHitbox();
}
@@ -102,7 +105,11 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
function buildNoteFrames(force:Bool = false):Null<FlxAtlasFrames>
{
var noteAssetPath = getNoteAssetPath();
if (noteAssetPath == null) return null;
if (noteAssetPath == null)
{
FlxG.log.warn('Note asset path not found: ${id}');
return null;
}
if (!FunkinSprite.isTextureCached(Paths.image(noteAssetPath)))
{
@@ -135,7 +142,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
if (raw)
{
var rawPath:Null<String> = _data?.assets?.note?.assetPath;
if (rawPath == null && fallback != null) return fallback.getNoteAssetPath(true);
if (rawPath == null) return fallback?.getNoteAssetPath(true);
return rawPath;
}
@@ -173,12 +180,13 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
public function isNoteAnimated():Bool
{
return _data.assets?.note?.animated ?? false;
// LOL is double ?? bad practice?
return _data.assets?.note?.animated ?? fallback?.isNoteAnimated() ?? false;
}
public function getNoteScale():Float
{
return _data.assets?.note?.scale ?? 1.0;
return _data.assets?.note?.scale ?? fallback?.getNoteScale() ?? 1.0;
}
function fetchNoteAnimationData(dir:NoteDirection):Null<AnimationData>
@@ -191,16 +199,15 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
case RIGHT: _data.assets?.note?.data?.right?.toNamed();
};
return (result == null && fallback != null) ? fallback.fetchNoteAnimationData(dir) : result;
return result ?? fallback?.fetchNoteAnimationData(dir);
}
public function getHoldNoteAssetPath(raw:Bool = false):Null<String>
{
if (raw)
{
// TODO: figure out why ?. didn't work here
var rawPath:Null<String> = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath;
return (rawPath == null && fallback != null) ? fallback.getHoldNoteAssetPath(true) : rawPath;
var rawPath:Null<String> = _data?.assets?.holdNote?.assetPath;
return rawPath ?? fallback?.getHoldNoteAssetPath(true);
}
// library:path
@@ -212,16 +219,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
public function isHoldNotePixel():Bool
{
var data = _data?.assets?.holdNote;
if (data == null && fallback != null) return fallback.isHoldNotePixel();
return data?.isPixel ?? false;
return _data?.assets?.holdNote?.isPixel ?? fallback?.isHoldNotePixel() ?? false;
}
public function fetchHoldNoteScale():Float
{
var data = _data?.assets?.holdNote;
if (data == null && fallback != null) return fallback.fetchHoldNoteScale();
return data?.scale ?? 1.0;
return _data?.assets?.holdNote?.scale ?? fallback?.fetchHoldNoteScale() ?? 1.0;
}
public function getHoldNoteOffsets():Array<Float>
{
return _data?.assets?.holdNote?.offsets ?? fallback?.getHoldNoteOffsets() ?? [0.0, 0.0];
}
public function applyStrumlineFrames(target:StrumlineNote):Void
@@ -246,9 +254,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
if (raw)
{
var rawPath:Null<String> = _data?.assets?.noteStrumline?.assetPath;
if (rawPath == null && fallback != null) return fallback.getStrumlineAssetPath(true);
return rawPath;
return _data?.assets?.noteStrumline?.assetPath ?? fallback?.getStrumlineAssetPath(true);
}
// library:path
@@ -270,11 +276,19 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
FlxAnimationUtil.addAtlasAnimations(target, getStrumlineAnimationData(dir));
}
/**
* Fetch the animation data for the strumline.
* NOTE: This function only queries the fallback note style if all the animations are missing for a given direction.
*
* @param dir The direction to fetch the animation data for.
* @return The animation data for the strumline in that direction.
*/
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
{
var result:Array<Null<AnimationData>> = switch (dir)
{
case NoteDirection.LEFT: [
case NoteDirection.LEFT:
[
_data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'),
_data.assets.noteStrumline?.data?.leftPress?.toNamed('press'),
_data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'),
@@ -301,33 +315,39 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
default: [];
};
return thx.Arrays.filterNull(result);
// New variable so we can change the type.
var filteredResult:Array<AnimationData> = thx.Arrays.filterNull(result);
if (filteredResult.length == 0) return fallback?.getStrumlineAnimationData(dir) ?? [];
return filteredResult;
}
public function getStrumlineOffsets():Array<Float>
{
return _data?.assets?.noteStrumline?.offsets ?? fallback?.getStrumlineOffsets() ?? [0.0, 0.0];
}
public function applyStrumlineOffsets(target:StrumlineNote):Void
{
var offsets = _data?.assets?.noteStrumline?.offsets ?? [0.0, 0.0];
var offsets = getStrumlineOffsets();
target.x += offsets[0];
target.y += offsets[1];
}
public function getStrumlineScale():Float
{
return _data?.assets?.noteStrumline?.scale ?? 1.0;
return _data?.assets?.noteStrumline?.scale ?? fallback?.getStrumlineScale() ?? 1.0;
}
public function isNoteSplashEnabled():Bool
{
var data = _data?.assets?.noteSplash?.data;
if (data == null) return fallback?.isNoteSplashEnabled() ?? false;
return data.enabled ?? false;
return _data?.assets?.noteSplash?.data?.enabled ?? fallback?.isNoteSplashEnabled() ?? false;
}
public function isHoldNoteCoverEnabled():Bool
{
var data = _data?.assets?.holdNoteCover?.data;
if (data == null) return fallback?.isHoldNoteCoverEnabled() ?? false;
return data.enabled ?? false;
return _data?.assets?.holdNoteCover?.data?.enabled ?? fallback?.isHoldNoteCoverEnabled() ?? false;
}
/**
@@ -438,20 +458,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case THREE:
var result = _data.assets.countdownThree?.isPixel;
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
return result ?? false;
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
return result;
case TWO:
var result = _data.assets.countdownTwo?.isPixel;
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
return result ?? false;
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
return result;
case ONE:
var result = _data.assets.countdownOne?.isPixel;
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
return result ?? false;
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
return result;
case GO:
var result = _data.assets.countdownGo?.isPixel;
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
return result ?? false;
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
return result;
default:
return false;
}
@@ -463,20 +483,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case THREE:
var result = _data.assets.countdownThree?.offsets;
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
return result ?? [0, 0];
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
return result;
case TWO:
var result = _data.assets.countdownTwo?.offsets;
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
return result ?? [0, 0];
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
return result;
case ONE:
var result = _data.assets.countdownOne?.offsets;
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
return result ?? [0, 0];
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
return result;
case GO:
var result = _data.assets.countdownGo?.offsets;
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
return result ?? [0, 0];
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
return result;
default:
return [0, 0];
}
@@ -501,7 +521,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
null;
}
return (rawPath == null && fallback != null) ? fallback.getCountdownSoundPath(step, true) : rawPath;
return (rawPath == null) ? fallback?.getCountdownSoundPath(step, true) : rawPath;
}
// library:path
@@ -565,20 +585,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case "sick":
var result = _data.assets.judgementSick?.isPixel;
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
return result ?? false;
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
return result;
case "good":
var result = _data.assets.judgementGood?.isPixel;
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
return result ?? false;
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
return result;
case "bad":
var result = _data.assets.judgementBad?.isPixel;
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
return result ?? false;
case "GO":
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
return result;
case "shit":
var result = _data.assets.judgementShit?.isPixel;
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
return result ?? false;
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
return result;
default:
return false;
}
@@ -616,20 +636,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case "sick":
var result = _data.assets.judgementSick?.offsets;
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
return result ?? [0, 0];
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
return result;
case "good":
var result = _data.assets.judgementGood?.offsets;
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
return result ?? [0, 0];
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
return result;
case "bad":
var result = _data.assets.judgementBad?.offsets;
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
return result ?? [0, 0];
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
return result;
case "shit":
var result = _data.assets.judgementShit?.offsets;
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
return result ?? [0, 0];
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
return result;
default:
return [0, 0];
}
@@ -730,44 +750,44 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case 0:
var result = _data.assets.comboNumber0?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 1:
var result = _data.assets.comboNumber1?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 2:
var result = _data.assets.comboNumber2?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 3:
var result = _data.assets.comboNumber3?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 4:
var result = _data.assets.comboNumber4?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 5:
var result = _data.assets.comboNumber5?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 6:
var result = _data.assets.comboNumber6?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 7:
var result = _data.assets.comboNumber7?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 8:
var result = _data.assets.comboNumber8?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
case 9:
var result = _data.assets.comboNumber9?.isPixel;
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
return result ?? false;
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
return result;
default:
return false;
}
@@ -817,44 +837,44 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
{
case 0:
var result = _data.assets.comboNumber0?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 1:
var result = _data.assets.comboNumber1?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 2:
var result = _data.assets.comboNumber2?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 3:
var result = _data.assets.comboNumber3?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 4:
var result = _data.assets.comboNumber4?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 5:
var result = _data.assets.comboNumber5?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 6:
var result = _data.assets.comboNumber6?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 7:
var result = _data.assets.comboNumber7?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 8:
var result = _data.assets.comboNumber8?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
case 9:
var result = _data.assets.comboNumber9?.offsets;
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
return result ?? [0, 0];
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
return result;
default:
return [0, 0];
}
+38 -16
View File
@@ -16,7 +16,6 @@ import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
import funkin.modding.events.ScriptEvent;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.util.SortUtil;
import openfl.utils.Assets;
/**
* This is a data structure managing information about the current song.
@@ -157,6 +156,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
{
for (vari in _data.playData.songVariations)
{
if (!validateVariationId(vari)) {
trace(' [WARN] Variation id "$vari" is invalid, skipping...');
continue;
}
var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari);
if (variMeta != null)
{
@@ -408,7 +412,6 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
if (possibleVariations == null)
{
possibleVariations = getVariationsByCharacter(currentCharacter);
possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
}
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
@@ -429,7 +432,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
*/
public function getVariationsByCharacter(?char:PlayableCharacter):Array<String>
{
if (char == null) return variations;
if (char == null)
{
var result = variations;
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
return result;
}
var result = [];
trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}');
@@ -446,6 +454,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
}
}
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
return result;
}
@@ -466,18 +476,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
if (variationIds.length == 0) return [];
// The difficulties array contains entries like 'normal', 'nightmare-erect', and 'normal-pico',
// so we have to map it to the actual difficulty names.
// We also filter out difficulties that don't match the variation or that don't exist.
var diffFiltered:Array<String> = difficulties.keys()
.array()
.map(function(diffId:String):Null<String> {
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
if (difficulty == null) return null;
if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null;
return difficulty.difficulty;
})
var diffFiltered:Array<String> = variationIds.map(function(variationId:String):Array<String> {
var metadata = _metadata.get(variationId);
return metadata?.playData?.difficulties ?? [];
})
.flatten()
.filterNull()
.distinct();
@@ -490,11 +493,15 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
return false;
});
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST));
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
return diffFiltered;
}
/**
* TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
* @return `easy`, `erect`, `normal-pico`, etc.
*/
public function listSuffixedDifficulties(variationIds:Array<String>, ?showLocked:Bool, ?showHidden:Bool):Array<String>
{
var result = [];
@@ -510,6 +517,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
}
}
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
return result;
}
@@ -630,6 +639,19 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
var meta:Null<SongMetadata> = SongRegistry.instance.parseEntryMetadataWithMigration(id, vari, version);
return meta;
}
static final VARIATION_REGEX = ~/^[a-z][a-z0-9]+$/;
/**
* Validate that the variation ID is valid.
* Auto-accept if it's one of the base game default variations.
* Reject if the ID starts with a number, or contains invalid characters.
*/
static function validateVariationId(variation:String):Bool {
if (Constants.DEFAULT_VARIATION_LIST.contains(variation)) return true;
return VARIATION_REGEX.match(variation);
}
}
class SongDifficulty
-3
View File
@@ -150,11 +150,8 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
*/
public function resetPosition()
{
var oldAnimOffsets = [animOffsets[0], animOffsets[1]];
animOffsets = [0, 0];
this.x = originalPosition.x;
this.y = originalPosition.y;
animOffsets = oldAnimOffsets;
}
function update_shouldAlternate():Void
+7 -6
View File
@@ -258,6 +258,9 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
propSprite.zIndex = dataProp.zIndex;
propSprite.flipX = dataProp.flipX;
propSprite.flipY = dataProp.flipY;
switch (dataProp.animType)
{
case 'packer':
@@ -440,12 +443,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
character.x = stageCharData.position[0] - character.characterOrigin.x;
character.y = stageCharData.position[1] - character.characterOrigin.y;
@:privateAccess(funkin.play.stage.Bopper)
{
// Undo animOffsets before saving original position.
character.originalPosition.x = character.x + character.animOffsets[0];
character.originalPosition.y = character.y + character.animOffsets[1];
}
character.originalPosition.set(character.x, character.y);
var finalScale = character.getBaseScale() * stageCharData.scale;
character.setScale(finalScale); // Don't use scale.set for characters!
@@ -464,6 +462,9 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
#end
}
// Set the characters type
character.characterType = charType;
// Add the character to the scene.
this.add(character);
+25 -7
View File
@@ -17,7 +17,7 @@ import thx.semver.Version;
@:nullSafety
class Save
{
public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.5";
public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.4";
public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x";
// We load this version's saves from a new save path, to maintain SOME level of backwards compatibility.
@@ -34,19 +34,19 @@ class Save
{
if (_instance == null)
{
_instance = new Save(FlxG.save.data);
return _instance = load();
}
return _instance;
}
var data:RawSaveData;
public static function load():Void
public static function load():Save
{
trace("[SAVE] Loading save...");
// Bind save data.
loadFromSlot(1);
return loadFromSlot(1);
}
/**
@@ -65,7 +65,9 @@ class Save
public static function getDefault():RawSaveData
{
return {
version: Save.SAVE_DATA_VERSION,
// Version number is an abstract(Array) internally.
// This means it copies by reference, so merging save data overides the version number lol.
version: thx.Dynamics.clone(Save.SAVE_DATA_VERSION),
volume: 1.0,
mute: false,
@@ -89,6 +91,7 @@ class Save
options:
{
// Reasonable defaults.
framerate: 60,
naughtyness: true,
downscroll: false,
flashingLights: true,
@@ -433,7 +436,9 @@ class Save
{
if (!data.unlocks.charactersSeen.contains(character))
{
trace('Character seen: ' + character);
data.unlocks.charactersSeen.push(character);
trace('New characters seen list: ' + data.unlocks.charactersSeen);
flush();
}
}
@@ -598,11 +603,14 @@ class Save
return;
}
var newCompletion = (newScoreData.tallies.sick + newScoreData.tallies.good) / newScoreData.tallies.totalNotes;
var previousCompletion = (previousScoreData.tallies.sick + previousScoreData.tallies.good) / previousScoreData.tallies.totalNotes;
// Set the high score and the high rank separately.
var newScore:SaveScoreData =
{
score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score,
tallies: (previousRank > newRank) ? previousScoreData.tallies : newScoreData.tallies
tallies: (previousRank > newRank || previousCompletion > newCompletion) ? previousScoreData.tallies : newScoreData.tallies
};
song.set(difficultyId, newScore);
@@ -832,7 +840,7 @@ class Save
* If you set slot to `2`, it will load an independe
* @param slot
*/
static function loadFromSlot(slot:Int):Void
static function loadFromSlot(slot:Int):Save
{
trace("[SAVE] Loading save from slot " + slot + "...");
@@ -850,12 +858,14 @@ class Save
trace('[SAVE] Found legacy save data, converting...');
var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData);
FlxG.save.mergeData(gameSave.data, true);
return gameSave;
}
else
{
trace('[SAVE] No legacy save data found.');
var gameSave = new Save();
FlxG.save.mergeData(gameSave.data, true);
return gameSave;
}
}
else
@@ -863,6 +873,8 @@ class Save
trace('[SAVE] Found existing save data.');
var gameSave = SaveDataMigrator.migrate(FlxG.save.data);
FlxG.save.mergeData(gameSave.data, true);
return gameSave;
}
}
@@ -1133,6 +1145,12 @@ typedef SaveScoreTallyData =
*/
typedef SaveDataOptions =
{
/**
* FPS
* @default `60`
*/
var framerate:Int;
/**
* Whether some particularly fowl language is displayed.
* @default `true`
+6
View File
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.4] - 2024-09-12
Note to self: Only update to 2.1.0 when migration is needed.
### Added
- `unlocks.charactersSeen:Array<String>` to `Save`
- `unlocks.oldChar:Bool` to `Save`
## [2.0.5] - 2024-05-21
### Fixed
- Resolved an issue where HTML5 wouldn't store the semantic version properly, causing the game to fail to load the save.
+14 -6
View File
@@ -37,17 +37,25 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler
return _conductorInUse = value;
}
public function new(bgColor:FlxColor = FlxColor.TRANSPARENT)
{
super();
this.bgColor = bgColor;
}
var controls(get, never):Controls;
inline function get_controls():Controls
return PlayerSettings.player1.controls;
public function new(bgColor:FlxColor = FlxColor.TRANSPARENT)
{
super();
this.bgColor = bgColor;
initCallbacks();
}
function initCallbacks()
{
subStateOpened.add(onOpenSubStateComplete);
subStateClosed.add(onCloseSubStateComplete);
}
override function create():Void
{
super.create();
+5
View File
@@ -50,8 +50,13 @@ class PixelatedIcon extends FlxFilteredSprite
if (!openfl.utils.Assets.exists(Paths.image(charPath)))
{
trace('[WARN] Character ${char} has no freeplay icon.');
this.visible = false;
return;
}
else
{
this.visible = true;
}
var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml'));
+24 -23
View File
@@ -11,6 +11,7 @@ import funkin.modding.IScriptedClass.IBPMSyncedScriptedClass;
import flixel.math.FlxMath;
import funkin.modding.events.ScriptEvent;
import funkin.vis.dsp.SpectralAnalyzer;
import funkin.data.freeplay.player.PlayerRegistry;
class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
{
@@ -27,7 +28,8 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
var analyzer:SpectralAnalyzer;
var curGF:GFChar = GF;
var currentGFPath:Null<String>;
var enableVisualizer:Bool = false;
public function new()
{
@@ -97,7 +99,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
function drawFFT()
{
if (curGF == NENE)
if (enableVisualizer)
{
var levels = analyzer.getLevels();
var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame);
@@ -172,28 +174,33 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
*/
public function switchGF(bf:String):Void
{
var prevGF:GFChar = curGF;
switch (bf)
{
case "pico":
curGF = NENE;
case "bf":
curGF = GF;
default:
curGF = GF;
}
var previousGFPath = currentGFPath;
var bfObj = PlayerRegistry.instance.fetchEntry(bf);
var gfData = bfObj?.getCharSelectData()?.gf;
currentGFPath = gfData?.assetPath != null ? Paths.animateAtlas(gfData?.assetPath) : null;
// We don't need to update any anims if we didn't change GF
if (prevGF != curGF)
trace('currentGFPath(${currentGFPath})');
if (currentGFPath == null)
{
loadAtlas(Paths.animateAtlas("charSelect/" + curGF + "Chill"));
this.visible = false;
return;
}
else if (previousGFPath != currentGFPath)
{
this.visible = true;
loadAtlas(currentGFPath);
animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "In.txt"));
animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "Out.txt"));
enableVisualizer = gfData?.visualizer ?? false;
var animInfoPath = Paths.file('images/${gfData?.animInfoPath}');
animInInfo = FramesJSFLParser.parse(animInfoPath + '/In.txt');
animOutInfo = FramesJSFLParser.parse(animInfoPath + '/Out.txt');
}
playAnimation("idle", true, false, false);
// addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false));
updateHitbox();
}
@@ -213,9 +220,3 @@ enum FadeStatus
FADE_OUT;
FADE_IN;
}
enum abstract GFChar(String) from String to String
{
var GF = "gf";
var NENE = "nene";
}
@@ -47,7 +47,6 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass
//
if (getCurrentAnimation() == "idle")
{
trace('Player beat hit');
playAnimation("idle", true, false, false);
}
};
@@ -71,6 +71,7 @@ class CharSelectSubState extends MusicBeatSubState
var availableChars:Map<Int, String> = new Map<Int, String>();
var pressedSelect:Bool = false;
var selectTimer:FlxTimer = new FlxTimer();
var allowInput:Bool = false;
var selectSound:FunkinSound;
var unlockSound:FunkinSound;
@@ -430,6 +431,8 @@ class CharSelectSubState extends MusicBeatSubState
overrideExisting: true,
restartTrack: true,
onLoad: function() {
allowInput = true;
@:privateAccess
gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1);
#if desktop
@@ -573,6 +576,8 @@ class CharSelectSubState extends MusicBeatSubState
overrideExisting: true,
restartTrack: true,
onLoad: function() {
allowInput = true;
@:privateAccess
gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1);
#if desktop
@@ -642,6 +647,7 @@ class CharSelectSubState extends MusicBeatSubState
function goToFreeplay():Void
{
allowInput = false;
autoFollow = false;
FlxTween.tween(cursor, {alpha: 0}, 0.8, {ease: FlxEase.expoOut});
@@ -695,7 +701,7 @@ class CharSelectSubState extends MusicBeatSubState
syncAudio(elapsed);
if (!pressedSelect)
if (allowInput && !pressedSelect)
{
if (controls.UI_UP) holdTmrUp += elapsed;
if (controls.UI_UP_R)
@@ -786,10 +792,9 @@ class CharSelectSubState extends MusicBeatSubState
&& availableChars.exists(getCurrentSelected())
&& Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()]))
{
gfChill.visible = true;
curChar = availableChars.get(getCurrentSelected());
if (!pressedSelect && controls.ACCEPT)
if (allowInput && !pressedSelect && controls.ACCEPT)
{
cursorConfirmed.visible = true;
cursorConfirmed.x = cursor.x - 2;
@@ -817,7 +822,7 @@ class CharSelectSubState extends MusicBeatSubState
});
}
if (pressedSelect && controls.BACK)
if (allowInput && pressedSelect && controls.BACK)
{
cursorConfirmed.visible = false;
grpCursors.visible = true;
@@ -847,7 +852,7 @@ class CharSelectSubState extends MusicBeatSubState
gfChill.visible = false;
if (controls.ACCEPT)
if (allowInput && controls.ACCEPT)
{
cursorDenied.visible = true;
cursorDenied.x = cursor.x - 2;
+3 -3
View File
@@ -4,7 +4,7 @@ package funkin.ui.charSelect;
import funkin.graphics.video.FlxVideo;
#end
#if hxCodec
import hxcodec.flixel.FlxVideoSprite;
import funkin.graphics.video.FunkinVideoSprite;
#end
import funkin.ui.MusicBeatSubState;
import funkin.audio.FunkinSound;
@@ -72,12 +72,12 @@ class IntroSubState extends MusicBeatSubState
#end
#if hxCodec
var vid:FlxVideoSprite;
var vid:FunkinVideoSprite;
function playVideoNative(filePath:String):Void
{
// Video displays OVER the FlxState.
vid = new FlxVideoSprite(0, 0);
vid = new FunkinVideoSprite(0, 0);
vid.scrollFactor.set();
@@ -24,7 +24,6 @@ import haxe.ui.core.Screen;
import haxe.ui.events.UIEvent;
import haxe.ui.RuntimeComponentBuilder;
import lime.utils.Assets as LimeAssets;
import openfl.Assets;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import openfl.geom.Rectangle;
@@ -239,6 +238,11 @@ class DebugBoundingState extends FlxState
{
movingCharacter = false;
}
if (FlxG.mouse.justReleased)
{
movingCharacter = false;
}
}
}
@@ -700,7 +700,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function get_isCursorOverHaxeUI():Bool
{
return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
}
/**
@@ -2274,8 +2274,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
this.openBackupAvailableDialog(welcomeDialog);
}
}
#if FEATURE_DISCORD_RPC
updateDiscordRPC();
#end
}
#if FEATURE_DISCORD_RPC
function updateDiscordRPC():Void
{
funkin.api.discord.DiscordClient.instance.setPresence(
{
// TODO: Make this display the song name and update when it changes.
// state: '${currentSongName} [${selectedDifficulty}]',
state: null,
details: 'Chart Editor [Charting]'
});
}
#end
function setupWelcomeMusic()
{
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
@@ -3840,7 +3857,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Handle scroll anchor
if (scrollAnchorScreenPos != null)
{
var currentScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
var currentScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewX);
var distance = currentScreenPos - scrollAnchorScreenPos;
var verticalDistance = distance.y;
@@ -4121,8 +4138,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var overlapsRenderedEvents:Bool = FlxG.mouse.overlaps(renderedEvents);
// Cursor position relative to the grid.
var cursorX:Float = FlxG.mouse.screenX - gridTiledSprite.x;
var cursorY:Float = FlxG.mouse.screenY - gridTiledSprite.y;
var cursorX:Float = FlxG.mouse.viewX - gridTiledSprite.x;
var cursorY:Float = FlxG.mouse.viewY - gridTiledSprite.y;
var overlapsSelectionBorder:Bool = overlapsGrid
&& ((cursorX % 40) < (GRID_SELECTION_BORDER_WIDTH / 2)
@@ -4137,7 +4154,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{
if (scrollAnchorScreenPos == null)
{
scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
selectionBoxStartPos = null;
}
else
@@ -4159,11 +4176,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
else if (notePreview != null && FlxG.mouse.overlaps(notePreview) && !isCursorOverHaxeUI)
{
// Clicked note preview
notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
}
else if (!isCursorOverHaxeUI && (!overlapsGrid || overlapsSelectionBorder))
{
selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
selectionBoxStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
// Drawing selection box.
targetCursorMode = Crosshair;
}
@@ -4188,7 +4205,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{
// Clicked on the playhead scroll area.
// Move the playhead to the cursor position.
this.playheadPositionInPixels = FlxG.mouse.screenY - (GRID_INITIAL_Y_POS);
this.playheadPositionInPixels = FlxG.mouse.viewY - (GRID_INITIAL_Y_POS);
moveSongToScrollPosition();
// Cursor should be a grabby hand.
@@ -4251,8 +4268,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
else
{
// Minimum of 0.
return 0;
// Minimum of -1.
return -1;
}
});
@@ -4313,27 +4330,27 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Clicking and dragging.
// Scroll the screen if the mouse is above or below the grid.
if (FlxG.mouse.screenY < MENU_BAR_HEIGHT)
if (FlxG.mouse.viewY < MENU_BAR_HEIGHT)
{
// Scroll up.
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY;
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
scrollPositionInPixels -= diff * 0.5; // Too fast!
moveSongToScrollPosition();
}
else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0))
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
{
// Scroll down.
var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0);
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
scrollPositionInPixels += diff * 0.5; // Too fast!
moveSongToScrollPosition();
}
// Render the selection box.
var selectionRect:FlxRect = new FlxRect();
selectionRect.x = Math.min(FlxG.mouse.screenX, selectionBoxStartPos.x);
selectionRect.y = Math.min(FlxG.mouse.screenY, selectionBoxStartPos.y);
selectionRect.width = Math.abs(FlxG.mouse.screenX - selectionBoxStartPos.x);
selectionRect.height = Math.abs(FlxG.mouse.screenY - selectionBoxStartPos.y);
selectionRect.x = Math.min(FlxG.mouse.viewX, selectionBoxStartPos.x);
selectionRect.y = Math.min(FlxG.mouse.viewY, selectionBoxStartPos.y);
selectionRect.width = Math.abs(FlxG.mouse.viewX - selectionBoxStartPos.x);
selectionRect.height = Math.abs(FlxG.mouse.viewY - selectionBoxStartPos.y);
setSelectionBoxBounds(selectionRect);
targetCursorMode = Crosshair;
@@ -4461,8 +4478,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Player is clicking and holding on note preview to scrub around.
targetCursorMode = Grabbing;
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.screenY, (notePreview?.y ?? 0.0),
(notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels);
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0),
0, songLengthInPixels);
scrollPositionInPixels = clickedPosInPixels;
moveSongToScrollPosition();
@@ -4520,17 +4537,17 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
targetCursorMode = Grabbing;
// Scroll the screen if the mouse is above or below the grid.
if (FlxG.mouse.screenY < MENU_BAR_HEIGHT)
if (FlxG.mouse.viewY < MENU_BAR_HEIGHT)
{
// Scroll up.
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY;
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
scrollPositionInPixels -= diff * 0.5; // Too fast!
moveSongToScrollPosition();
}
else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0))
else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
{
// Scroll down.
var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0);
var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
scrollPositionInPixels += diff * 0.5; // Too fast!
moveSongToScrollPosition();
}
@@ -4811,11 +4828,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Show the context menu connected to the note.
if (useSingleNoteContextMenu)
{
this.openNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedNote.noteData);
this.openNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedNote.noteData);
}
else
{
this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
}
}
else
@@ -4835,11 +4852,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|| (isHighlightedEventSelected && currentEventSelection.length == 1);
if (useSingleEventContextMenu)
{
this.openEventContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedEvent.eventData);
this.openEventContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedEvent.eventData);
}
else
{
this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
}
}
else
@@ -4860,11 +4877,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Show the context menu connected to the note.
if (useSingleNoteContextMenu)
{
this.openHoldNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedHoldNote.noteData);
this.openHoldNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedHoldNote.noteData);
}
else
{
this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
}
}
else
@@ -5139,10 +5156,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2);
var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2);
if (songPos < 0) songPosMinutes = '-' + songPosMinutes;
var songPosString:String = '${songPosMinutes}:${songPosSeconds}';
var songPosString:String = '${songPosMinutes}:${songPosSeconds}:${songPosMilliseconds}';
if (playbarSongPos.value != songPosString) playbarSongPos.value = songPosString;
@@ -5614,7 +5632,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
else
{
trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).');
// trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).');
}
}
@@ -3,7 +3,6 @@ package funkin.ui.debug.charting.components;
import funkin.data.event.SongEventRegistry;
import flixel.graphics.frames.FlxAtlasFrames;
import openfl.display.BitmapData;
import openfl.utils.Assets;
import flixel.FlxObject;
import flixel.FlxBasic;
import flixel.FlxSprite;
@@ -95,7 +95,7 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
}
var LIMIT = 6;
charButton.icon = CharacterDataParser.getCharPixelIconAsset(charId);
charButton.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(charId));
charButton.text = charData.name.length > LIMIT ? '${charData.name.substr(0, LIMIT)}.' : '${charData.name}';
charButton.onClick = _ -> {
@@ -13,7 +13,6 @@ import funkin.audio.waveform.WaveformSprite;
import flixel.util.FlxColor;
import haxe.io.Bytes;
import haxe.io.Path;
import openfl.utils.Assets;
/**
* Functions for loading audio for the chart editor.
@@ -221,7 +221,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
var charDataOpponent:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent);
if (charDataOpponent != null)
{
buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent);
buttonCharacterOpponent.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent));
buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}';
}
else
@@ -233,7 +233,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
var charDataGirlfriend:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
if (charDataGirlfriend != null)
{
buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
buttonCharacterGirlfriend.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend));
buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}';
}
else
@@ -245,7 +245,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
var charDataPlayer:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player);
if (charDataPlayer != null)
{
buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player);
buttonCharacterPlayer.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player));
buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}';
}
else
+10 -2
View File
@@ -16,6 +16,7 @@ import funkin.ui.debug.latency.CoolStatsGraph;
import openfl.events.KeyboardEvent;
import funkin.input.PreciseInputManager;
import funkin.play.notes.Strumline;
import funkin.ui.mainmenu.MainMenuState;
import funkin.play.notes.notestyle.NoteStyle;
import funkin.data.notestyle.NoteStyleData;
import funkin.data.notestyle.NoteStyleRegistry;
@@ -188,6 +189,12 @@ class LatencyState extends MusicBeatSubState
}
override public function close():Void
{
cleanup();
super.close();
}
function cleanup():Void
{
PreciseInputManager.instance.onInputPressed.remove(preciseInputPressed);
PreciseInputManager.instance.onInputReleased.remove(preciseInputReleased);
@@ -200,7 +207,6 @@ class LatencyState extends MusicBeatSubState
FlxG.state.persistentDraw = prevPersistentDraw;
FlxG.state.persistentUpdate = prevPersistentUpdate;
super.close();
}
function regenNoteData()
@@ -311,7 +317,9 @@ class LatencyState extends MusicBeatSubState
if (controls.BACK)
{
close();
// close();
cleanup();
FlxG.switchState(() -> new MainMenuState());
}
super.update(elapsed);
-1
View File
@@ -11,7 +11,6 @@ import funkin.data.freeplay.album.AlbumRegistry;
import funkin.util.assets.FlxAnimationUtil;
import funkin.graphics.FunkinSprite;
import funkin.util.SortUtil;
import openfl.utils.Assets;
/**
* The graphic for the album roll in the FreeplayState.
+92 -52
View File
@@ -51,10 +51,12 @@ import funkin.ui.transition.LoadingState;
import funkin.ui.transition.StickerSubState;
import funkin.util.MathUtil;
import funkin.util.SortUtil;
import lime.utils.Assets;
import openfl.display.BlendMode;
import funkin.data.freeplay.style.FreeplayStyleRegistry;
import funkin.data.song.SongData.SongMusicData;
#if FEATURE_DISCORD_RPC
import funkin.api.discord.DiscordClient;
#end
/**
* Parameters used to initialize the FreeplayState.
@@ -145,11 +147,37 @@ class FreeplayState extends MusicBeatSubState
var songs:Array<Null<FreeplaySongData>> = [];
// List of available difficulties for the current song, without `-variation` at the end (no duplicates or nulls).
var diffIdsCurrent:Array<String> = [];
// List of available difficulties for the total song list, without `-variation` at the end (no duplicates or nulls).
var diffIdsTotal:Array<String> = [];
// List of available difficulties for the current song, with `-variation` at the end (no duplicates or nulls).
var suffixedDiffIdsCurrent:Array<String> = [];
// List of available difficulties for the total song list, with `-variation` at the end (no duplicates or nulls).
var suffixedDiffIdsTotal:Array<String> = [];
var curSelected:Int = 0;
var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY;
var currentSuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY;
var currentUnsuffixedDifficulty(get, never):String;
function get_currentUnsuffixedDifficulty():String
{
if (Constants.DEFAULT_DIFFICULTY_LIST_FULL.contains(currentSuffixedDifficulty)) return currentSuffixedDifficulty;
// Else, we need to strip the suffix.
return currentSuffixedDifficulty.substring(0, currentSuffixedDifficulty.lastIndexOf('-'));
}
var currentVariation(get, never):String;
function get_currentVariation():String
{
if (Constants.DEFAULT_DIFFICULTY_LIST.contains(currentSuffixedDifficulty)) return Constants.DEFAULT_VARIATION;
if (Constants.DEFAULT_DIFFICULTY_LIST_ERECT.contains(currentSuffixedDifficulty)) return 'erect';
// Else, we need to isolate the suffix.
return currentSuffixedDifficulty.substring(currentSuffixedDifficulty.lastIndexOf('-') + 1, currentSuffixedDifficulty.length);
}
public var fp:FreeplayScore;
@@ -313,7 +341,7 @@ class FreeplayState extends MusicBeatSubState
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence('In the Menus', null);
DiscordClient.instance.setPresence({state: 'In the Menus', details: null});
#end
var isDebug:Bool = false;
@@ -357,11 +385,15 @@ class FreeplayState extends MusicBeatSubState
trace('Available Difficulties: $availableDifficultiesForSong');
if (availableDifficultiesForSong.length == 0) continue;
songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations));
songs.push(new FreeplaySongData(levelId, songId, song, currentCharacter, displayedVariations));
for (difficulty in unsuffixedDifficulties)
{
diffIdsTotal.pushUnique(difficulty);
}
for (difficulty in availableDifficultiesForSong)
{
suffixedDiffIdsTotal.pushUnique(difficulty);
}
}
}
@@ -454,7 +486,7 @@ class FreeplayState extends MusicBeatSubState
wait: 0.1
});
for (diffId in diffIdsTotal)
for (diffId in suffixedDiffIdsTotal)
{
var diffSprite:DifficultySprite = new DifficultySprite(diffId);
diffSprite.difficultyId = diffId;
@@ -468,7 +500,7 @@ class FreeplayState extends MusicBeatSubState
for (diffSprite in grpDifficulties.group.members)
{
if (diffSprite == null) continue;
if (diffSprite.difficultyId == currentDifficulty) diffSprite.visible = true;
if (diffSprite.difficultyId == currentSuffixedDifficulty) diffSprite.visible = true;
}
albumRoll.albumId = null;
@@ -586,13 +618,13 @@ class FreeplayState extends MusicBeatSubState
}
};
exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite],
exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite],
{
x: FlxG.width,
speed: 0.3
});
exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite],
exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite],
{
y: -270,
speed: 0.8,
@@ -744,17 +776,14 @@ class FreeplayState extends MusicBeatSubState
{
var tempSongs:Array<Null<FreeplaySongData>> = songs;
// Remember just the difficulty because it's important for song sorting.
currentDifficulty = rememberedDifficulty;
if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff);
// Filter further by current selected difficulty.
if (currentDifficulty != null)
if (currentSuffixedDifficulty != null)
{
tempSongs = tempSongs.filter(song -> {
if (song == null) return true; // Random
return song.songDifficulties.contains(currentDifficulty);
return song.suffixedSongDifficulties.contains(currentSuffixedDifficulty);
});
}
@@ -1345,7 +1374,6 @@ class FreeplayState extends MusicBeatSubState
var dyTouch:Float = 0;
var velTouch:Float = 0;
var veloctiyLoopShit:Float = 0;
var touchTimer:Float = 0;
var initTouchPos:FlxPoint = new FlxPoint();
@@ -1376,7 +1404,7 @@ class FreeplayState extends MusicBeatSubState
#if FEATURE_DEBUG_FUNCTIONS
if (FlxG.keys.justPressed.P)
{
FlxG.switchState(FreeplayState.build(
FlxG.switchState(() -> FreeplayState.build(
{
{
character: currentCharacterId == "pico" ? Constants.DEFAULT_CHARACTER : "pico",
@@ -1757,16 +1785,18 @@ class FreeplayState extends MusicBeatSubState
{
touchTimer = 0;
var currentDifficultyIndex:Int = diffIdsCurrent.indexOf(currentDifficulty);
var currentDifficultyIndex:Int = suffixedDiffIdsCurrent.indexOf(currentSuffixedDifficulty);
if (currentDifficultyIndex == -1) currentDifficultyIndex = diffIdsCurrent.indexOf(Constants.DEFAULT_DIFFICULTY);
if (currentDifficultyIndex == -1) currentDifficultyIndex = suffixedDiffIdsCurrent.indexOf(Constants.DEFAULT_DIFFICULTY);
currentDifficultyIndex += change;
if (currentDifficultyIndex < 0) currentDifficultyIndex = diffIdsCurrent.length - 1;
if (currentDifficultyIndex >= diffIdsCurrent.length) currentDifficultyIndex = 0;
if (currentDifficultyIndex < 0) currentDifficultyIndex = suffixedDiffIdsCurrent.length - 1;
if (currentDifficultyIndex >= suffixedDiffIdsCurrent.length) currentDifficultyIndex = 0;
currentDifficulty = diffIdsCurrent[currentDifficultyIndex];
currentSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex];
trace('Switching to difficulty: ${currentSuffixedDifficulty}');
var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected].songData;
if (daSong != null)
@@ -1777,21 +1807,20 @@ class FreeplayState extends MusicBeatSubState
FlxG.log.warn('WARN: could not find song with id (${daSong.songId})');
return;
}
var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty) ?? '';
// TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION
&& targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty;
var suffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex];
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
trace(songScore);
intendedScore = songScore?.score ?? 0;
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
rememberedDifficulty = suffixedDifficulty;
currentSuffixedDifficulty = suffixedDifficulty;
}
else
{
intendedScore = 0;
intendedCompletion = 0.0;
rememberedDifficulty = currentDifficulty;
rememberedDifficulty = currentSuffixedDifficulty;
}
if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion))
@@ -1806,7 +1835,7 @@ class FreeplayState extends MusicBeatSubState
for (diffSprite in grpDifficulties.group.members)
{
if (diffSprite == null) continue;
if (diffSprite.difficultyId == currentDifficulty)
if (diffSprite.difficultyId == currentSuffixedDifficulty)
{
if (change != 0)
{
@@ -1833,7 +1862,9 @@ class FreeplayState extends MusicBeatSubState
if (songCapsule == null) continue;
if (songCapsule.songData != null)
{
songCapsule.songData.currentDifficulty = currentDifficulty;
songCapsule.songData.currentVariation = currentVariation;
songCapsule.songData.currentUnsuffixedDifficulty = currentUnsuffixedDifficulty;
songCapsule.songData.currentSuffixedDifficulty = currentSuffixedDifficulty;
songCapsule.init(null, null, songCapsule.songData);
songCapsule.checkClip();
}
@@ -1859,7 +1890,7 @@ class FreeplayState extends MusicBeatSubState
albumRoll.setDifficultyStars(daSong?.difficultyRating);
}
// Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String)
// Clears the cache of songs to free up memory, they'll have to be loaded in later tho
function clearDaCache(actualSongTho:String):Void
{
for (song in songs)
@@ -1921,8 +1952,9 @@ class FreeplayState extends MusicBeatSubState
return;
}
var targetSong:Song = targetSongNullable;
var targetDifficultyId:String = currentDifficulty;
var targetVariation:Null<String> = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter);
var targetDifficultyId:String = currentUnsuffixedDifficulty;
var targetVariation:Null<String> = currentVariation;
trace('target song: ${targetSongId} (${targetVariation})');
var targetLevelId:Null<String> = cap?.songData?.levelId;
PlayStatePlaylist.campaignId = targetLevelId ?? null;
@@ -2002,8 +2034,8 @@ class FreeplayState extends MusicBeatSubState
return;
}
var targetSong:Song = targetSongNullable;
var targetDifficultyId:String = currentDifficulty;
var targetVariation:Null<String> = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter);
var targetDifficultyId:String = currentUnsuffixedDifficulty;
var targetVariation:Null<String> = currentVariation;
var targetLevelId:Null<String> = cap?.songData?.levelId;
PlayStatePlaylist.campaignId = targetLevelId ?? null;
@@ -2069,7 +2101,7 @@ class FreeplayState extends MusicBeatSubState
if (rememberedDifficulty != null)
{
currentDifficulty = rememberedDifficulty;
currentSuffixedDifficulty = rememberedDifficulty;
}
}
@@ -2087,10 +2119,11 @@ class FreeplayState extends MusicBeatSubState
var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected];
if (daSongCapsule.songData != null)
{
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty);
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.songData.songId, currentSuffixedDifficulty);
intendedScore = songScore?.score ?? 0;
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
diffIdsCurrent = daSongCapsule.songData.songDifficulties;
suffixedDiffIdsCurrent = daSongCapsule.songData.suffixedSongDifficulties;
rememberedSongId = daSongCapsule.songData.songId;
changeDiff();
}
@@ -2099,6 +2132,7 @@ class FreeplayState extends MusicBeatSubState
intendedScore = 0;
intendedCompletion = 0.0;
diffIdsCurrent = diffIdsTotal;
suffixedDiffIdsCurrent = suffixedDiffIdsTotal;
rememberedSongId = null;
rememberedDifficulty = Constants.DEFAULT_DIFFICULTY;
albumRoll.albumId = null;
@@ -2143,17 +2177,18 @@ class FreeplayState extends MusicBeatSubState
if (previewSongId == null) return;
var previewSong:Null<Song> = SongRegistry.instance.fetchEntry(previewSongId);
var currentVariation = previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST;
var songDifficulty:Null<SongDifficulty> = previewSong?.getDifficulty(currentDifficulty,
previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST);
if (previewSong == null) return;
// var currentVariation = previewSong.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST;
var targetDifficultyId:String = currentUnsuffixedDifficulty;
var targetVariation:Null<String> = currentVariation;
var songDifficulty:Null<SongDifficulty> = previewSong.getDifficulty(targetDifficultyId, targetVariation ?? Constants.DEFAULT_VARIATION);
var baseInstrumentalId:String = previewSong?.getBaseInstrumentalId(currentDifficulty, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? '';
var altInstrumentalIds:Array<String> = previewSong?.listAltInstrumentalIds(currentDifficulty,
var baseInstrumentalId:String = previewSong.getBaseInstrumentalId(targetDifficultyId, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? '';
var altInstrumentalIds:Array<String> = previewSong.listAltInstrumentalIds(targetDifficultyId,
songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? [];
var instSuffix:String = baseInstrumentalId;
// TODO: Make this a UI element.
#if FEATURE_DEBUG_FUNCTIONS
if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL)
{
@@ -2312,6 +2347,7 @@ class FreeplaySongData
public var songId(default, null):String = '';
public var songDifficulties(default, null):Array<String> = [];
public var suffixedSongDifficulties(default, null):Array<String> = [];
public var songName(default, null):String = '';
public var songCharacter(default, null):String = '';
@@ -2319,22 +2355,25 @@ class FreeplaySongData
public var difficultyRating(default, null):Int = 0;
public var albumId(default, null):Null<String> = null;
public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
public var currentCharacter:PlayableCharacter;
public var currentVariation:String = Constants.DEFAULT_VARIATION;
public var currentSuffixedDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
public var currentUnsuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY;
public var scoringRank:Null<ScoringRank> = null;
var displayedVariations:Array<String> = [Constants.DEFAULT_VARIATION];
function set_currentDifficulty(value:String):String
function set_currentSuffixedDifficulty(value:String):String
{
if (currentDifficulty == value) return value;
if (currentSuffixedDifficulty == value) return value;
currentDifficulty = value;
currentSuffixedDifficulty = value;
updateValues(displayedVariations);
return value;
}
public function new(levelId:String, songId:String, song:Song, ?displayedVariations:Array<String>)
public function new(levelId:String, songId:String, song:Song, currentCharacter:PlayableCharacter, ?displayedVariations:Array<String>)
{
this.levelId = levelId;
this.songId = songId;
@@ -2342,6 +2381,7 @@ class FreeplaySongData
this.isFav = Save.instance.isSongFavorited(songId);
this.currentCharacter = currentCharacter;
if (displayedVariations != null) this.displayedVariations = displayedVariations;
updateValues(displayedVariations);
@@ -2368,15 +2408,18 @@ class FreeplaySongData
function updateValues(variations:Array<String>):Void
{
this.songDifficulties = song.listDifficulties(null, variations, false, false);
if (!this.songDifficulties.contains(currentDifficulty))
this.suffixedSongDifficulties = song.listSuffixedDifficulties(variations, false, false);
if (!this.songDifficulties.contains(currentUnsuffixedDifficulty))
{
currentDifficulty = Constants.DEFAULT_DIFFICULTY;
currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY;
// This method gets called again by the setter-method
// or the difficulty didn't change, so there's no need to continue.
return;
}
var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations);
var targetVariation:Null<String> = currentVariation;
var songDifficulty:SongDifficulty = song.getDifficulty(currentUnsuffixedDifficulty, targetVariation);
if (songDifficulty == null) return;
this.songStartingBpm = songDifficulty.getStartingBPM();
this.songName = songDifficulty.songName;
@@ -2392,10 +2435,7 @@ class FreeplaySongData
this.albumId = songDifficulty.album;
}
// TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
// `easy`, `erect`, `normal-pico`, etc.
var suffixedDifficulty = (songDifficulty.variation != Constants.DEFAULT_VARIATION
&& songDifficulty.variation != 'erect') ? '$currentDifficulty-${songDifficulty.variation}' : currentDifficulty;
var suffixedDifficulty = currentSuffixedDifficulty;
this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty);
+1 -1
View File
@@ -678,7 +678,7 @@ class SongMenuItem extends FlxSpriteGroup
public function confirm():Void
{
if (songText != null) songText.flickerText();
if (pixelIcon != null)
if (pixelIcon != null && pixelIcon.visible)
{
pixelIcon.animation.play('confirm');
}
@@ -18,7 +18,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.graphics.FunkinSprite;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.ui.MusicBeatSubState;
import lime.utils.Assets;
import openfl.display.BlendMode;
import flixel.group.FlxSpriteGroup;
@@ -18,7 +18,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.graphics.FunkinSprite;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.ui.MusicBeatSubState;
import lime.utils.Assets;
import openfl.display.BlendMode;
import flixel.group.FlxSpriteGroup;
@@ -177,20 +176,21 @@ class BoyfriendCard extends BackingCard
}
var beatFreq:Int = 1;
var beatFreqList:Array<Int> = [1,2,4,8];
var beatFreqList:Array<Int> = [1, 2, 4, 8];
public override function beatHit():Void {
public override function beatHit():Void
{
// increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms.....
beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)];
beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm / 140)];
if(Conductor.instance.currentBeat % beatFreq != 0) return;
if (Conductor.instance.currentBeat % beatFreq != 0) return;
FlxTween.cancelTweensOf(glow);
FlxTween.cancelTweensOf(glowDark);
glow.alpha = 0.8;
FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut});
FlxTween.tween(glow, {alpha: 0}, 16 / 24, {ease: FlxEase.quartOut});
glowDark.alpha = 0;
FlxTween.tween(glowDark, {alpha: 0.6}, 18/24, {ease: FlxEase.quartOut});
FlxTween.tween(glowDark, {alpha: 0.6}, 18 / 24, {ease: FlxEase.quartOut});
}
public override function introDone():Void
@@ -20,7 +20,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.graphics.FunkinSprite;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.ui.MusicBeatSubState;
import lime.utils.Assets;
import openfl.display.BlendMode;
import flixel.group.FlxSpriteGroup;
import funkin.graphics.shaders.AdjustColorShader;
@@ -20,7 +20,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.graphics.FunkinSprite;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.ui.MusicBeatSubState;
import lime.utils.Assets;
import openfl.display.BlendMode;
import flixel.group.FlxSpriteGroup;
import funkin.graphics.shaders.AdjustColorShader;
@@ -233,20 +232,21 @@ class PicoCard extends BackingCard
}
var beatFreq:Int = 1;
var beatFreqList:Array<Int> = [1,2,4,8];
var beatFreqList:Array<Int> = [1, 2, 4, 8];
public override function beatHit():Void {
public override function beatHit():Void
{
// increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms.....
beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)];
beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm / 140)];
if(Conductor.instance.currentBeat % beatFreq != 0) return;
if (Conductor.instance.currentBeat % beatFreq != 0) return;
FlxTween.cancelTweensOf(glow);
FlxTween.cancelTweensOf(glowDark);
glow.alpha = 1;
FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut});
FlxTween.tween(glow, {alpha: 0}, 16 / 24, {ease: FlxEase.quartOut});
glowDark.alpha = 0;
FlxTween.tween(glowDark, {alpha: 1}, 18/24, {ease: FlxEase.quartOut});
FlxTween.tween(glowDark, {alpha: 1}, 18 / 24, {ease: FlxEase.quartOut});
}
public override function introDone():Void
@@ -113,7 +113,9 @@ class PlayableCharacter implements IRegistryEntry<PlayerData>
switch (rank)
{
case PERFECT | PERFECT_GOLD:
case PERFECT_GOLD:
return _data.results.perfectGold;
case PERFECT:
return _data.results.perfect;
case EXCELLENT:
return _data.results.excellent;
+30 -25
View File
@@ -28,7 +28,7 @@ import funkin.ui.story.StoryMenuState;
import funkin.ui.Prompt;
import funkin.util.WindowUtil;
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
import funkin.api.discord.DiscordClient;
#end
#if newgrounds
import funkin.ui.NgPrompt;
@@ -55,8 +55,7 @@ class MainMenuState extends MusicBeatState
override function create():Void
{
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence("In the Menus", null);
DiscordClient.instance.setPresence({state: "In the Menus", details: null});
#end
FlxG.cameras.reset(new FunkinCamera('mainMenu'));
@@ -123,7 +122,7 @@ class MainMenuState extends MusicBeatState
}));
});
#if CAN_OPEN_LINKS
#if FEATURE_OPEN_URL
// In order to prevent popup blockers from triggering,
// we need to open the link as an immediate result of a keypress event,
// so we can't wait for the flicker animation to complete.
@@ -234,7 +233,7 @@ class MainMenuState extends MusicBeatState
camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y);
}
#if CAN_OPEN_LINKS
#if FEATURE_OPEN_URL
function selectDonate()
{
WindowUtil.openURL(Constants.URL_ITCH);
@@ -344,6 +343,8 @@ class MainMenuState extends MusicBeatState
}
}
Conductor.instance.update();
// Open the debug menu, defaults to ` / ~
// This includes stuff like the Chart Editor, so it should be present on all builds.
if (controls.DEBUG_MENU)
@@ -356,10 +357,11 @@ class MainMenuState extends MusicBeatState
#if FEATURE_DEBUG_FUNCTIONS
// Ctrl+Alt+Shift+P = Character Unlock screen
// Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock
// Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock
// Ctrl+Alt+Shift+M = Revoke requirements for Pico Unlock
// Ctrl+Alt+Shift+R = Score/Rank conflict test
// Ctrl+Alt+Shift+N = Mark all characters as not seen
// Ctrl+Alt+Shift+E = Dump save data
// Ctrl+Alt+Shift+L = Force crash and create a log dump
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P)
{
@@ -369,7 +371,7 @@ class MainMenuState extends MusicBeatState
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W)
{
FunkinSound.playOnce(Paths.sound('confirmMenu'));
// Give the user a score of 1 point on Weekend 1 story mode.
// Give the user a score of 1 point on Weekend 1 story mode (Easy difficulty).
// This makes the level count as cleared and displays the songs in Freeplay.
funkin.save.Save.instance.setLevelScore('weekend1', 'easy',
{
@@ -389,27 +391,30 @@ class MainMenuState extends MusicBeatState
});
}
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L)
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.M)
{
FunkinSound.playOnce(Paths.sound('confirmMenu'));
// Give the user a score of 0 points on Weekend 1 story mode.
// Give the user a score of 0 points on Weekend 1 story mode (all difficulties).
// This makes the level count as uncleared and no longer displays the songs in Freeplay.
funkin.save.Save.instance.setLevelScore('weekend1', 'easy',
{
score: 1,
tallies:
{
sick: 0,
good: 0,
bad: 0,
shit: 0,
missed: 0,
combo: 0,
maxCombo: 0,
totalNotesHit: 0,
totalNotes: 0,
}
});
for (diff in ['easy', 'normal', 'hard'])
{
funkin.save.Save.instance.setLevelScore('weekend1', diff,
{
score: 0,
tallies:
{
sick: 0,
good: 0,
bad: 0,
shit: 0,
missed: 0,
combo: 0,
maxCombo: 0,
totalNotesHit: 0,
totalNotes: 0,
}
});
}
}
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.R)
+9 -4
View File
@@ -28,10 +28,14 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page
[NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT],
[UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK],
[CUTSCENE_ADVANCE],
[FREEPLAY_FAVORITE, FREEPLAY_LEFT, FREEPLAY_RIGHT],
[WINDOW_FULLSCREEN, WINDOW_SCREENSHOT],
[FREEPLAY_FAVORITE, FREEPLAY_LEFT, FREEPLAY_RIGHT, FREEPLAY_CHAR_SELECT],
[WINDOW_FULLSCREEN, #if FEATURE_SCREENSHOTS WINDOW_SCREENSHOT, #end],
[VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE],
[DEBUG_MENU, DEBUG_CHART]
[
DEBUG_MENU,
#if FEATURE_CHART_EDITOR DEBUG_CHART, #end
#if FEATURE_STAGE_EDITOR DEBUG_STAGE, #end
]
];
var itemGroups:Array<Array<InputItem>> = [for (i in 0...controlGroups.length) []];
@@ -137,7 +141,8 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page
if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length);
var label = labels.add(new AtlasText(100, y, name, AtlasFont.BOLD));
var formatName = name.replace('_', ' ');
var label = labels.add(new AtlasText(100, y, formatName, AtlasFont.BOLD));
label.alpha = 0.6;
for (i in 0...COLUMNS)
createItem(label.x + 550 + i * 400, y, control, i);
+4 -3
View File
@@ -6,7 +6,6 @@ import flixel.system.FlxAssets;
import flixel.tweens.FlxEase;
import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.utils.Assets;
import funkin.util.MathUtil;
/**
@@ -80,10 +79,12 @@ class FunkinSoundTray extends FlxSoundTray
y = MathUtil.coolLerp(y, lerpYPos, 0.1);
alpha = MathUtil.coolLerp(alpha, alphaTarget, 0.25);
var shouldHide = (FlxG.sound.muted == false && FlxG.sound.volume > 0);
// Animate sound tray thing
if (_timer > 0)
{
_timer -= (MS / 1000);
if (shouldHide) _timer -= (MS / 1000);
alphaTarget = 1;
}
else if (y >= -height)
@@ -122,7 +123,7 @@ class FunkinSoundTray extends FlxSoundTray
active = true;
var globalVolume:Int = Math.round(FlxG.sound.logToLinear(FlxG.sound.volume) * 10);
if (FlxG.sound.muted)
if (FlxG.sound.muted || FlxG.sound.volume == 0)
{
globalVolume = 0;
}
+5
View File
@@ -1,5 +1,6 @@
package funkin.ui.options;
import funkin.ui.transition.LoadingState;
import funkin.ui.debug.latency.LatencyState;
import flixel.FlxSprite;
import flixel.FlxSubState;
@@ -185,7 +186,11 @@ class OptionsMenu extends Page
createItem("PREFERENCES", function() switchPage(Preferences));
createItem("CONTROLS", function() switchPage(Controls));
createItem("INPUT OFFSETS", function() {
#if web
LoadingState.transitionToState(() -> new LatencyState());
#else
FlxG.state.openSubState(new LatencyState());
#end
});
#if newgrounds
+4 -1
View File
@@ -77,6 +77,10 @@ class PreferencesMenu extends Page
createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void {
Preferences.unlockedFramerate = value;
}, Preferences.unlockedFramerate);
#else
createPrefItemNumber('FPS', 'The maximum framerate that the game targets', function(value:Float) {
Preferences.framerate = Std.int(value);
}, null, Preferences.framerate, 30, 300, 5, 0);
#end
}
@@ -87,7 +91,6 @@ class PreferencesMenu extends Page
// Indent the selected item.
items.forEach(function(daItem:TextMenuItem) {
var thyOffset:Int = 0;
// Initializing thy text width (if thou text present)
var thyTextWidth:Int = 0;
if (Std.isOfType(daItem, EnumPreferenceItem)) thyTextWidth = cast(daItem, EnumPreferenceItem).lefthandText.getWidth();
+4 -1
View File
@@ -24,6 +24,9 @@ import funkin.ui.transition.LoadingState;
import funkin.ui.transition.StickerSubState;
import funkin.util.MathUtil;
import openfl.utils.Assets;
#if FEATURE_DISCORD_RPC
import funkin.api.discord.DiscordClient;
#end
class StoryMenuState extends MusicBeatState
{
@@ -218,7 +221,7 @@ class StoryMenuState extends MusicBeatState
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence('In the Menus', null);
DiscordClient.instance.setPresence({state: 'In the Menus', details: null});
#end
}
+3 -3
View File
@@ -4,7 +4,7 @@ package funkin.ui.title;
import funkin.graphics.video.FlxVideo;
#end
#if hxCodec
import hxcodec.flixel.FlxVideoSprite;
import funkin.graphics.video.FunkinVideoSprite;
#end
import funkin.ui.MusicBeatState;
@@ -62,12 +62,12 @@ class AttractState extends MusicBeatState
#end
#if hxCodec
var vid:FlxVideoSprite;
var vid:FunkinVideoSprite;
function playVideoNative(filePath:String):Void
{
// Video displays OVER the FlxState.
vid = new FlxVideoSprite(0, 0);
vid = new FunkinVideoSprite(0, 0);
if (vid != null)
{
+8 -7
View File
@@ -232,7 +232,8 @@ class TitleState extends MusicBeatState
{
startingVolume: 0.0,
overrideExisting: true,
restartTrack: true
restartTrack: false,
persist: true
});
// Fade from 0.0 to 1 over 4 seconds
if (shouldFadeIn) FlxG.sound.music.fadeIn(4.0, 0.0, 1.0);
@@ -273,11 +274,6 @@ class TitleState extends MusicBeatState
}
#end
if (Save.instance.charactersSeen.contains("pico"))
{
Save.instance.charactersSeen.remove("pico");
Save.instance.oldChar = false;
}
Conductor.instance.update();
/* if (FlxG.onMobile)
@@ -490,7 +486,12 @@ class TitleState extends MusicBeatState
case 13:
addMoreText('Friday');
case 14:
addMoreText('Night');
// easter egg for when the game is trending with the wrong spelling
// the random intro text would be "trending--only on x"
if (curWacky[0] == "trending") addMoreText('Nigth');
else
addMoreText('Night');
case 15:
addMoreText('Funkin');
case 16:
+10 -7
View File
@@ -3,24 +3,23 @@ package funkin.ui.transition;
import flixel.FlxSprite;
import flixel.math.FlxMath;
import flixel.tweens.FlxEase;
import funkin.graphics.FunkinSprite;
import flixel.tweens.FlxTween;
import flixel.util.FlxTimer;
import flixel.util.typeLimit.NextState;
import funkin.graphics.FunkinSprite;
import funkin.graphics.shaders.ScreenWipeShader;
import funkin.play.PlayState;
import funkin.play.PlayStatePlaylist;
import funkin.play.song.Song.SongDifficulty;
import funkin.ui.MusicBeatState;
import haxe.io.Path;
import funkin.graphics.FunkinSprite;
import lime.app.Future;
import lime.app.Promise;
import lime.utils.AssetLibrary;
import lime.utils.AssetManifest;
import lime.utils.Assets as LimeAssets;
import openfl.filters.ShaderFilter;
import openfl.utils.Assets;
import flixel.util.typeLimit.NextState;
import openfl.utils.Assets as OpenFLAssets;
class LoadingState extends MusicBeatSubState
{
@@ -98,7 +97,7 @@ class LoadingState extends MusicBeatSubState
function checkLoadSong(path:String):Void
{
if (!Assets.cache.hasSound(path))
if (!OpenFLAssets.cache.hasSound(path))
{
var library = Assets.getLibrary('songs');
var symbolPath = path.split(':').pop();
@@ -277,7 +276,7 @@ class LoadingState extends MusicBeatSubState
#if NO_PRELOAD_ALL
static function isSoundLoaded(path:String):Bool
{
return Assets.cache.hasSound(path);
return OpenFLAssets.cache.hasSound(path);
}
static function isLibraryLoaded(library:String):Bool
@@ -314,7 +313,6 @@ class LoadingState extends MusicBeatSubState
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num7'));
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num8'));
FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num9'));
FunkinSprite.cacheTexture(Paths.image('notes', 'shared'));
FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared'));
FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared'));
@@ -453,6 +451,11 @@ class LoadingState extends MusicBeatSubState
return promise.future;
}
public static function transitionToState(state:NextState, stopMusic:Bool = false):Void
{
FlxG.switchState(() -> new LoadingState(state, stopMusic));
}
}
class MultiCallback
@@ -2,7 +2,6 @@ package funkin.ui.transition;
import flixel.FlxSprite;
import haxe.Json;
import lime.utils.Assets;
import funkin.graphics.FunkinSprite;
// import flxtyped group
import funkin.ui.MusicBeatSubState;
@@ -56,7 +55,7 @@ class StickerSubState extends MusicBeatSubState
// make sure that ONLY plays mp3/ogg files
// if there's no mp3/ogg file, then it regenerates/reloads the random folder
var assetsInList = openfl.utils.Assets.list();
var assetsInList = Assets.list();
var soundFilterFunc = function(a:String) {
return a.startsWith('assets/shared/sounds/stickersounds/');
@@ -84,7 +83,7 @@ class StickerSubState extends MusicBeatSubState
var filterFunc = function(a:String) {
return a.startsWith('assets/shared/sounds/stickersounds/' + soundSelection + '/');
};
var assetsInList3 = openfl.utils.Assets.list();
var assetsInList3 = Assets.list();
sounds = assetsInList3.filter(filterFunc);
for (i in 0...sounds.length)
{
+11 -5
View File
@@ -78,7 +78,12 @@ class Constants
/**
* Link to download the game on Itch.io.
*/
public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin/purchase';
public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin';
/**
* Link to play the game on Newgrounds.
*/
public static final URL_NEWGROUNDS:String = 'https://www.newgrounds.com/portal/view/770371';
/**
* Link to the game's page on Kickstarter.
@@ -186,6 +191,11 @@ class Constants
*/
public static final DEFAULT_DIFFICULTY_LIST:Array<String> = ['easy', 'normal', 'hard'];
/**
* Default list of difficulties for Erect mode.
*/
public static final DEFAULT_DIFFICULTY_LIST_ERECT:Array<String> = ['erect', 'nightmare'];
/**
* List of all difficulties used by the base game.
* Includes Erect and Nightmare.
@@ -481,10 +491,6 @@ class Constants
public static final JUDGEMENT_BAD_COMBO_BREAK:Bool = true;
public static final JUDGEMENT_SHIT_COMBO_BREAK:Bool = true;
// % Sick
public static final RANK_PERFECT_PLAT_THRESHOLD:Float = 1.0; // % Sick
public static final RANK_PERFECT_GOLD_THRESHOLD:Float = 0.85; // % Sick
// % Hit
public static final RANK_PERFECT_THRESHOLD:Float = 1.00;
public static final RANK_EXCELLENT_THRESHOLD:Float = 0.90;

Some files were not shown because too many files have changed in this diff Show More