Compare commits

...
698 Commits
Author SHA1 Message Date
EricandGitHub 0b976b0d71 Merge pull request #4942 from AbnormalPoof/0.6.4-changelog-version-bump
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (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
[DOCS] CHANGELOG for 0.6.4 + Bump version to 0.6.4
2025-05-02 22:28:13 -04:00
Abnormal ae1239c57d CHANGELOG for 0.6.4 2025-05-02 21:20:14 -05:00
Abnormal bfbbf9cb01 Bump game version to 0.6.4 2025-05-02 21:02:22 -05:00
EliteMasterEric d29bb47d22 Update assets submodule 2025-05-02 18:52:21 -04:00
EricandGitHub d29ecfb7c4 Merge pull request #4936 from CrusherNotDrip/bugfix/tooltip-chart-editor
[BUGFIX] Prevent the game from crashing when clicking a recent chart before tooltip shows up
2025-05-02 17:55:41 -04:00
EricandGitHub cdd17ce033 Merge pull request #4938 from AbnormalPoof/bugfix/quick-web-fix
2 more commits from #3032
2025-05-02 17:54:38 -04:00
EricandGitHub 8e8b26f029 Merge pull request #4564 from AbnormalPoof/bugfix/texture-atlas-looping
[BUGFIX] Fix texture atlas sprites looping infinitely
2025-05-02 17:52:13 -04:00
cyn0x8andAbnormal 6f43438cdb hopefully fix #4814 2025-05-02 16:41:03 -05:00
cyn0x8andAbnormal a74369c77e fixes + stronger sandboxing 2025-05-02 16:40:50 -05:00
CrusherNotDrip def1b74eb6 Stop the game from crashing when clicking a recent chart before tooltip appears 2025-05-02 16:40:31 -04:00
EricandGitHub c70fa7c94a Merge pull request #4933 from VioletSnowLeopard/patch2
Fix the Changelog on the develop branch again
2025-05-02 16:06:29 -04:00
Abnormal c0353bca2b remove extra callback (already gets called in _onAnimationComplete() by dispatching the animation name to onAnimationComplete 2025-05-02 13:53:30 -05:00
Abnormal f385cf9fd3 fix: Fix texture atlases looping indefinitely 2025-05-02 13:52:16 -05:00
EricandGitHub 301f71b428 Merge pull request #4930 from Hundrec/Lasercar/commit-recovery
<RECOVERY> Restore two of Lasercar's commits
2025-05-02 14:30:11 -04:00
EricandGitHub 189e028442 Merge pull request #4931 from ACrazyTown/fix/crash-log-memory-overflow
Fix memory overflow in crash log (Redo)
2025-05-02 14:30:03 -04:00
EricandGitHub a9647cf9fc Merge pull request #4617 from Lasercar/destroy-the-volume-plugin
[BUGFIX] Destroy the volume plugin when wiping save data
2025-05-02 14:29:54 -04:00
EricandGitHub 05b9d68645 Merge pull request #4227 from Lasercar/main-menu-not-remembering-freeplay-menu-selection-fix
Main menu not remembering freeplay menu selection fix
2025-05-02 14:29:29 -04:00
EricandGitHub 45f0f14ed9 Merge pull request #4318 from Lasercar/fix-strumline-offset-when-downscroll
Fix strumline offset when downscroll
2025-05-02 14:29:11 -04:00
EricandGitHub a8262a8d3b Merge pull request #3090 from anysad/fix-animation-file-save
[BUGFIX] Animation Editor not saving the file name
2025-05-02 14:21:46 -04:00
EricandGitHub 264c2d8e77 Merge pull request #4266 from NotHyper-474/bugfix/chart-editor-broken-resize
[BUGFIX] Chart Editor - Fix resolution breaking after returning from PlayState
2025-05-02 14:21:33 -04:00
EricandGitHub b2f231e889 Merge pull request #4871 from NotHyper-474/bugfix/initstate-spam-medal-crash-fix
[BUGFIX] Fix crash when spamming enter when opening game (properly this time)
2025-05-02 14:21:21 -04:00
VioletSnowLeopard 34bb201104 Fix the changelog again 2025-05-02 11:02:29 -04:00
HundrecandLasercar d9fcaf0e63 Restore Lasercar's changes
Dropped them somewhere whoopsie

Co-Authored-By: Lasercar <64717068+Lasercar@users.noreply.github.com>
2025-05-02 05:02:29 -06:00
EricandGitHub 56259b9143 Merge pull request #4923 from Hundrec/negative-freeplay-clear
[BUGFIX] Fix `Fix Fix scoring changes`
2025-05-01 23:43:49 -04:00
HundrecandHyper_ dc2acac152 no more negative clear percent shenanigans
"a thousand curses upon you for not testing your prs before making them /j"
- AbnormalPoof

Co-Authored-By: Hyper_ <40342021+NotHyper-474@users.noreply.github.com>
2025-05-01 21:23:55 -06:00
EricandGitHub bf5a669592 Merge pull request #4919 from Kade-github/real-capsule-fix
Sorting in freeplay is weird
2025-05-01 21:56:24 -04:00
kade-github 8b9775d91f the falsening by VioletSnowLeopard 2025-05-01 18:50:03 -07:00
EricandGitHub 6caeda9a9d Merge pull request #4898 from Lasercar/fix-fix-scoring-changes
[BUGFIX] Fix `Fix scoring changes`
2025-05-01 21:42:29 -04:00
EricandGitHub 9983556748 Merge pull request #4358 from VioletSnowLeopard/fix-special-pause-menu-chance
[BUGFIX] Fix the chance of getting the special pause menu
2025-05-01 21:40:58 -04:00
EliteMasterEric 651298e908 Update assets submodule 2025-05-01 21:37:52 -04:00
Hyper_ 142ea6db0c fix: Force UI Camera resize 2025-05-01 22:32:02 -03:00
EricandGitHub 5397924edd Merge pull request #4913 from VioletSnowLeopard/fix-switching-filters
[BUGFIX] Fix the Behavior of Selected Song when Changing Filters in Freeplay
2025-05-01 21:24:52 -04:00
EliteMasterEric 94bd18fe17 Merge remote-tracking branch 'public/main' into develop 2025-05-01 21:10:40 -04:00
EricandGitHub 664d9e0fb3 Merge pull request #4214 from Lasercar/freeplay-ui-fixes
Freeplay UI fixes
2025-05-01 21:07:51 -04:00
VioletSnowLeopard edf6889af9 fix switching filters to do its intended behavior 2025-05-01 20:57:39 -04:00
EricandGitHub c65dddacc0 Merge pull request #4894 from AbnormalPoof/chore/art-submod
[GITHUB] Update `art` submodule to the latest commit
2025-05-01 20:43:41 -04:00
EricandGitHub 659ea41206 Merge pull request #4649 from NotHyper-474/feature/chart-more-song-info
[ENHANCEMENT] Chart Editor - Display current beat & step
2025-05-01 20:37:40 -04:00
EricandGitHub 5cd47a4414 Merge pull request #4553 from VioletSnowLeopard/fix-dialogue-pause-menu
Change order of Restart and Skip in Dialogue pause menu
2025-05-01 20:37:18 -04:00
Eric 65699ee865 Update CONTRIBUTING.md 2025-05-01 01:38:44 -04:00
HundrecandEric d423eb3ddd Update Charting PR policy in CONTRIBUTING.md
We no longer accept chart modifications.
2025-05-01 01:38:44 -04:00
unknown c67085a46a Fix memory overflow in crash log 2025-04-30 23:41:14 +02:00
Hyper_ a83a4a599c fix: Null-check MedalList's internal map 2025-04-30 12:31:01 -03:00
Lasercar f6ac4cad43 Whoops, missed this one 2025-04-30 23:58:09 +10:00
VioletSnowLeopard 0101bae7ec convert decimal chance to percent 2025-04-30 09:31:22 -04:00
Abnormal 4c5335d7a3 art submod 2025-04-30 02:37:13 -05:00
EliteMasterEric b811ca91a6 Update link to art submodule to include latest assets 2025-04-30 02:01:54 -04:00
Hyper_andEric c5f2a74494 fix: Prevent loading invalid variation 2025-04-30 00:44:12 -04:00
KoloandEric 3e0dbe2758 performCleanup on reload 2025-04-30 00:43:37 -04:00
bbc0546c74 Shortened statement based on suggestion.
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-04-30 00:42:15 -04:00
thesuperpig56andEric 617d5ffa06 Called the wrong character here, whoops! 2025-04-30 00:42:15 -04:00
thesuperpig56andEric 73114e2da6 Avoid crash when restarting song without characters. 2025-04-30 00:42:15 -04:00
KoloandEric 808698ace7 medal fix thing 2025-04-30 00:41:28 -04:00
VioletSnowLeopardandEric 832bc5bd83 fix two issues with random capsule 2025-04-30 00:37:08 -04:00
TechnikTilandEric b15e809c63 fix freeplay dj softlock 2025-04-29 18:01:55 -04:00
LasercarandEric 8074d57186 Don't add the default difficulty to song metadata
It'll now only add the current difficulty to the metadata if it doesn't exist in it when saved.
2025-04-29 18:01:23 -04:00
KoloandEric 31d3718e5c music file priority thing
(updated a misleading comment, lols!)
2025-04-29 16:27:21 -04:00
LasercarandEric 5fdbd23a17 Misses now actually make you miss your grade
Sustain notes no longer add to the miss tally
2025-04-29 16:24:50 -04:00
EricandGitHub 23a9e7f944 Merge pull request #4881 from Lasercar/fix-preferences-not-saving-due-to-enums-AGAIN
[BIGFIX] Fix Options not loading from Save Data
2025-04-29 16:23:47 -04:00
EricandGitHub 0397a41a7f Merge pull request #4883 from Hundrec/patch-11
[DOCS] Credit Lasercar for a crash fix from an assets PR
2025-04-29 16:23:31 -04:00
Lasercar afbb335993 Destroy the volume plugin 2025-04-29 20:23:52 +10:00
Lasercar 2bc1a31427 fix capsule jumpin and random capsule starting x position 2025-04-29 20:04:56 +10:00
Lasercar dafbb43532 capsule jump in 2025-04-29 19:59:35 +10:00
Lasercar 4978c89ac3 capsule options menu null reference fix 2025-04-29 19:57:31 +10:00
LasercarandLasercar 29b541af38 First rank overrides itself fix 2025-04-29 19:57:31 +10:00
LasercarandLasercar fc09350be7 This should fix the squashed capsule text, right? 2025-04-29 19:57:23 +10:00
LasercarandLasercar e1ca3c69f0 Fixed letter sort animation 2025-04-29 19:53:32 +10:00
LasercarandLasercar a15bd36943 Freeplay UI fixes
Input is disabled as soon as possible when a capsule is open
Input re-enables after capsule errors
instrument selector uses the capsule's target position as it's position, rather than the capsule's position
2025-04-29 19:53:32 +10:00
HundrecandGitHub 51605e50f8 Credit Lasercar for a crash fix from assets PR 2025-04-29 01:31:19 -06:00
Lasercar 3a1b573ea3 Fix save being loaded twice for no reason 2025-04-29 17:14:23 +10:00
Lasercar ef6b214872 Save vsync mode as string but get as vsync mode 2025-04-29 17:14:23 +10:00
EricandGitHub 8f2a8c8335 Merge pull request #4873 from NotHyper-474/patch-1
Remove leftover from merge-conflict in CHANGELOG
2025-04-28 17:59:02 -04:00
Hyper_andGitHub 7f5b4974c3 Update CHANGELOG.md
Remove left-over from merge conflict.
2025-04-28 18:30:39 -03:00
EricandGitHub d63782ee9d Merge pull request #4869 from ShadzXD/patch-3
[DOCS] Update CHANGELOG.MD to include my pull request.
2025-04-28 17:01:12 -04:00
EliteMasterEric 19b1c32124 Merge remote-tracking branch 'public/develop' into develop 2025-04-28 16:56:51 -04:00
ShadzXDandGitHub d183876514 Merge pull request #1 from Hundrec/patch-11
Tiny polish for Eggnog cutscene Changelog entry
2025-04-28 22:50:36 +02:00
HundrecandGitHub db0ac48192 Tiny polish for Eggnog cutscene Changelog entry 2025-04-28 14:47:42 -06:00
EricandGitHub ba37405e4b Merge pull request #4868 from Hundrec/remove-changelog
Remove Changelog from game files
2025-04-28 16:40:53 -04:00
ShadzXDandGitHub 66197b34f6 Update CHANGELOG.md 2025-04-28 22:40:26 +02:00
HundrecandHyper_ a7da71c8a8 Remove Changelog from game files
since it keeps getting revised after each release

Co-Authored-By: Hyper_ <40342021+NotHyper-474@users.noreply.github.com>
2025-04-28 14:38:52 -06:00
EricandGitHub 5bd081c2af Merge pull request #4866 from Hundrec/0.6.3-changelog-additions
[DOCS] Additional 0.6.3 Changelog bugfix entries + updated commit links
2025-04-28 16:26:51 -04:00
EricandGitHub aefc4db277 Merge branch 'main' into 0.6.3-changelog-additions 2025-04-28 16:26:43 -04:00
EricandGitHub adc14cc15d Merge pull request #4867 from FunkinCrew/develop2
Copied some files that weren't in main before back into develop
2025-04-28 16:21:54 -04:00
EricandGitHub a8294a9cce Merge pull request #4865 from FunkinCrew/0.6.3-release
Move public fix to main branch
2025-04-28 16:15:57 -04:00
EliteMasterEric 80569c806c Merge remote-tracking branch 'public/main' into 0.6.3-release 2025-04-28 16:15:09 -04:00
EliteMasterEric d6837eba2e Merge remote-tracking branch 'public/main' into 0.6.3-release 2025-04-28 16:14:37 -04:00
HundrecandGitHub 924b1cf386 Remove Newgrounds authentication entry
because it wasn't actually fixed
2025-04-27 20:43:09 -06:00
HundrecandGitHub 0839c16535 More 0.6.3 entries + updated commit links 2025-04-27 06:04:15 -06:00
HundrecandGitHub db3e012cb0 [DOCS] Changelog for 0.6.3 (#4816)
* Changelog for 0.6.3

* Clarify mod API version entry

* 0.6.3 Changelog tweaks
2025-04-26 05:18:01 -04:00
6c2ebff680 bump to 0.6.3 (#4448)
Co-authored-by: Eric <ericmyllyoja@gmail.com>
2025-04-26 00:48:37 -04:00
EricandGitHub df0f915be5 Merge pull request #1014 from FunkinCrew/kade-github/pico-mix-bugfix
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (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
FUNK-1944 Bugfix for Pico (Pico Mix's) that would cause the doppelganger cutscene bad shit
2025-04-25 22:29:54 -04:00
EliteMasterEric 104d3cffcb Merge branch 'rewrite/master' into kade-github/pico-mix-bugfix 2025-04-25 22:29:32 -04:00
EliteMasterEric 584b1ece07 Update assets submodule 2025-04-25 22:27:57 -04:00
Eric 4555b6736e Rewrote recommendation to use Funkin haxelib and hmm 2025-04-25 21:41:16 -04:00
HundrecandEric 0c674ac23b Specify "flip horizontally" shortcut in Changelog entry 2025-04-25 21:37:11 -04:00
Eric c5e5ab16df Recommend Funkin's fork of hmm (fewer issues with Lime) 2025-04-25 17:50:45 -04:00
EliteMasterEricandKade adefa902e7 Fix several issues preventing builds on HTML5 2025-04-25 12:14:28 -07:00
kade-github 63f216ea71 assets submodule update 2025-04-25 12:06:48 -07:00
EliteMasterEric 03d46084b4 Update game version to v0.6.3. 2025-04-25 02:32:28 -04:00
kade-githubandCameron Taylor 19eb138666 vwooshin for retry 2025-04-25 00:32:07 -04:00
EliteMasterEricandCameron Taylor e21b01aa66 Fix a broken usage. 2025-04-25 00:32:00 -04:00
EliteMasterEricandCameron Taylor c41c800998 Fix a bug where render distance ignores scroll speed (test on 0.5x scroll speed), then do some code cleanup and documentation. 2025-04-25 00:32:00 -04:00
Cameron Taylor b7675aa440 assets submod (Cheer overrides lightning scare from kade) 2025-04-25 00:20:46 -04:00
Cameron TaylorandKade 745f49ca6d tiny little cleans in char select nametag 2025-04-24 19:26:35 -07:00
Cameron TaylorandKade 78646c4635 fix for difficulty stars not appearing when returning from character select 2025-04-24 19:14:11 -07:00
Cameron Taylor f1cc092820 quickie haxe checkstyle thing that annoy me all the time grr.. 2025-04-24 21:29:18 -04:00
Cameron Taylor 7e200241ef assets submod (satin panties fixins) 2025-04-24 20:54:57 -04:00
EricandGitHub 1c4b8751b7 Pico Results Screen Easter Egg (#1007) 2025-04-23 16:52:29 -07:00
926d8c0517 Contributor's Guide Maintenance Policy
Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-04-23 17:06:13 -04:00
EliteMasterEricandCameron Taylor e290e0c702 Make merch referrals error-proof (they don't work if the API is disabled whoops!) 2025-04-22 19:14:15 -04:00
nebulazoruaandCameron Taylor 53dec057be vuln patch part 1
so now you cant open files as easily i think

oops
2025-04-22 19:14:15 -04:00
Cameron Taylor b3f1798320 assets submod (tankman deathlines for bf) 2025-04-22 19:02:58 -04:00
Hyper_andCameron Taylor f20b938f3f fix: Pad number with 1 decimal place with zero
Merge pull request #1000 from FunkinCrew/hyper/chart-editor-display-beat

[PUBLIC PR] Display current beat and step in the Chart Editor
2025-04-22 19:02:56 -04:00
Hyper_andCameron Taylor 85915eae8c Implement suggestion: Fractional beat display 2025-04-22 19:02:09 -04:00
Hyper_andCameron Taylor 83bb3bb507 feat: Show current beat and step next to song position 2025-04-22 19:02:09 -04:00
KadeandCameron Taylor 642b2142ca Merge pull request #999 from FunkinCrew/kolo/chart-event-crash-fix
[PUBLIC PR] Fix a crash when messing with events in the chart editor
2025-04-22 19:00:24 -04:00
KadeandCameron Taylor 0c6b730647 Merge pull request #998 from FunkinCrew/kolo/cap-score-display
[PUBLIC PR] Cap Score Displays to their biggest possible values
2025-04-22 19:00:24 -04:00
KoloandCameron Taylor 83c367e23b another bugfix yeah
i hate dropdowns i hate dropdowns i hate dropdowns
2025-04-22 19:00:24 -04:00
KadeandCameron Taylor fe7bf3dd55 Merge pull request #994 from FunkinCrew/cyn0x8/fileutil-sandbox
[PUBLIC PR] Sandboxing for FileUtil (prevent deleting important game files etc)
2025-04-22 19:00:24 -04:00
KadeandCameron Taylor 273d950899 Merge branch 'rewrite/master' into kolo/cap-score-display 2025-04-22 19:00:24 -04:00
KoloandCameron Taylor 9e61481cfe Merge branch 'develop' of https://github.com/FunkinCrew/Funkin into chart-events-fix 2025-04-22 19:00:24 -04:00
SuperandCameron Taylor e572c7c2fb Remove FlxG.fixedTimeStep from PlayState
It's in TitleState now
2025-04-22 19:00:24 -04:00
cyn0x8andCameron Taylor 95ade2a08b FileUtil overhaul + sandboxing 2025-04-22 19:00:24 -04:00
KoloandCameron Taylor 51324e9c28 mmyes 2025-04-22 19:00:24 -04:00
AbnormalandCameron Taylor e6e3a30c0c docs: Add missing documentation to the remaining functions in Module 2025-04-22 19:00:24 -04:00
SuperandCameron Taylor 2b7254fbd2 Add FlxG.fixedTimestep change to initState 2025-04-22 19:00:24 -04:00
HundrecandCameron Taylor d54df57b95 Two more Chart Editor entries in Changelog 2025-04-22 19:00:24 -04:00
Cameron Taylor b295e31266 Merge branch 'rewrite/master' into public-changes 2025-04-22 19:00:24 -04:00
HundrecandCameron Taylor 695c708cb0 Add a few fixes and changes from 0.6.0 2025-04-22 19:00:24 -04:00
EliteMasterEricandCameron Taylor 4a7f56a7ad Merge remote-tracking branch 'public/develop' into develop 2025-04-22 19:00:24 -04:00
HundrecandCameron Taylor 030abed207 Oops, one more lil space 2025-04-22 19:00:24 -04:00
HundrecandCameron Taylor 0d8cfaf104 Remove 0.6.0 Changelog entries that weren't implemented + polish 2025-04-22 19:00:24 -04:00
EliteMasterEricandCameron Taylor caf708fe4a Merge remote-tracking branch 'public/main' into develop 2025-04-22 18:41:41 -04:00
HundrecandCameron Taylor e7cf5fbbdc Grammatical fix in style-guide.md 2025-04-22 18:41:41 -04:00
HundrecandCameron Taylor ccaa3d1070 Consistent hyphens in CODESTYLE.md 2025-04-22 18:41:41 -04:00
4b883d4339 Restore Contributing Guide to latest version
Merge conflicts yay

Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-04-22 18:41:41 -04:00
sector-aandEric b40b4b0369 Fix Animation Editor Crash
Fix poor code formatting

This is unnecessary now
2025-04-22 15:53:53 -04:00
Cameron TaylorandEric aa37745bbd assets submod (week 6 shader fixin) 2025-04-22 15:51:45 -04:00
EliteMasterEricandCameron Taylor df6ffca01f Update assets submodule (charting revert stuff) 2025-04-19 19:41:27 -04:00
EliteMasterEricandCameron Taylor 9dd8a257df Update assets submodule to include twenty-seven chart tweak commits 2025-04-19 19:38:18 -04:00
mint 2984ce4852 hotfix(ci): use our own runners again :) 2025-04-19 03:23:27 +02:00
mint 8fb35ac822 hotfix(ci): for now, disable fail-fast so we can get some windows builds 2025-04-19 03:17:47 +02:00
mint e8c42c281f hotfix: mac lime ndlls again? 2025-04-19 02:58:52 +02:00
mint 68892b92ab hotfix(ci): bump neko version to 2.4.1 2025-04-19 02:32:22 +02:00
Cameron Taylor 12ee60f776 Mac ndlls lime hmm bump 2025-04-18 20:18:39 -04:00
Cameron Taylor 945314d271 lime bump for windows fix 2025-04-18 19:41:53 -04:00
EliteMasterEricandCameron Taylor 93d4f30cad Make ScreenshotPlugin null-safe. 2025-04-18 19:40:39 -04:00
AbnormalandCameron Taylor dda91cf770 change requested by eric 2025-04-18 19:35:24 -04:00
AbnormalandCameron Taylor 6a1160feab chore: Enable null safety for 11 classes 2025-04-18 19:35:24 -04:00
kade-githubandEric b48b5ae1aa remember diff for generate song list 2025-04-18 17:33:31 -04:00
fabsandCameron Taylor 5bf8154e0b otis muzzle flashing (assets submod) 2025-04-17 19:59:59 -04:00
EliteMasterEricandCameron Taylor 6de51848fd Update assets submodule 2025-04-17 19:59:59 -04:00
Cameron Taylor ee906ae8c0 fix: make the sound tray volume be less loud (#990) 2025-04-17 19:59:59 -04:00
7eebce432d [PUBLIC PR] Prevent softlock caused by removing all keybinds for a UI control (#988)
* prevent removing last keybind for UI controls

* add popup to alert you cannot remove keybind

* ensure controls list is unique

* Use public submodule URLs (would be nice if this was automatic but oh well)

---------

Co-authored-by: VioletSnowLeopard <ngzeretzke@gmail.com>
Co-authored-by: EliteMasterEric <ericmyllyoja@gmail.com>
2025-04-17 19:59:59 -04:00
EliteMasterEric 750779a3fb Disable the pop-in animation on the Random capsule for consistency. 2025-04-17 18:25:44 -04:00
kade-githubandEric 095bc9006d animation on all diffs 2025-04-17 18:25:44 -04:00
kade-githubandEric 09fdd0c91e going to erect with the erect takes you to the closest erect 2025-04-17 18:25:44 -04:00
kade-githubandEric be5d6227a7 erect nearest neighbor select 2025-04-17 18:25:44 -04:00
KoloandCameron Taylor 855deb5828 set enabled when prompt gone 2025-04-16 16:06:39 -04:00
EliteMasterEricandCameron Taylor 963e2ecd63 Edit RegistryMacro to automatically populate baseGameEntryIds list. 2025-04-15 20:25:18 -04:00
lemz1andCameron Taylor 14975212a9 macro
registry macro

Merge branch 'lemz1/registry-entry-data' into lemz1/registry-macro-stufff
2025-04-15 20:25:18 -04:00
Hyper_andCameron Taylor 3ad14bac32 fix: Double check if events are the same when doing indexOf
This is basically copy-pasted from SongNoteDataArrayTools lol
2025-04-15 19:47:39 -04:00
Cameron Taylor e672c0978f hmm lime bump 2025-04-14 23:35:43 -04:00
Cameron Taylor 0d5b7d4ed4 also conditional for WindowUtils.setVSyncMode() for mac 2025-04-14 23:27:34 -04:00
kade-githubandCameron Taylor 7e90423495 Pre-Processor to disable VSync on MacOS 2025-04-14 23:27:34 -04:00
kade-githubandCameron Taylor c7c2620217 Set vsync on launch (might need to be set elsewhere too) 2025-04-14 21:42:24 -04:00
kade-githubandCameron Taylor 3944816021 Error handling from wiki 2025-04-14 21:42:24 -04:00
kade-githubandCameron Taylor db00feff93 Vsync does work now 2025-04-14 21:42:24 -04:00
kade-githubandCameron Taylor 6e2a077d6b Fixes from merge 2025-04-14 21:42:22 -04:00
EliteMasterEricandCameron Taylor 1ee8246b48 Added a preference to enable VSync. 2025-04-14 21:40:58 -04:00
EricandCameron Taylor 20c3228d8c Don't discount the score so much on miss, but still keep it meaningful. 2025-04-14 19:32:55 -04:00
EliteMasterEricandCameron Taylor 01bf3bee11 Dropping hold notes should no longer cost health by default. 2025-04-14 19:32:55 -04:00
EliteMasterEricandCameron Taylor 4d9638f0ac Fix the clamping. 2025-04-14 19:32:55 -04:00
EliteMasterEricandCameron Taylor b00589367c Make hold drop penalty threshold match the hit window. 2025-04-14 19:32:55 -04:00
EliteMasterEricandCameron Taylor 577421a782 Scoring rework: Penalize the player (deducting health and score) for dropping a hold note before it's finished. 2025-04-14 19:32:54 -04:00
EliteMasterEricandCameron Taylor 72e9fb641e Scoring rework: Reduce health given by hold notes by 20%. 2025-04-14 19:32:16 -04:00
EliteMasterEricandCameron Taylor 429f6f9bc0 Remove the unused input splitter. 2025-04-14 19:32:16 -04:00
EliteMasterEricandCameron Taylor 550bf95c76 Split miss penalty and ghost miss penalty into two variables (but make them equal for now). 2025-04-14 19:32:16 -04:00
EliteMasterEricandCameron Taylor da686ed0c4 Scoring rebalance: Misses now reduce your final grade, which impacts your rank 2025-04-14 19:32:16 -04:00
EliteMasterEricandCameron Taylor 9f3711bf43 Scoring rebalance: Misses are now worth -250 points (up from -10). 2025-04-14 19:32:16 -04:00
EliteMasterEricandCameron Taylor 6390725ef0 Redo data format for sticker packs to make it simpler and allow for song-specific selections. 2025-04-14 19:25:42 -04:00
AbnormalandCameron Taylor cdc468ba15 feat: Sticker Registry 2025-04-14 19:25:29 -04:00
EliteMasterEricandCameron Taylor deb4e1921d Fix an issue where Stress would crash on the second playthrough 2025-04-14 15:45:29 -04:00
KoloandCameron Taylor 068c9fb43d no thoughts save empty
also more code clarity ig
2025-04-14 15:28:14 -04:00
AbnormalandCameron Taylor 5be4f3bbb9 chore: Remove ComboMilestone 2025-04-14 15:28:14 -04:00
AbnormalandCameron Taylor b83ae65a65 docs: Add missing documentation to the remaining functions in Module 2025-04-14 15:28:14 -04:00
HundrecandCameron Taylor dc876be57c Two more Chart Editor entries in Changelog 2025-04-14 15:28:14 -04:00
HundrecandCameron Taylor c08847f48d Add a few fixes and changes from 0.6.0 2025-04-14 15:28:14 -04:00
HundrecandCameron Taylor 19912b5f89 Oops, one more lil space 2025-04-14 15:28:14 -04:00
HundrecandCameron Taylor 019473dec2 Remove 0.6.0 Changelog entries that weren't implemented + polish 2025-04-14 15:28:14 -04:00
EliteMasterEricandCameron Taylor f001562270 Update HXVLC to 2.1.2 2025-04-13 21:45:39 -04:00
HundrecandEric 34bb58015d Add Combo Milestones to Rejected Features list 2025-04-13 00:37:16 -04:00
AbnormalandEric d86fe68d80 docs: Add missing documentation to the remaining functions in Module 2025-04-12 00:54:04 -04:00
LasercarandEric 1434820d10 remove removed debug keys 2025-04-12 00:53:51 -04:00
HundrecandEric 08fb5b8459 Two more Chart Editor entries in Changelog 2025-04-12 00:53:29 -04:00
Hyper_andEric 8e8dcaa7f9 docs: (TROUBLESHOOTING.md) Correct outdated information about Lime troubleshooting
The commit of Lime that Funkin uses now includes Linux NDLLs. These are built on a system with GLibC 2.38 though which breaks compatibility with lots of stable distributions troubleshooting was added for those systems too.
2025-04-12 00:53:18 -04:00
Hyper_andEric b35059ec99 docs: (COMPILING.md) Remove outdated info about Lime fork 2025-04-12 00:53:18 -04:00
EliteMasterEricandCameron Taylor b28ba8f465 Update assets submodule 2025-04-11 16:07:53 -04:00
EliteMasterEricandCameron Taylor dcc8085691 Update assets submodule 2025-04-11 16:00:16 -04:00
EricandCameron Taylor c186666402 Update mod version number (this requires mods to check they are working, then change their metadata) 2025-04-11 15:58:51 -04:00
EliteMasterEricandCameron Taylor 6f93960cb5 Update HaxeUI to their latest versions. 2025-04-11 15:58:34 -04:00
Cameron TaylorandEric a756ceac22 properly initialize soundtray on game start if muted 2025-04-10 18:43:54 -04:00
Cameron TaylorandEric c394520019 small cleanups / tidying of FunkinSoundTray.hx 2025-04-10 18:43:54 -04:00
Cameron TaylorandEric 2d93baf968 properly save mute preferences by doing the save on show() in the soundtray 2025-04-10 18:43:54 -04:00
EliteMasterEricandCameron Taylor 4a98e6999f Update assets submodule 2025-04-09 18:13:30 -04:00
EliteMasterEricandCameron Taylor 9ff14aed42 Fix an issue where Pico's retry animation is broken on Ugh/Guns Pico Mix 2025-04-09 15:58:44 -04:00
EliteMasterEricandCameron Taylor 0a7bd3111f Fix a crash with the chart editor Note window (via Lasercar) 2025-04-09 15:52:47 -04:00
VioletSnowLeopardandCameron Taylor 1f88a3b6e1 swap restart and skip in dialogue pause menu 2025-04-09 15:33:54 -04:00
HundrecandEric fcb47ff4fc Grammatical fix in style-guide.md 2025-04-08 23:18:17 -04:00
HundrecandEric 3218ceeecd Consistent hyphens in CODESTYLE.md 2025-04-08 23:18:17 -04:00
HundrecandEric 1823373d7e Add a few fixes and changes from 0.6.0 2025-04-08 23:18:04 -04:00
HundrecandEric af14d42939 Oops, one more lil space 2025-04-08 23:18:04 -04:00
HundrecandEric 3dd3338ab2 Remove 0.6.0 Changelog entries that weren't implemented + polish 2025-04-08 23:18:04 -04:00
Hyper_ 26f2578bf2 fix: Pad number with 1 decimal place with zero 2025-04-08 16:02:03 -03:00
Hyper_ c32ade49b9 Implement suggestion: Fractional beat display 2025-04-07 23:59:55 -03:00
Hyper_ d4eee38fd2 feat: Show current beat and step next to song position 2025-04-07 21:08:01 -03:00
6543c58363 Restore Contributing Guide to latest version
Merge conflicts yay

Co-Authored-By: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-04-06 03:50:32 -04:00
EliteMasterEric 158c015682 Use public URLs for git submodules 2025-04-04 15:16:58 -04:00
EricandGitHub 278bac7b6d Merge pull request #4554 from FunkinCrew/release/v0.6.2
Release the source code for v0.6.2
2025-04-04 15:03:23 -04:00
EliteMasterEric 29cddfb528 Merge remote-tracking branch 'public/main' into release/v0.6.2 2025-04-04 15:01:59 -04:00
VioletSnowLeopard da9f17cf87 swap restart and skip in dialogue pause menu 2025-04-04 14:41:33 -04:00
EliteMasterEricandCameron Taylor 02dc353032 Update assets submodule 2025-04-04 14:41:22 -04:00
EliteMasterEric d31ef12363 Use public submodule URLs (would be nice if this was automatic but oh well) 2025-04-04 14:28:12 -04:00
EliteMasterEric c7d4406a34 Fix results screen music continuing to play when using the debugger 2025-04-03 22:01:32 -04:00
EliteMasterEricandCameron Taylor 68e9daffe8 Zero out the ABot visualizer before the song starts. 2025-04-03 16:04:19 -04:00
EliteMasterEricandCameron Taylor c157338783 Fix certain characters pixel icons not displaying properly in the chart editor. 2025-04-03 16:04:07 -04:00
EliteMasterEricandCameron Taylor eb9c2c2c99 Fix Pixo's freeplay AFK animation not playing (properly this time). 2025-04-03 16:02:10 -04:00
EliteMasterEricandCameron Taylor afb4a3dd68 Remove some unused/redundant debug hotkeys. 2025-04-03 16:02:10 -04:00
Cameron Taylor 9b5032ee84 quick patch for cory 2025-04-02 21:54:27 -04:00
Cameron Taylor 62621881c0 data -> data.score 2025-04-02 16:18:58 -04:00
Cameron Taylor 52be941b45 Auto Pause -> Pause on Unfocus (was changed before but prob bad merge somewhere reverted it?) 2025-04-02 13:55:54 -04:00
Cameron Taylor c94b3a3b65 2024 -> 2025 0.6.x changelog date fixins (closes FUNK-1740) 2025-04-02 13:41:54 -04:00
EliteMasterEricandCameron Taylor 8291fe0407 Make the back of ABot's stereo display slightly wider. 2025-04-02 13:37:50 -04:00
EliteMasterEricandCameron Taylor f935526baa Update assets submodule 2025-04-02 13:36:22 -04:00
EliteMasterEricandCameron Taylor 102ac4bfc8 Fix a bug where restarting the level would add more Tankmen to the background. 2025-04-02 13:34:23 -04:00
EliteMasterEricandCameron Taylor f8b212a318 Improve null safety of medal and leaderboard classes. 2025-04-02 13:33:32 -04:00
EliteMasterEricandCameron Taylor 3bd79b822e Fix a deprecation warning. 2025-04-02 13:33:32 -04:00
EliteMasterEricandCameron Taylor 17a4be66b9 Fix highscores not submitting to the website unless they are a personal best. 2025-04-02 13:33:06 -04:00
EliteMasterEricandCameron Taylor 54cd52db76 Fix an issue where story mode medals would not be awarded without a personal best. 2025-04-02 13:33:06 -04:00
Cameron Taylor 4fa0334e7b easier script for creating macos universal binaries 2025-04-01 16:41:46 -04:00
EricandCameron Taylor b7761d45b7 Disable FEATURE_RESULTS_DEBUG on release builds by default.
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows-latest, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (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
2025-03-31 22:39:08 -04:00
HundrecandEric 3c6466bec7 Bump repo versions to 0.6.2 2025-03-31 21:20:18 -04:00
Cameron Taylor 1d5d0ddd52 IGJHSpritin credits fix (assets submod) 2025-03-31 19:55:42 -04:00
Cameron Taylor 0818bd9c93 disable results screen debugger 2025-03-31 19:51:22 -04:00
Cameron Taylor 43f6cf6267 changelog update 0.6.2 2025-03-31 19:48:06 -04:00
Cameron Taylor cfd380b243 creds update (assets submod) 2025-03-31 19:45:09 -04:00
Cameron Taylor dd1b09a293 same shader fix but on the DropShadowScreenspace
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows-latest, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (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
2025-03-31 19:25:10 -04:00
HundrecandEric 3ccd1b04da Bump repo versions to 0.6.1 2025-03-31 18:42:17 -04:00
Cameron Taylor 0526eb7a64 0.6.1 quick hotfix crap 2025-03-31 16:01:50 -04:00
Cameron Taylor 6b321b72ae fix the ternary operator for DropShadowShader 2025-03-31 15:37:39 -04:00
Cameron Taylor 9580875c23 remove NewgroundsCredentials.hx derp
Build and Upload nightly game builds / gather-changes (push) Canceled after 0s
Build and Upload nightly game builds / gather-tags (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (macos, macos) (push) Canceled after 0s
Build and Upload nightly game builds / build-game-on-host (windows-latest, windows) (push) Canceled after 0s
Build and Upload nightly game builds / docker-image (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
2025-03-31 14:42:16 -04:00
EricandGitHub d6d8df9f67 Merge pull request #949 from FunkinCrew/ng-partial-autologin
only do a partial auto login, when logging in via NG or via saved session
2025-03-31 14:28:39 -04:00
Cameron Taylor 4eb4b00271 only do a partial auto login, when logging in via NG or via saved session 2025-03-31 14:15:06 -04:00
EliteMasterEricandCameron Taylor e7634c90e7 Fix an animation issue with the cans in 2hot. 2025-03-31 13:28:13 -04:00
HundrecandEric 439be3cb26 Update templates and docs to 0.6.0 2025-03-31 13:21:55 -04:00
EricandGitHub 5e93920797 Merge pull request #948 from FunkinCrew/fix/stress-null-script
null out rimlightCamera and remove it from FlxG.cameras(assets submod)
2025-03-31 12:20:20 -04:00
Cameron Taylor a4069eba2a null out rimlightCamera and remove it from FlxG.cameras(assets submod) 2025-03-31 00:43:13 -04:00
EliteMasterEricandCameron Taylor 30168a1160 Fix a build error caused by references to invalid leaderboards. 2025-03-31 00:10:06 -04:00
EliteMasterEric a2fcaec9ff Use production build medal IDs and leaderboard IDs in release builds. 2025-03-30 22:51:52 -04:00
EliteMasterEricandCameron Taylor e5e3453c1f Add Stress Pico + Char Select medals, and fix medals to work on release builds 2025-03-30 21:59:17 -04:00
EliteMasterEricandCameron Taylor 0d8b04dd56 Add an option to destroy save data in the options menu. 2025-03-30 19:17:08 -04:00
EliteMasterEricandCameron Taylor 3b997d7c0f Add finalized loss SFX 2025-03-30 19:00:04 -04:00
EliteMasterEricandCameron Taylor 3ff93f1923 Fixed some bugs with death quotes and added final lines. 2025-03-30 18:54:12 -04:00
EliteMasterEricandCameron Taylor 64d8e81ed1 Rework death quotes logic to make more sense. 2025-03-30 18:54:06 -04:00
EliteMasterEricandCameron Taylor a741b4eed3 Add Stress Pico Intro Cutscene (assets submod) 2025-03-30 18:38:18 -04:00
EliteMasterEric 81e7c6b84a Fix a bug with the intro and end cutscenes conflicting. 2025-03-30 16:02:10 -04:00
fabs 77e06bc9d4 assets submod 2025-03-29 21:54:20 +00:00
fabs c6966c2b63 screenspace shader 2025-03-29 21:47:39 +00:00
EricandGitHub a9652544f5 Merge pull request #937 from FunkinCrew/album-roll-expansion2
change expansion 2 -> volume 4, and add the proper new expansion 2 stuff
2025-03-28 22:02:56 -04:00
Cameron Taylor 042d29309f volume4 spritesheet crap 2025-03-28 21:47:36 -04:00
Cameron Taylor 05d88ba0bf change expansion 2 -> volume 4, and add the proper new expansion 2 stuff 2025-03-28 20:27:12 -04:00
EliteMasterEricandCameron Taylor d07d173631 Fixed the seizure bug. 2025-03-28 19:07:43 -04:00
EricandGitHub d02d86edcd Merge pull request #935 from FunkinCrew/2hot-rain-fix
fix: phillystreets rain starts properly
2025-03-27 20:35:02 -04:00
EricandGitHub e99526d195 Merge pull request #933 from FunkinCrew/freeplay-ranking-tidy
refactor some FreeplayRank stuff to hold both blurred and unblurred ranking
2025-03-27 20:27:00 -04:00
Cameron Taylor 14e5c1c655 fix: phillystreets rain starts properly 2025-03-27 20:26:50 -04:00
Cameron TaylorandEric f7a48bcb3b refactor some FreeplayRank stuff to hold both blurred and unblurred ranking 2025-03-27 20:26:50 -04:00
EliteMasterEricandCameron Taylor db43704fe3 Roses stage animation fix 2025-03-27 20:11:07 -04:00
EricandGitHub 35780ec9f3 Merge pull request #929 from FunkinCrew/pico-chart-editor-fix
variations loading via fnfc fix in progress
2025-03-27 19:13:02 -04:00
Cameron TaylorandEric 36997e8b30 variations loading via fnfc fix in progress 2025-03-27 18:00:24 -04:00
AbnormalandCameron Taylor abe4ac8485 Remove the Alphabet class 2025-03-27 15:59:35 -04:00
EliteMasterEricandCameron Taylor f61dfa1f66 Fix typo. 2025-03-27 15:49:09 -04:00
EliteMasterEricandCameron Taylor 0bc938d0fa Implement support for Newgrounds Events 2025-03-27 15:49:09 -04:00
EliteMasterEricandCameron Taylor 668b2cdfb7 Remove a problematic mask from the medal animation. 2025-03-27 15:49:07 -04:00
EliteMasterEricandCameron Taylor 96e29b7921 Tweaks to medals and leaderboards (split Erect/character remixes, fix test medals not working etc) 2025-03-27 15:48:53 -04:00
EliteMasterEric 00893768d1 Evil school shader fix 2025-03-27 13:16:54 -04:00
Cameron Taylor 8e43a7ae0c bump FlxAnimate back to commit 713d3d for now 2025-03-27 10:44:03 -04:00
EricandGitHub 251e96b426 Merge pull request #908 from FunkinCrew/hxcpp-hmm-bump
bump hxcpp hmm version to v4.3.75
2025-03-26 03:29:22 -04:00
Cameron TaylorandEric 94331bd938 bump hxcpp hmm version to v4.3.75 2025-03-26 02:53:06 -04:00
EliteMasterEricandCameron Taylor c4b9097868 Update difficulty rankings 2025-03-26 01:16:53 -04:00
EliteMasterEricandCameron Taylor 64eb80e8b7 Game Over (Pico Pixel) 2025-03-26 01:15:24 -04:00
EliteMasterEricandCameron Taylor d84c2e7875 Fix an issue where the game would try to render destroyed note graphics. 2025-03-25 22:02:43 -04:00
EliteMasterEricandCameron Taylor d08c8a541e Fix some issues with HScript, and enable the ?? operator. 2025-03-25 22:02:43 -04:00
EliteMasterEricandCameron Taylor ba7c263d23 Update changelog to include contributor list. 2025-03-25 22:02:43 -04:00
Cameron Taylor 293cd7d50a shader fix for week 3 gameover 2025-03-25 19:06:58 -04:00
Cameron Taylor 57b2ae9f37 2hot pico gameover fix 2025-03-25 18:55:44 -04:00
Cameron Taylor 431241bf19 quick fix for results screen debug crap 2025-03-25 18:14:53 -04:00
EliteMasterEricandCameron Taylor 703eae8c62 Update the changelog with all the public fixes (thanks Hundrec) 2025-03-25 15:37:13 -04:00
EliteMasterEricandCameron Taylor 34c07811d1 Update assets submodule 2025-03-25 15:37:13 -04:00
871709bb7d Some additions to the Contributor's Guide
Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-03-25 15:18:43 -04:00
HundrecandCameron Taylor 91a594cc85 Nudge Results totals left if 4 digits long 2025-03-25 15:03:08 -04:00
EliteMasterEricandCameron Taylor 43bdd38a44 Fix all game over screen being broken 2025-03-25 14:59:16 -04:00
Cameron Taylor 6e463e0188 debug: add simple result screen debug mode 2025-03-25 14:48:31 -04:00
Cameron Taylor 319419c541 refactor: refactor some of the Page menu handling out of OptionsState 2025-03-24 19:20:25 -04:00
Cameron Taylor e8c07c9ec6 debug: added debug menu option to open ResultsState (and fixed small crash when opening ResultsScreen in this way)
part 1 of results screen debug stuff
2025-03-24 19:20:25 -04:00
Cameron Taylor fa5a80df08 screenshot plugin fix for high dpi / larger window sizes 2025-03-24 17:42:35 -04:00
LasercarandCameron Taylor e51b6147b5 unused code removed and comment cleanup 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 2a9712466e Fixed cursor & preview not being reset for state changes 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor e9891c4d00 Fancy preview is back!
Also now saves on window close/crash.
Also standardised the option descriptions.
2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 5c47ed4a8c Set screenshotBeingSpammed to false after state change
Because the timer has been killed
2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 6e4e7008f2 another whoops 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 79e31636e2 Save unsaved screenshots in buffer before state change 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 8fcd145d53 Option to only show the preview when a screenshot is saved
Enabled by default, the idea is that the less tech savy players won't bother changing the option to false and end up reporting that they lost screenshots after changing states
2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor e30e6ee4ed comment cleanup 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor bab920dc82 comment typo 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor ab2dd75986 now it's actually asynchronous
Though with the caveat of unsaved screenshots not being saved after state change
2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor a8440062b8 fixed duplicate screenshot handling code 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 824cf7cf1b frame delayed screenshots + timer'd screenshot save 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 65786d8f1c small fix 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor bcd29b5d67 idk 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 95847440b5 didn't reverse my test of the JPEG encoder 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor c776900df0 screenshot options 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor fc9b395138 forgot to uncomment the bit making the async loop null 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 7b54292bf7 another whoops 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 4ef0c18212 idk 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 8e4f9fe66b forgot a thing 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 92b24b91e7 asynchronous screenshot buffer saving 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 0db0d88256 Show a preview of last image in the image buffer 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 535ff2211a Popup no longer shows up in screenshots 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor f7329e0687 Improved? screenshotting 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 868932cd13 screenshot preview in screenshot fix 2025-03-24 17:32:49 -04:00
LasercarandCameron Taylor 9c2ef02368 NuN GF
Adds a none/null option for the character selector dropdown
Also fixes a few null references that happen when one or both characters are null in the playstate
2025-03-24 15:00:01 -04:00
Cameron Taylor 4187244305 Merge branch 'bugfix/missing-pitstop2-mp3s' into rewrite/master 2025-03-24 14:41:51 -04:00
KoloandCameron Taylor 65b9466ce3 eric's suggestion 2025-03-24 14:40:55 -04:00
KoloandCameron Taylor a5e5c1dee2 freeplay random button fix 2025-03-24 14:40:55 -04:00
KoloandCameron Taylor a90b911653 freeplay random button fix 2025-03-24 14:40:55 -04:00
EliteMasterEric 06940573ca Update assets submodule 2025-03-24 13:38:07 -04:00
EliteMasterEricandCameron Taylor 01693eb4ce Display additional info messages in the terminal (without breaking VSCode!) 2025-03-21 20:07:29 -04:00
Cameron TaylorandGitHub 1adcc67acb Merge pull request #914 from FunkinCrew/public/copybara-refs/pull/4355/merge
[PUBLIC PR] [BUGFIX] Fallback when no defined inputs
2025-03-21 19:10:15 -04:00
EliteMasterEricandCameron Taylor 1506225100 Last batch of chart tweaks I think. 2025-03-21 19:09:16 -04:00
EliteMasterEricandCameron Taylor 43a09f668e Update assets submodule 2025-03-21 19:06:56 -04:00
Cameron Taylor 07c433e6d4 Merge branch 'notehold-styles' into rewrite/master 2025-03-21 18:58:29 -04:00
EliteMasterEricandCameron Taylor febe5e84a2 Don't display the rank animation in Freeplay if Practice Mode or Bot Play Mode were enabled. 2025-03-20 15:13:32 -04:00
EliteMasterEricandCameron Taylor d7c3b64e02 Disable note inputs when the song is over. 2025-03-20 15:13:32 -04:00
EliteMasterEricandCameron Taylor 0f6e6c4701 Fix a crash when using -DRESULTS. playerCharacterId was already calculated earlier. 2025-03-20 15:13:32 -04:00
KoloandCameron Taylor b70946f3c3 fix backspace and enter causing crash 2025-03-20 15:08:07 -04:00
Hyper_andEliteMasterEric 099c309f9b fix: Fallback to 'N/A' text when no inputs avaliable in getDialogueName 2025-03-20 03:05:59 -04:00
ember / mintandGitHub 02dcef4727 hotfix: temporarily use windows-latest runners for windows builds (#910) 2025-03-18 19:25:42 +00:00
HundrecandLasercar bf36a86877 Remember selection when exiting to Title Screen 2025-03-18 20:47:21 +10:00
Cameron Taylor a72fce14d1 Merge branch 'public-develop' into rewrite/master 2025-03-17 22:20:28 -04:00
EliteMasterEricandCameron Taylor 2f339e8113 Update FlxAnimate 2025-03-17 14:40:22 -04:00
anysadandEric 9829103671 Fix Animation Editor not saving the file name 2025-03-17 07:13:14 -04:00
LasercarandEric e83b88d320 I'm so done with this stupid bug
Eric wuz here!
2025-03-17 06:44:21 -04:00
KoloandEric 3667c51c1e prevent unnecessary resync 2025-03-17 06:19:54 -04:00
HundrecandEric a55bf60fcf Correctly list all new contributors since Weekend 1
Gives those contributors their credit!
Lists all first-time GitHub contributors, even if their change isn't listed as an entry in the Changelog.
Quadruple-checked for good measure.
2025-03-15 19:49:54 -04:00
HundrecandEric 90c5eea0af Remove docs entries in Changelog + add punctuation 2025-03-15 19:49:54 -04:00
HundrecandEric 63883a1f07 A few more rewordings 2025-03-15 19:49:54 -04:00
HundrecandEric 5ecad9ea9b Combine those lines
Thanks Hyper!
2025-03-15 19:49:54 -04:00
HundrecandEric 128642264d Changelog overhaul for 0.4.1, 0.4.0, 0.3.3, 0.3.2, 0.3.1, 0.3.0 2025-03-15 19:49:54 -04:00
HundrecandEric fa772bdec1 Changelog overhaul for 0.5.3, 0.5.2, 0.5.1
Plus added line breaks to match Keep A Changelog's format
2025-03-15 19:49:54 -04:00
Hyper_andEric 0a8d7a23bf Minor adjustments
Some reformatting and shortening
2025-03-15 19:49:54 -04:00
Hyper_andEric bf1a238f6a docs: Some Linux troubleshooting 2025-03-15 19:49:54 -04:00
HundrecandEric 3a5b625f05 Add more rejected features to Contributing Guide 2025-03-15 19:49:54 -04:00
HundrecandEric f94a202f9c Remove issue reopening action 2025-03-15 19:49:54 -04:00
HundrecandEric 5e3dfbb1f5 Table of Contents for CONTRIBUTING.md 2025-03-15 19:49:54 -04:00
MidyGamyandEric dd82bb8ed5 More dump save info + force crash now accurate 2025-03-15 19:49:54 -04:00
MidyGamyandEric 8fa3384c1e Rewording missing Funkin' Debug Hotkeys.md (thx Hundrec) 2025-03-15 19:49:54 -04:00
MidyGamyandEric d51622f563 Added missing debug hotkeys 2025-03-15 19:49:54 -04:00
HundrecandEric 2041b6969c adjust link in PR Template 2025-03-15 19:49:54 -04:00
HundrecandEric e1fde6ddd9 PR Template 2025-03-15 19:49:54 -04:00
HundrecandEric b8f2524fa2 Revert spacing 2025-03-15 19:49:54 -04:00
HundrecandEric 4adb3005ae Fix Contributing link 2025-03-15 19:49:54 -04:00
HundrecandEric b0151da0e7 Contributing Guide in Minor Bug Template 2025-03-15 19:49:54 -04:00
HundrecandEric b74df06f48 Reword some debug hotkeys 2025-03-14 23:37:25 -04:00
LasercarandEric 055c4d9b75 Add remaining debug keys 2025-03-14 23:37:25 -04:00
Lasercar ea93ec90cb Fix strumline offset when downscroll 2025-03-15 13:20:39 +10:00
HundrecandEric 4383fcf32c Correctly list all new contributors since Weekend 1
Gives those contributors their credit!
Lists all first-time GitHub contributors, even if their change isn't listed as an entry in the Changelog.
Quadruple-checked for good measure.
2025-03-14 02:17:46 -04:00
HundrecandEric cef0cbf9d4 Remove docs entries in Changelog + add punctuation 2025-03-14 02:17:46 -04:00
EricandGitHub 3158e5a5da Merge pull request #898 from FunkinCrew/public-develop
Two commits from public
2025-03-12 19:01:39 -04:00
EliteMasterEric 20403eb80f Merge branch 'public-develop' into public-develop-2 2025-03-12 18:58:43 -04:00
Cameron Taylor 6b9e6c9ebc holdnotecover implementation stuff 2025-03-11 23:17:29 -04:00
HundrecandEric 7d80e6657b A few more rewordings 2025-03-11 19:26:36 -04:00
HundrecandEric bb8d3ae3dc Combine those lines
Thanks Hyper!
2025-03-11 19:26:36 -04:00
HundrecandEric 56033b3288 Changelog overhaul for 0.4.1, 0.4.0, 0.3.3, 0.3.2, 0.3.1, 0.3.0 2025-03-11 19:26:36 -04:00
HundrecandEric 6e44484a1a Changelog overhaul for 0.5.3, 0.5.2, 0.5.1
Plus added line breaks to match Keep A Changelog's format
2025-03-11 19:26:36 -04:00
Cameron Taylor 26de08c005 note hold and splash in progress 2025-03-11 18:46:06 -04:00
Cameron Taylor d5e3fbb384 change the default scrollFactor for stagedata prop stuff from 0,0 to 1,1 2025-03-11 18:39:00 -04:00
Cameron Taylor b46e61a650 forgotten assets submod for the note splash PR 2025-03-11 18:31:32 -04:00
Cameron Taylor 82a316c5b3 Merge branch 'rewrite/master' into public-develop-merge 2025-03-11 17:19:24 -04:00
fabsandCameron Taylor 44d41a848c assets submod 2025-03-11 16:39:48 -04:00
EricandGitHub 99657f1c79 Merge pull request #827 from FunkinCrew/ninjamuffin99/funk-1328
feat: Switching sorting in Freeplay, if your currently selected song …
2025-03-10 22:55:20 -04:00
Cameron TaylorandEric fb26aeb71a feat: Switching sorting in Freeplay, if your currently selected song is in the next section, we move there immediately for easier navigation 2025-03-10 21:44:24 -04:00
EliteMasterEric 6b404c4fcf Don't award Friday Night medal just for logging in, you have to beat a song. 2025-03-10 20:47:06 -04:00
EliteMasterEric 4e05d16cb6 Merge branch 'public-develop' into public-develop-merge 2025-03-10 20:46:33 -04:00
EricandGitHub 7ab3818344 Merge pull request #877 from FunkinCrew/notesplash-styles
W6 Strumline Assets: Pixel Note splashes
2025-03-10 20:40:08 -04:00
Cameron TaylorandEliteMasterEric 93e6d0685b reimplement my notesplash stuff i accidentally deleted derp 2025-03-10 20:39:38 -04:00
Cameron TaylorandEliteMasterEric ea3f1be425 NoteSplash animation cleanup 2025-03-10 20:39:38 -04:00
Cameron TaylorandEliteMasterEric f9a40a2bf7 notesplash notestyle implementation 2025-03-10 20:39:32 -04:00
Cameron Taylor f8c546b82c pico/erect week6 parallax 2025-03-10 20:03:02 -04:00
EliteMasterEricandCameron Taylor 8d3772fdfb Revamp Lit Up (BF Mix), plus other chart tweaks 2025-03-10 19:56:42 -04:00
EliteMasterEricandCameron Taylor 436b735d48 Use the correct chart for Ugh (Pico Mix) 2025-03-10 19:52:13 -04:00
fabsandCameron Taylor fc7e518373 nene hair blowing assets submod 2025-03-10 19:41:09 -04:00
EricandGitHub 3fcb8ec3f2 Merge pull request #888 from FunkinCrew/spirit-fix
fix: spirit trail fix
2025-03-10 18:21:56 -04:00
Cameron Taylor fccfe3432b fix: revert FlxAnimate version 2025-03-10 16:14:39 -04:00
Hyper_andEric 9708e20dd4 Minor adjustments
Some reformatting and shortening
2025-03-10 12:56:42 -04:00
Hyper_andEric df353a1ee8 docs: Some Linux troubleshooting 2025-03-10 12:56:42 -04:00
HundrecandEric 6c9c3e418a Add more rejected features to Contributing Guide 2025-03-10 12:54:48 -04:00
EliteMasterEricandCameron Taylor 2a1766fd7b Update charts via Cory 2025-03-07 22:34:54 -05:00
EliteMasterEricandCameron Taylor 63a8403e7b add bloody tankman song event 2025-03-07 21:56:44 -05:00
EliteMasterEricandCameron Taylor 7231b3f645 New chart event: Set the character's health icon. 2025-03-07 21:56:44 -05:00
Cameron Taylor 96bdb0d4b2 fix: spirit trail fix 2025-03-06 20:24:22 -05:00
Cameron Taylor 7c9f048776 fix: add null checks to fix crash when creating charts via templates 2025-03-06 18:17:32 -05:00
Cameron Taylor 6b835931c5 fix: changing variations in chart editor properly updates the display / BPM 2025-03-06 18:17:32 -05:00
Cameron Taylor f4da1ced3a fix for loading variations in fnfc files 2025-03-06 18:17:32 -05:00
Cameron Taylor 2633538596 fix for loading variations in fnfc files 2025-03-06 18:09:13 -05:00
Cameron Taylor 6e55bcfc77 fixing for loading .fnfc files 2025-03-06 18:09:13 -05:00
Cameron Taylor 9bf83f9159 fix performance when using selection in Chart Editor 2025-03-06 18:09:00 -05:00
Cameron Taylor 9e7b43ef4f fix: On MacOS, properly use Command key instead of Control key in Chart Editor 2025-03-05 16:57:54 -05:00
Cameron Taylor 3370e0186d redo the dropshadowshader's for loop for proper glsl version 100 crud... 2025-03-05 16:57:39 -05:00
fabsandCameron Taylor 85b225eeb7 assets submod 2025-03-05 16:57:39 -05:00
fabsandCameron Taylor 9121e98428 tweaks to drop shadow shader + editable antialias amount 2025-03-05 16:57:39 -05:00
EliteMasterEricandCameron Taylor 47dda7041d Update assets submodule 2025-03-03 10:55:22 -05:00
EliteMasterEricandCameron Taylor 2983c7b5bc Fix error spam when Nene tries to use hair blow. 2025-03-03 10:53:21 -05:00
Cameron Taylor 6e7d511faa remove flxtracker from nene/otis 2025-03-02 21:47:27 -05:00
JVN-PixelsandEric edb270d15e Update ResultState.hx 2025-02-28 17:21:27 -05:00
EliteMasterEricandCameron Taylor 17bf4924bc Update assets submodule 2025-02-28 16:03:43 -05:00
Cameron Taylor 7a624bc3a3 revert the freeplay lag fix since it was causing crashes 2025-02-28 15:02:34 -05:00
EliteMasterEricandCameron Taylor 869726fc6b Additional chart fixes 2025-02-27 19:45:44 -05:00
fabsandCameron Taylor 66ed3f2644 assets submod 2025-02-27 16:41:36 -05:00
Cameron Taylor 3168814328 Merge branch 'feature/final-pico-dialogue' into rewrite/master 2025-02-27 16:22:56 -05:00
Cameron Taylor e077603806 assets submod 2025-02-27 16:22:08 -05:00
Cameron Taylor 99337a7123 assets submod 2025-02-27 16:21:31 -05:00
EliteMasterEricandCameron Taylor be0ad00913 Update assets submodule to include more chart tweaks 2025-02-27 16:19:00 -05:00
EliteMasterEric c61a943f80 Dialogue fixes. 2025-02-26 00:12:14 -05:00
EliteMasterEric 29dcf4f59a Update assets submodule (Roses Pico Mix + dialogue) 2025-02-25 23:43:48 -05:00
EliteMasterEric b35abffd1b Fix a crash with the chart editor. 2025-02-25 23:42:20 -05:00
Lasercar 07c872c775 A fix for a thing 2025-02-26 01:02:42 +10:00
ember / mintandGitHub 4891e54586 hotfix: missing https in Dockerfile build (caused by #870) (#871) 2025-02-24 18:52:17 +01:00
anaandCameron Taylor a31257f10f is this a fastly problem? 2025-02-24 12:40:27 -05:00
anaandCameron Taylor 5329a17439 hardcode download urls for now? 2025-02-24 12:40:27 -05:00
anaandCameron Taylor 3975c4fa78 chore: enable curl debug logs 2025-02-24 12:40:27 -05:00
anaandCameron Taylor 04185e150c chore: update build deps 2025-02-24 12:40:27 -05:00
anaandCameron Taylor 5e02db372d fix: build_defines not being read by CI task 2025-02-24 12:40:27 -05:00
HundrecandEric bd3acc319c Remove issue reopening action 2025-02-22 23:28:23 -05:00
Cameron TaylorandEric cde7382713 tidy up settings.json via lime.buildTypes 2025-02-21 22:53:48 -05:00
EliteMasterEricandCameron Taylor 44337a6b81 Make the game more lenient with loading older data from mods, as long it's compatible. 2025-02-21 16:58:51 -05:00
EliteMasterEricandCameron Taylor e610b7624c Fix a build issue with DiscordClient 2025-02-21 16:58:50 -05:00
Cameron Taylor e6aadf9a31 Merge branch 'bugfix/chart-issues-fixes' into rewrite/master 2025-02-21 16:45:16 -05:00
Cameron TaylorandEric f6caa9b67b update FlxPartialSound w/ better ogg streaming 2025-02-20 19:38:46 -05:00
EliteMasterEric 838f7b0125 Make several tweaks to existing charts 2025-02-18 15:51:14 -05:00
EliteMasterEricandCameron Taylor a411ce13c1 Update flixel haxelib 2025-02-18 13:38:20 -05:00
EliteMasterEricandCameron Taylor e07c4487b9 Removed commented code snippet 2025-02-18 13:38:20 -05:00
EliteMasterEricandCameron Taylor 6061c7762e Resolve issues caused by updating Flixel to latest 2025-02-18 13:38:20 -05:00
Cameron Taylor bda3ab1192 update to latest upstream flixel + flixel-addon + flxanimate 2025-02-18 13:38:20 -05:00
AbnormalandEric 5054c58dca set the default to 1 2025-02-18 13:24:25 -05:00
AbnormalandEric de02137d7c Add the ability to flip the character in the Animation Editor 2025-02-17 23:32:49 -05:00
AbnormalandEric 128afcaad1 quick fixin 2025-02-17 23:28:38 -05:00
AbnormalandEric f6d9d29181 add angle too bc why not 2025-02-17 23:28:38 -05:00
AbnormalandEric ff56b1948a add scrollfactor and alpha + grammatical fix in StageData 2025-02-17 23:28:38 -05:00
EliteMasterEric 87b1fc92f8 Renamed the new controls (I had to edit the margins to make the name fit) 2025-02-17 23:25:09 -05:00
AbnormalandEric bb974c2642 home and end can now jump to the beginning and end of freeplay 2025-02-17 23:25:09 -05:00
AbnormalandEric 0e0c4aeb77 fix: Fix the instrumental selector still allowing inputs after a song is selected 2025-02-17 22:36:49 -05:00
AbnormalandEric 3492d412c6 Blacklist SharedObject 2025-02-17 22:00:08 -05:00
AbnormalandEric b13bf05d16 fix: Fix the difficulty graphic in the Result Screen cutting off 2025-02-17 21:56:22 -05:00
AbnormalandEric 36df61ba9e the checkbox is now grouped together with the rest 2025-02-17 21:29:18 -05:00
AbnormalandEric ee53ccd327 feat: Add a setting that automatically launches the game in fullscreen 2025-02-17 21:29:18 -05:00
AbnormalandEric 7058126e99 fix: Actually check if the Playable Character is unlocked 2025-02-17 21:26:16 -05:00
AbnormalandEric 06c12e36c6 Revert "blacklist one additional class"
This reverts commit 3267c61258.
2025-02-17 20:36:36 -05:00
AbnormalandEric c06d79441d Add comments to 3 functions in funkin.Assets 2025-02-17 20:33:40 -05:00
Cameron Taylor 0a911ae607 remove a buncho unused imports 2025-02-17 19:25:33 -05:00
Cameron Taylor 13fb02599b Merge branch 'nene-abot-sync' into rewrite/master 2025-02-17 19:25:00 -05:00
Cameron Taylor 2a3cf4a211 assets submod 2025-02-17 19:22:43 -05:00
Cameron Taylor 2a2e36a713 Merge branch 'feature/week-6-pico-dialogue' into rewrite/master 2025-02-17 19:12:08 -05:00
EliteMasterEricandCameron Taylor 43d109df55 Implement Pico and Nene portraits 2025-02-17 19:11:19 -05:00
Cameron Taylor 4223b1d5ec Merge branch 'week6-pico-death' into rewrite/master 2025-02-17 11:42:02 -05:00
fabsandCameron Taylor 72730b67f1 assets submod 2025-02-17 11:38:55 -05:00
EliteMasterEricandCameron Taylor 3cdaf2c543 First draft of changelog. 2025-02-17 11:08:35 -05:00
EliteMasterEricandCameron Taylor eaff62baf5 Update to latestest haxeui-core and haxeui-flixel 2025-02-17 10:29:41 -05:00
EliteMasterEricandCameron Taylor 103a705e24 Update hxvlc to the latest version 2025-02-17 10:24:50 -05:00
HundrecandEric 894d0743c9 Table of Contents for CONTRIBUTING.md 2025-02-16 21:36:59 -05:00
EliteMasterEricandCameron Taylor 482530c569 Update flixel-addons to include changes from main 2025-02-16 18:36:39 -05:00
AbnormalandEric 6795c33980 remove leftover legacy code 2025-02-16 04:08:15 -05:00
AbnormalandEric 6466b88d88 a -> an 2025-02-14 18:15:59 -05:00
AbnormalandEric 9b774e3264 format a few files 2025-02-14 18:13:05 -05:00
MidyGamyandEric 33f943a672 More dump save info + force crash now accurate 2025-02-14 18:10:01 -05:00
MidyGamyandEric f5efc16611 Rewording missing Funkin' Debug Hotkeys.md (thx Hundrec) 2025-02-14 18:10:01 -05:00
MidyGamyandEric 7e820f9497 Added missing debug hotkeys 2025-02-14 18:10:01 -05:00
MrScottyPieeyandEric f3ea19ec31 Update Main.hx 2025-02-14 18:05:41 -05:00
HundrecandEric 40d2a892a9 adjust link in PR Template 2025-02-13 21:23:29 -05:00
HundrecandEric b4a477e800 PR Template 2025-02-13 21:23:29 -05:00
HundrecandEric 54ddb652b6 Enhancement Template 2025-02-13 21:23:29 -05:00
HundrecandEric 7cb9eb797a Crash Template 2025-02-13 21:23:29 -05:00
HundrecandEric 422feb2c6d Compiling Help Template 2025-02-13 21:23:29 -05:00
HundrecandEric f7df118b7b Charting Template 2025-02-13 21:23:29 -05:00
HundrecandEric 02a1af6fd9 Revert spacing 2025-02-13 21:23:29 -05:00
HundrecandEric 87fe63af5e A lil spacing 2025-02-13 21:23:29 -05:00
HundrecandEric 7ebf4a4558 Fix Contributing link 2025-02-13 21:23:29 -05:00
HundrecandEric 74cd7c3353 quote 2025-02-13 21:23:29 -05:00
HundrecandEric 5f80641d5f Contributing Guide in Minor Bug Template 2025-02-13 21:23:29 -05:00
HundrecandEric ba6461e249 Link CONTRIBUTING.md in README 2025-02-13 21:23:29 -05:00
HundrecandEric 24a97524ac Add more console outputs to Troubleshooting Guide
Includes a line about warnings and deprecated functions, as well as a line about the hxcpp prompt.
2025-02-13 21:23:29 -05:00
09c2d21111 Contributor's guide
Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-02-13 21:23:29 -05:00
HundrecandEric 07b6d8f86f adjust link in PR Template 2025-02-13 21:23:18 -05:00
HundrecandEric 8126cca29b PR Template 2025-02-13 21:23:18 -05:00
HundrecandEric ba78ded457 Enhancement Template 2025-02-13 21:23:18 -05:00
HundrecandEric bda5d90bbc Crash Template 2025-02-13 21:23:18 -05:00
HundrecandEric a9d0c1cb88 Compiling Help Template 2025-02-13 21:23:18 -05:00
HundrecandEric f8f533ad37 Charting Template 2025-02-13 21:23:18 -05:00
HundrecandEric 0bc0ab4eec Revert spacing 2025-02-13 21:23:18 -05:00
HundrecandEric d11027fb08 A lil spacing 2025-02-13 21:23:18 -05:00
HundrecandEric 7b9e375fea Fix Contributing link 2025-02-13 21:23:18 -05:00
HundrecandEric dd215687d4 quote 2025-02-13 21:23:18 -05:00
HundrecandEric e3eddc892d Contributing Guide in Minor Bug Template 2025-02-13 21:23:18 -05:00
HundrecandEric 36fd05b1f9 Link CONTRIBUTING.md in README 2025-02-13 21:23:18 -05:00
HundrecandEric c6ef9b17a2 Add more console outputs to Troubleshooting Guide
Includes a line about warnings and deprecated functions, as well as a line about the hxcpp prompt.
2025-02-13 19:04:07 -05:00
943c38767b Contributor's guide
Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-02-13 19:01:55 -05:00
Cameron Taylor c83d2bbc69 Merge branch 'bugfix/week7-shaders-web' into rewrite/master 2025-02-12 14:31:32 -05:00
fabsandCameron Taylor cbcf3e2754 assets submod 2025-02-12 14:21:46 -05:00
Cameron Taylor 34c67fdb54 fix(debug): pressing H on pause screen removes the 'background' sprite properly as well now 2025-02-12 14:11:18 -05:00
EliteMasterEricandCameron Taylor 731f38a2bb Fix a bug with strum backgrounds when setting strumline.alpha (thanks QT:RW!) 2025-02-12 14:10:38 -05:00
EliteMasterEricandCameron Taylor a8b854a807 Fix looping death animation for Stress Pico 2025-02-12 14:02:05 -05:00
fabs 9bc217d3f5 add web support for altMaskImage 2025-02-12 01:51:19 +00:00
fabs 11d6c0bc88 add web support to swappedImage 2025-02-12 01:51:09 +00:00
fabsandCameron Taylor 072264dce5 assets submod
fixup! assets submod

Merge branch 'senpai-angry-icon' into rewrite/master

assets submod

update assets submod
2025-02-07 19:41:35 -05:00
Cameron Taylor 265d3808e5 fixup! assets submod 2025-02-07 14:29:38 -05:00
Cameron Taylor 609812a4a1 assets submod 2025-02-07 14:26:06 -05:00
fabsandEric f48deb1ade update assets submod 2025-02-07 12:51:05 -05:00
EliteMasterEric 06f6a4a42c Update asset submodule 2025-02-07 12:51:05 -05:00
EliteMasterEric da4af6198d Set the damn version number already! 2025-02-07 12:51:05 -05:00
fabsandEric 557f9800f2 add tankman-bloody to the valid pixel icons 2025-02-07 12:51:05 -05:00
fabsandEric 0a7a73388e assets submod 2025-02-07 12:51:05 -05:00
fabsandEric 9923e29901 wip drop shadow/rimlight shader 2025-02-07 12:51:05 -05:00
EliteMasterEric 58758b1d6a Remove new labels from older songs 2025-02-07 08:33:16 -05:00
fabsandEric a07cb7ba32 assets submod 2025-02-07 08:33:16 -05:00
fabsandEric 58ea0287d3 disable pixel perfect rendering on sprites 2025-02-07 08:33:16 -05:00
fabsandEric 60b1b9aa1f fixed pixel vis positions 2025-02-07 08:33:16 -05:00
EricandGitHub 6f40aeac1c Merge pull request #4106 from FunkinCrew/main
Merge from main into develop
2025-02-05 05:51:43 -05:00
EricandGitHub ca16d41592 Merge pull request #4100 from Lasercar/update-art-submodule
Update art submodule commit version
2025-02-04 05:23:10 -05:00
Lasercar 72b06b4a81 update art submodule 2025-02-04 19:43:47 +10:00
Cameron Taylor e59ca3080c assets submod 2025-02-03 18:37:54 -05:00
EliteMasterEricandCameron Taylor 4f12cc4efa Rebalance song difficulty rankings 2025-02-03 18:37:54 -05:00
EricandGitHub 796cbb3812 Merge pull request #4095 from AbnormalPoof/main-to-develop
Move changes from `main` to `develop`
2025-02-03 18:24:40 -05:00
AbnormalandGitHub 246de95e46 Merge branch 'develop' into main-to-develop 2025-02-03 23:22:56 +00:00
Cameron Taylor fdb4ad11ab fixup! fixup! Implement Week 6 characters, and pixel A-Bot visualizer. 2025-02-03 18:21:07 -05:00
Cameron Taylor d1c87febae fixup! Implement Week 6 characters, and pixel A-Bot visualizer. 2025-02-03 18:21:07 -05:00
EliteMasterEricandCameron Taylor 7100ff0ba3 Implement Week 6 characters, and pixel A-Bot visualizer. 2025-02-03 18:21:07 -05:00
EliteMasterEricandCameron Taylor b5bb09a2f7 Add .git folders to Polymod ignore list. 2025-02-03 18:21:07 -05:00
EliteMasterEricandCameron Taylor ea2d45e6c9 Fix some warnings/crashes in Week 6
assets submod
2025-01-28 16:39:00 -05:00
EliteMasterEricandCameron Taylor d9fd814645 Disable swapping out freeplay graphics until we get it fixed up. 2025-01-28 16:39:00 -05:00
fabsandCameron Taylor 019a6ed25b Merge pull request #841 from FunkinCrew/public-develop
More public contributions
2025-01-28 16:39:00 -05:00
fabs db39b19e79 resolved merge conflicts with ReflectUtil 2025-01-27 22:36:43 +00:00
fabs a6388962dd Merge branch 'public-develop' into rewrite/master 2025-01-27 22:31:38 +00:00
HundrecandGitHub df142a9144 [GITHUB] Add Links to Guides in Issue Templates (#4053)
* Issues Guide in bug template

* Issues Guide in charting template

* Guide links in compiling template

* Issues Guide in crash template

* Issues Guide in enhancement template
2025-01-27 13:37:42 -05:00
47e320e96f [GITHUB] Add status: pending triage to all PRs (#4035)
* Add `status: pending triage` to all PRs

* Update label-pull-request.yml

* now size and pr labels can be updated every commit!

* remove this

* move the pending triage thing to a new workflow

* Rename label-pr-on-create.yml to label-pull-request-on-create.yml

* fix the identation on this

* almost forgot to remove this

---------

Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
2025-01-27 13:37:27 -05:00
HundrecandGitHub 0c06ba942e Add needs r&d label to unlabel list (#4034) 2025-01-24 18:21:34 -05:00
EliteMasterEric 5e939bd769 Fix more build issues. 2025-01-23 19:19:05 -05:00
EliteMasterEric 0b309403e0 Fix compile error 2025-01-23 18:22:58 -05:00
EliteMasterEric c232224f04 Added more functions to ReflectUtil, and made it so importing Reflect imports it instead of throwing an error. 2025-01-23 18:16:30 -05:00
EliteMasterEric 526f326323 Use the bound BACK key to quit the game from Title rather than hardcoding to ESC. 2025-01-23 17:29:02 -05:00
EliteMasterEric 0b0556a8b0 Merge remote-tracking branch 'public/main' into public-develop 2025-01-23 17:27:32 -05:00
AbnormalandGitHub 62166554e7 Add 6 more functions to ReflectUtil (#4019) 2025-01-23 17:21:46 -05:00
lemzandGitHub a01bcc3da8 change ui controls order (#3027)
a lot of squashed stuff
2025-01-23 16:32:35 -05:00
AbnormalandGitHub 7e0f4d9c84 Update labeler workflow (#4023) 2025-01-23 16:19:58 -05:00
HundrecandGitHub 2adae38805 Update Contributing section in README (#4026) 2025-01-23 16:18:37 -05:00
HundrecandGitHub 981aad214f Change size label names in PR labeler (#3918) 2025-01-22 23:31:59 -05:00
HundrecandGitHub 48a72ce32c Add status: stale to auto-close (#4017) 2025-01-22 21:27:36 -05:00
dfe02ec668 check if the vocal files actually exist (#3861)
Co-authored-by: Kolo <67389779+JustKolosaki@users.noreply.github.com>
2025-01-17 15:52:02 -05:00
AbnormalandGitHub a3e23733db fix early return in hasbeatensong and hasbeatenlevel (#3820) 2025-01-17 15:49:21 -05:00
SincoandGitHub 1c12b8467e Mouse cursor is no longer visible outside of the ingame editors (#3881) 2025-01-17 15:48:06 -05:00
AbnormalandGitHub ad45b72b1a Update Constants.hx (#3853) 2025-01-17 15:45:01 -05:00
KadeandGitHub 785c4be88b [ENHANCEMENT] [MODDING] Several QOL modding changes (#4009)
* Custom render distance strumline

* Custom note positions

* Custom vertices for holds

* Song Retry Event

Song retry event for pausesubstate.hx
Song retry event for playstate.hx
Song retry event for stage.hx
Song retry event for bopper.hx
Song retry event for song.hx
Scripted class event
Module event

* this should be cast

* Show notesplash toggle

* Formatting and EOF
2025-01-17 15:37:00 -05:00
TilandGitHub 22d41d21b8 i think this does it (#3955) 2025-01-17 15:33:16 -05:00
AbnormalandGitHub 69d8570a9e [ENHANCEMENT] Add offsets support for Album titles (#3618)
* add album title offsets

* cleanup

* cleanup

* fix inconsistency
2025-01-17 15:32:03 -05:00
anysadandGitHub a17b0e8b3c [ENHANCEMENT] Preference Descriptions + Other Tweaks (#3872)
* updated preference menu

* update comment
2025-01-17 14:47:47 -05:00
AbnormalandGitHub e73be4a2b3 Update ReflectUtil.hx (#4008) 2025-01-17 14:46:53 -05:00
AbnormalandCameron Taylor c38967b501 [ENHANCEMENT] Add Script Events for losing/gaining focus (#3721)
* add events for focus gain/lost

* add callbacks

* move the events to a new interface

* Ok NOW it works

* the event can now longer be canceled
2025-01-17 12:17:48 -05:00
MrMaderaandCameron Taylor 95f46d01ce added gamepad binds (#3934) 2025-01-17 12:17:48 -05:00
AbnormalandCameron Taylor 8188b19622 more reflectutil additions (#3809) 2025-01-17 12:17:48 -05:00
AbnormalandCameron Taylor 250f01f207 add setField (#3622) 2025-01-17 12:17:48 -05:00
8014302d58 Move changes made in main to develop (#4006)
* Rewrite CHANGELOG.md for v0.5.2

* [docs] Add missing changes and links to Changelog (#3655)

* changelog sweep

* Resolve a few conflicts

* Resolve more conflicts

* DadBattle

* Re-add @ianharrigan

* Add links to 0.5.0

* Add links and contributors to 0.4.1 and 0.4.0

* Add links to 0.3.3 and finishing touches

* Add and polish 0.5.3 changes

* Make spacing consistent

* Make label actions more convenient (#3771)

* fixed a plethora of dead links (#3831)

* Add `status: planned` label to label actions (#3910)

* Make label actions more convenient

* chore: Add status: planned to label actions

* Bump the Stage data version to indicate that new values were added.

* Updated Save data version to indicate new values.

* Only display the Stage Editor in builds that enable it, and enable it by default (this re-enables the Stage Editor keybind).

* Enable log messages on all builds by default after we got too many complaints.

* Remove unused custom type resolver.

* Update save data format and error handling.

* Fix a typo.

* proj hxp version bump

* changelog yoink

* Remove duplicate issue detector. (#3944)

---------

Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
Co-authored-by: Cameron Taylor <cameron.taylor.ninja@gmail.com>
2025-01-17 12:17:48 -05:00
TilandCameron Taylor 19023645df use event.isComboBreak instead of isComboBreak (#3936) 2025-01-17 12:17:48 -05:00
AbnormalandCameron Taylor a98f680f8f Update PolymodHandler.hx (#3993) 2025-01-17 12:17:48 -05:00
AbnormalandGitHub 4b127b6413 [ENHANCEMENT] Add Script Events for losing/gaining focus (#3721)
* add events for focus gain/lost

* add callbacks

* move the events to a new interface

* Ok NOW it works

* the event can now longer be canceled
2025-01-16 20:25:19 -05:00
MrMaderaandGitHub 2b7f62edd3 added gamepad binds (#3934) 2025-01-16 20:23:29 -05:00
AbnormalandGitHub b5d95d59ff more reflectutil additions (#3809) 2025-01-16 20:13:59 -05:00
AbnormalandGitHub 9f23a7c54c add setField (#3622) 2025-01-16 20:13:40 -05:00
JVN-PixelsandGitHub 5d5d12dbfd [ENHANCEMENT]: Compiling Error Issue Template (#3835)
* Create compiling.yml

* Update compiling.yml

* Update compiling.yml

* Update compiling.yml

* Update compiling.yml

* Update compiling.yml

* charting (Hundrec)

thanks hundrec i like this

* Delete .github/ISSUE_TEMPLATE/charting.yml
2025-01-16 20:05:37 -05:00
HundrecandGitHub c3a188b357 [GITHUB] Create a dedicated charting issue template (and bump version to 0.5.3) (#3834)
* Create Charting Issue template

* Include images and videos in charting issue template

* Update version in bug report template

* Update version in crash report template
2025-01-16 20:02:59 -05:00
UltimateQuackandGitHub bc521b7e7f "Fixed" the Apache 2.0 LICENSE file part (#3843)
very simple
2025-01-16 19:51:15 -05:00
a08da8793b Move changes made in main to develop (#4006)
* Rewrite CHANGELOG.md for v0.5.2

* [docs] Add missing changes and links to Changelog (#3655)

* changelog sweep

* Resolve a few conflicts

* Resolve more conflicts

* DadBattle

* Re-add @ianharrigan

* Add links to 0.5.0

* Add links and contributors to 0.4.1 and 0.4.0

* Add links to 0.3.3 and finishing touches

* Add and polish 0.5.3 changes

* Make spacing consistent

* Make label actions more convenient (#3771)

* fixed a plethora of dead links (#3831)

* Add `status: planned` label to label actions (#3910)

* Make label actions more convenient

* chore: Add status: planned to label actions

* Bump the Stage data version to indicate that new values were added.

* Updated Save data version to indicate new values.

* Only display the Stage Editor in builds that enable it, and enable it by default (this re-enables the Stage Editor keybind).

* Enable log messages on all builds by default after we got too many complaints.

* Remove unused custom type resolver.

* Update save data format and error handling.

* Fix a typo.

* proj hxp version bump

* changelog yoink

* Remove duplicate issue detector. (#3944)

---------

Co-authored-by: Hundrec <hundrecard@gmail.com>
Co-authored-by: Abnormal <86753001+AbnormalPoof@users.noreply.github.com>
Co-authored-by: Cameron Taylor <cameron.taylor.ninja@gmail.com>
2025-01-16 19:50:07 -05:00
EricandGitHub cb131d8c9d Merge branch 'develop' into main 2025-01-16 19:49:59 -05:00
TilandGitHub 3aad825f86 use event.isComboBreak instead of isComboBreak (#3936) 2025-01-16 19:41:04 -05:00
AbnormalandGitHub 1c2fb43ae1 Update PolymodHandler.hx (#3993) 2025-01-16 19:40:22 -05:00
mintandEric 3305e3099b [docker rebuild] update ci change detector to trigger on force-push & manual requests using commit message 2025-01-16 14:37:18 -05:00
EliteMasterEric 4554487ded Fix a build issue with HTML5 2025-01-16 14:37:18 -05:00
EliteMasterEric a0ce19f1e0 Update Lime commit again 2025-01-15 17:46:11 -05:00
EliteMasterEric 12ed07b074 Update commit hash again. 2025-01-15 17:46:11 -05:00
EliteMasterEric 6aa57a22de Update lime commit. 2025-01-15 17:46:11 -05:00
Cameron TaylorandEric d294eb170d point towards big lime merge crap 2025-01-15 17:46:11 -05:00
EliteMasterEricandCameron Taylor 04a7007f6e Move Tracy debug message into trace() 2025-01-13 14:33:21 -05:00
Cameron Taylor bdcd7b8a91 Merge branch 'feature/swap-freeplay-graphic' into rewrite/master 2025-01-10 22:46:06 -05:00
Cameron Taylor 1f5b1ad025 assets submod 2025-01-10 22:45:58 -05:00
EliteMasterEricandCameron Taylor c4749636d3 Fix some variable naming issues caused by HaxeUI (Ideally revert this in the future) 2025-01-06 22:32:12 -08:00
EliteMasterEricandCameron Taylor 533876680b Update HaxeUI to the latest commits. 2025-01-06 22:32:12 -08:00
EliteMasterEricandCameron Taylor 43e55ccee0 Use full commit ID for Newgrounds 2025-01-06 22:32:12 -08:00
EliteMasterEricandCameron Taylor 17bb2d23ba Update flxanimate 2025-01-06 22:32:12 -08:00
EricandCameron Taylor f3ff8279c0 Update additional haxelibs 2025-01-06 22:29:31 -08:00
EliteMasterEricandCameron Taylor 1dd97ff9e2 Replace hxCodec with hxVLC 2025-01-06 22:29:31 -08:00
EliteMasterEricandCameron Taylor 9863206fad Fix medal bug, and add v0.6 songs for web. 2025-01-06 15:54:45 -08:00
EliteMasterEricandCameron Taylor 4813e6f476 Fix crash when medal data fails to load. 2025-01-06 15:54:45 -08:00
EliteMasterEricandCameron Taylor 69cca7e97b Add four new songs. 2025-01-06 15:54:44 -08:00
Cameron Taylor f4d4b67df4 fix: remove controls on results screen that allowed moving the results text 2024-12-19 18:33:22 -05:00
Cameron TaylorandEric a5a5382a60 fix: fix A-Bot bars to display no volume, rather than 1 single bar, on no input 2024-12-18 12:08:14 -05:00
Cameron TaylorandEric 69b7bcb58b fix: tweaks to A-Bot to fine tune his visuals 2024-12-18 12:08:14 -05:00
Cameron TaylorandEric e0738e0674 chore: create a dedicated tracy build directory when compiling with tracy 2024-12-18 11:20:48 -05:00
Cameron TaylorandEric 8e7fc52712 fix: pico/nene have proper positions on xmas stages 2024-12-18 11:12:44 -05:00
EricandGitHub bb24821f13 Remove duplicate issue detector. (#3944) 2024-12-18 10:44:01 -05:00
EricandGitHub 57870bf8c5 Merge pull request #828 from FunkinCrew/ninjamuffin99/funk-1158
fix: remove the input delay on pause menu, allowing for inputs immedi…
2024-12-18 10:32:26 -05:00
EricandGitHub 1274986f7d Merge branch 'rewrite/master' into ninjamuffin99/funk-1158 2024-12-18 10:26:33 -05:00
EricandGitHub 6e1eb2c8dd Merge pull request #831 from FunkinCrew/high-dpi
fix: explicitly allow high DPI
2024-12-18 10:26:09 -05:00
EricandGitHub e69d58d0fd Merge branch 'rewrite/master' into high-dpi 2024-12-18 10:14:14 -05:00
EliteMasterEric 0ea4320dfb Update assets submodule to add additional freeplay backgrounds. 2024-12-17 12:54:44 -05:00
EliteMasterEric eafa3db1b5 Fix asset fallback. 2024-12-17 12:54:31 -05:00
EliteMasterEric e0911b2861 Implemented hot swapping the backing image. 2024-12-17 10:41:01 -05:00
EliteMasterEric 6efd8b122f Fix an issue with the medal entry sound 2024-12-17 10:38:00 -05:00
Cameron Taylor f8cf32e0a9 feat: MERCH link on main menu is now fetched via NG api 2024-12-13 14:53:50 -05:00
Cameron Taylor 02de1c43e2 fix: explicitly allow high DPI 2024-12-10 18:02:53 -05:00
mintandCameron Taylor 5df14f76fe rework the game build as a multijob workflow 2024-12-10 17:29:50 -05:00
mintandCameron Taylor 0513ac60cf compare against current branch not master 2024-12-10 17:29:50 -05:00
mintandCameron Taylor 83b1333191 typo in docker workflow file 2024-12-10 17:29:50 -05:00
mintandCameron Taylor 56c94bee31 always run docker rebuild task check 2024-12-10 17:29:50 -05:00
mintandCameron Taylor 0eb1223202 task dependencies test 2024-12-10 17:29:50 -05:00
mintandCameron Taylor da558ddaa2 move ubuntu 23.10 -> 24.04 2024-12-10 17:29:50 -05:00
Cameron Taylor be3fe9028a fix: remove the input delay on pause menu, allowing for inputs immediately when opening the pause menu 2024-12-08 20:37:46 -05:00
Kolo 71ed154b81 fix that one annoying ass bug for events 2024-12-05 22:24:49 +01:00
EliteMasterEricandCameron Taylor c0c5fa4617 Update assets submodule 2024-12-02 15:07:56 -05:00
Cameron Taylor 769707e54a remove trace() call when getting song scores 2024-11-26 16:09:39 -05:00
Cameron Taylor 76bedb8079 some random hxformat crap fixes in Stage.hx 2024-11-26 16:08:45 -05:00
Cameron Taylor 1612005656 fix: volume properly muted when at 0 2024-11-26 15:56:22 -05:00
Cameron Taylor a5cee7c5ad update/merge latest changes from upstream openfl (and update our hmm.json here) 2024-11-26 15:49:22 -05:00
c6d5bda802 feat: Added non-naughty Perfect results screen animation for Boyfriend (#821)
* change result state stuff

* add more fields

* change testing

* assets submod

---------

Co-authored-by: Cameron Taylor <cameron.taylor.ninja@gmail.com>
2024-11-26 15:39:12 -05:00
Cameron Taylor a9f6521b0e fuck it turn on compilation server? 2024-11-24 21:29:27 -05:00
EliteMasterEricandCameron Taylor e3b1a7d850 Update assets submodule 2024-11-24 21:07:20 -05:00
EliteMasterEricandCameron Taylor 2143792369 Fix an issue with setting music.asset to "" 2024-11-24 21:07:00 -05:00
Cameron Taylor 7456b5c4fd assets submod rebase/merge 2024-11-23 15:22:38 -05:00
CheemsAndFriendsandCameron Taylor cba2caa78b fix idle easter egg freeplay 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor 490760caa0 fix the ignore in the ignore 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor b28b1d8810 Fix middle click funky stuff 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor ef44bda9da fix album popping prematurely 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor 90f6eac3fa add -hold animations 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor 6851cfc8aa fix album random issue 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor a1cf76e89c Fix easter egg idle and cartoon to play as intended 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor 1ac91b35ca Bump funkin.vis version 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor 6d48de2107 Readd blood extension 2024-11-23 15:21:28 -05:00
CheemsAndFriendsandCameron Taylor fcb48ea52f Remove traces 2024-11-23 15:20:30 -05:00
CheemsAndFriendsandCameron Taylor 3d5e91f455 Fix blazin issue and holds not playing properly 2024-11-23 15:20:30 -05:00
CheemsAndFriendsandCameron Taylor 61639e5b51 fix isAnimationFinished 2024-11-23 15:19:59 -05:00
CheemsAndFriendsandCameron Taylor d3c001c673 Trying to fix blazin issues 2024-11-23 15:19:57 -05:00
CheemsAndFriendsandCameron Taylor 65dc9d487d conditional for release with debug functions 2024-11-23 15:19:48 -05:00
EliteMasterEricandCameron Taylor 1212c694e8 Add a new option to put a transparent background on the strumline 2024-11-23 14:42:46 -05:00
EliteMasterEricandCameron Taylor b7f2112c60 feat: Add alternate sticker set, and sticker pack swapping. 2024-11-14 22:25:44 -05:00
Cameron Taylor a356e6e520 properly persist medal icons across states 2024-11-14 17:24:39 -05:00
Cameron Taylor 71d0d38190 unlock the NG medal only once you've pressed ENTER on title screen, rather than when game boots, so that it feels like a player unlocks a medal from input, rather than random automatically 2024-11-14 17:24:39 -05:00
CheemsAndFriendsandCameron Taylor 673b4f8a6b Implement StartGame and FridayNight 2024-11-14 17:24:39 -05:00
EliteMasterEricandCameron Taylor 2ade41f152 assets submod update for community PRs 2024-11-11 18:47:46 -05:00
Cameron Taylor d64cf595d6 secret repo gitmodules 2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor e974718947 Disallow scripts from messing with medals.
Some cleanup and readd support for fetching URLs on web builds.

Link the missing medals

base64 medal stuff, and some debug crap

remove trace crap

update assets stuff

assets stuff

newgrounds username on titlescreen and replace things with NG.core instead of our own client singleton
2024-11-04 15:05:33 -05:00
CheemsAndFriendsandCameron Taylor 97da5f0122 bump flxanimate
NewgroundsCredentials.hx add to gitignore

hardcode images
2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor 00be427794 Display medal popup only if medal isn't unlocked.
change art stuff
2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor 775904a7c0 Use public medal IDs on release builds. 2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor aa08dcfbbc Specify credentials via -DAPI_NG_APP_ID=value and -DAPI_NG_ENC_KEY=value at build time 2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor b75a550c5b Nice little login prompt for desktop users. Scores/medals work nicely 2024-11-04 15:05:33 -05:00
CheemsAndFriendsandCameron Taylor df094f15cf Medal stuff 2024-11-04 15:05:33 -05:00
EliteMasterEricandCameron Taylor e9e639500a Newly revamped Newgrounds integration, with working medals and leaderboards 2024-11-04 15:05:33 -05:00
EricandGitHub 8cad041035 Merge pull request #812 from FunkinCrew/hmm-macos15-fix
openfl, lime, and hxcpp hmm update
2024-11-01 18:18:48 -04:00
Cameron Taylor 0fd8624483 fix: fix the edges of sprites appearing darker with the adjustColor shader 2024-11-01 16:29:38 -04:00
Cameron Taylor 9cf808b5d3 lime commit fixie 2024-11-01 16:19:04 -04:00
Cameron Taylor 3362f0bdd0 openfl, lime, and hxcpp hmm update 2024-11-01 15:28:14 -04:00
Cameron TaylorandGitHub 97c3114200 Merge pull request #811 from FunkinCrew/public-release/develop
fix: re-enable precise chart editor scrolling, and also fix smooth sc…
2024-10-30 13:15:04 -04:00
Cameron TaylorandGitHub 0d8e4a5330 fix: re-enable precise chart editor scrolling, and also fix smooth scroll playhead/playbar playback (#3806) 2024-10-30 12:41:28 -04:00
Cameron Taylor 6321983eba assets submod 2024-10-28 14:27:00 -04:00
Cameron Taylor 101b9f59b3 assets submod 2024-10-28 14:24:30 -04:00
KeoikiandGitHub e570dfb8e7 fix: Fix beat/step ticks sometimes not appearing on non-4/4 time signatures in chart editor (#2860)
Beat and step ticks now appear fully on 5/4, 6/4 and 9/8 time signatures.
2024-10-26 16:11:49 -04:00
Hyper_andGitHub e6b6b41766 revert: "[BUGFIX?] Reset CWD before Preloader" (#3538) 2024-10-26 16:03:42 -04:00
Cameron Taylor 090ddd1f1c fix: fixes the initial camera position on the debug menu 2024-10-26 15:59:13 -04:00
AbnormalandGitHub 76c8c8b520 docs: Fix a 'ludem' -> 'ludum' typo in CHANGELOG.md 2024-10-26 15:58:12 -04:00
Cameron Taylor 20d9016984 feat: Added smoother scrolling when using the Chart Editor
smoother drag / movement in chart editor

playbarHead movement fixie
2024-10-26 15:54:15 -04:00
Cameron Taylor 144ba00377 refactor: remove commented out code from draw() in PlayState.hx 2024-10-26 15:53:22 -04:00
Cameron Taylor 7159cad2c1 style: remove a buncho unused imports from PlayState.hx 2024-10-26 15:51:38 -04:00
EricandGitHub 62de2a0345 ...sandwiches. 2024-10-23 13:40:35 -04:00
EricandGitHub 8cf346c3b0 Update CHANGELOG.md 2024-10-22 20:36:10 -04:00
Cameron Taylor a0cefba9fd changelog yoink 2024-10-22 12:14:14 -04:00
Cameron Taylor f46f57e23d proj hxp version bump 2024-10-18 19:51:06 -04:00
EliteMasterEricandCameron Taylor 5819a43522 Fix a typo. 2024-10-18 19:11:27 -04:00
EliteMasterEricandCameron Taylor dff4135fc9 Update save data format and error handling. 2024-10-18 19:11:27 -04:00
EliteMasterEricandCameron Taylor 24ad7f4a39 Remove unused custom type resolver. 2024-10-18 19:11:27 -04:00
EliteMasterEricandCameron Taylor 4dbb0baa17 Enable log messages on all builds by default after we got too many complaints. 2024-10-18 19:11:27 -04:00
EliteMasterEricandCameron Taylor ce85ee20a7 Only display the Stage Editor in builds that enable it, and enable it by default (this re-enables the Stage Editor keybind). 2024-10-18 19:11:27 -04:00
EliteMasterEricandCameron Taylor 4effd709eb Updated Save data version to indicate new values. 2024-10-18 19:11:27 -04:00
EliteMasterEric 55c2dabe84 Bump the Stage data version to indicate that new values were added. 2024-10-11 23:44:31 -04:00
283 changed files with 11017 additions and 5780 deletions
+10 -6
View File
@@ -3,13 +3,17 @@ description: Report a bug or an issue in the game.
labels: ["type: minor bug", "status: pending triage"]
title: "Bug Report: "
body:
- type: markdown
attributes:
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
- type: checkboxes
attributes:
label: Issue Checklist
description: Be sure to complete these steps to increase the chances of your issue being addressed!
options:
- label: I have properly named my issue
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- type: dropdown
attributes:
@@ -40,11 +44,11 @@ body:
- type: input
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.5.0
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.6.3
validations:
required: true
- type: markdown
attributes:
value: "## Describe your bug."
@@ -56,11 +60,11 @@ body:
- type: textarea
attributes:
label: Description (include any images, videos, errors, or crash logs)
description: Provide as much detail as you can. The better others understand your issue, the more they can help you!
description: Provide as much detail as you can. The better others understand your issue, the more they can help you!
placeholder: Describe your issue here...
validations:
required: true
- type: textarea
attributes:
label: Steps to Reproduce
+75
View File
@@ -0,0 +1,75 @@
name: Charting Issue
description: Report an issue with the placement of notes in the game.
labels: ["type: charting issue", "status: pending triage"]
title: "Charting Issue: "
body:
- type: markdown
attributes:
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
- type: checkboxes
attributes:
label: Issue Checklist
description: Be sure to complete these steps to increase the chances of your issue being addressed!
options:
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- type: dropdown
attributes:
label: Platform
description: Which platform are you playing on?
options:
- Newgrounds (Web/HTML5)
- Itch.io (Web/HTML5)
- Itch.io (Downloadable Build) - Windows
- Itch.io (Downloadable Build) - MacOS
- Itch.io (Downloadable Build) - Linux
- Compiled from GitHub Source Code
validations:
required: true
- type: dropdown
attributes:
label: Browser
description: (Web/HTML5 users only) Which browser are you playing on?
options:
- Google Chrome
- Microsoft Edge
- Firefox
- Opera
- Safari
- Other (Specify in Description field)
- type: input
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.6.3
validations:
required: true
- type: markdown
attributes:
value: "## Describe the charting issue(s)."
- type: markdown
attributes:
value: "### Please do not report issues from other engines. These must be reported in their respective repositories."
- type: textarea
attributes:
label: Location
description: Where did you find the issue(s)? Include the name of the song, the variation, the difficulty, the time/section of the song, and any images or videos.
placeholder: ex. Cocoa Erect on Erect/Nightmare difficulties at Section 30
validations:
required: true
- type: textarea
attributes:
label: Description
description: Why do you believe this is an issue? Is a note at the wrong time, a hold note too short/long, or something else?
placeholder: Describe the charting issue(s) here...
validations:
required: true
+63
View File
@@ -0,0 +1,63 @@
name: Compiling Help
description: Report an issue with compiling the game.
labels: ["type: compilation help", "status: pending triage"]
title: "Compiling Help: "
body:
- type: markdown
attributes:
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
- type: checkboxes
attributes:
label: Issue Checklist
description: Be sure to complete these steps to increase the chances of your issue being addressed!
options:
- label: I have followed the [Compiling Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/COMPILING.md) and the [Troubleshooting Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/TROUBLESHOOTING.md)
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- type: dropdown
attributes:
label: Platform
description: Which platform are you compiling for?
options:
- Web/HTML5
- Desktop (Windows)
- Desktop (Mac)
- Desktop (Linux)
- Other
validations:
required: true
- type: input
attributes:
label: Version
description: Which version are you compiling? The game version is in the bottom left corner of the main menu or in the project.hxp file.
placeholder: ex. 0.6.3
validations:
required: true
- type: markdown
attributes:
value: "## Describe your compiling issue."
- type: markdown
attributes:
value: "### Please do not report issues from other engines. These must be reported in their respective repositories."
- type: textarea
attributes:
label: Console Output
description: Paste any errors or warnings from the console here.
placeholder: Paste output here...
validations:
required: true
- type: textarea
attributes:
label: Context
description: Provide as much detail as you can. Did you modify any code? Provide any relevant images or videos.
placeholder: Describe the context here...
validations:
required: true
+7 -2
View File
@@ -3,13 +3,18 @@ description: Report a crash that occurred while playing the game.
labels: ["type: major bug", "status: pending triage"]
title: "Crash Report: "
body:
- type: markdown
attributes:
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
- type: checkboxes
attributes:
label: Issue Checklist
description: Be sure to complete these steps to increase the chances of your issue being addressed!
options:
- label: I have properly named my issue
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
- label: I have properly titled my issue
- type: dropdown
attributes:
@@ -41,7 +46,7 @@ body:
attributes:
label: Version
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
placeholder: ex. 0.5.0
placeholder: ex. 0.6.3
validations:
required: true
+6 -1
View File
@@ -3,13 +3,18 @@ description: Suggest a new feature.
labels: ["type: enhancement", "status: pending triage"]
title: "Enhancement: "
body:
- type: markdown
attributes:
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
- type: checkboxes
attributes:
label: Issue Checklist
description: Be sure to complete these steps to increase the chances of your suggestion being considered!
options:
- label: I have properly named my enhancement
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
- label: I have checked the Issues/Discussions pages to see if my enhancement has already been suggested
- label: I have properly titled my enhancement
- type: textarea
attributes:
+2 -2
View File
@@ -5,7 +5,7 @@ inputs:
haxe:
description: 'Version of haxe to install'
required: true
default: '4.3.4'
default: '4.3.6'
hxcpp-cache:
description: 'Whether to use a shared hxcpp compile cache'
required: true
@@ -30,7 +30,7 @@ runs:
echo "TIMER_HAXE=$(date +%s)" >> "$GITHUB_ENV"
- name: Install Haxe
uses: funkincrew/ci-haxe@v3.1.0
uses: funkincrew/ci-haxe@v3.2.7
with:
haxe-version: ${{ inputs.haxe }}
+6 -6
View File
@@ -1,12 +1,12 @@
# Add 'small' to any changes below 10 lines
small:
# Add 'size: small' to any changes below 10 lines
'size: small':
max: 9
# Add 'medium' to any changes between 10 and 100 lines
medium:
# Add 'size: medium' to any changes between 10 and 100 lines
'size: medium':
min: 10
max: 99
# Add 'large' to any changes of at least 100 lines
large:
# Add 'size: large' to any changes of at least 100 lines
'size: large':
min: 100
+53 -5
View File
@@ -7,21 +7,23 @@
comment: >
This issue is a duplicate. Please direct all discussion to the original issue.
# Close the issue
close: true
close: false
# Set a close reason
close-reason: 'not planned'
# close-reason: 'not planned'
# Remove other status labels
unlabel:
- 'status: accepted'
- 'status: bug reproduced'
- 'status: cannot reproduce'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: rejected'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
prs:
@@ -29,6 +31,27 @@
comment: >
This pull request is a duplicate. Please direct all discussion to the original pull request.
# Close the pull request
close: false
# Remove other status labels
unlabel:
- 'status: accepted'
- 'status: bug reproduced'
- 'status: cannot reproduce'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: rejected'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
'status: stale':
issues:
# Close the issue
close: true
# Set a close reason
close-reason: 'not planned'
@@ -37,15 +60,36 @@
- 'status: accepted'
- 'status: bug reproduced'
- 'status: cannot reproduce'
- 'status: duplicate'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: rejected'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
prs:
# Close the pull request
close: true
# Remove other status labels
unlabel:
- 'status: accepted'
- 'status: bug reproduced'
- 'status: cannot reproduce'
- 'status: duplicate'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: rejected'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
'status: rejected':
issues:
@@ -60,18 +104,18 @@
- 'status: cannot reproduce'
- 'status: duplicate'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
prs:
# Close the pull request
close: true
# Set a close reason
close-reason: 'not planned'
# Remove other status labels
unlabel:
- 'status: accepted'
@@ -79,11 +123,13 @@
- 'status: cannot reproduce'
- 'status: duplicate'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: resolved'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
@@ -100,10 +146,12 @@
- 'status: cannot reproduce'
- 'status: duplicate'
- 'status: needs clarification'
- 'status: needs r&d'
- 'status: needs revision'
- 'status: pending pull request'
- 'status: pending triage'
- 'status: planned'
- 'status: rejected'
- 'status: resolved internally'
- 'status: reviewing internally'
- 'status: stale'
+9 -2
View File
@@ -1,11 +1,18 @@
# Add Documentation tag to PR's changing markdown files, or anything in the docs folder
Documentation:
'pr: documentation':
- changed-files:
- any-glob-to-any-file:
- docs/*
- '**/*.md'
# Add Haxe tag to PR's changing haxe code files
Haxe:
'pr: haxe':
- changed-files:
- any-glob-to-any-file: '**/*.hx'
# Add GitHub tag to PR's changing yml files, or anything in the .github folder
'pr: github':
- changed-files:
- any-glob-to-any-file:
- github/*
- '**/*.yml'
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Please check for duplicates or similar PRs before submitting this PR. -->
<!-- Please read the Contributing Guide (https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) before submitting this PR. -->
## Does this PR close any issues? If so, link them below.
## Briefly describe the issue(s) fixed.
-53
View File
@@ -1,53 +0,0 @@
name: Create and publish Docker image
on:
workflow_dispatch:
push:
paths:
- '**/Dockerfile'
- '.github/workflows/build-docker-image.yml'
jobs:
build-and-push-image:
runs-on: build-set
permissions:
contents: read
packages: write
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: false
token: ${{ steps.app_token.outputs.token }}
- name: Log into GitHub Container Registry
uses: docker/login-action@v3.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5.3.0
with:
context: ./build
push: true
tags: |
ghcr.io/funkincrew/build-dependencies:latest
ghcr.io/funkincrew/build-dependencies:${{ github.sha }}
labels: |
org.opencontainers.image.description=precooked haxe build-dependencies
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.title=${{ github.repository_owner }}/build-dependencies
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.version=${{ github.sha }}
+214 -121
View File
@@ -12,146 +12,239 @@ on:
description: Save the build artifact to Github Actions (sends to itch otherwise)
default: false
push:
paths-ignore:
- '**/Dockerfile'
- '.github/workflows/build-docker-image.yml'
jobs:
gather-changes:
runs-on: build-set
outputs:
trigger-build: ${{ steps.should-trigger.outputs.result }}
steps:
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: false
- uses: dorny/paths-filter@v3
id: filter
with:
base: ${{ github.ref }}
filters: |
docker:
- '.github/workflows/build-game.yml'
- '**/Dockerfile'
- uses: actions/github-script@v7
id: should-trigger
with:
result-encoding: string
script: |
const { payload } = context
const changes = ${{ steps.filter.outputs.changes }}
const manual = payload.commits
.some(c => c.message.toLowerCase().replace(/\W/g, " ").includes("docker rebuild"))
console.log({ payload, changes, manual, commits: payload.commits })
return payload.created
|| payload.forced
|| changes.includes("docker")
|| manual
gather-tags:
runs-on: build-set
outputs:
primary: ${{ steps.build-tags.outputs.primary }}
list: ${{ steps.build-tags.outputs.list }}
steps:
- name: Gather build tags
uses: actions/github-script@v7
id: build-tags
with:
script: |
const base = "ghcr.io/funkincrew/build-dependencies"
const default_branch = "rewrite/master"
const ref_path = context.ref.split("/").slice(2)
const ref = ref_path.join("/")
const ref_tag = ref_path.join("-")
const tags = [ref_tag, context.sha]
if (ref === default_branch) tags.push("latest")
console.log([
`ref: ${ref}`,
`default_branch: ${default_branch}`,
`tags: ${tags.join(", ")}`
].join('\n'))
const tag_list = tags
.map(tag => `${base}:${tag}`)
.join("\n")
core.setOutput("primary", ref_tag)
core.setOutput("list", tag_list)
docker-image:
needs: [gather-changes, gather-tags]
if: needs.gather-changes.outputs.trigger-build == 'true'
runs-on: build-set
permissions:
contents: read
packages: write
steps:
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: false
- name: Log into GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: ./build
push: true
tags: ${{ needs.gather-tags.outputs.list }}
labels: |
org.opencontainers.image.description=precooked haxe build dependencies
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.title=${{ github.repository_owner }}/build-dependencies
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.version=${{ github.sha }}
build-game-on-host:
strategy:
fail-fast: false
matrix:
include:
- target: windows
- target: macos
- target: windows
runs-on: windows
- target: macos
runs-on: macos
runs-on:
- ${{ matrix.target }}
- ${{ matrix.runs-on }}
defaults:
run:
shell: bash
env:
BUILD_DEFINES: ${{ github.event.inputs.build-defines || '-DGITHUB_BUILD' }}
steps:
- name: Make git happy
run: |
git config --global --replace-all safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
persist-credentials: false
- name: Setup build environment
uses: ./.github/actions/setup-haxe
with:
gh-token: ${{ steps.app_token.outputs.token }}
- name: Setup HXCPP dev commit
run: |
cd .haxelib/hxcpp/git/tools/hxcpp
haxe compile.hxml
cd ../../../../..
- name: Build game
if: ${{ matrix.target == 'windows' }}
run: |
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 ${{ 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:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}
- name: Make git happy
run: |
git config --global --replace-all safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
persist-credentials: false
- name: Setup build environment
uses: ./.github/actions/setup-haxe
with:
gh-token: ${{ steps.app_token.outputs.token }}
- name: Setup HXCPP dev commit
run: |
cd .haxelib/hxcpp/git/tools/hxcpp
haxe compile.hxml
cd ../../../../..
- name: Build game (windows)
if: ${{ matrix.target == 'windows' }}
run: |
haxelib run lime build windows -v -release $BUILD_DEFINES
timeout-minutes: 120
- name: Build game (unix)
if: ${{ matrix.target != 'windows' }}
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times $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:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}
build-game-in-container:
needs: [gather-tags, docker-image]
if: ${{ ! cancelled() }}
runs-on: build-set
container: ghcr.io/funkincrew/build-dependencies:latest
container: ghcr.io/funkincrew/build-dependencies:${{ needs.gather-tags.outputs.primary }}
strategy:
matrix:
include:
- target: linux
- target: html5
- target: linux
- target: html5
defaults:
run:
shell: bash
env:
BUILD_DEFINES: ${{ github.event.inputs.build-defines || '-DGITHUB_BUILD' }}
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
persist-credentials: false
- name: Config haxelib
run: |
haxelib --never newrepo
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
name: Install dependencies
run: |
git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/
git config --global advice.detachedHead false
haxelib --global run hmm install -q
cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml
- if: ${{ matrix.target != 'html5' }}
name: Restore hxcpp cache
uses: actions/cache@v4
with:
path: /usr/share/hxcpp
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
- name: Build game
run: |
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:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
persist-credentials: false
- name: Config haxelib
run: |
haxelib --never newrepo
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
name: Install dependencies
run: |
git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/
git config --global advice.detachedHead false
haxelib --global run hmm install -q
cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml
- if: ${{ matrix.target != 'html5' }}
name: Restore hxcpp cache
uses: actions/cache@v4
with:
path: /usr/share/hxcpp
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
- name: Build game
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times $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:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}
-52
View File
@@ -1,52 +0,0 @@
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.
@@ -0,0 +1,19 @@
name: "Pull Request Labeler 2 (Runs on PR creation)"
on:
pull_request_target:
types:
- opened
jobs:
# Apply `status: pending triage` to newly created pull requests
apply-pending-triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Apply "status pending triage" to new pull requests
uses: actions-ecosystem/action-add-labels@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
labels: "status: pending triage"
+2
View File
@@ -4,10 +4,12 @@
APIStuff.hx
dump/
export/
project/
RECOVER_*.fla
shitAudio/
.build_time
.swp
NewgroundsCredentials.hx
# Exclude JS stuff
node_modules/
+1 -2
View File
@@ -6,7 +6,6 @@
"vshaxe.hxcpp-debugger", // CPP debugging
"openfl.lime-vscode-extension", // Lime integration
"esbenp.prettier-vscode", // JSON formatting
"redhat.vscode-xml", // XML formatting
"ryanluker.vscode-coverage-gutters" // Highlight code coverage
"redhat.vscode-xml" // XML formatting
]
}
+16 -49
View File
@@ -70,7 +70,7 @@
"files.eol": "\n",
"haxe.displayPort": "auto",
"haxe.enableCompilationServer": false,
"haxe.enableCompilationServer": true,
"haxe.enableServerView": true,
"haxe.displayServer": {
"arguments": ["-v"]
@@ -91,26 +91,6 @@
"haxecheckstyle.codeSimilarityBufferSize": 100,
"lime.targetConfigurations": [
{
"label": "Windows / Debug",
"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",
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug",
"target": "hl",
"args": ["-debug"]
},
{
"label": "Windows / Debug (Discord)",
"target": "windows",
@@ -170,23 +150,13 @@
"target": "windows",
"args": ["-debug", "-DRESULTS"]
},
{
"label": "Windows / Debug (Straight to Chart Editor)",
"target": "windows",
"args": ["-debug", "-DCHARTING", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Straight to Chart Editor)",
"target": "hl",
"args": ["-debug", "-DCHARTING"]
},
{
"label": "Windows / Debug (Straight to Animation Editor)",
"target": "windows",
"args": ["-debug", "-DANIMDEBUG", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Debug (Debug hxCodec)",
"label": "Windows / Debug (Debug hxvlc)",
"target": "windows",
"args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFEATURE_DEBUG_FUNCTIONS"]
},
@@ -210,11 +180,6 @@
"target": "windows",
"args": ["-debug", "-DWAVEFORM", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Release",
"target": "windows",
"args": ["-release"]
},
{
"label": "Windows / Release (GitHub Actions)",
"target": "windows",
@@ -225,29 +190,31 @@
"target": "hl",
"args": ["-debug", "-DWAVEFORM"]
},
{
"label": "HTML5 / Debug",
"target": "html5",
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HTML5 / Debug (Watch)",
"target": "html5",
"args": ["-debug", "-watch", "-DFEATURE_DEBUG_FUNCTIONS"]
},
}
],
"lime.buildTypes": [
{
"label": "macOS / Debug",
"target": "mac",
"label": "Debug",
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "macOS / Release",
"target": "mac",
"label": "Debug (Tracy)",
"args": ["-debug", "-DFEATURE_DEBUG_TRACY", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Debug (Straight to Chart Editor)",
"args": ["-debug", "-DCHARTING", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Release",
"args": ["-release"]
},
{
"label": "macOS / Release (GitHub Actions)",
"target": "mac",
"label": "Release (GitHub Actions)",
"args": ["-release", "-DGITHUB_BUILD"]
}
],
+623 -239
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -14,8 +14,8 @@ Code Quality is handled by the `vshaxe.haxe-checkstyle` extension, which include
* `IndentationCharacter` checks what is used to indent, `Indentation` checks how deep the indentation is.
* `CommentedOutCode` check is in place because old code should be retrieved via Git history.
* TODO items: Enable these one-by-one and fix them to improve the overall code quality.
- Reconfigure `MethodLength`
- Reconfigure `CyclomaticComplexity`
- Re-configure `MethodLength`
- Re-configure `CyclomaticComplexity`
- Re-enable `MagicNumber`
- Re-configure `NestedControlFlow`
- Re-configure `NestedIfDepth`
@@ -28,5 +28,5 @@ Prettier automatically handles formatting of JSON files, and can be configured i
### Prettier Notes
* Prettier will automatically attempt to place expressions on a single line if they fit, but will keep them multi-line if they are manually made multi-line.
* This means that long singleline objects are automatically expanded, and short multiline objects aren't automatically collapsed.
* This means that long single-line objects are automatically expanded, and short multi-line objects aren't automatically collapsed.
* You may want to use regex replacement to manually remove the first newline in short multi-line objects to convince Prettier to collapse them.
+2 -1
View File
@@ -8,7 +8,7 @@ All Rights Reserved. "Friday Night Funkin'" and the "Friday Night Funkin'" logo
You can view the `funkin-assets` license here: (https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md)
## Apache 2.0 License
```
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@@ -210,3 +210,4 @@ You can view the `funkin-assets` license here: (https://github.com/FunkinCrew/fu
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
+2 -2
View File
@@ -11,11 +11,11 @@ This game was made with love to Newgrounds and its community. Extra love to Tom
**PLEASE USE THE LINKS ABOVE IF YOU JUST WANT TO PLAY THE GAME**
To learn how to install the necessary dependencies and compile the game from source, please check out our [building the game](/docs/COMPILING.md) guide.
To learn how to install the necessary dependencies and compile the game from source, please follow our [Compiling Guide](/docs/COMPILING.md).
# Contributing
Please check out our [Contributor's guide](./CONTRIBUTORS.md) on how you can actively participate in the development of Friday Night Funkin'.
Check out our [Contributing Guide](/docs/CONTRIBUTING.md) to learn how you can actively contribute to the development of Friday Night Funkin'!
# Modding
+1 -1
Submodule art updated: fbd3e3df77...8402339e2e
+1 -1
Submodule assets updated: 4abd6cc06e...c108a7ff0d
+15 -13
View File
@@ -1,8 +1,8 @@
FROM ubuntu:mantic
FROM ubuntu:noble
ARG haxe_version=4.3.4
ARG haxe_version=4.3.6
ARG haxelib_version=4.1.0
ARG neko_version=2.3.0
ARG neko_version=2.4.0
# prepare runner
ENV GITHUB_HOME="/github/home"
@@ -98,11 +98,12 @@ EOF
# neko
# https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-linux64.tar.gz
RUN <<EOF
neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -sfL \
| jq '.[] | select(.name == "'"$neko_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
curl -sfL "$neko_url" | tar -xz -C /usr/local
#neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -fL \
# | jq '.[] | select(.name == "'"$neko_version"'")' \
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
# | jq -r '.browser_download_url')
neko_url="https://geo.thei.rs/funkin/neko-2.4.1-linux64.tar.gz"
curl -fL "$neko_url" | tar -xz -C /usr/local
EOF
RUN <<EOF
@@ -117,11 +118,12 @@ ENV PATH="$NEKOPATH:$PATH"
# haxe
# https://github.com/HaxeFoundation/haxe/releases/download/4.0.5/haxe-4.0.5-linux64.tar.gz
RUN <<EOF
haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -sfL \
| jq '.[] | select(.name == "'"$haxe_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
curl -sfL "$haxe_url" | tar -xz -C /usr/local
#haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -fL \
# | jq '.[] | select(.name == "'"$haxe_version"'")' \
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
# | jq -r '.browser_download_url')
haxe_url="https://geo.thei.rs/funkin/haxe-4.3.6-linux64.tar.gz"
curl -fL "$haxe_url" | tar -xz -C /usr/local
EOF
RUN <<EOF
+1 -1
View File
@@ -347,7 +347,7 @@
{
"props": {
"allowSingleLineStatement": true,
"tokens": ["FOR", "IF", "ELSE_IF", "WHILE", "DO_WHILE"]
"tokens": ["FOR", "ELSE_IF", "WHILE", "DO_WHILE"]
},
"type": "NeedBraces"
},
+7 -4
View File
@@ -13,17 +13,20 @@
- NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information.
5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json
6. Run `hmm install` to install all haxelibs of the current branch
7. Run `haxelib run lime setup` to set up lime
8. Perform additional platform setup
- If you have issues installing Lime, try utilizing Funkin's patched libraries for hmm and haxelib: `haxelib --global git haxelib https://github.com/FunkinCrew/haxelib.git` and `haxelib --global git hmm https://github.com/FunkinCrew/hmm.git`
8. Run `haxelib run lime setup` to set up Lime
9. Perform additional platform setup
- For Windows, download the [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe)
- When prompted, select "Individual Components" and make sure to download the following:
- MSVC v143 VS 2022 C++ x64/x86 build tools
- Windows 10/11 SDK
- Mac: [`lime setup mac` Documentation](https://lime.openfl.org/docs/advanced-setup/macos/)
- Linux: [`lime setup linux` Documentation](https://lime.openfl.org/docs/advanced-setup/linux/)
- One of Funkin's dependencies uses libVLC, which requires you to install some development packages to be able to compile.
Command for Ubuntu/Debian based systems: `sudo apt install libvlc-dev libvlccore-dev libvlccore9`
- HTML5: Compiles without any extra setup
9. If you are targeting for native, you may need to run `lime rebuild <PLATFORM>` and `lime rebuild <PLATFORM> -debug`
10. `lime test <PLATFORM>` to build and launch the game for your platform (for example, `lime test windows`)
10. If you are targeting for native, you may need to run `lime rebuild <PLATFORM>` and `lime rebuild <PLATFORM> -debug`
11. `lime test <PLATFORM>` to build and launch the game for your platform (for example, `lime test windows`)
## Build Flags
+10
View File
@@ -0,0 +1,10 @@
# Mac Compiling Guide + Considerations
There's a few extra considerations when compiling FNF for Mac that *we* have to handle when creating a wider release.
- [Creating a Universal Binary](#creating-a-universal-binary)
- Code-signing
- Notarizing
## Creating a Universal Binary
Run the `art/macos-universal.sh` script, which automatically compiles release versions of both arm64 and x86 of Funkin. You can also see there for reference of how it's done.
+421
View File
@@ -0,0 +1,421 @@
# Contributing
Welcome to the Contributing Guide!
You can contribute to the Funkin' repository by opening issues or pull requests.
This guide will cover best practices for each type of contribution.
# Table of Contents
<details open>
<summary><b>Contents</b></summary>
[Part 1: Etiquette](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#part-1-etiquette)
<details>
<summary><a href="https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#part-2-issues">Part 2: Issues</a></summary>
* [Requirements](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#requirements)
* [Rejected Features](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#rejected-features)
* [Issue Types](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#issue-types)
* [Before You Submit...](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#before-you-submit)
</details>
<details>
<summary><a href="https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#part-3-pull-requests">Part 3: Pull Requests</a></summary>
* [Choosing a base branch](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#choosing-a-base-branch)
* [Merge conflicts and rebasing](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#merge-conflicts-and-rebasing)
* [Code PRs](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#code-prs)
* [Documentation PRs](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#documentation-prs)
* [GitHub PRs](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#github-prs)
* [funkin.assets PRs](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#funkinassets-prs)
* [Charting PRs](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#charting-prs)
</details>
[Closing](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md#closing)
</details>
# Part 1: Etiquette
- Be respectful to one another. We're here to help each other out!
- Keep your titles clear and concise. Do not type the whole description into the title.
- Do not spam by creating unnecessary issues and pull requests.
- Use common sense!
# Part 2: Issues
Issues serve many purposes, from reporting bugs to suggesting new features.
This section provides guidelines to follow when [opening an issue](https://github.com/FunkinCrew/Funkin/issues).
## Requirements
Make sure you're playing:
- the latest version of the game (currently v0.6.3)
- without any mods
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
## Rejected Features
If you want to **suggest a feature**, make sure it hasn't already been rejected.
Here's a list of commonly suggested features and the reasons why they won't be added:
| Feature | Reason |
| ------- | ------- |
| Combo Break + Accuracy Displays | https://github.com/FunkinCrew/Funkin/pull/2681#issuecomment-2156308982 |
| Toggleable Ghost Tapping | https://github.com/FunkinCrew/Funkin/pull/2564#issuecomment-2119701802 |
| Perfectly Centered Strumlines | _same as above^_ |
| MultiKey, 9k, More than 4 keys, etc. | https://github.com/FunkinCrew/Funkin/issues/4243#issuecomment-2692371969 |
| Flashy Combo Milestones | https://github.com/FunkinCrew/Funkin/pull/4700#issuecomment-2798916579 |
| Losing Icons for DD and Parents | https://github.com/FunkinCrew/Funkin/issues/3048#issuecomment-2243491536 |
| Playable GF / Speaker BF / Speaker Pico | https://github.com/FunkinCrew/Funkin/issues/2953#issuecomment-2216985230 |
| Fresh (Chill Mix) as Title Screen Music | https://github.com/FunkinCrew/Funkin/pull/4282#issuecomment-2709334718 |
| Adjusted Difficulty Ratings | https://github.com/FunkinCrew/Funkin/issues/2781#issuecomment-2172053144 |
| Difficulty Ratings above 20 | https://github.com/FunkinCrew/Funkin/issues/3075#issuecomment-2368984497 |
| Ability to Reset a Song's Score | https://github.com/FunkinCrew/Funkin/issues/3916#issuecomment-2525408261 |
| Quick Restart Keybind (not R) | https://github.com/FunkinCrew/Funkin/issues/3268#issuecomment-2351095232 |
| Countdown after Unpausing Song | https://github.com/FunkinCrew/Funkin/issues/2721#issuecomment-2159330106 |
| 4:3 Aspect Ratio for Week 6 | https://github.com/FunkinCrew/Funkin/issues/3840#issuecomment-2689158438 |
| "Philly Glow" Effect from Psych Engine | https://github.com/FunkinCrew/Funkin/issues/3788#issuecomment-2688966982 |
| Importing Charts from Psych Engine (and other mod content) | https://github.com/FunkinCrew/Funkin/issues/2586#issuecomment-2125733327 |
| Backwards Compatibility for Modding | https://github.com/FunkinCrew/Funkin/issues/3949#issuecomment-2608391329 |
| Lua Support | https://github.com/FunkinCrew/Funkin/issues/2643#issuecomment-2143718093 |
## Issue Types
Choose the issue template that best suits your needs!
Here's what each template is designed for:
### Bug Report ([view list](https://github.com/FunkinCrew/Funkin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22type%3A%20minor%20bug%22))
For minor bugs and general issues with the game. Choose this one if none of the others fit your needs.
### Crash Report ([view list](https://github.com/FunkinCrew/Funkin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22type%3A%20major%20bug%22))
For crashes and freezes like the [Null Object Reference](https://github.com/FunkinCrew/Funkin/issues/2209) problem from v0.3.0.
### Charting Issue ([view list](https://github.com/FunkinCrew/Funkin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22type%3A%20charting%20issue%22))
For misplaced notes, wonky camera movements, broken song events, and everything related to the game's charts.
### Enhancement ([view list](https://github.com/FunkinCrew/Funkin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22type%3A%20enhancement%22))
For suggestions to add new features or improve existing ones. We'd love to hear your ideas!
### Compiling Help (only after reading the [Troubleshooting Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/TROUBLESHOOTING.md))
For issues with compiling the game. Legacy versions (before v0.3.0) are not supported.
> [!TIP]
> If none of the above Issue templates suit your inquiry (e.g. Questions or Coding Help), please [open a discussion](https://github.com/FunkinCrew/Funkin/discussions).
## Before You Submit...
Complete the Issue Checklist at the top of your template!
> [!IMPORTANT]
> If you do not complete each step of the Issue Checklist, **your issue may be closed.**
Be sure to use the search bar on the Issues page to check that your issue hasn't already been reported by someone else.
Duplicate issues make it harder to keep track of important issues with the game.
Also only report one issue or enhancement at a time! If you have multiple bug reports or suggestions, split them up into separate submissions so they can be checked off one by one.
Once you're sure your issue is unique and specific, feel free to submit it.
> [!IMPORTANT]
> **DO NOT CLOSE YOUR ISSUE FOR ANY REASON!** Your issue will be taken care of by a moderator!
**Thank you for opening issues!**
# Part 3: Pull Requests
Community members are welcome to contribute their changes by [opening pull requests](https://github.com/FunkinCrew/Funkin/pulls).
This section covers guidelines for opening and managing pull requests (PRs).
## Choosing a base branch
When creating a branch in your fork, base your branch on either the `main` or `develop` branch depending on the types of changes you want to make.
> [!CAUTION]
> Avoid using your fork's default branch (`main` in this case) for your PR. This is considered an [anti-pattern](https://jmeridth.com/posts/do-not-issue-pull-requests-from-your-master-branch/) by GitHub themselves!
> Instead, make a separate branch for your additions (ex. `docs/fix-typo` or `minor-bugfix`).
Choose the `main` branch if you modify:
- Documentation (`.md` files)
- GitHub files (`.yml` files or anything in the `.github` folder)
Choose the `develop` branch if you modify:
- Game code (`.hx` files)
- Any other type of file
> [!TIP]
> When in doubt, base your branch on the `develop` branch.
Choosing the right base branch helps keep your commit history clean and avoid merge conflicts.
Once you’re satisfied with the changes you’ve made, open a PR and base it on the same branch you previously chose.
## Maintaining your pull request
Keeping your pull request clean and easy to review increases the chance that it will be accepted!
Our maintenance policy is as follows:
- If we require changes to your PR, we will label your PR `status: needs revision`.
- We may also leave a comment under your PR specifying what changes you should make.
- If you receive a comment, you have 90 days to implement the requested changes.
- After this period, your PR will be closed due to inactivity and labeled `status: stale`.
- Even after your PR is closed, you may request for us to reopen it. Just be sure to address the issues!
This policy ensures that PRs awaiting review are up to date and ready to merge.
### Merge conflicts and rebasing
Some game updates introduce significant breaking changes that may create merge conflicts in your PR. To resolve them, you will need to update or rebase your PR.
Most merge conflicts are small and will only require you to modify a few files to resolve them.
However, some changes are so big that your commit history will be a total mess!
In this case, you will have to perform a [**rebase**](https://docs.github.com/en/get-started/using-git/about-git-rebase).
This process reapplies your changes on top of the updated branch and cleanly resolves the merge conflicts.
> [!TIP]
> If your commit history becomes too long, you can use rebase to `squash` your PR's commits into a single commit.
## Code PRs
> [!IMPORTANT]
> This guide does not cover compiling. If you have trouble compiling the game, refer to the [Compilation Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/COMPILING.md).
Code-based PRs make changes such as **fixing bugs** or **implementing new features** in the game.
This involves modifying one or several of the repository’s `.hx` files, found within the `source/` folder.
### Codestyle
Before submitting your PR, check that your code follows the [Style Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/style-guide.md). This keeps your code consistent with the rest of the codebase!
### Code comments
Code comments help others understand your changes, so the way you write them is important!
Here are some guidelines for writing comments in your code:
- Leave comments only when you believe a piece of code warrants explanation. If a piece of code is self-explanatory, it does not need a comment.
- Ensure that your comments provide meaningful insight into the function or purpose of the code.
- Write your comments in a clear and concise manner.
- Only sign your comments with your name when your changes are complex and may require further explanation.
### Example code comments
#### DO NOT:
Below are examples of what you SHOULD NOT do when writing code comments.
```haxe
/**
* jumps around the song
* works with bpm changes but skipped notes still hurt
* @param sections how many sections to jump, negative = backwards
*/
function changeSection(sections:Int):Void
{
// Pause the music, as you probably guessed
// FlxG.sound.music.pause();
// Set the target time in steps, I don’t really get how this works though lol - [GitHub username]
var targetTimeSteps:Float = Conductor.instance.currentStepTime + (Conductor.instance.stepsPerMeasure * sections);
var targetTimeMs:Float = Conductor.instance.getStepTimeInMs(targetTimeSteps);
// Don't go back in time to before the song started, that would probably break a lot of things and cause a bunch of problems!
targetTimeMs = Math.max(0, targetTimeMs);
if (FlxG.sound.music != null) // If the music is not null, set the time to the target time
{
FlxG.sound.music.time = targetTimeMs;
}
// Handle skipped notes and events and all that jazz
handleSkippedNotes();
SongEventRegistry.handleSkippedEvents(songEvents, Conductor.instance.songPosition);
// regenNoteData(FlxG.sound.music.time);
Conductor.instance.update(FlxG.sound?.music?.time ?? 0.0);
// I hate this function - [GitHub username]
resyncVocals();
}
```
```haxe
// End the song when the music is complete.
FlxG.sound.music.onComplete = function() {
endSong(skipEndingTransition);
};
// 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, Math.max(0, startTimestamp - Conductor.instance.combinedOffset));
FlxG.sound.music.pitch = playbackRate;
// Prevent the volume from being wrong.
FlxG.sound.music.volume = 1.0;
// IF fadetween is not null we cancel it
if (FlxG.sound.music.fadeTween != null) FlxG.sound.music.fadeTween.cancel();
// Play the vocals
trace('Playing vocals...');
// Add the vocals
add(vocals);
// Play the vocals for real this time lol
vocals.play();
// Set the vocals volume
vocals.volume = 1.0;
// Set the vocals pitch
vocals.pitch = playbackRate;
// Set the vocals time to the music time
vocals.time = FlxG.sound.music.time;
// trace('${FlxG.sound.music.time}');
// trace('${vocals.time}');
// functionThatWasntHereBeforeThisPRorSomethingIdKLOL();
/* testsprite = new FlxSprite(0, 0);
testsprite.loadGraphic(Paths.image('test'));
testsprite.screenCenter();
add(testsprite); */
// Me too [GitHub username] I hate this function it gave me pain and suffering - Girlfriend
resyncVocals();
```
```haxe
#if FEATURE_DEBUG_FUNCTIONS
// PAGEUP: who knows what this does
// SHIFT+PAGEUP: There will be dire consequences.
if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2);
// PAGEUP: who knows what this does
// SHIFT+PAGEUP: There will be dire consequences.
if (FlxG.keys.justPressed.PAGEDOWN) changeSection(FlxG.keys.pressed.SHIFT ? -20 : -2);
#end
```
#### DO:
Below are examples on what you SHOULD do when writing code comments.
```haxe
/**
* Jumps forward or backward a number of sections in the song.
* Accounts for BPM changes, does not prevent death from skipped notes.
* @param sections The number of sections to jump, negative to go backwards.
*/
function changeSection(sections:Int):Void
{
var targetTimeSteps:Float = Conductor.instance.currentStepTime + (Conductor.instance.stepsPerMeasure * sections);
var targetTimeMs:Float = Conductor.instance.getStepTimeInMs(targetTimeSteps);
// Don't go back in time to before the song started.
targetTimeMs = Math.max(0, targetTimeMs);
if (FlxG.sound.music != null)
{
FlxG.sound.music.time = targetTimeMs;
}
handleSkippedNotes();
SongEventRegistry.handleSkippedEvents(songEvents, Conductor.instance.songPosition);
Conductor.instance.update(FlxG.sound?.music?.time ?? 0.0);
resyncVocals();
}
```
```haxe
FlxG.sound.music.onComplete = function() {
endSong(skipEndingTransition);
};
// 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, Math.max(0, startTimestamp - Conductor.instance.combinedOffset));
FlxG.sound.music.pitch = playbackRate;
// Prevent the volume from being wrong.
FlxG.sound.music.volume = 1.0;
if (FlxG.sound.music.fadeTween != null) FlxG.sound.music.fadeTween.cancel();
trace('Playing vocals...');
add(vocals);
vocals.play();
vocals.volume = 1.0;
vocals.pitch = playbackRate;
vocals.time = FlxG.sound.music.time;
resyncVocals();
```
```haxe
#if FEATURE_DEBUG_FUNCTIONS
// PAGEUP: Skip forward two sections.
// SHIFT+PAGEUP: Skip forward twenty sections.
if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2);
// PAGEDOWN: Skip backward two section. Doesn't replace notes.
// SHIFT+PAGEDOWN: Skip backward twenty sections.
if (FlxG.keys.justPressed.PAGEDOWN) changeSection(FlxG.keys.pressed.SHIFT ? -20 : -2);
#end
```
## Documentation PRs
Documentation-based PRs make changes such as **fixing typos** or **adding new information** in documentation files.
This involves modifying one or several of the repository’s `.md` files, found throughout the repository.
Make sure your changes are easy to understand and formatted consistently to maximize clarity and readability.
> [!CAUTION]
> DO NOT TOUCH THE `LICENSE.md` FILE, EVEN TO MAKE SMALL CHANGES!
### Example Documentation PR
#### DO NOT:
```
// The original documentation
- `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting.
- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too!
- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out!
- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data).
- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
// The new PR additions
- `ctrl alt shift e`: No idea what this does
- `alt-f4`: closes the game
```
#### DO:
```
// The original documentation
- `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting.
- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too!
- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out!
- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data).
- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
// The new PR additions
- `CTRL-ALT-SHIFT-E`: ***DUMP SAVE DATA***: Prompts the user to save their save data as a JSON file, so its contents can be viewed. Only available on debug builds.
- `ALT-F4`: ***CLOSE GAME***: Closes the game forcibly on Windows.
```
## GitHub PRs
GitHub-related PRs make changes such as **tweaking Issue Templates** or **updating the repository’s workflows**.
This involves modifying one or several of the repository’s `.yml` files, or any other file in the `.github` folder.
Please test these changes on your fork’s main branch to avoid breaking anything in this repository (e.g. GitHub Actions, issue templates, etc.)!
## funkin.assets PRs
The `assets` submodule has its own repository called [funkin.assets](https://github.com/FunkinCrew/funkin.assets).
If you only modify files in the `assets` folder, open a PR in the `funkin.assets` repository instead of the main repository.
If you simultaneously modify files from both repositories, then open two separate PRs and explain the connection in your PR descriptions.
Be sure to choose `main` as the base branch for `funkin.assets` PRs, as no `develop` branch exists for that repository.
### Charting PRs
Charting PRs make changes such as **adjusting chart metadata**.
This involves modifying one or several of the `funkin.assets` repository's `*-metadata.json` files, found in the `preload/data/songs/` directory.
> [!CAUTION]
> We **do not** accept changes to the chart `.json` file itself.
> If you find an error in the game's charts, please open an issue in the `Funkin` repo, and the Funkin' Crew will review it and make tweaks themselves as necessary.
These PRs should only be opened in the `funkin.assets` repository.
# Closing
Thank you for reading the Contributing Guide.
We look forward to seeing your contributions to the game!
+19 -4
View File
@@ -3,10 +3,13 @@
Most of this functionality is only available on debug builds of the game!
## Any State
- `INSERT`: ***MEMORY GARBAGE COLLECTION***: Immediately perform memory garbage collection.
- `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting.
- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too!
- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out!
- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data).
- `CTRL-ALT-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. (Only works in the Main Menu on debug builds).
- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
## **Play State**
@@ -17,15 +20,27 @@ Most of this functionality is only available on debug builds of the game!
- `9`: NEATO!
- `PAGEUP` (MacOS: `Fn-Up`): ***FORWARDS TIME TRAVEL***: Move forward by 2 sections. Hold SHIFT to move forward by 20 sections instead.
- `PAGEDOWN` (MacOS: `Fn-Down`): ***BACKWARDS TIME TRAVEL***: Move backward by 2 sections. Hold SHIFT to move backward by 20 sections instead.
- `CHART Hotkey`: ***OPEN CHART EDITOR***: Open the Chart Editor with the current song loaded.
- `STAGE Hotkey`: ***OPEN STAGE EDITOR***: Open the old Stage Editor overlay.
## **Freeplay State**
- `F` (Freeplay Menu) - Move to Favorites
- `Q` (Freeplay Menu) - Back one category
- `E` (Freeplay Menu) - Forward one category
- `P`: ***SWITCH TO PICO/BF***: Switch to Pico or BF (reopens Freeplay as the other character).
- `T`: ***TEST RANK ANIMATION***: Play the Gold Perfect rank animation on the currently selected song.
- `SHIFT-ACCEPT`: ***BOTPLAY MODE***: Start a song with Botplay mode enabled.
- `CTRL-Switch Song`: Play the first unlocked alternate instrumental as the song preview.
## **Title State**
- `Y` - WOAH
- `ESCAPE`: ***QUIT***: Quit the game.
- `D`: COOL
- `UI LEFT`/`UI RIGHT Hotkey`: 2COOL
- `Y`: WOAH
## **Main Menu**
- `~`: ***DEBUG***: Opens a menu to access the Chart Editor and other work-in-progress editors. Rebindable in the options menu.
- `SHIFT-ACCEPT`: ***OPEN FREEPLAY AS PICO***: When selecting Freeplay, open the Freeplay menu with the playable character set to Pico.
- `CTRL-ALT-SHIFT-W`: ***ALL ACCESS***: Unlocks all songs in Freeplay. Only available on debug builds.
- `CTRL-ALT-SHIFT-M`: ***NO MORE ACCESS***: Re-locks all songs in Freeplay except those unlocked by default. Only available on debug builds.
- `CTRL-ALT-SHIFT-R`: ***GREAT SCORE?***: Give the user a hypothetical overridden score, and see if we can maintain that golden P rank. Only available on debug builds.
- `CTRL-ALT-SHIFT-P`: ***CHARACTER UNLOCK SCREEN***: Forces the Character Select screen to play Pico's unlocking animation. Only available on debug builds.
- `CTRL-ALT-SHIFT-N`: ***CHARACTER NOT SEEN***: Marks all characters as not seen and enables BF's new character unlocked animation in Freeplay. Only available on debug builds.
- `CTRL-ALT-SHIFT-E`: ***DUMP SAVE DATA***: Prompts the user to save their save data as a JSON file, so its contents can be viewed. Only available on debug builds.
+33 -3
View File
@@ -1,11 +1,19 @@
# Troubleshooting Common Compilation Issues
- Any output containing `WARNING` or `(WDeprecated)`
- Will not disrupt compilation and can be safely ignored.
- `This version of hxcpp` ... `Would you like to do this now [y/n]`
- Type "y" into the console and press Enter.
- 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.
- `Get Thread Context Failed`: Turn off other expensive applications while building
- `Get Thread Context Failed`
- Turn off other expensive applications while building.
- `Type not found: T1`: This is thrown by `json2object`, make sure the data type of `@:default` is correct.
- `Type not found: T1`
- This is thrown by `json2object`, make sure the data type of `@:default` is correct.
- NOTE: `flixel.util.typeLimit.OneOfTwo` isn't supported.
- `Class lists not properly generated. Try cleaning out your export folder, restarting your IDE, and rebuilding your project.`
@@ -15,9 +23,31 @@
- 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.
- 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**.
## Lime Related Issues
- Segmentation fault and/or crash after `Done mapping time changes: [SongTimeChange(0ms,102bpm)]`
- Caused by using official Lime instead of Funkin's fork. Reinstalling Lime should fix it.
(NOTE: Make sure you do this via `hmm` (e.g `hmm reinstall -f lime`) to guarantee you get Funkin's version of Lime.)
- `Uncaught exception - Could not find lime.ndll.` ... `Advanced users may run "lime rebuild cpp" instead.`
- If on Linux:
- The binaries GLibC version might more recent than the one your system supports. Running the commands below should fix it.
```
cd .haxelib/lime/git
git submodule init
git submodule sync
git submodule update
cd ../../..
# Note: The command and packages here might be different depending on your distro.
sudo apt install libgl1-mesa-dev libglu1-mesa-dev g++ g++-multilib gcc-multilib libasound2-dev libx11-dev libxext-dev libxi-dev libxrandr-dev libxinerama-dev libpulse-dev
lime rebuild cpp -64 -release -clean
```
- The binaries are missing for some reason. You can download pre-built binaries from [Funkin's Lime](https://github.com/FunkinCrew/lime/tree/dev-funkin/ndll).
You should copy them to `.haxelib/lime/git/ndll/<PLATFORM>64/`, where `<PLATFORM>` is the current platform you're on, which can be either Windows, Linux or MacOS.
+1 -1
View File
@@ -4,7 +4,7 @@ This short document is designed to give a run-down on how code should be formatt
## Notes on IDEs and Extensions
The Visual Studio Code IDE is highly recommended, as this repo contains various configuration that works with VSCode extensions to automatically style certain things for you.
The Visual Studio Code IDE is highly recommended, as this repo contains various configurations that work with VSCode extensions to automatically style certain things for you.
VSCode is also the only IDE that has any good tools for Haxe so yeah.
+25 -20
View File
@@ -4,21 +4,21 @@
"name": "FlxPartialSound",
"type": "git",
"dir": null,
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
"ref": "41f35ddb1eb9d10bc742e6f8b5bcc62f9ef8ad84",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "flixel",
"type": "git",
"dir": null,
"ref": "ffa691cb2d2d81de35b900a4411e4062ac84ab58",
"ref": "fffb1a74cf08f63dacc2ab09976340563f5b6e6d",
"url": "https://github.com/FunkinCrew/flixel"
},
{
"name": "flixel-addons",
"type": "git",
"dir": null,
"ref": "7424db4e9164ff46f224a7c47de1b732d2542dd7",
"ref": "b9118f47f43a66bc0e5fbfcfd9903f0425e918ee",
"url": "https://github.com/FunkinCrew/flixel-addons"
},
{
@@ -32,8 +32,8 @@
"name": "flxanimate",
"type": "git",
"dir": null,
"ref": "0654797e5eb7cd7de0c1b2dbaa1efe5a1e1d9412",
"url": "https://github.com/Dot-Stuff/flxanimate"
"ref": "f8842cea9883d6112a2c854cf93fa72856171428",
"url": "https://github.com/FunkinCrew/flxanimate"
},
{
"name": "format",
@@ -44,7 +44,7 @@
"name": "funkin.vis",
"type": "git",
"dir": null,
"ref": "22b1ce089dd924f15cdc4632397ef3504d464e90",
"ref": "1966f8fbbbc509ed90d4b520f3c49c084fc92fd6",
"url": "https://github.com/FunkinCrew/funkVis"
},
{
@@ -63,36 +63,29 @@
"name": "haxeui-core",
"type": "git",
"dir": null,
"ref": "51c23588614397089a5ce182cddea729f0be6fa0",
"ref": "07fc7aa8098deaea633b0726d01f83eb4ef8a832",
"url": "https://github.com/haxeui/haxeui-core"
},
{
"name": "haxeui-flixel",
"type": "git",
"dir": null,
"ref": "da27e833947f32ef007ed11f523aa5524f5a5d54",
"ref": "b899a4c7d7318c5ff2b1bb645fbc73728fad1ac9",
"url": "https://github.com/haxeui/haxeui-flixel"
},
{
"name": "hscript",
"type": "git",
"dir": null,
"ref": "12785398e2f07082f05034cb580682e5671442a2",
"ref": "27c86f9a761c1d16d4433c4cf252eccb7b2e18de",
"url": "https://github.com/FunkinCrew/hscript"
},
{
"name": "hxCodec",
"type": "git",
"dir": null,
"ref": "61b98a7a353b7f529a8fec84ed9afc919a2dffdd",
"url": "https://github.com/FunkinCrew/hxCodec"
},
{
"name": "hxcpp",
"type": "git",
"dir": null,
"ref": "c6bac3d6c7d683f25104296b2f4c50f8c90b8349",
"url": "https://github.com/cortex-engine/hxcpp"
"ref": "v4.3.75",
"url": "https://github.com/HaxeFoundation/hxcpp"
},
{
"name": "hxcpp-debug-server",
@@ -120,6 +113,11 @@
"type": "haxelib",
"version": "1.3.0"
},
{
"name": "hxvlc",
"type": "haxelib",
"version": "2.1.2"
},
{
"name": "json2object",
"type": "git",
@@ -145,7 +143,7 @@
"name": "lime",
"type": "git",
"dir": null,
"ref": "fe3368f611a84a19afc03011353945ae4da8fffd",
"ref": "be81ad7e4e1a92c3482bcc009648a4ac892cfa35",
"url": "https://github.com/FunkinCrew/lime"
},
{
@@ -176,11 +174,18 @@
"ref": "f61be7f7ba796595f45023ca65164a485aba0e7e",
"url": "https://github.com/FunkinCrew/MassiveUnit"
},
{
"name": "newgrounds",
"type": "git",
"dir": null,
"ref": "c8b30832027fa04f48fe6a45fa7903d5b265d56e",
"url": "https://github.com/Geokureli/Newgrounds/"
},
{
"name": "openfl",
"type": "git",
"dir": null,
"ref": "8306425c497766739510ab29e876059c96f77bd2",
"ref": "d061c936b462f040304ec2bd42d9f59d2e59e285",
"url": "https://github.com/FunkinCrew/openfl"
},
{
+58 -18
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.3";
static final VERSION:String = "0.6.4";
/**
* The game's name. Used as the default window title.
@@ -178,6 +178,33 @@ class Project extends HXProject {
*/
static final FEATURE_NEWGROUNDS:FeatureFlag = "FEATURE_NEWGROUNDS";
/**
* `-DFEATURE_NEWGROUNDS_DEBUG`
* If this flag is enabled, the game will enable Newgrounds.io's debug functions.
* This provides additional information in requests, as well as "faking" medal and leaderboard submissions.
*/
static final FEATURE_NEWGROUNDS_DEBUG:FeatureFlag = "FEATURE_NEWGROUNDS_DEBUG";
/**
* `-DFEATURE_NEWGROUNDS_AUTOLOGIN`
* If this flag is enabled, the game will attempt to automatically login to Newgrounds on startup.
*/
static final FEATURE_NEWGROUNDS_AUTOLOGIN:FeatureFlag = "FEATURE_NEWGROUNDS_AUTOLOGIN";
/**
* `-DFEATURE_NEWGROUNDS_TESTING_MEDALS`
* If this flag is enabled, use the medal IDs from the debug test bench.
* If disabled, use the actual medal IDs from the release project on Newgrounds.
*/
static final FEATURE_NEWGROUNDS_TESTING_MEDALS:FeatureFlag = "FEATURE_NEWGROUNDS_TESTING_MEDALS";
/**
* `-DFEATURE_NEWGROUNDS_EVENTS`
* If this flag is enabled, the game will attempt to send events to Newgrounds when the user does stuff.
* This lets us see cool anonymized stats! It only works if the user is logged in.
*/
static final FEATURE_NEWGROUNDS_EVENTS:FeatureFlag = "FEATURE_NEWGROUNDS_EVENTS";
/**
* `-DFEATURE_FUNKVIS`
* If this flag is enabled, the game will enable the Funkin Visualizer library.
@@ -197,7 +224,7 @@ class Project extends HXProject {
/**
* `-DFEATURE_VIDEO_PLAYBACK`
* If this flag is enabled, the game will enable support for video playback.
* This requires the hxCodec library on desktop platforms.
* This requires the hxvlc library on desktop platforms.
*/
static final FEATURE_VIDEO_PLAYBACK:FeatureFlag = "FEATURE_VIDEO_PLAYBACK";
@@ -232,6 +259,12 @@ class Project extends HXProject {
*/
static final FEATURE_STAGE_EDITOR:FeatureFlag = "FEATURE_STAGE_EDITOR";
/**
* `-DFEATURE_RESULTS_DEBUG
* If this flag is enabled, a debug menu for Results screen will be accessible from the debug menu.
*/
static final FEATURE_RESULTS_DEBUG:FeatureFlag = "FEATURE_RESULTS_DEBUG";
/**
* `-DFEATURE_POLYMOD_MODS`
* If this flag is enabled, the game will enable the Polymod library's support for atomic mod loading from the `./mods` folder.
@@ -330,6 +363,8 @@ class Project extends HXProject {
this.window.hardware = true;
this.window.vsync = false;
// force / allow high DPI
this.window.allowHighDPI = true;
if (isWeb()) {
this.window.resizable = true;
@@ -460,7 +495,6 @@ class Project extends HXProject {
// Should be false unless explicitly requested.
GITHUB_BUILD.apply(this, false);
FEATURE_NEWGROUNDS.apply(this, false);
FEATURE_GHOST_TAPPING.apply(this, false);
// Should be true unless explicitly requested.
@@ -474,11 +508,18 @@ 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_RESULTS_DEBUG.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
// Got a lot of complains about this being turned off by default on some builds.
// TODO: Look into ways to optimize logging (maybe by using a thread pool?)
FEATURE_LOG_TRACE.apply(this, true);
FEATURE_NEWGROUNDS.apply(this, true);
FEATURE_NEWGROUNDS_DEBUG.apply(this, false);
FEATURE_NEWGROUNDS_TESTING_MEDALS.apply(this, FEATURE_NEWGROUNDS.isEnabled(this) && FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
FEATURE_NEWGROUNDS_AUTOLOGIN.apply(this, FEATURE_NEWGROUNDS.isEnabled(this) && isWeb());
FEATURE_NEWGROUNDS_EVENTS.apply(this, FEATURE_NEWGROUNDS.isEnabled(this));
// Should default to true on workspace builds and false on release builds.
REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop());
@@ -579,7 +620,7 @@ class Project extends HXProject {
// Ensure all Flixel classes are available at runtime.
// Explicitly ignore packages which require additional dependencies.
addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*' ])");
addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*', 'flixel.addons.tile.FlxRayCastTilemap' ])");
}
/**
@@ -593,7 +634,15 @@ class Project extends HXProject {
function configureOutputDir() {
// Set the output directory. Depends on the target platform and build type.
var buildDir = 'export/${isDebug() ? 'debug' : 'release'}/';
var buildDir = 'export/${isDebug() ? 'debug' : 'release'}';
// we use a dedicated 'tracy' folder, since it generally needs a recompile when in use
if (FEATURE_DEBUG_TRACY.isEnabled(this))
buildDir += "-tracy";
// trailing slash might not be needed, works fine on macOS without it, but I haven't tested on Windows!
buildDir += "/";
info('Output directory: $buildDir');
// setenv('BUILD_DIR', buildDir);
@@ -650,9 +699,9 @@ class Project extends HXProject {
}
if (isDesktop() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this)) {
// hxCodec doesn't function on HashLink or non-desktop platforms
// hxvlc doesn't function on HashLink or non-desktop platforms
// It's also unnecessary if video playback is disabled
addHaxelib('hxCodec'); // Video playback
addHaxelib('hxvlc'); // Video playback
}
if (FEATURE_DISCORD_RPC.isEnabled(this)) {
@@ -724,13 +773,12 @@ class Project extends HXProject {
addAssetLibrary("weekend1", shouldEmbed, shouldPreload);
addAssetPath("assets/weekend1", "assets/weekend1", "weekend1", ["*"], exclude, shouldEmbed);
// Art asset library (where README and CHANGELOG pull from)
// Art asset library (where README pulls from)
var shouldEmbedArt = false;
var shouldPreloadArt = false;
addAssetLibrary("art", shouldEmbedArt, shouldPreloadArt);
addAsset("art/readme.txt", "do NOT readme.txt", "art", shouldEmbedArt);
addAsset("LICENSE.md", "LICENSE.md", "art", shouldEmbedArt);
addAsset("CHANGELOG.md", "CHANGELOG.md", "art", shouldEmbedArt);
}
/**
@@ -1041,15 +1089,7 @@ class Project extends HXProject {
* Display an info message. This should not interfere with the build process.
*/
public function info(message:String):Void {
// CURSED: We have to disable info() log calls because of a bug.
// https://github.com/haxelime/lime-vscode-extension/issues/88
// Log.info('[INFO] ${message}');
// trace(message);
// Sys.println(message);
// Sys.stdout().writeString(message);
// Sys.stderr().writeString(message);
if(command != "display") { Log.info('[INFO] ${message}'); }
}
}
+13 -7
View File
@@ -13,6 +13,7 @@ import openfl.events.Event;
import openfl.Lib;
import openfl.media.Video;
import openfl.net.NetStream;
import funkin.util.WindowUtil;
/**
* The main class which initializes HaxeFlixel and starts the game in its initial state.
@@ -61,12 +62,6 @@ class Main extends Sprite
function init(?event:Event):Void
{
#if web
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
#end
if (hasEventListener(Event.ADDED_TO_STAGE))
{
removeEventListener(Event.ADDED_TO_STAGE, init);
@@ -104,10 +99,21 @@ class Main extends Sprite
// George recommends binding the save before FlxGame is created.
Save.load();
// Don't call anything from the preferences until the save is loaded!
#if web
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
#end
WindowUtil.setVSyncMode(funkin.Preferences.vsyncMode);
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
// create() in there, which gets called when it's added to the stage
// which is why it needs to be added before addChild(game) here
@:privateAccess
game._customSoundTray = funkin.ui.options.FunkinSoundTray;
+32 -1
View File
@@ -9,10 +9,23 @@ class Prebuild
{
static inline final BUILD_TIME_FILE:String = '.build_time';
static final NG_CREDS_PATH:String = './source/funkin/api/newgrounds/NewgroundsCredentials.hx';
static final NG_CREDS_TEMPLATE:String = "package funkin.api.newgrounds;
class NewgroundsCredentials
{
public static final APP_ID:String = #if API_NG_APP_ID haxe.macro.Compiler.getDefine(\"API_NG_APP_ID\") #else 'INSERT APP ID HERE' #end;
public static final ENCRYPTION_KEY:String = #if API_NG_ENC_KEY haxe.macro.Compiler.getDefine(\"API_NG_ENC_KEY\") #else 'INSERT ENCRYPTION KEY HERE' #end;
}";
static function main():Void
{
saveBuildTime();
trace('Building...');
saveBuildTime();
buildCredsFile();
}
static function saveBuildTime():Void
@@ -22,4 +35,22 @@ class Prebuild
fo.writeDouble(now);
fo.close();
}
static function buildCredsFile():Void
{
#if sys
if (sys.FileSystem.exists(NG_CREDS_PATH))
{
trace('NewgroundsCredentials.hx already exists, skipping.');
}
else
{
trace('Creating NewgroundsCredentials.hx...');
var fileContents:String = NG_CREDS_TEMPLATE;
sys.io.File.saveContent(NG_CREDS_PATH, fileContents);
}
#end
}
}
+16
View File
@@ -6,6 +6,7 @@ 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.
*/
@:nullSafety
class Assets
{
/**
@@ -144,16 +145,31 @@ class Assets
return openfl.utils.Assets.list(type);
}
/**
* Checks if a library with the given name exists.
* @param name The name to check.
* @return Whether or not the library exists.
*/
public static function hasLibrary(name:String):Bool
{
return openfl.utils.Assets.hasLibrary(name);
}
/**
* Retrieves a library with the given name.
* @param name The name of the library to get.
* @return The library with the given name.
*/
public static function getLibrary(name:String):lime.utils.AssetLibrary
{
return openfl.utils.Assets.getLibrary(name);
}
/**
* Loads a library with the given name.
* @param name The name of the library to load.
* @return An `AssetLibary` object.
*/
public static function loadLibrary(name:String):Future<openfl.utils.AssetLibrary>
{
return openfl.utils.Assets.loadLibrary(name);
+27 -5
View File
@@ -18,6 +18,7 @@ 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.stickers.StickerRegistry;
import funkin.data.event.SongEventRegistry;
import funkin.data.stage.StageRegistry;
import funkin.data.story.level.LevelRegistry;
@@ -38,6 +39,9 @@ import openfl.display.BitmapData;
#if FEATURE_DISCORD_RPC
import funkin.api.discord.DiscordClient;
#end
#if FEATURE_NEWGROUNDS
import funkin.api.newgrounds.NewgroundsClient;
#end
/**
* A core class which performs initialization of the game.
@@ -82,6 +86,10 @@ class InitState extends FlxState
// Disable the thing on Windows where it tries to send a bug report to Microsoft because why do they care?
WindowUtil.disableCrashHandler();
#if FEATURE_DEBUG_TRACY
funkin.util.WindowUtil.initTracy();
#end
// This ain't a pixel art game! (most of the time)
FlxSprite.defaultAntialiasing = true;
@@ -90,9 +98,18 @@ class InitState extends FlxState
FlxG.sound.volumeDownKeys = [];
FlxG.sound.muteKeys = [];
// A small jumpstart to the soundtray, it usually sets itself to inactive (somewhere...)
// but that makes our soundtray not show up on init if we have the game muted.
// We set it to active so it at least calls it's update function once (see FlxGame.onEnterFrame(), it's called there)
// and also see FunkinSoundTray.update() to see what we do and how we check if we are muted or not
FlxG.game.soundTray.active = true;
// Set the game to a lower frame rate while it is in the background.
FlxG.game.focusLostFramerate = 30;
// Makes Flixel use frame times instead of locked movements per frame for things like tweens
FlxG.fixedTimestep = false;
setupFlixelDebug();
//
@@ -117,8 +134,8 @@ class InitState extends FlxState
//
// NEWGROUNDS API SETUP
//
#if newgrounds
NGio.init();
#if FEATURE_NEWGROUNDS
NewgroundsClient.instance.init();
#end
//
@@ -151,6 +168,7 @@ class InitState extends FlxState
#if FEATURE_SCREENSHOTS
funkin.util.plugins.ScreenshotPlugin.initialize();
#end
funkin.util.plugins.NewgroundsMedalPlugin.initialize();
funkin.util.plugins.EvacuateDebugPlugin.initialize();
funkin.util.plugins.ForceCrashPlugin.initialize();
funkin.util.plugins.ReloadAssetsDebugPlugin.initialize();
@@ -176,6 +194,7 @@ class InitState extends FlxState
FreeplayStyleRegistry.instance.loadEntries();
AlbumRegistry.instance.loadEntries();
StageRegistry.instance.loadEntries();
StickerRegistry.instance.loadEntries();
// TODO: CharacterDataParser doesn't use json2object, so it's way slower than the other parsers and more prone to syntax errors.
// Move it to use a BaseRegistry.
@@ -187,6 +206,8 @@ class InitState extends FlxState
ModuleHandler.loadModuleCache();
ModuleHandler.callOnCreate();
funkin.input.Cursor.hide();
trace('Parsing game data took: ${TimerUtil.ms(perfStart)}');
}
@@ -230,8 +251,8 @@ class InitState extends FlxState
storyMode: true,
title: "Cum Song Erect by Kawai Sprite",
songId: "cum",
characterId: "pico-playable",
difficultyId: "nightmare",
characterId: "pico",
difficultyId: "hard",
isNewHighscore: true,
scoreData:
{
@@ -246,9 +267,10 @@ class InitState extends FlxState
combo: 69,
maxCombo: 69,
totalNotesHit: 140,
totalNotes: 190
totalNotes: 240
}
// 2400 total notes = 7% = LOSS
// 275 total notes = 69% = NICE
// 240 total notes = 79% = GOOD
// 230 total notes = 82% = GREAT
// 210 total notes = 91% = EXCELLENT
+1 -3
View File
@@ -2,11 +2,9 @@ package funkin;
import funkin.save.Save;
import funkin.input.Controls;
import flixel.FlxCamera;
import funkin.input.PreciseInputManager;
import flixel.input.actions.FlxActionInput;
import flixel.input.gamepad.FlxGamepad;
import flixel.util.FlxSignal;
import flixel.util.FlxSignal.FlxTypedSignal;
/**
* A core class which represents the current player(s) and their controls and other configuration.
+185
View File
@@ -1,6 +1,7 @@
package funkin;
import funkin.save.Save;
import funkin.util.WindowUtil;
/**
* A core class which provides a store of user-configurable, globally relevant values.
@@ -157,6 +158,72 @@ class Preferences
return value;
}
/**
* If enabled, the game will automatically launch in fullscreen on startup.
* @default `true`
*/
public static var autoFullscreen(get, set):Bool;
static function get_autoFullscreen():Bool
{
return Save?.instance?.options?.autoFullscreen ?? true;
}
static function set_autoFullscreen(value:Bool):Bool
{
var save:Save = Save.instance;
save.options.autoFullscreen = value;
save.flush();
return value;
}
/**
* If enabled, the game will utilize VSync (or adaptive VSync) on startup.
* @default `OFF`
*/
public static var vsyncMode(get, set):lime.ui.WindowVSyncMode;
static function get_vsyncMode():lime.ui.WindowVSyncMode
{
var value = Save?.instance?.options?.vsyncMode ?? "Off";
return switch (value)
{
case "Off":
lime.ui.WindowVSyncMode.OFF;
case "On":
lime.ui.WindowVSyncMode.ON;
case "Adaptive":
lime.ui.WindowVSyncMode.ADAPTIVE;
default:
lime.ui.WindowVSyncMode.OFF;
};
}
static function set_vsyncMode(value:lime.ui.WindowVSyncMode):lime.ui.WindowVSyncMode
{
var string;
switch (value)
{
case lime.ui.WindowVSyncMode.OFF:
string = "Off";
case lime.ui.WindowVSyncMode.ON:
string = "On";
case lime.ui.WindowVSyncMode.ADAPTIVE:
string = "Adaptive";
default:
string = "Off";
};
WindowUtil.setVSyncMode(value);
var save:Save = Save.instance;
save.options.vsyncMode = string;
save.flush();
return value;
}
public static var unlockedFramerate(get, set):Bool;
static function get_unlockedFramerate():Bool
@@ -199,6 +266,121 @@ class Preferences
public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
#end
/**
* If >0, the game will display a semi-opaque background under the notes.
* `0` for no background, `100` for solid black if you're freaky like that
* @default `0`
*/
public static var strumlineBackgroundOpacity(get, set):Int;
static function get_strumlineBackgroundOpacity():Int
{
return (Save?.instance?.options?.strumlineBackgroundOpacity ?? 0);
}
static function set_strumlineBackgroundOpacity(value:Int):Int
{
var save:Save = Save.instance;
save.options.strumlineBackgroundOpacity = value;
save.flush();
return value;
}
/**
* If enabled, the game will hide the mouse when taking a screenshot.
* @default `true`
*/
public static var shouldHideMouse(get, set):Bool;
static function get_shouldHideMouse():Bool
{
return Save?.instance?.options?.screenshot?.shouldHideMouse ?? true;
}
static function set_shouldHideMouse(value:Bool):Bool
{
var save:Save = Save.instance;
save.options.screenshot.shouldHideMouse = value;
save.flush();
return value;
}
/**
* If enabled, the game will show a preview after taking a screenshot.
* @default `true`
*/
public static var fancyPreview(get, set):Bool;
static function get_fancyPreview():Bool
{
return Save?.instance?.options?.screenshot?.fancyPreview ?? true;
}
static function set_fancyPreview(value:Bool):Bool
{
var save:Save = Save.instance;
save.options.screenshot.fancyPreview = value;
save.flush();
return value;
}
/**
* If enabled, the game will show the preview only after a screenshot is saved.
* @default `true`
*/
public static var previewOnSave(get, set):Bool;
static function get_previewOnSave():Bool
{
return Save?.instance?.options?.screenshot?.previewOnSave ?? true;
}
static function set_previewOnSave(value:Bool):Bool
{
var save:Save = Save.instance;
save.options.screenshot.previewOnSave = value;
save.flush();
return value;
}
/**
* The game will save any screenshots taken to this format.
* @default `PNG`
*/
public static var saveFormat(get, set):Any;
static function get_saveFormat():Any
{
return Save?.instance?.options?.screenshot?.saveFormat ?? 'PNG';
}
static function set_saveFormat(value):Any
{
var save:Save = Save.instance;
save.options.screenshot.saveFormat = value;
save.flush();
return value;
}
/**
* The game will save JPEG screenshots with this quality percentage.
* @default `80`
*/
public static var jpegQuality(get, set):Int;
static function get_jpegQuality():Int
{
return Save?.instance?.options?.screenshot?.jpegQuality ?? 80;
}
static function set_jpegQuality(value:Int):Int
{
var save:Save = Save.instance;
save.options.screenshot.jpegQuality = value;
save.flush();
return value;
}
/**
* Loads the user's preferences from the save data and apply them.
*/
@@ -206,11 +388,14 @@ class Preferences
{
// Apply the autoPause setting (enables automatic pausing on focus lost).
FlxG.autoPause = Preferences.autoPause;
// WindowUtil.setVSyncMode(Preferences.vsyncMode);
// Apply the debugDisplay setting (enables the FPS and RAM display).
toggleDebugDisplay(Preferences.debugDisplay);
#if web
toggleFramerateCap(Preferences.unlockedFramerate);
#end
// Apply the autoFullscreen setting (launches the game in fullscreen automatically)
FlxG.fullscreen = Preferences.autoFullscreen;
}
static function toggleFramerateCap(unlocked:Bool):Void
+4 -1
View File
@@ -2,7 +2,10 @@ package funkin.api.discord;
#if FEATURE_DISCORD_RPC
import hxdiscord_rpc.Discord;
import hxdiscord_rpc.Types;
import hxdiscord_rpc.Types.DiscordButton;
import hxdiscord_rpc.Types.DiscordEventHandlers;
import hxdiscord_rpc.Types.DiscordRichPresence;
import hxdiscord_rpc.Types.DiscordUser;
import sys.thread.Thread;
class DiscordClient
+106
View File
@@ -0,0 +1,106 @@
package funkin.api.newgrounds;
import io.newgrounds.Call.CallOutcome;
import io.newgrounds.NG;
import io.newgrounds.objects.events.Outcome;
import io.newgrounds.objects.events.Result;
/**
* Use Newgrounds to perform basic telemetry. Ignore if not logged in to Newgrounds.
*/
@:nullSafety
class Events
{
// Only allow letters, numbers, spaces, dashes, and underscores.
static final EVENT_NAME_REGEX:EReg = ~/[^a-zA-Z0-9 -_]/g;
public static function logEvent(eventName:String):Void
{
#if (FEATURE_NEWGROUNDS && FEATURE_NEWGROUNDS_EVENTS)
if (NewgroundsClient.instance.isLoggedIn())
{
var eventHandler = NG.core.calls.event;
if (eventHandler != null)
{
var sanitizedEventName = EVENT_NAME_REGEX.replace(eventName, '');
var outcomeHandler = onEventLogged.bind(sanitizedEventName, _);
eventHandler.logEvent(sanitizedEventName).addOutcomeHandler(outcomeHandler).send();
}
}
#end
}
static function onEventLogged(eventName:String, outcome:CallOutcome<LogEventData>)
{
switch (outcome)
{
case SUCCESS(data):
trace('[NEWGROUNDS] Logged event: ${data.eventName}');
case FAIL(outcome):
switch (outcome)
{
case HTTP(error):
trace('[NEWGROUNDS] HTTP error while logging event: ${error}');
case RESPONSE(error):
trace('[NEWGROUNDS] Response error (${error.code}) while logging event: ${error.message}');
case RESULT(error):
switch (error.code)
{
case 103: // Invalid custom event name
trace('[NEWGROUNDS] Invalid custom event name: ${eventName}');
default:
trace('[NEWGROUNDS] Result error (${error.code}) while logging event: ${error.message}');
}
}
}
}
public static inline function logStartGame():Void
{
logEvent('start-game');
}
public static inline function logStartSong(songId:String, variation:String):Void
{
logEvent('start-song_${songId}-${variation}');
}
public static inline function logFailSong(songId:String, variation:String):Void
{
logEvent('blueballs_${songId}-${variation}');
}
public static inline function logCompleteSong(songId:String, variation:String):Void
{
logEvent('complete-song_${songId}-${variation}');
}
public static inline function logStartLevel(levelId:String):Void
{
logEvent('start-level_${levelId}');
}
public static inline function logCompleteLevel(levelId:String):Void
{
logEvent('complete-level_${levelId}');
}
public static inline function logEarnRank(rankName:String):Void
{
logEvent('earn-rank_${rankName}');
}
public static inline function logWatchCartoon():Void
{
logEvent('watch-cartoon');
}
// Note there is already a loadReferral call for the merch link
// and that gets logged as an event!
public static inline function logOpenCredits():Void
{
logEvent('open-credits');
}
}
@@ -0,0 +1,395 @@
package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS
import io.newgrounds.Call.CallError;
import io.newgrounds.objects.ScoreBoard as LeaderboardData;
import io.newgrounds.objects.events.Outcome;
import io.newgrounds.utils.ScoreBoardList;
class Leaderboards
{
public static function listLeaderboardData():Map<Leaderboard, LeaderboardData>
{
var leaderboardList:Null<ScoreBoardList> = NewgroundsClient.instance.leaderboards;
if (leaderboardList == null)
{
trace('[NEWGROUNDS] Not logged in, cannot fetch medal data!');
return [];
}
else
{
var result:Map<Leaderboard, LeaderboardData> = [];
for (leaderboardId in leaderboardList.keys())
{
var leaderboardData = leaderboardList.get(leaderboardId);
if (leaderboardData == null) continue;
// A little hacky, but it works.
result.set(cast leaderboardId, leaderboardData);
}
return result;
}
}
/**
* Submit a score to Newgrounds.
* @param leaderboard The leaderboard to submit to.
* @param score The score to submit.
* @param tag An optional tag to attach to the score.
*/
public static function submitScore(leaderboard:Leaderboard, score:Int, ?tag:String):Void
{
// Silently reject submissions for unknown leaderboards.
if (leaderboard == Leaderboard.Unknown) return;
if (NewgroundsClient.instance.isLoggedIn())
{
var leaderboardList = NewgroundsClient.instance.leaderboards;
if (leaderboardList == null) return;
var leaderboardData:Null<LeaderboardData> = leaderboardList.get(leaderboard.getId());
if (leaderboardData != null)
{
leaderboardData.postScore(score, function(outcome:Outcome<CallError>):Void {
switch (outcome)
{
case SUCCESS:
trace('[NEWGROUNDS] Submitted score!');
case FAIL(error):
trace('[NEWGROUNDS] Failed to submit score!');
trace(error);
}
});
}
}
}
/**
* Submit a score for a Story Level to Newgrounds.
*/
public static function submitLevelScore(levelId:String, difficultyId:String, score:Int):Void
{
var tag = '${difficultyId}';
Leaderboards.submitScore(Leaderboard.getLeaderboardByLevel(levelId), score, tag);
}
/**
* Submit a score for a song to Newgrounds.
*/
public static function submitSongScore(songId:String, difficultyId:String, score:Int):Void
{
var tag = '${difficultyId}';
Leaderboards.submitScore(Leaderboard.getLeaderboardBySong(songId, difficultyId), score, tag);
}
}
#end
enum abstract Leaderboard(Int)
{
/**
* Represents an undefined or invalid leaderboard.
*/
var Unknown = -1;
//
// STORY LEVELS
//
var StoryWeek1 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14239 #else 9615 #end;
var StoryWeek2 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14240 #else 9616 #end;
var StoryWeek3 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14242 #else 9767 #end;
var StoryWeek4 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14241 #else 9866 #end;
var StoryWeek5 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14243 #else 9956 #end;
var StoryWeek6 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14244 #else 9957 #end;
var StoryWeek7 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14245 #else 14682 #end;
var StoryWeekend1 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14237 #else 14683 #end;
//
// SONGS
//
// Tutorial
var Tutorial = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14249 #else 14684 #end;
// Week 1
var Bopeebo = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14246 #else 9603 #end;
var BopeeboErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14685 #end;
var BopeeboPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14686 #end;
var Fresh = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14247 #else 9602 #end;
var FreshErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14687 #end;
var FreshPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14688 #end;
var DadBattle = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 14248 #else 9605 #end;
var DadBattleErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14689 #end;
var DadBattlePicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14690 #end;
// Week 2
var Spookeez = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9604 #end;
var SpookeezErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14691 #end;
var SpookeezPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14692 #end;
var South = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9606 #end;
var SouthErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14693 #end;
var SouthPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14694 #end;
var Monster = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14703 #end;
// Week 3
var Pico = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9766 #end;
var PicoErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14695 #end;
var PicoPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14696 #end;
var PhillyNice = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9769 #end;
var PhillyNiceErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14697 #end;
var PhillyNicePicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14698 #end;
var Blammed = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9768 #end;
var BlammedErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14704 #end;
var BlammedPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14705 #end;
// Week 4
var SatinPanties = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9869 #end;
var SatinPantiesErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14701 #end;
var High = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9867 #end;
var HighErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14699 #end;
var MILF = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9868 #end;
// Week 5
var Cocoa = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14706 #end;
var CocoaErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14707 #end;
var CocoaPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14708 #end;
var Eggnog = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14709 #end;
var EggnogErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14711 #end;
var EggnogPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14710 #end;
var WinterHorrorland = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14712 #end;
// Week 6
var Senpai = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9958 #end;
var SenpaiErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14713 #end;
var SenpaiPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14716 #end;
var Roses = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9959 #end;
var RosesErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14714 #end;
var RosesPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14717 #end;
var Thorns = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 9960 #end;
var ThornsErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14715 #end;
// Week 7
var Ugh = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14718 #end;
var UghErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14722 #end;
var UghPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14721 #end;
var Guns = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14719 #end;
var GunsPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14723 #end;
var Stress = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14720 #end;
var StressPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14724 #end;
// Weekend 1
var Darnell = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14725 #end;
var DarnellErect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14727 #end;
var DarnellBFMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14726 #end;
var LitUp = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14728 #end;
var LitUpBFMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14729 #end;
var TwoHot = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14730 #end; // Variable names can't start with a number!
var Blazin = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 1000000 #else 14731 #end;
public function getId():Int
{
return this;
}
/**
* Get the leaderboard for a given level and difficulty.
* @param levelId The ID for the story level.
* @param difficulty The current difficulty.
* @return The Leaderboard ID for the given level and difficulty.
*/
public static function getLeaderboardByLevel(levelId:String):Leaderboard
{
switch (levelId)
{
case "week1":
return StoryWeek1;
case "week2":
return StoryWeek2;
case "week3":
return StoryWeek3;
case "week4":
return StoryWeek4;
case "week5":
return StoryWeek5;
case "week6":
return StoryWeek6;
case "week7":
return StoryWeek7;
case "weekend1":
return StoryWeekend1;
default:
return Unknown;
}
}
/**
* Get the leaderboard for a given level and difficulty.
* @param levelId The ID for the story level.
* @param difficulty The current difficulty, suffixed with the variation, like `easy-pico` or `nightmare`.
* @return The Leaderboard ID for the given level and difficulty.
*/
public static function getLeaderboardBySong(songId:String, difficulty:String):Leaderboard
{
var variation = Constants.DEFAULT_VARIATION;
var difficultyParts = difficulty.split('-');
if (difficultyParts.length >= 2)
{
variation = difficultyParts[difficultyParts.length - 1];
}
else if (Constants.DEFAULT_DIFFICULTY_LIST_ERECT.contains(difficulty))
{
variation = "erect";
}
switch (variation)
{
case "pico":
switch (songId)
{
case "bopeebo":
return BopeeboPicoMix;
case "fresh":
return FreshPicoMix;
case "dadbattle":
return DadBattlePicoMix;
case "spookeez":
return SpookeezPicoMix;
case "south":
return SouthPicoMix;
case "pico":
return PicoPicoMix;
case "philly-nice":
return PhillyNicePicoMix;
case "blammed":
return BlammedPicoMix;
case "cocoa":
return CocoaPicoMix;
case "eggnog":
return EggnogPicoMix;
case "senpai":
return SenpaiPicoMix;
case "roses":
return RosesPicoMix;
case "ugh":
return UghPicoMix;
case "guns":
return GunsPicoMix;
case "stress":
return StressPicoMix;
default:
return Unknown;
}
case "bf":
switch (songId)
{
case "darnell":
return DarnellBFMix;
case "litup":
return LitUpBFMix;
default:
return Unknown;
}
case "erect":
switch (songId)
{
case "bopeebo":
return BopeeboErect;
case "fresh":
return FreshErect;
case "dadbattle":
return DadBattleErect;
case "spookeez":
return SpookeezErect;
case "south":
return SouthErect;
case "pico":
return PicoErect;
case "philly-nice":
return PhillyNiceErect;
case "blammed":
return BlammedErect;
case "satin-panties":
return SatinPantiesErect;
case "high":
return HighErect;
case "cocoa":
return CocoaErect;
case "eggnog":
return EggnogErect;
case "senpai":
return SenpaiErect;
case "roses":
return RosesErect;
case "thorns":
return ThornsErect;
case "ugh":
return UghErect;
case "darnell":
return DarnellErect;
default:
return Unknown;
}
case "default":
switch (songId)
{
case "tutorial":
return Tutorial;
case "bopeebo":
return Bopeebo;
case "fresh":
return Fresh;
case "dadbattle":
return DadBattle;
case "spookeez":
return Spookeez;
case "south":
return South;
case "monster":
return Monster;
case "pico":
return Pico;
case "philly-nice":
return PhillyNice;
case "blammed":
return Blammed;
case "satin-panties":
return SatinPanties;
case "high":
return High;
case "milf":
return MILF;
case "cocoa":
return Cocoa;
case "eggnog":
return Eggnog;
case "winter-horrorland":
return WinterHorrorland;
case "senpai":
return Senpai;
case "roses":
return Roses;
case "thorns":
return Thorns;
case "ugh":
return Ugh;
case "guns":
return Guns;
case "stress":
return Stress;
case "darnell":
return Darnell;
case "litup":
return LitUp;
case "2hot":
return TwoHot;
case "blazin":
return Blazin;
default:
return Unknown;
}
default:
return Unknown;
}
}
}
+347
View File
@@ -0,0 +1,347 @@
package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS
import io.newgrounds.objects.Medal as MedalData;
import funkin.util.plugins.NewgroundsMedalPlugin;
import flixel.graphics.FlxGraphic;
import openfl.display.BitmapData;
import io.newgrounds.utils.MedalList;
import haxe.Json;
class Medals
{
public static var medalJSON:Array<MedalJSON> = [];
public static function listMedalData():Map<Medal, MedalData>
{
var medalList = NewgroundsClient.instance.medals;
if (medalList == null)
{
trace('[NEWGROUNDS] Not logged in, cannot fetch medal data!');
return [];
}
else
{
// TODO: Why do I have to do this, @:nullSafety is fucked up
var result:Map<Medal, MedalData> = [];
for (medalId in medalList.keys())
{
var medalData = medalList.get(medalId);
if (medalData == null) continue;
// A little hacky, but it works.
result.set(cast medalId, medalData);
}
return result;
}
}
public static function award(medal:Medal):Void
{
if (NewgroundsClient.instance.isLoggedIn())
{
var medalList = NewgroundsClient.instance.medals;
@:privateAccess
if (medalList == null || medalList._map == null) return;
var medalData:Null<MedalData> = medalList.get(medal.getId());
@:privateAccess
if (medalData == null || medalData._data == null)
{
trace('[NEWGROUNDS] Could not retrieve data for medal: ${medal}');
return;
}
else if (!medalData.unlocked)
{
trace('[NEWGROUNDS] Awarding medal (${medal}).');
medalData.sendUnlock();
// Play the medal unlock animation, but only if the user has not already unlocked it.
#if html5
// Web builds support parsing the bitmap data from the URL directly.
BitmapData.loadFromFile("https:" + medalData.icon).onComplete(function(bmp:BitmapData) {
var medalGraphic = FlxGraphic.fromBitmapData(bmp);
medalGraphic.persist = true;
NewgroundsMedalPlugin.play(medalData.value, medalData.name, medalGraphic);
});
#else
if ((medalJSON?.length ?? 0) == 0) loadMedalJSON();
// We have to use a medal image from the game files. We use a Base64 encoded image that NG spits out.
// TODO: Wait, don't they give us the medal icon?
var localMedalData:Null<MedalJSON> = medalJSON.filter(function(jsonMedal) {
#if FEATURE_NEWGROUNDS_TESTING_MEDALS
return medal == jsonMedal.idTest;
#else
return medal == jsonMedal.id;
#end
})[0];
if (localMedalData == null) throw "You forgot to encode a Base64 image for medal: " + medal;
var str:String = localMedalData.icon;
// Lime/OpenFL parses it without the included prefix stuff, so we remove it.
str = str.replace("data:image/png;base64,", "").trim();
var bitmapData = BitmapData.fromBase64(str, "image/png");
var medalGraphic:Null<FlxGraphic> = null;
if (str != null)
{
medalGraphic = FlxGraphic.fromBitmapData(bitmapData);
medalGraphic.persist = true;
}
NewgroundsMedalPlugin.play(medalData.value, medalData.name, medalGraphic);
#end
}
else
{
trace('[NEWGROUNDS] User already has medal (${medal}).');
}
}
else
{
trace('[NEWGROUNDS] Attempted to award medal (${medal}), but not logged into Newgrounds.');
}
}
public static function loadMedalJSON():Void
{
var jsonPath = Paths.json('medals');
var jsonString = Assets.getText(jsonPath);
var parser = new json2object.JsonParser<Array<MedalJSON>>();
parser.ignoreUnknownVariables = false;
trace('[NEWGROUNDS] Parsing local medal data...');
parser.fromJson(jsonString, jsonPath);
if (parser.errors.length > 0)
{
trace('[NEWGROUNDS] Failed to parse local medal data!');
for (error in parser.errors)
funkin.data.DataError.printError(error);
medalJSON = [];
}
else
{
medalJSON = parser.value;
}
}
public static function awardStoryLevel(id:String):Void
{
switch (id)
{
case 'tutorial':
Medals.award(Medal.StoryTutorial);
case 'week1':
Medals.award(Medal.StoryWeek1);
case 'week2':
Medals.award(Medal.StoryWeek2);
case 'week3':
Medals.award(Medal.StoryWeek3);
case 'week4':
Medals.award(Medal.StoryWeek4);
case 'week5':
Medals.award(Medal.StoryWeek5);
case 'week6':
Medals.award(Medal.StoryWeek6);
case 'week7':
Medals.award(Medal.StoryWeek7);
case 'weekend1':
Medals.award(Medal.StoryWeekend1);
default:
trace('[NEWGROUNDS] Story level does not have a medal! (${id}).');
}
}
}
#end
/**
* Represents NG Medal data in a JSON format.
*/
typedef MedalJSON =
{
/**
* Medal ID to use for release builds
*/
var id:Int;
/**
* Medal ID to use for testing builds
*/
var idTest:Int;
/**
* The English name for the medal
*/
var name:String;
/**
* The English name for the medal
*/
var icon:String;
}
enum abstract Medal(Int) from Int to Int
{
/**
* Represents an undefined or invalid medal.
*/
var Unknown = -1;
/**
* I Said Funkin'!
* Start the game for the first time.
*/
var StartGame = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80894 #else 60960 #end;
/**
* That's How You Do It!
* Beat Tutoria l in Story Mode (on any difficulty).
*/
var StoryTutorial = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80906 #else 83647 #end;
/**
* More Like Daddy Queerest
* Beat Week 1 in Story Mode (on any difficulty).
*/
var StoryWeek1 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80899 #else 60961 #end;
/**
* IT IS THE SPOOKY MONTH
* Beat Week 2 in Story Mode (on any difficulty).
*/
var StoryWeek2 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80900 #else 83648 #end;
/**
* Pico Funny
* Beat Week 3 in Story Mode (on any difficulty).
*/
var StoryWeek3 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80901 #else 83649 #end;
/**
* Mommy Must Murder
* Beat Week 4 in Story Mode (on any difficulty).
*/
var StoryWeek4 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80902 #else 83650 #end;
/**
* Yule Tide Joy
* Beat Week 5 in Story Mode (on any difficulty).
*/
var StoryWeek5 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80903 #else 83651 #end;
/**
* A Visual Novelty
* Beat Week 6 in Story Mode (on any difficulty).
*/
var StoryWeek6 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80904 #else 83652 #end;
/**
* I <3 JohnnyUtah
* Beat Week 7 in Story Mode (on any difficulty).
*/
var StoryWeek7 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80905 #else 83653 #end;
/**
* Yo, Really Think So?
* Beat Weekend 1 in Story Mode (on any difficulty).
*/
var StoryWeekend1 = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80907 #else 83654 #end;
/**
* Stay Funky
* Press TAB in Freeplay and unlock your first character.
*/
var CharSelect = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 83633 #else 83655 #end;
/**
* A Challenger Appears
* Beat any Pico remix in Freeplay (on any difficulty).
*/
var FreeplayPicoMix = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80910 #else 83656 #end;
/**
* De-Stressing
* Beat Stress (Pico Mix) in Freeplay (on Normal difficulty or higher).
*/
var FreeplayStressPico = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 83629 #else 83657 #end;
/**
* L
* Earn a Loss rating on any song (on any difficulty).
*/
var LossRating = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80915 #else 83658 #end;
/**
* Getting Freaky
* Earn a Perfect rating on any song on Hard difficulty or higher.
* NOTE: Should also be awarded for a Gold Perfect because otherwise that would be annoying.
*/
var PerfectRatingHard = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80908 #else 83659 #end;
/**
* You Should Drink More Water
* Earn a Golden Perfect rating on any song on Hard difficulty or higher.
*/
var GoldPerfectRatingHard = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80909 #else 83660 #end;
/**
* Harder Than Hard
* Beat any Erect remix in Freeplay on Erect or Nightmare difficulty.
*/
var ErectDifficulty = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80911 #else 83661 #end;
/**
* The Rap God
* Earn a Gold Perfect rating on any song on Nightmare difficulty.
*/
var GoldPerfectRatingNightmare = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80912 #else 83662 #end;
/**
* Just like the game!
* Get freaky on a Friday.
* NOTE: You must beat at least one song on any difficulty.
*/
var FridayNight = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80913 #else 61034 #end;
/**
* Nice
* Earn a rating of EXACTLY 69% (good luck).
*/
var Nice = #if FEATURE_NEWGROUNDS_TESTING_MEDALS 80914 #else 83646 #end;
public function getId():Int
{
return this;
}
public static function getMedalByStoryLevel(levelId:String):Medal
{
switch (levelId)
{
case "week1":
return StoryWeek1;
case "week2":
return StoryWeek2;
case "week3":
return StoryWeek3;
case "week4":
return StoryWeek4;
case "week5":
return StoryWeek5;
case "week6":
return StoryWeek6;
case "week7":
return StoryWeek7;
case "weekend1":
return StoryWeekend1;
default:
return Unknown;
}
}
}
-71
View File
@@ -1,71 +0,0 @@
package funkin.api.newgrounds;
#if newgrounds
import io.newgrounds.NG;
import io.newgrounds.NGLite;
import io.newgrounds.components.ScoreBoardComponent.Period;
import io.newgrounds.objects.Error;
import io.newgrounds.objects.Medal;
import io.newgrounds.objects.Score;
import io.newgrounds.objects.ScoreBoard;
import io.newgrounds.objects.events.Response;
import io.newgrounds.objects.events.Result.GetCurrentVersionResult;
import io.newgrounds.objects.events.Result.GetVersionResult;
#end
/**
* Contains any script functions which should be BLOCKED from use by modded scripts.
*/
class NGUnsafe
{
static public function logEvent(event:String)
{
#if newgrounds
NG.core.calls.event.logEvent(event).send();
trace('should have logged: ' + event);
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('event:$event - not logged, missing NG.io lib');
#end
#end
}
static public function unlockMedal(id:Int)
{
#if newgrounds
if (isLoggedIn)
{
var medal = NG.core.medals.get(id);
if (!medal.unlocked) medal.sendUnlock();
}
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('medal:$id - not unlocked, missing NG.io lib');
#end
#end
}
static public function postScore(score:Int = 0, song:String)
{
#if newgrounds
if (isLoggedIn)
{
for (id in NG.core.scoreBoards.keys())
{
var board = NG.core.scoreBoards.get(id);
if (song == board.name)
{
board.postScore(score, "Uhh meow?");
}
// trace('loaded scoreboard id:$id, name:${board.name}');
}
}
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('Song:$song, Score:$score - not posted, missing NG.io lib');
#end
#end
}
}
-243
View File
@@ -1,243 +0,0 @@
package funkin.api.newgrounds;
import flixel.util.FlxSignal;
import flixel.util.FlxTimer;
import lime.app.Application;
import openfl.display.Stage;
#if newgrounds
import io.newgrounds.NG;
import io.newgrounds.NGLite;
import io.newgrounds.components.ScoreBoardComponent.Period;
import io.newgrounds.objects.Error;
import io.newgrounds.objects.Medal;
import io.newgrounds.objects.Score;
import io.newgrounds.objects.ScoreBoard;
import io.newgrounds.objects.events.Response;
import io.newgrounds.objects.events.Result.GetCurrentVersionResult;
import io.newgrounds.objects.events.Result.GetVersionResult;
#end
/**
* Contains any script functions which should be ALLOWD for use by modded scripts.
*/
class NGUtil
{
#if newgrounds
/**
* True, if the saved sessionId was used in the initial login, and failed to connect.
* Used in MainMenuState to show a popup to establish a new connection
*/
public static var savedSessionFailed(default, null):Bool = false;
public static var scoreboardsLoaded:Bool = false;
public static var isLoggedIn(get, never):Bool;
inline static function get_isLoggedIn()
{
return NG.core != null && NG.core.loggedIn;
}
public static var scoreboardArray:Array<Score> = [];
public static var ngDataLoaded(default, null):FlxSignal = new FlxSignal();
public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal();
public static var GAME_VER:String = "";
static public function checkVersion(callback:String->Void)
{
trace('checking NG.io version');
GAME_VER = "v" + Application.current.meta.get('version');
NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response) {
GAME_VER = response.result.data.currentVersion;
trace('CURRENT NG VERSION: ' + GAME_VER);
callback(GAME_VER);
}).send();
}
static public function init()
{
var api = APIStuff.API;
if (api == null || api.length == 0)
{
trace("Missing Newgrounds API key, aborting connection");
return;
}
trace("connecting to newgrounds");
#if NG_FORCE_EXPIRED_SESSION
var sessionId:String = "fake_session_id";
function onSessionFail(error:Error)
{
trace("Forcing an expired saved session. " + "To disable, comment out NG_FORCE_EXPIRED_SESSION in Project.xml");
savedSessionFailed = true;
}
#else
var sessionId:String = NGLite.getSessionId();
if (sessionId != null) trace("found web session id");
#if (debug)
if (sessionId == null && APIStuff.SESSION != null)
{
trace("using debug session id");
sessionId = APIStuff.SESSION;
}
#end
var onSessionFail:Error->Void = null;
if (sessionId == null && Save.instance.ngSessionId != null)
{
trace("using stored session id");
sessionId = Save.instance.ngSessionId;
onSessionFail = function(error) savedSessionFailed = true;
}
#end
NG.create(api, sessionId, #if NG_DEBUG true #else false #end, onSessionFail);
#if NG_VERBOSE
NG.core.verbose = true;
#end
// Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet
NG.core.initEncryption(APIStuff.EncKey); // Found in you NG project view
if (NG.core.attemptingLogin)
{
/* a session_id was found in the loadervars, this means the user is playing on newgrounds.com
* and we should login shortly. lets wait for that to happen
*/
trace("attempting login");
NG.core.onLogin.add(onNGLogin);
}
// GK: taking out auto login, adding a login button to the main menu
// else
// {
// /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
// * Note: This will cause a new browser window to pop up where they can log in to newgrounds
// */
// NG.core.requestLogin(onNGLogin);
// }
}
/**
* Attempts to log in to newgrounds by requesting a new session ID, only call if no session ID was found automatically
* @param popupLauncher The function to call to open the login url, must be inside
* a user input event or the popup blocker will block it.
* @param onComplete A callback with the result of the connection.
*/
static public function login(?popupLauncher:(Void->Void)->Void, onComplete:ConnectionResult->Void)
{
trace("Logging in manually");
var onPending:Void->Void = null;
if (popupLauncher != null)
{
onPending = function() popupLauncher(NG.core.openPassportUrl);
}
var onSuccess:Void->Void = onNGLogin;
var onFail:Error->Void = null;
var onCancel:Void->Void = null;
if (onComplete != null)
{
onSuccess = function() {
onNGLogin();
onComplete(Success);
}
onFail = function(e) onComplete(Fail(e.message));
onCancel = function() onComplete(Cancelled);
}
NG.core.requestLogin(onSuccess, onPending, onFail, onCancel);
}
inline static public function cancelLogin():Void
{
NG.core.cancelLoginRequest();
}
static function onNGLogin():Void
{
trace('logged in! user:${NG.core.user.name}');
Save.instance.ngSessionId = NG.core.sessionId;
Save.instance.flush();
// Load medals then call onNGMedalFetch()
NG.core.requestMedals(onNGMedalFetch);
// Load Scoreboards hten call onNGBoardsFetch()
NG.core.requestScoreBoards(onNGBoardsFetch);
ngDataLoaded.dispatch();
}
static public function logout()
{
NG.core.logOut();
Save.instance.ngSessionId = null;
Save.instance.flush();
}
// --- MEDALS
static function onNGMedalFetch():Void
{
/*
// Reading medal info
for (id in NG.core.medals.keys())
{
var medal = NG.core.medals.get(id);
trace('loaded medal id:$id, name:${medal.name}, description:${medal.description}');
}
// Unlocking medals
var unlockingMedal = NG.core.medals.get(54352);// medal ids are listed in your NG project viewer
if (!unlockingMedal.unlocked)
unlockingMedal.sendUnlock();
*/
}
// --- SCOREBOARDS
static function onNGBoardsFetch():Void
{
/*
// Reading medal info
for (id in NG.core.scoreBoards.keys())
{
var board = NG.core.scoreBoards.get(id);
trace('loaded scoreboard id:$id, name:${board.name}');
}
*/
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
// Posting a score thats OVER 9000!
// board.postScore(FlxG.random.int(0, 1000));
// --- To view the scores you first need to select the range of scores you want to see ---
// add an update listener so we know when we get the new scores
// board.onUpdate.add(onNGScoresFetch);
trace("shoulda got score by NOW!");
// board.requestScores(20);// get the best 10 scores ever logged
// more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores
}
static function onNGScoresFetch():Void
{
scoreboardsLoaded = true;
ngScoresLoaded.dispatch();
/*
for (score in NG.core.scoreBoards.get(8737).scores)
{
trace('score loaded user:${score.user.name}, score:${score.formatted_value}');
}
*/
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
// board.postScore(HighScore.score);
// NGUtil.scoreboardArray = NG.core.scoreBoards.get(8004).scores;
}
#end
}
-298
View File
@@ -1,298 +0,0 @@
package funkin.api.newgrounds;
#if newgrounds
import flixel.util.FlxSignal;
import io.newgrounds.NG;
import io.newgrounds.NGLite;
import io.newgrounds.objects.Error;
import io.newgrounds.objects.Score;
import lime.app.Application;
#end
/**
* MADE BY GEOKURELI THE LEGENED GOD HERO MVP
*/
class NGio
{
#if newgrounds
/**
* True, if the saved sessionId was used in the initial login, and failed to connect.
* Used in MainMenuState to show a popup to establish a new connection
*/
public static var savedSessionFailed(default, null):Bool = false;
public static var scoreboardsLoaded:Bool = false;
public static var isLoggedIn(get, never):Bool;
inline static function get_isLoggedIn()
{
return NG.core != null && NG.core.loggedIn;
}
public static var scoreboardArray:Array<Score> = [];
public static var ngDataLoaded(default, null):FlxSignal = new FlxSignal();
public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal();
public static var GAME_VER:String = "";
static public function checkVersion(callback:String->Void)
{
trace('checking NG.io version');
GAME_VER = "v" + Application.current.meta.get('version');
NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response) {
GAME_VER = response.result.data.currentVersion;
trace('CURRENT NG VERSION: ' + GAME_VER);
callback(GAME_VER);
}).send();
}
static public function init()
{
var api = APIStuff.API;
if (api == null || api.length == 0)
{
trace("Missing Newgrounds API key, aborting connection");
return;
}
trace("connecting to newgrounds");
#if NG_FORCE_EXPIRED_SESSION
var sessionId:String = "fake_session_id";
function onSessionFail(error:Error)
{
trace("Forcing an expired saved session. " + "To disable, comment out NG_FORCE_EXPIRED_SESSION in Project.xml");
savedSessionFailed = true;
}
#else
var sessionId:String = NGLite.getSessionId();
if (sessionId != null) trace("found web session id");
#if (debug)
if (sessionId == null && APIStuff.SESSION != null)
{
trace("using debug session id");
sessionId = APIStuff.SESSION;
}
#end
var onSessionFail:Error->Void = null;
if (sessionId == null && Save.instance.ngSessionId != null)
{
trace("using stored session id");
sessionId = Save.instance.ngSessionId;
onSessionFail = function(error) savedSessionFailed = true;
}
#end
NG.create(api, sessionId, #if NG_DEBUG true #else false #end, onSessionFail);
#if NG_VERBOSE
NG.core.verbose = true;
#end
// Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet
NG.core.initEncryption(APIStuff.EncKey); // Found in you NG project view
if (NG.core.attemptingLogin)
{
/* a session_id was found in the loadervars, this means the user is playing on newgrounds.com
* and we should login shortly. lets wait for that to happen
*/
trace("attempting login");
NG.core.onLogin.add(onNGLogin);
}
// GK: taking out auto login, adding a login button to the main menu
// else
// {
// /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
// * Note: This will cause a new browser window to pop up where they can log in to newgrounds
// */
// NG.core.requestLogin(onNGLogin);
// }
}
/**
* Attempts to log in to newgrounds by requesting a new session ID, only call if no session ID was found automatically
* @param popupLauncher The function to call to open the login url, must be inside
* a user input event or the popup blocker will block it.
* @param onComplete A callback with the result of the connection.
*/
static public function login(?popupLauncher:(Void->Void)->Void, onComplete:ConnectionResult->Void)
{
trace("Logging in manually");
var onPending:Void->Void = null;
if (popupLauncher != null)
{
onPending = function() popupLauncher(NG.core.openPassportUrl);
}
var onSuccess:Void->Void = onNGLogin;
var onFail:Error->Void = null;
var onCancel:Void->Void = null;
if (onComplete != null)
{
onSuccess = function() {
onNGLogin();
onComplete(Success);
}
onFail = function(e) onComplete(Fail(e.message));
onCancel = function() onComplete(Cancelled);
}
NG.core.requestLogin(onSuccess, onPending, onFail, onCancel);
}
inline static public function cancelLogin():Void
{
NG.core.cancelLoginRequest();
}
static function onNGLogin():Void
{
trace('logged in! user:${NG.core.user.name}');
Save.instance.ngSessionId = NG.core.sessionId;
Save.instance.flush();
// Load medals then call onNGMedalFetch()
NG.core.requestMedals(onNGMedalFetch);
// Load Scoreboards hten call onNGBoardsFetch()
NG.core.requestScoreBoards(onNGBoardsFetch);
ngDataLoaded.dispatch();
}
static public function logout()
{
NG.core.logOut();
Save.instance.ngSessionId = null;
Save.instance.flush();
}
// --- MEDALS
static function onNGMedalFetch():Void
{
/*
// Reading medal info
for (id in NG.core.medals.keys())
{
var medal = NG.core.medals.get(id);
trace('loaded medal id:$id, name:${medal.name}, description:${medal.description}');
}
// Unlocking medals
var unlockingMedal = NG.core.medals.get(54352);// medal ids are listed in your NG project viewer
if (!unlockingMedal.unlocked)
unlockingMedal.sendUnlock();
*/
}
// --- SCOREBOARDS
static function onNGBoardsFetch():Void
{
/*
// Reading medal info
for (id in NG.core.scoreBoards.keys())
{
var board = NG.core.scoreBoards.get(id);
trace('loaded scoreboard id:$id, name:${board.name}');
}
*/
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
// Posting a score thats OVER 9000!
// board.postScore(FlxG.random.int(0, 1000));
// --- To view the scores you first need to select the range of scores you want to see ---
// add an update listener so we know when we get the new scores
// board.onUpdate.add(onNGScoresFetch);
trace("shoulda got score by NOW!");
// board.requestScores(20);// get the best 10 scores ever logged
// more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores
}
static function onNGScoresFetch():Void
{
scoreboardsLoaded = true;
ngScoresLoaded.dispatch();
/*
for (score in NG.core.scoreBoards.get(8737).scores)
{
trace('score loaded user:${score.user.name}, score:${score.formatted_value}');
}
*/
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
// board.postScore(HighScore.score);
// NGio.scoreboardArray = NG.core.scoreBoards.get(8004).scores;
}
#end
static public function logEvent(event:String)
{
#if newgrounds
NG.core.calls.event.logEvent(event).send();
trace('should have logged: ' + event);
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('event:$event - not logged, missing NG.io lib');
#end
#end
}
static public function unlockMedal(id:Int)
{
#if newgrounds
if (isLoggedIn)
{
var medal = NG.core.medals.get(id);
if (!medal.unlocked) medal.sendUnlock();
}
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('medal:$id - not unlocked, missing NG.io lib');
#end
#end
}
static public function postScore(score:Int = 0, song:String)
{
#if newgrounds
if (isLoggedIn)
{
for (id in NG.core.scoreBoards.keys())
{
var board = NG.core.scoreBoards.get(id);
if (song == board.name)
{
board.postScore(score, "Uhh meow?");
}
// trace('loaded scoreboard id:$id, name:${board.name}');
}
}
#else
#if FEATURE_DEBUG_FUNCTIONS
trace('Song:$song, Score:$score - not posted, missing NG.io lib');
#end
#end
}
}
enum ConnectionResult
{
/** Log in successful */
Success;
/** Could not login */
Fail(msg:String);
/** User cancelled the login */
Cancelled;
}
@@ -0,0 +1,334 @@
package funkin.api.newgrounds;
import funkin.save.Save;
import funkin.api.newgrounds.Medals.Medal;
#if FEATURE_NEWGROUNDS
import io.newgrounds.Call.CallError;
import io.newgrounds.NG;
import io.newgrounds.NGLite;
import io.newgrounds.NGLite.LoginOutcome;
import io.newgrounds.NGLite.LoginFail;
import io.newgrounds.objects.events.Outcome;
import io.newgrounds.utils.MedalList;
import io.newgrounds.utils.ScoreBoardList;
import io.newgrounds.objects.User;
@:nullSafety
class NewgroundsClient
{
public static var instance(get, never):NewgroundsClient;
static var _instance:Null<NewgroundsClient> = null;
static function get_instance():NewgroundsClient
{
if (NewgroundsClient._instance == null) _instance = new NewgroundsClient();
if (NewgroundsClient._instance == null) throw "Could not initialize singleton NewgroundsClient!";
return NewgroundsClient._instance;
}
public var user(get, never):Null<User>;
public var medals(get, never):Null<MedalList>;
public var leaderboards(get, never):Null<ScoreBoardList>;
private function new()
{
trace('[NEWGROUNDS] Initializing client...');
#if FEATURE_NEWGROUNDS_DEBUG
trace('[NEWGROUNDS] App ID: ${NewgroundsCredentials.APP_ID}');
trace('[NEWGROUNDS] Encryption Key: ${NewgroundsCredentials.ENCRYPTION_KEY}');
#end
if (!hasValidCredentials())
{
FlxG.log.warn("Tried to initialize Newgrounds client, but credentials are invalid!");
return;
}
var debug = #if FEATURE_NEWGROUNDS_DEBUG true #else false #end;
NG.create(NewgroundsCredentials.APP_ID, getSessionId(), debug, onLoginResolved);
NG.core.setupEncryption(NewgroundsCredentials.ENCRYPTION_KEY);
}
public function init()
{
if (NG.core == null) return;
trace('[NEWGROUNDS] Setting up connection...');
#if FEATURE_NEWGROUNDS_DEBUG
NG.core.verbose = true;
#end
NG.core.onLogin.add(onLoginSuccessful);
if (NG.core.attemptingLogin)
{
// Session ID was valid and we should be logged in soon.
trace('[NEWGROUNDS] Waiting for existing login!');
}
else
{
#if FEATURE_NEWGROUNDS_AUTOLOGIN
// Attempt an automatic login.
trace('[NEWGROUNDS] Attempting new login immediately!');
this.autoLogin();
#else
trace('[NEWGROUNDS] Not logged in, you have to login manually!');
#end
}
}
/**
* Attempt to log into Newgrounds and create a session ID.
* @param onSuccess An optional callback for when the login is successful.
* @param onError An optional callback for when the login fails.
*/
public function login(?onSuccess:Void->Void, ?onError:Void->Void):Void
{
if (NG.core == null)
{
FlxG.log.warn("No Newgrounds client initialized! Are your credentials invalid?");
return;
}
if (onSuccess != null && onError != null)
{
NG.core.requestLogin(onLoginResolvedWithCallbacks.bind(_, onSuccess, onError));
}
else
{
NG.core.requestLogin(onLoginResolved);
}
}
public function autoLogin(?onSuccess:Void->Void, ?onError:Void->Void):Void
{
if (NG.core == null)
{
FlxG.log.warn("No Newgrounds client initialized! Are your credentials invalid?");
return;
}
var dummyPassport:String->Void = function(_) {
// just a dummy passport, so we don't create a popup
// otherwise `NG.core.requestLogin()` will automatically attempt to open a tab at the beginning of the game
// users should go to the Options Menu to login to NG
// we cancel the request, so we can call it later
NG.core.cancelLoginRequest();
};
if (onSuccess != null && onError != null)
{
NG.core.requestLogin(onLoginResolvedWithCallbacks.bind(_, onSuccess, onError), dummyPassport);
}
else
{
NG.core.requestLogin(onLoginResolved, dummyPassport);
}
}
/**
* Log out of Newgrounds and invalidate the current session.
* @param onSuccess An optional callback for when the logout is successful.
*/
public function logout(?onSuccess:Void->Void, ?onError:Void->Void):Void
{
if (NG.core != null)
{
if (onSuccess != null && onError != null)
{
NG.core.logOut(onLogoutResolvedWithCallbacks.bind(_, onSuccess, onError));
}
else
{
NG.core.logOut(onLogoutResolved);
}
}
Save.instance.ngSessionId = null;
}
/**
* @return `true` if the user is logged in to Newgrounds.
*/
public function isLoggedIn():Bool
{
#if FEATURE_NEWGROUNDS
return NG.core != null && NG.core.loggedIn;
#else
return false;
#end
}
/**
* @returns `false` if either the app ID or the encryption key is invalid.
*/
static function hasValidCredentials():Bool
{
return !(NewgroundsCredentials.APP_ID == null
|| NewgroundsCredentials.APP_ID == ""
|| NewgroundsCredentials.APP_ID.contains(" ")
|| NewgroundsCredentials.ENCRYPTION_KEY == null
|| NewgroundsCredentials.ENCRYPTION_KEY == ""
|| NewgroundsCredentials.ENCRYPTION_KEY.contains(" "));
}
function onLoginResolved(outcome:LoginOutcome):Void
{
switch (outcome)
{
case SUCCESS:
onLoginSuccessful();
case FAIL(result):
onLoginFailed(result);
}
}
function onLoginResolvedWithCallbacks(outcome:LoginOutcome, onSuccess:Void->Void, onError:Void->Void):Void
{
onLoginResolved(outcome);
switch (outcome)
{
case SUCCESS:
onSuccess();
case FAIL(result):
onError();
}
}
function onLogoutResolved(outcome:Outcome<CallError>):Void
{
switch (outcome)
{
case SUCCESS:
onLogoutSuccessful();
case FAIL(result):
onLogoutFailed(result);
}
}
function onLogoutResolvedWithCallbacks(outcome:Outcome<CallError>, onSuccess:Void->Void, onError:Void->Void):Void
{
onLogoutResolved(outcome);
switch (outcome)
{
case SUCCESS:
onSuccess();
case FAIL(result):
onError();
}
}
function onLoginSuccessful():Void
{
if (NG.core == null) return;
trace('[NEWGROUNDS] Login successful!');
// Persist the session ID.
Save.instance.ngSessionId = NG.core.sessionId;
trace('[NEWGROUNDS] Submitting medal request...');
NG.core.requestMedals(onFetchedMedals);
trace('[NEWGROUNDS] Submitting leaderboard request...');
NG.core.scoreBoards.loadList(onFetchedLeaderboards);
}
function onLoginFailed(result:LoginFail):Void
{
switch (result)
{
case CANCELLED(type):
switch (type)
{
case PASSPORT:
trace('[NEWGROUNDS] Login cancelled by passport website.');
case MANUAL:
trace('[NEWGROUNDS] Login cancelled by application.');
default:
trace('[NEWGROUNDS] Login cancelled by unknown source.');
}
case ERROR(error):
switch (error)
{
case HTTP(error):
trace('[NEWGROUNDS] Login failed due to HTTP error: ${error}');
case RESPONSE(error):
trace('[NEWGROUNDS] Login failed due to response error: ${error.message} (${error.code})');
case RESULT(error):
trace('[NEWGROUNDS] Login failed due to result error: ${error.message} (${error.code})');
default:
trace('[NEWGROUNDS] Login failed due to unknown error: ${error}');
}
default:
trace('[NEWGROUNDS] Login failed due to unknown reason.');
}
}
function onLogoutSuccessful():Void
{
trace('[NEWGROUNDS] Logout successful!');
}
function onLogoutFailed(result:CallError):Void
{
switch (result)
{
case HTTP(error):
trace('[NEWGROUNDS] Logout failed due to HTTP error: ${error}');
case RESPONSE(error):
trace('[NEWGROUNDS] Logout failed due to response error: ${error.message} (${error.code})');
case RESULT(error):
trace('[NEWGROUNDS] Logout failed due to result error: ${error.message} (${error.code})');
default:
trace('[NEWGROUNDS] Logout failed due to unknown error: ${result}');
}
}
function onFetchedMedals(outcome:Outcome<CallError>):Void
{
trace('[NEWGROUNDS] Fetched medals!');
}
function onFetchedLeaderboards(outcome:Outcome<CallError>):Void
{
trace('[NEWGROUNDS] Fetched leaderboards!');
// trace(funkin.api.newgrounds.Leaderboards.listLeaderboardData());
}
function get_user():Null<User>
{
if (NG.core == null || !this.isLoggedIn()) return null;
return NG.core.user;
}
function get_medals():Null<MedalList>
{
if (NG.core == null || !this.isLoggedIn()) return null;
return NG.core.medals;
}
function get_leaderboards():Null<ScoreBoardList>
{
if (NG.core == null || !this.isLoggedIn()) return null;
return NG.core.scoreBoards;
}
static function getSessionId():Null<String>
{
#if js
// We can fetch the session ID from the URL.
var result:Null<String> = NGLite.getSessionId();
if (result != null) return result;
#end
// We have to fetch the session ID from the save file.
return Save.instance.ngSessionId;
}
}
#end
-101
View File
@@ -1,101 +0,0 @@
package funkin.api.newgrounds;
#if newgrounds
import funkin.NGio;
import funkin.ui.Prompt;
class NgPrompt extends Prompt
{
public function new(text:String, style:ButtonStyle = Yes_No)
{
super(text, style);
}
static public function showLogin()
{
return showLoginPrompt(true);
}
static public function showSavedSessionFailed()
{
return showLoginPrompt(false);
}
static function showLoginPrompt(fromUi:Bool)
{
var prompt = new NgPrompt("Talking to server...", None);
prompt.openCallback = NGUtil.login.bind(function popupLauncher(openPassportUrl)
{
var choiceMsg = fromUi ? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups
: "Your session has expired.\n Please login again.";
if (choiceMsg != null)
{
prompt.setText(choiceMsg);
prompt.setButtons(Yes_No);
#if web
prompt.buttons.getItem("yes").fireInstantly = true;
#end
prompt.onYes = function() {
prompt.setText("Connecting..." #if web + "\n(check your popup blocker)" #end);
prompt.setButtons(None);
openPassportUrl();
};
prompt.onNo = function() {
prompt.close();
prompt = null;
NGio.cancelLogin();
};
}
else
{
prompt.setText("Connecting...");
openPassportUrl();
}
}, function onLoginComplete(result:ConnectionResult)
{
switch (result)
{
case Success:
{
prompt.setText("Login Successful");
prompt.setButtons(Ok);
prompt.onYes = prompt.close;
}
case Fail(msg):
{
trace("Login Error:" + msg);
prompt.setText("Login failed");
prompt.setButtons(Ok);
prompt.onYes = prompt.close;
}
case Cancelled:
{
if (prompt != null)
{
prompt.setText("Login cancelled by user");
prompt.setButtons(Ok);
prompt.onYes = prompt.close;
}
else
trace("Login cancelled via prompt");
}
}
});
return prompt;
}
static public function showLogout()
{
var user = io.newgrounds.NG.core.user.name;
var prompt = new NgPrompt('Log out of $user?', Yes_No);
prompt.onYes = function() {
NGio.logout();
prompt.close();
};
prompt.onNo = prompt.close;
return prompt;
}
}
#end
-9
View File
@@ -1,9 +0,0 @@
# funkin.api.newgrounds
This package contains two main classes:
- `NGUtil` contains utility functions for interacting with the Newgrounds API.
- This includes any functions which scripts should be able to use,
such as retrieving achievement status.
- `NGUnsafe` contains sensitive utility functions for interacting with the Newgrounds API.
- This includes any functions which scripts should not be able to use,
such as writing high scores or posting achievements.
+55
View File
@@ -0,0 +1,55 @@
package funkin.api.newgrounds;
#if FEATURE_NEWGROUNDS
import io.newgrounds.NG;
#end
import funkin.api.newgrounds.NewgroundsClient;
import funkin.util.WindowUtil;
/**
* Handles referrals to links retrieved from the Newgrounds API.
*/
class Referral
{
/**
* Opens the referral page with the given name.
* @param referralName The name of the referral.
* @param fallbackUrl The URL to open if the referral fails or is not available.
*/
static function doReferral(referralName:String, fallbackUrl:String):Void
{
#if FEATURE_NEWGROUNDS
if (NewgroundsClient.instance.isLoggedIn())
{
NG.core?.calls.loader.loadReferral(false)
.addComponentParameter("referral_name", referralName)
.addResponseHandler(response -> {
trace(response);
if (response.success)
{
WindowUtil.openURL(response.result.data.url);
}
else
{
WindowUtil.openURL(fallbackUrl);
}
})
.send();
}
else
{
WindowUtil.openURL(fallbackUrl);
}
#else
WindowUtil.openURL(fallbackUrl);
#end
}
/**
* Opens the merch referral page.
*/
public static function doMerchReferral():Void
{
doReferral("merch_link", Constants.URL_MERCH_FALLBACK);
}
}
-3
View File
@@ -1,9 +1,6 @@
package funkin.audio;
import flash.media.Sound;
#if flash11
import flash.utils.ByteArray;
#end
import flixel.sound.FlxSound;
import flixel.system.FlxAssets.FlxSoundAsset;
import openfl.Assets;
+58 -6
View File
@@ -13,9 +13,11 @@ import funkin.data.song.SongRegistry;
import funkin.util.tools.ICloneable;
import funkin.util.flixel.sound.FlxPartialSound;
import funkin.Paths.PathsFunction;
import openfl.Assets;
import lime.app.Future;
import lime.app.Promise;
import lime.media.AudioSource;
import openfl.events.Event;
import openfl.media.Sound;
import openfl.media.SoundChannel;
import openfl.media.SoundMixer;
#if (openfl >= "8.0.0")
@@ -110,6 +112,11 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
return _waveformData;
}
/**
* If true, the game will forcefully add this sound's channel to the list of playing sounds.
*/
public var important:Bool = false;
/**
* Are we in a state where the song should play but time is negative?
*/
@@ -147,6 +154,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
else
{
super.update(elapsedSec);
@:privateAccess
{
if (important && _channel != null && !SoundMixer.__soundChannels.contains(_channel))
{
SoundMixer.__soundChannels.push(_channel);
}
}
}
}
@@ -433,13 +448,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
* @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.
* @param important If `true`, the sound channel will forcefully be added onto the channel array, even if full. Use sparingly!
* @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,
persist:Bool = false, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
persist:Bool = false, ?onComplete:Void->Void, ?onLoad:Void->Void, important:Bool = false):Null<FunkinSound>
{
@:privateAccess
if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS)
if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS && !important)
{
FlxG.log.error('FunkinSound could not play sound, channels exhausted! Found ${SoundMixer.__soundChannels.length} active sound channels.');
return null;
@@ -464,6 +480,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
sound.volume = volume;
sound.group = FlxG.sound.defaultSoundGroup;
sound.persist = persist;
sound.important = important;
// Make sure to add the sound to the list.
// If it's already in, it won't get re-added.
@@ -536,15 +553,50 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
this._label = 'unknown';
}
@:access(openfl.media.Sound)
@:access(openfl.media.SoundChannel)
@:access(openfl.media.SoundMixer)
override function startSound(startTime:Float)
{
if (!important)
{
super.startSound(startTime);
return;
}
_time = startTime;
_paused = false;
if (_sound == null) return;
// Create a channel manually if the sound is considered important.
var pan:Float = FlxMath.bound(SoundMixer.__soundTransform.pan + _transform.pan, -1, 1);
var volume:Float = FlxMath.bound(SoundMixer.__soundTransform.volume * _transform.volume, 0, MAX_VOLUME);
var audioSource:AudioSource = new AudioSource(_sound.__buffer);
audioSource.offset = Std.int(startTime);
audioSource.gain = volume;
var position:lime.math.Vector4 = audioSource.position;
position.x = pan;
position.z = -1 * Math.sqrt(1 - Math.pow(pan, 2));
audioSource.position = position;
_channel = new SoundChannel(_sound, audioSource, _transform);
_channel.addEventListener(Event.SOUND_COMPLETE, stopped);
pitch = _pitch;
active = true;
}
/**
* Play a sound effect once, then destroy it.
* @param key
* @param volume
* @return A `FunkinSound` object, or `null` if the sound could not be loaded.
*/
public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void, important:Bool = false):Null<FunkinSound>
{
var result:Null<FunkinSound> = FunkinSound.load(key, volume, false, true, true, false, onComplete, onLoad);
var result:Null<FunkinSound> = FunkinSound.load(key, volume, false, true, true, false, onComplete, onLoad, important);
return result;
}
-1
View File
@@ -1,7 +1,6 @@
package funkin.audio;
import flixel.group.FlxGroup.FlxTypedGroup;
import funkin.audio.FunkinSound;
import flixel.tweens.FlxTween;
/**
+63 -106
View File
@@ -1,60 +1,76 @@
package funkin.audio.visualize;
import funkin.graphics.FunkinSprite;
import flixel.FlxSprite;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
import flixel.sound.FlxSound;
import funkin.vis.dsp.SpectralAnalyzer;
import funkin.vis.audioclip.frontends.LimeAudioClip;
using Lambda;
@:nullSafety
class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
{
// public var vis:VisShit;
var analyzer:SpectralAnalyzer;
var analyzer:Null<SpectralAnalyzer> = null;
var volumes:Array<Float> = [];
public var snd:FlxSound;
public var snd:Null<FlxSound> = null;
public function new(snd:FlxSound)
static final BAR_COUNT:Int = 7;
// TODO: Make the sprites easier to soft code.
public function new(snd:FlxSound, pixel:Bool)
{
super();
this.snd = snd;
// vis = new VisShit(snd);
// vis.snd = snd;
var visCount = pixel ? (BAR_COUNT + 1) : (BAR_COUNT + 1);
var visScale = pixel ? 6 : 1;
var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas('aBotViz');
var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas(pixel ? 'characters/abotPixel/aBotVizPixel' : 'characters/abot/aBotViz');
// these are the differences in X position, from left to right
var positionX:Array<Float> = [0, 59, 56, 66, 54, 52, 51];
var positionY:Array<Float> = [0, -8, -3.5, -0.4, 0.5, 4.7, 7];
var positionX:Array<Float> = pixel ? [0, 7 * 6, 8 * 6, 9 * 6, 10 * 6, 6 * 6, 7 * 6] : [0, 59, 56, 66, 54, 52, 51];
var positionY:Array<Float> = pixel ? [0, -2 * 6, -1 * 6, 0, 0, 1 * 6, 2 * 6] : [0, -8, -3.5, -0.4, 0.5, 4.7, 7];
for (lol in 1...8)
for (index in 1...visCount)
{
// pushes initial value
volumes.push(0.0);
var sum = function(num:Float, total:Float) return total += num;
var posX:Float = positionX.slice(0, lol).fold(sum, 0);
var posY:Float = positionY.slice(0, lol).fold(sum, 0);
var viz:FlxSprite = new FlxSprite(posX, posY);
// Sum the offsets up to the current index
var sum = function(num:Float, total:Float) return total += num;
var posX:Float = positionX.slice(0, index).fold(sum, 0);
var posY:Float = positionY.slice(0, index).fold(sum, 0);
var viz:FunkinSprite = new FunkinSprite(posX, posY);
viz.frames = visFrms;
viz.antialiasing = pixel ? false : true;
viz.scale.set(visScale, visScale);
add(viz);
var visStr = 'viz';
viz.animation.addByPrefix('VIZ', visStr + lol, 0);
viz.animation.play('VIZ', false, false, 6);
viz.animation.addByPrefix('VIZ', '$visStr${index}0', 0);
viz.animation.play('VIZ', false, false, 1);
}
}
public function initAnalyzer()
public function initAnalyzer():Void
{
if (snd == null) return;
@:privateAccess
analyzer = new SpectralAnalyzer(snd._channel.__audioSource, 7, 0.1, 40);
analyzer = new SpectralAnalyzer(snd._channel.__audioSource, BAR_COUNT, 0.1, 40);
// A-Bot tuning...
analyzer.minDb = -65;
analyzer.maxDb = -25;
analyzer.maxFreq = 22000;
// we use a very low minFreq since some songs use low low subbass like a boss
analyzer.minFreq = 10;
#if desktop
// On desktop it uses FFT stuff that isn't as optimized as the direct browser stuff we use on HTML5
@@ -66,16 +82,17 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
// analyzer.fftN = 2048;
}
public function dumpSound():Void
{
snd = null;
analyzer = null;
}
var visTimer:Float = -1;
var visTimeMax:Float = 1 / 30;
override function update(elapsed:Float)
{
// updateViz();
// updateFFT(elapsed);
//
super.update(elapsed);
}
@@ -86,8 +103,8 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
override function draw()
{
if (analyzer != null) drawFFT();
super.draw();
drawFFT();
}
/**
@@ -95,17 +112,17 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
*/
function drawFFT():Void
{
var levels = analyzer.getLevels();
var levels = (analyzer != null) ? analyzer.getLevels() : getDefaultLevels();
for (i in 0...min(group.members.length, levels.length))
{
var animFrame:Int = Math.round(levels[i].value * 5);
var animFrame:Int = Math.round(levels[i].value * 6);
#if desktop
// Web version scales with the Flixel volume level.
// This line brings platform parity but looks worse.
// animFrame = Math.round(animFrame * FlxG.sound.volume);
#end
// don't display if we're at 0 volume from the level
group.members[i].visible = animFrame > 0;
// decrement our animFrame, so we can get a value from 0-5 for animation frames
animFrame -= 1;
animFrame = Math.floor(Math.min(5, animFrame));
animFrame = Math.floor(Math.max(0, animFrame));
@@ -116,79 +133,19 @@ class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
}
}
// function updateFFT(elapsed:Float)
// {
// if (vis.snd != null)
// {
// vis.checkAndSetBuffer();
// if (vis.setBuffer)
// {
// var remappedShit:Int = 0;
// if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples));
// else
// remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, vis.numSamples));
// var fftSamples:Array<Float> = [];
// var swagBucks = remappedShit;
// for (i in remappedShit...remappedShit + (Std.int((44100 * (1 / 144)))))
// {
// var left = vis.audioData[swagBucks] / 32767;
// var right = vis.audioData[swagBucks + 1] / 32767;
// var balanced = (left + right) / 2;
// swagBucks += 2;
// fftSamples.push(balanced);
// }
// var freqShit = vis.funnyFFT(fftSamples);
// for (i in 0...group.members.length)
// {
// var getSliceShit = function(s:Int) {
// var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, MathUtil.logBase(10, freqShit[0].length));
// return Math.round(Math.pow(10, powShit));
// };
// // var powShit:Float = getSliceShit(i);
// var hzSliced:Int = getSliceShit(i);
// var sliceLength:Int = Std.int(freqShit[0].length / group.members.length);
// var volSlice = freqShit[0].slice(hzSliced, getSliceShit(i + 1));
// var avgVel:Float = 0;
// for (slice in volSlice)
// {
// avgVel += slice;
// }
// avgVel /= volSlice.length;
// avgVel *= 10000000;
// volumes[i] += avgVel - (elapsed * (volumes[i] * 50));
// var animFrame:Int = Std.int(volumes[i]);
// animFrame = Math.floor(Math.min(5, animFrame));
// animFrame = Math.floor(Math.max(0, animFrame));
// animFrame = Std.int(Math.abs(animFrame - 5)); // shitty dumbass flip, cuz dave got da shit backwards lol!
// group.members[i].animation.curAnim.curFrame = animFrame;
// if (FlxG.keys.justPressed.U)
// {
// trace(avgVel);
// trace(group.members[i].animation.curAnim.curFrame);
// }
// }
// // group.members[0].animation.curAnim.curFrame =
// }
// }
// }
// public function updateViz()
// {
// if (vis.snd != null)
// {
// var remappedShit:Int = 0;
// vis.checkAndSetBuffer();
// if (vis.setBuffer)
// {
// // var startingSample:Int = Std.int(FlxMath.remapToRange)
// if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples));
// for (i in 0...group.members.length)
// {
// var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, remappedShit, remappedShit + 500));
// var left = vis.audioData[sampleApprox] / 32767;
// var animFrame:Int = Std.int(FlxMath.remapToRange(left, -1, 1, 0, 6));
// group.members[i].animation.curAnim.curFrame = animFrame;
// }
// }
// }
// }
/**
* Explicitly define the default levels to draw when the analyzer is not available.
* @return Array<Bar>
*/
static function getDefaultLevels():Array<Bar>
{
var result:Array<Bar> = [];
for (i in 0...BAR_COUNT)
{
result.push({value: 0, peak: 0.0});
}
return result;
}
}
@@ -4,7 +4,7 @@ import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import flixel.sound.FlxSound;
import flixel.util.FlxColor;
import funkin.audio.visualize.VisShit;
import funkin.audio.visualize.VisShit.CurAudioInfo;
import funkin.graphics.rendering.MeshRender;
import lime.utils.Int16Array;
+14
View File
@@ -16,6 +16,7 @@ typedef EntryConstructorFunction = String->Void;
* @param J The type of the JSON data used when constructing.
*/
@:generic
@:autoBuild(funkin.util.macro.DataRegistryMacro.buildRegistry())
abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructorFunction>), J>
{
/**
@@ -189,6 +190,19 @@ abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructo
return entries.get(id);
}
/**
* A list of all entries included in the base game.
* The actual function exists and is auto-generated on each registry at build time.
* @return Array<String>
*/
// public function listBaseGameEntryIds():Array<String> {}
/**
* A list of all entries that are not included in the base game.
* @return Array<String>
*/
// public function listModdedEntryIds():Array<String> {}
public function toString():String
{
return 'Registry(' + registryId + ', ${countEntries()} entries)';
@@ -0,0 +1,9 @@
package funkin.data;
/**
* An interface which automatically implements essential fields for a class extending `BaseRegistry`.
*
* @see `funkin.data.BaseRegistry`
*/
@:autoBuild(funkin.util.macro.RegistryMacro.buildRegistry())
interface DefaultRegistryImpl {}
+1
View File
@@ -5,6 +5,7 @@ package funkin.data;
* A `String->Void` constructor is also mandatory, but enforced elsewhere.
* @param T The JSON data type of the registry entry.
*/
@:autoBuild(funkin.util.macro.RegistryMacro.buildEntry())
interface IRegistryEntry<T>
{
public final id:String;
@@ -17,6 +17,16 @@ class AnimationDataUtil
};
}
/**
* @param data
* @param name (adds index to name)
* @return Array<AnimationData>
*/
public static function toNamedArray(data:Array<UnnamedAnimationData>, ?name:String = ""):Array<AnimationData>
{
return data.mapi(function(animItem, ind) return toNamed(animItem, '$name$ind'));
}
public static function toUnnamed(data:AnimationData):UnnamedAnimationData
{
return {
@@ -30,6 +40,11 @@ class AnimationDataUtil
frameIndices: data.frameIndices
};
}
public static function toUnnamedArray(data:Array<AnimationData>):Array<UnnamedAnimationData>
{
return data.map(toUnnamed);
}
}
/**
@@ -2,8 +2,10 @@ package funkin.data.dialogue.conversation;
import funkin.play.cutscene.dialogue.Conversation;
import funkin.play.cutscene.dialogue.ScriptedConversation;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class ConversationRegistry extends BaseRegistry<Conversation, ConversationData>
class ConversationRegistry extends BaseRegistry<Conversation, ConversationData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the dialogue box data format.
@@ -14,74 +16,8 @@ class ConversationRegistry extends BaseRegistry<Conversation, ConversationData>
public static final CONVERSATION_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static var instance(get, never):ConversationRegistry;
static var _instance:Null<ConversationRegistry> = null;
static function get_instance():ConversationRegistry
{
if (_instance == null) _instance = new ConversationRegistry();
return _instance;
}
public function new()
{
super('CONVERSATION', 'dialogue/conversations', CONVERSATION_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<ConversationData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<ConversationData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<ConversationData>
{
var parser = new json2object.JsonParser<ConversationData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):Conversation
{
return ScriptedConversation.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedConversation.listScriptClasses();
}
}
@@ -3,8 +3,10 @@ package funkin.data.dialogue.dialoguebox;
import funkin.play.cutscene.dialogue.DialogueBox;
import funkin.data.dialogue.dialoguebox.DialogueBoxData;
import funkin.play.cutscene.dialogue.ScriptedDialogueBox;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class DialogueBoxRegistry extends BaseRegistry<DialogueBox, DialogueBoxData>
class DialogueBoxRegistry extends BaseRegistry<DialogueBox, DialogueBoxData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the dialogue box data format.
@@ -13,76 +15,10 @@ class DialogueBoxRegistry extends BaseRegistry<DialogueBox, DialogueBoxData>
*/
public static final DIALOGUEBOX_DATA_VERSION:thx.semver.Version = "1.1.0";
public static final DIALOGUEBOX_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x";
public static var instance(get, never):DialogueBoxRegistry;
static var _instance:Null<DialogueBoxRegistry> = null;
static function get_instance():DialogueBoxRegistry
{
if (_instance == null) _instance = new DialogueBoxRegistry();
return _instance;
}
public static final DIALOGUEBOX_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.2.0";
public function new()
{
super('DIALOGUEBOX', 'dialogue/boxes', DIALOGUEBOX_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<DialogueBoxData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<DialogueBoxData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<DialogueBoxData>
{
var parser = new json2object.JsonParser<DialogueBoxData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):DialogueBox
{
return ScriptedDialogueBox.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedDialogueBox.listScriptClasses();
}
}
@@ -1,10 +1,11 @@
package funkin.data.dialogue.speaker;
import funkin.play.cutscene.dialogue.Speaker;
import funkin.data.dialogue.speaker.SpeakerData;
import funkin.play.cutscene.dialogue.ScriptedSpeaker;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class SpeakerRegistry extends BaseRegistry<Speaker, SpeakerData>
class SpeakerRegistry extends BaseRegistry<Speaker, SpeakerData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the speaker data format.
@@ -15,74 +16,8 @@ class SpeakerRegistry extends BaseRegistry<Speaker, SpeakerData>
public static final SPEAKER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static var instance(get, never):SpeakerRegistry;
static var _instance:Null<SpeakerRegistry> = null;
static function get_instance():SpeakerRegistry
{
if (_instance == null) _instance = new SpeakerRegistry();
return _instance;
}
public function new()
{
super('SPEAKER', 'dialogue/speakers', SPEAKER_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<SpeakerData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<SpeakerData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<SpeakerData>
{
var parser = new json2object.JsonParser<SpeakerData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):Speaker
{
return ScriptedSpeaker.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedSpeaker.listScriptClasses();
}
}
@@ -1,7 +1,6 @@
package funkin.data.event;
import funkin.play.event.SongEvent;
import funkin.data.event.SongEventSchema;
import funkin.data.song.SongData.SongEventData;
import funkin.util.macro.ClassMacro;
import funkin.play.event.ScriptedSongEvent;
@@ -1,11 +1,5 @@
package funkin.data.event;
import funkin.play.event.SongEvent;
import funkin.data.event.SongEventSchema;
import funkin.data.song.SongData.SongEventData;
import funkin.util.macro.ClassMacro;
import funkin.play.event.ScriptedSongEvent;
@:forward(name, title, type, keys, min, max, step, units, defaultValue, iterator)
abstract SongEventSchema(SongEventSchemaRaw)
{
@@ -36,6 +36,13 @@ typedef AlbumData =
*/
public var albumTitleAsset:String;
/**
* Offsets for the album title.
*/
@:optional
@:default([0, 0])
public var albumTitleOffsets:Null<Array<Float>>;
/**
* An optional array of animations for the album title.
*/
@@ -3,8 +3,10 @@ package funkin.data.freeplay.album;
import funkin.ui.freeplay.Album;
import funkin.data.freeplay.album.AlbumData;
import funkin.ui.freeplay.ScriptedAlbum;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class AlbumRegistry extends BaseRegistry<Album, AlbumData>
class AlbumRegistry extends BaseRegistry<Album, AlbumData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the album data format.
@@ -15,70 +17,8 @@ class AlbumRegistry extends BaseRegistry<Album, AlbumData>
public static final ALBUM_DATA_VERSION_RULE:thx.semver.VersionRule = '1.0.x';
public static final instance:AlbumRegistry = new AlbumRegistry();
public function new()
{
super('ALBUM', 'ui/freeplay/albums', ALBUM_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
* @param id The ID of the entry to load.
* @return The parsed data object.
*/
public function parseEntryData(id:String):Null<AlbumData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser:json2object.JsonParser<AlbumData> = new json2object.JsonParser<AlbumData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
* @return The parsed data object.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<AlbumData>
{
var parser:json2object.JsonParser<AlbumData> = new json2object.JsonParser<AlbumData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):Album
{
return ScriptedAlbum.init(clsName, 'unknown');
}
function getScriptedClassNames():Array<String>
{
return ScriptedAlbum.listScriptClasses();
}
}
@@ -5,5 +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.1]
### Added
- Added `stickerPack` to specify which sticker pack to use when transitioning into and out of song featuring this character.
- If the value isn't present, it will use a default sticker pack instead.
## [1.0.0]
Initial release.
@@ -31,6 +31,15 @@ class PlayerData
@:default(false)
public var showUnownedChars:Bool = false;
/**
* The default sticker pack to use for songs featuring this playable character.
* Can be overridden by specific songs.
* @default `default`
*/
@:optional
@:default(funkin.util.Constants.DEFAULT_STICKER_PACK)
public var stickerPack:String = Constants.DEFAULT_STICKER_PACK;
/**
* Which freeplay style to use for this character.
*/
@@ -325,12 +334,20 @@ typedef PlayerResultsAnimationData =
*/
var renderType:String;
var assetPath:String;
@:optional
var assetPath:Null<String>;
@:optional
var scriptClass:Null<String>;
@:optional
@:default([0, 0])
var offsets:Array<Float>;
@:optional
@:default("both")
var filter:String;
@:optional
@:default(500)
var zIndex:Int;
@@ -347,6 +364,10 @@ typedef PlayerResultsAnimationData =
@:default('')
var startFrameLabel:Null<String>;
@:optional
@:default('')
var sound:Null<String>;
@:optional
@:default(true)
var looped:Bool;
@@ -4,8 +4,10 @@ import funkin.data.freeplay.player.PlayerData;
import funkin.ui.freeplay.charselect.PlayableCharacter;
import funkin.ui.freeplay.charselect.ScriptedPlayableCharacter;
import funkin.save.Save;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData>
class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the stage data format.
@@ -16,15 +18,6 @@ class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData>
public static final PLAYER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static var instance(get, never):PlayerRegistry;
static var _instance:Null<PlayerRegistry> = null;
static function get_instance():PlayerRegistry
{
if (_instance == null) _instance = new PlayerRegistry();
return _instance;
}
/**
* A mapping between stage character IDs and Freeplay playable character IDs.
*/
@@ -130,79 +123,4 @@ class PlayerRegistry extends BaseRegistry<PlayableCharacter, PlayerData>
{
return ownedCharacterIds.exists(characterId);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<PlayerData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<PlayerData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<PlayerData>
{
var parser = new json2object.JsonParser<PlayerData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):PlayableCharacter
{
return ScriptedPlayableCharacter.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedPlayableCharacter.listScriptClasses();
}
/**
* A list of all the playable characters from the base game, in order.
*/
public function listBaseGamePlayerIds():Array<String>
{
return ["bf", "pico"];
}
/**
* A list of all installed playable characters that are not from the base game.
*/
public function listModdedPlayerIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGamePlayerIds().indexOf(id) == -1;
});
}
}
@@ -3,8 +3,10 @@ package funkin.data.freeplay.style;
import funkin.ui.freeplay.FreeplayStyle;
import funkin.data.freeplay.style.FreeplayStyleData;
import funkin.ui.freeplay.ScriptedFreeplayStyle;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class FreeplayStyleRegistry extends BaseRegistry<FreeplayStyle, FreeplayStyleData>
class FreeplayStyleRegistry extends BaseRegistry<FreeplayStyle, FreeplayStyleData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the style data format.
@@ -15,70 +17,8 @@ class FreeplayStyleRegistry extends BaseRegistry<FreeplayStyle, FreeplayStyleDat
public static final FREEPLAYSTYLE_DATA_VERSION_RULE:thx.semver.VersionRule = '1.0.x';
public static final instance:FreeplayStyleRegistry = new FreeplayStyleRegistry();
public function new()
{
super('FREEPLAYSTYLE', 'ui/freeplay/styles', FREEPLAYSTYLE_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
* @param id The ID of the entry to load.
* @return The parsed data object.
*/
public function parseEntryData(id:String):Null<FreeplayStyleData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser:json2object.JsonParser<FreeplayStyleData> = new json2object.JsonParser<FreeplayStyleData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
* @return The parsed data object.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<FreeplayStyleData>
{
var parser:json2object.JsonParser<FreeplayStyleData> = new json2object.JsonParser<FreeplayStyleData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):FreeplayStyle
{
return ScriptedFreeplayStyle.init(clsName, 'unknown');
}
function getScriptedClassNames():Array<String>
{
return ScriptedFreeplayStyle.listScriptClasses();
}
}
@@ -5,6 +5,8 @@ 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).
<!-- TODO: Include NoteSplash and NoteStyle changes made to accomodate week 6 note splash/hold stuff -->
## [1.1.0]
### Added
- Added several new `assets`:
@@ -187,6 +187,10 @@ typedef NoteStyleAssetData<T> =
@:optional
var isPixel:Bool;
@:default(1.0)
@:optional
var alpha:Float;
/**
* If true, animations will be played on the graphic.
* @default `false` to save performance.
@@ -251,6 +255,30 @@ typedef NoteStyleData_NoteSplash =
@:optional
@:default(true)
var enabled:Bool;
@:optional
@:default(24)
var framerateDefault:Int;
@:optional
@:default(2)
var framerateVariance:Int;
@:optional
@:default("normal")
var blendMode:String;
@:optional
var leftSplashes:Array<UnnamedAnimationData>;
@:optional
var downSplashes:Array<UnnamedAnimationData>;
@:optional
var upSplashes:Array<UnnamedAnimationData>;
@:optional
var rightSplashes:Array<UnnamedAnimationData>;
};
typedef NoteStyleData_HoldNoteCover =
@@ -262,4 +290,33 @@ typedef NoteStyleData_HoldNoteCover =
@:optional
@:default(true)
var enabled:Bool;
@:optional
var left:NoteStyleData_HoldNoteCoverDirectionData;
@:optional
var down:NoteStyleData_HoldNoteCoverDirectionData;
@:optional
var up:NoteStyleData_HoldNoteCoverDirectionData;
@:optional
var right:NoteStyleData_HoldNoteCoverDirectionData;
};
typedef NoteStyleData_HoldNoteCoverDirectionData =
{
/**
* Optionally specify an asset path to use for this specific animation.
* @:default The assetPath of the main holdNoteCover asset
*/
@:optional
var assetPath:String;
@:optional
var start:UnnamedAnimationData;
@:optional
var hold:UnnamedAnimationData;
@:optional
var end:UnnamedAnimationData;
}
@@ -3,8 +3,10 @@ package funkin.data.notestyle;
import funkin.play.notes.notestyle.NoteStyle;
import funkin.play.notes.notestyle.ScriptedNoteStyle;
import funkin.data.notestyle.NoteStyleData;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the note style data format.
@@ -13,16 +15,7 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
*/
public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.1.0";
public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x";
public static var instance(get, never):NoteStyleRegistry;
static var _instance:Null<NoteStyleRegistry> = null;
static function get_instance():NoteStyleRegistry
{
if (_instance == null) _instance = new NoteStyleRegistry();
return _instance;
}
public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.2.0";
public function new()
{
@@ -33,61 +26,4 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
{
return fetchEntry(Constants.DEFAULT_NOTE_STYLE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<NoteStyleData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<NoteStyleData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<NoteStyleData>
{
var parser = new json2object.JsonParser<NoteStyleData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):NoteStyle
{
return ScriptedNoteStyle.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedNoteStyle.listScriptClasses();
}
}
+5
View File
@@ -5,6 +5,11 @@ 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.2.5]
### Added
- Added `playData.stickerPack` to specify which sticker pack to use when transitioning into and out of a song.
- If the value isn't present, it will use the character's sticker pack instead.
## [2.2.4]
### Added
- Added `playData.characters.opponentVocals` to specify which vocal track(s) to play for the opponent.
+7
View File
@@ -471,6 +471,13 @@ class SongPlayData implements ICloneable<SongPlayData>
@:optional
public var album:Null<String>;
/**
* The sticker pack for the song to use during transitions.
* If `null`, display the character's sticker pack.
*/
@:optional
public var stickerPack:Null<String>;
/**
* The start time for the audio preview in Freeplay.
* Defaults to 0 seconds in.
+37 -43
View File
@@ -1,5 +1,6 @@
package funkin.data.song;
import funkin.data.freeplay.player.PlayerRegistry;
import funkin.data.song.SongData;
import funkin.data.song.migrator.SongData_v2_0_0.SongMetadata_v2_0_0;
import funkin.data.song.migrator.SongData_v2_1_0.SongMetadata_v2_1_0;
@@ -9,11 +10,13 @@ import funkin.play.song.ScriptedSong;
import funkin.play.song.Song;
import funkin.util.assets.DataAssets;
import funkin.util.VersionUtil;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
using funkin.data.song.migrator.SongDataMigrator;
@:nullSafety
class SongRegistry extends BaseRegistry<Song, SongMetadata>
class SongRegistry extends BaseRegistry<Song, SongMetadata> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the stage data format.
@@ -39,19 +42,6 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
return '${Constants.TITLE} - ${Constants.VERSION}';
}
/**
* TODO: What if there was a Singleton macro which automatically created the property for us?
*/
public static var instance(get, never):SongRegistry;
static var _instance:Null<SongRegistry> = null;
static function get_instance():SongRegistry
{
if (_instance == null) _instance = new SongRegistry();
return _instance;
}
public function new()
{
super('SONG', 'songs', SONG_METADATA_VERSION_RULE);
@@ -171,7 +161,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
public function parseEntryMetadataWithMigration(id:String, variation:String, version:thx.semver.Version):Null<SongMetadata>
{
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
variation = variation ?? Constants.DEFAULT_VARIATION;
// If a version rule is not specified, do not check against it.
if (SONG_METADATA_VERSION_RULE == null || VersionUtil.validateVersion(version, SONG_METADATA_VERSION_RULE))
@@ -192,12 +182,13 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
}
}
public function parseEntryMetadataRawWithMigration(contents:String, ?fileName:String = 'raw', version:thx.semver.Version):Null<SongMetadata>
public function parseEntryMetadataRawWithMigration(contents:String, ?fileName:String = 'raw', version:thx.semver.Version,
?variation:String):Null<SongMetadata>
{
// If a version rule is not specified, do not check against it.
if (SONG_METADATA_VERSION_RULE == null || VersionUtil.validateVersion(version, SONG_METADATA_VERSION_RULE))
{
return parseEntryMetadataRaw(contents, fileName);
return parseEntryMetadataRaw(contents, fileName, variation);
}
else if (VersionUtil.validateVersion(version, "2.1.x"))
{
@@ -417,16 +408,6 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
}
}
function createScriptedEntry(clsName:String):Song
{
return ScriptedSong.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedSong.listScriptClasses();
}
function loadEntryMetadataFile(id:String, ?variation:String):Null<JsonFile>
{
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
@@ -502,24 +483,37 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
}
/**
* A list of all the story weeks from the base game, in order.
* TODO: Should this be hardcoded?
* A list of all difficulties for a specific character.
*/
public function listBaseGameSongIds():Array<String>
public function listAllDifficulties(characterId:String):Array<String>
{
return [
"tutorial", "bopeebo", "fresh", "dadbattle", "spookeez", "south", "monster", "pico", "philly-nice", "blammed", "satin-panties", "high", "milf", "cocoa",
"eggnog", "winter-horrorland", "senpai", "roses", "thorns", "ugh", "guns", "stress", "darnell", "lit-up", "2hot", "blazin"
];
}
var allDifficulties:Array<String> = Constants.DEFAULT_DIFFICULTY_LIST.copy();
var character = PlayerRegistry.instance.fetchEntry(characterId);
/**
* A list of all installed story weeks that are not from the base game.
*/
public function listModdedSongIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameSongIds().indexOf(id) == -1;
});
if (character == null)
{
trace(' [WARN] Could not locate character $characterId');
return allDifficulties;
}
allDifficulties = [];
for (songId in listEntryIds())
{
var song = fetchEntry(songId);
if (song == null) continue;
for (diff in song.listDifficulties(null, song.getVariationsByCharacter(character)))
{
if (!allDifficulties.contains(diff)) allDifficulties.push(diff);
}
}
if (allDifficulties.length == 0)
{
trace(' [WARN] No difficulties found. Returning default difficulty list.');
allDifficulties = Constants.DEFAULT_DIFFICULTY_LIST.copy();
}
return allDifficulties;
}
}
+31 -3
View File
@@ -171,12 +171,12 @@ typedef StageDataProp =
* How much the prop scrolls relative to the camera. Used to create a parallax effect.
* Represented as an [x, y] array of two floats.
* [1, 1] means the prop moves 1:1 with the camera.
* [0.5, 0.5] means the prop half as much as the camera.
* [0.5, 0.5] means the prop moves half as much as the camera.
* [0, 0] means the prop is not moved.
* @default [0, 0]
* @default [1, 1]
*/
@:optional
@:default([0, 0])
@:default([1, 1])
var scroll:Array<Float>;
/**
@@ -261,4 +261,32 @@ typedef StageDataCharacter =
*/
@:optional
var cameraOffsets:Array<Float>;
/**
* How much the character scrolls relative to the camera. Used to create a parallax effect.
* Represented as an [x, y] array of two floats.
* [1, 1] means the character moves 1:1 with the camera.
* [0.5, 0.5] means the character moves half as much as the camera.
* [0, 0] means the character is not moved.
* @default [1, 1]
*/
@:optional
@:default([1, 1])
var scroll:Array<Float>;
/**
* The alpha of the character, as a float.
* @default 1.0
*/
@:optional
@:default(1.0)
var alpha:Float;
/**
* The angle of the character, as a float.
* @default 1.0
*/
@:optional
@:default(0.0)
var angle:Float;
};
+4 -91
View File
@@ -1,10 +1,11 @@
package funkin.data.stage;
import funkin.data.stage.StageData;
import funkin.play.stage.Stage;
import funkin.play.stage.ScriptedStage;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class StageRegistry extends BaseRegistry<Stage, StageData>
class StageRegistry extends BaseRegistry<Stage, StageData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the stage data format.
@@ -13,98 +14,10 @@ class StageRegistry extends BaseRegistry<Stage, StageData>
*/
public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.3";
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <=1.0.3";
public static var instance(get, never):StageRegistry;
static var _instance:Null<StageRegistry> = null;
static function get_instance():StageRegistry
{
if (_instance == null) _instance = new StageRegistry();
return _instance;
}
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.1.0";
public function new()
{
super('STAGE', 'stages', STAGE_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<StageData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<StageData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<StageData>
{
var parser = new json2object.JsonParser<StageData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):Stage
{
return ScriptedStage.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedStage.listScriptClasses();
}
/**
* A list of all the stages from the base game, in order.
* TODO: Should this be hardcoded?
*/
public function listBaseGameStageIds():Array<String>
{
return [
"mainStage", "mainStageErect", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallXmasErect", "mallEvil",
"school", "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyStreetsErect", "phillyBlazin",
];
}
/**
* A list of all installed story weeks that are not from the base game.
*/
public function listModdedStageIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameStageIds().indexOf(id) == -1;
});
}
}
+9
View File
@@ -0,0 +1,9 @@
# Sticker Pack Data Schema Changelog
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.0]
Initial release. Sticker packs have been restructured compared to previous versions to be less complicated.
@@ -0,0 +1,30 @@
package funkin.data.stickers;
/**
* A type definition for a sticker pack.
* It includes things like its name, the artist, and what sticker graphics to use.
* @see https://lib.haxe.org/p/json2object/
*/
typedef StickerData =
{
/**
* Semantic version of the sticker set data.
*/
public var version:String;
/**
* Readable name of the sticker set.
*/
public var name:String;
/**
* The artist of the sticker set.
*/
public var artist:String;
/**
* The stickers in the set.
* This is simply a list of asset files to use.
*/
public var stickers:Array<String>;
}
@@ -0,0 +1,89 @@
package funkin.data.stickers;
import funkin.data.stickers.StickerData;
import funkin.ui.transition.stickers.StickerPack;
import funkin.ui.transition.stickers.ScriptedStickerPack;
class StickerRegistry extends BaseRegistry<StickerPack, StickerData>
{
/**
* The current version string for the sticker pack data format.
* Handle breaking changes by incrementing this value
* and adding migration to the `migrateStickerData()` function.
*/
public static final STICKER_DATA_VERSION:thx.semver.Version = '1.0.0';
public static final STICKER_DATA_VERSION_RULE:thx.semver.VersionRule = '1.0.x';
public static final instance:StickerRegistry = new StickerRegistry();
public function new()
{
super('STICKER', 'stickerpacks', STICKER_DATA_VERSION_RULE);
}
public function fetchDefault():StickerPack
{
return fetchEntry(Constants.DEFAULT_STICKER_PACK);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
* @param id The ID of the entry to load.
* @return The parsed data object.
*/
public function parseEntryData(id:String):Null<StickerData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser:json2object.JsonParser<StickerData> = new json2object.JsonParser<StickerData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
* @return The parsed data object.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<StickerData>
{
var parser:json2object.JsonParser<StickerData> = new json2object.JsonParser<StickerData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):StickerPack
{
return ScriptedStickerPack.init(clsName, 'unknown');
}
function getScriptedClassNames():Array<String>
{
return ScriptedStickerPack.listScriptClasses();
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ 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.1.0]
## [1.0.1]
- Added `visible` attribute.
## [1.0.0]
+24 -92
View File
@@ -2,10 +2,11 @@ package funkin.data.story.level;
import funkin.util.SortUtil;
import funkin.ui.story.Level;
import funkin.data.story.level.LevelData;
import funkin.ui.story.ScriptedLevel;
import funkin.util.tools.ISingleton;
import funkin.data.DefaultRegistryImpl;
class LevelRegistry extends BaseRegistry<Level, LevelData>
class LevelRegistry extends BaseRegistry<Level, LevelData> implements ISingleton implements DefaultRegistryImpl
{
/**
* The current version string for the level data format.
@@ -14,112 +15,43 @@ class LevelRegistry extends BaseRegistry<Level, LevelData>
*/
public static final LEVEL_DATA_VERSION:thx.semver.Version = "1.0.1";
public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static var instance(get, never):LevelRegistry;
static var _instance:Null<LevelRegistry> = null;
static function get_instance():LevelRegistry
{
if (_instance == null) _instance = new LevelRegistry();
return _instance;
}
public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <1.1.0";
public function new()
{
super('LEVEL', 'levels', LEVEL_DATA_VERSION_RULE);
}
/**
* Read, parse, and validate the JSON data and produce the corresponding data object.
*/
public function parseEntryData(id:String):Null<LevelData>
{
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser<LevelData>();
parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
case {fileName: fileName, contents: contents}:
parser.fromJson(contents, fileName);
default:
return null;
}
if (parser.errors.length > 0)
{
printErrors(parser.errors, id);
return null;
}
return parser.value;
}
/**
* Parse and validate the JSON data and produce the corresponding data object.
*
* NOTE: Must be implemented on the implementation class.
* @param contents The JSON as a string.
* @param fileName An optional file name for error reporting.
*/
public function parseEntryDataRaw(contents:String, ?fileName:String):Null<LevelData>
{
var parser = new json2object.JsonParser<LevelData>();
parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
{
printErrors(parser.errors, fileName);
return null;
}
return parser.value;
}
function createScriptedEntry(clsName:String):Level
{
return ScriptedLevel.init(clsName, "unknown");
}
function getScriptedClassNames():Array<String>
{
return ScriptedLevel.listScriptClasses();
}
/**
* A list of all the story weeks from the base game, in order.
* TODO: Should this be hardcoded?
* @return Array<String>
*/
public function listBaseGameLevelIds():Array<String>
public function listBaseGameEntryIds():Array<String>
{
// This MUST be hard-coded (overriding the auto-generated method)
// because the auto-generated method spits out values in alphabetical order.
return [
"tutorial",
"week1",
"week2",
"week3",
"week4",
"week5",
"week6",
"week7",
"weekend1"
'tutorial',
'week1',
'week2',
'week3',
'week4',
'week5',
'week6',
'week7',
'weekend1'
];
}
/**
* A list of all the story weeks in the game, in order.
* Modded levels are in alphabetical order at the end of the list.
* @return Array<String>
*/
public function listSortedLevelIds():Array<String>
{
var result = listEntryIds();
result.sort(SortUtil.defaultsThenAlphabetically.bind(listBaseGameLevelIds()));
var result:Array<String> = listEntryIds();
result.sort(SortUtil.defaultsThenAlphabetically.bind(listBaseGameEntryIds()));
return result;
}
/**
* A list of all installed story weeks that are not from the base game.
*/
public function listModdedLevelIds():Array<String>
{
return listEntryIds().filter(function(id:String):Bool {
return listBaseGameLevelIds().indexOf(id) == -1;
});
}
}
+30 -14
View File
@@ -3,38 +3,54 @@ package funkin.effects;
import flixel.addons.effects.FlxTrail;
import funkin.play.stage.Bopper;
import flixel.FlxSprite;
import flixel.system.FlxAssets;
import flixel.system.FlxAssets.FlxGraphicAsset;
import flixel.math.FlxPoint;
/**
* An offshoot of FlxTrail, but accomodates the way Funkin
* does offsets for characters. example, fixes Spirits trail
*/
@:nullSafety
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.
* @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)
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);
super(target, graphic, length, delay, alpha, diff);
}
override public function update(elapsed:Float):Void
/**
* An offset applied to the target position whenever a new frame is saved.
*/
public final frameOffset:FlxPoint = FlxPoint.get();
override function destroy():Void
{
super.destroy();
frameOffset.put();
}
override function addTrailFrame():Void
{
super.addTrailFrame();
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);
}
@:privateAccess
frameOffset.set((targ.animOffsets[0] - targ.globalOffsets[0]) * targ.scale.x, (targ.animOffsets[1] - targ.globalOffsets[1]) * targ.scale.y);
super.update(elapsed);
_recentPositions[0]?.subtract(frameOffset.x, frameOffset.y);
}
}
}
+1
View File
@@ -4,6 +4,7 @@ import flixel.util.FlxTimer;
import flixel.FlxCamera;
import openfl.filters.ColorMatrixFilter;
@:nullSafety
class RetroCameraFade
{
// im lazy, but we only use this for week 6
@@ -7,23 +7,17 @@ import flixel.FlxSprite;
import flixel.graphics.FlxGraphic;
import flixel.graphics.frames.FlxFrame;
import flixel.math.FlxMatrix;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.util.FlxColor;
import lime.graphics.cairo.Cairo;
import openfl.display.BitmapData;
import openfl.display.BlendMode;
import openfl.display.DisplayObjectRenderer;
import openfl.display.Graphics;
import openfl.display.OpenGLRenderer;
import openfl.display._internal.Context3DGraphics;
import openfl.display3D.Context3D;
import openfl.display3D.Context3DClearMask;
import openfl.filters.BitmapFilter;
import openfl.filters.BlurFilter;
import openfl.geom.ColorTransform;
import openfl.geom.Matrix;
import openfl.geom.Point;
import openfl.geom.Rectangle;
#if (js && html5)
import lime._internal.graphics.ImageCanvasUtil;
+47 -3
View File
@@ -9,7 +9,7 @@ import funkin.graphics.framebuffer.FixedBitmapData;
import openfl.display.BitmapData;
import flixel.math.FlxRect;
import flixel.math.FlxPoint;
import flixel.graphics.frames.FlxFrame;
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
import flixel.FlxCamera;
/**
@@ -97,14 +97,58 @@ class FunkinSprite extends FlxSprite
return this;
}
public function loadTextureAsync(key:String, fade:Bool = false):Void
{
var fadeTween:Null<FlxTween> = null;
if (fade)
{
fadeTween = FlxTween.tween(this, {alpha: 0}, 0.25);
}
trace('[ASYNC] Start loading image (${key})');
graphic.persist = true;
openfl.Assets.loadBitmapData(key)
.onComplete(function(bitmapData:openfl.display.BitmapData) {
trace('[ASYNC] Finished loading image');
var cache:Bool = false;
loadBitmapData(bitmapData, cache);
if (fadeTween != null)
{
fadeTween.cancel();
FlxTween.tween(this, {alpha: 1.0}, 0.25);
}
})
.onError(function(error:Dynamic) {
trace('[ASYNC] Failed to load image: ${error}');
if (fadeTween != null)
{
fadeTween.cancel();
this.alpha = 1.0;
}
})
.onProgress(function(progress:Int, total:Int) {
trace('[ASYNC] Loading image progress: ${progress}/${total}');
});
}
/**
* Apply an OpenFL `BitmapData` to this sprite.
* @param input The OpenFL `BitmapData` to apply
* @return This sprite, for chaining
*/
public function loadBitmapData(input:BitmapData):FunkinSprite
public function loadBitmapData(input:BitmapData, cache:Bool = true):FunkinSprite
{
loadGraphic(input);
if (cache)
{
loadGraphic(input);
}
else
{
var graphic:FlxGraphic = FlxGraphic.fromBitmapData(input, false, null, false);
this.graphic = graphic;
this.frames = this.graphic.imageFrame;
}
return this;
}
@@ -3,10 +3,8 @@ package funkin.graphics.adobeanimate;
import flixel.util.FlxSignal.FlxTypedSignal;
import flxanimate.FlxAnimate;
import flxanimate.FlxAnimate.Settings;
import flxanimate.frames.FlxAnimateFrames;
import flixel.graphics.frames.FlxFrame;
import flixel.system.FlxAssets.FlxGraphicAsset;
import openfl.display.BitmapData;
import flixel.math.FlxPoint;
import flxanimate.animate.FlxKeyFrame;
@@ -37,6 +35,11 @@ class FlxAtlasSprite extends FlxAnimate
*/
public var onAnimationComplete:FlxTypedSignal<String->Void> = new FlxTypedSignal();
/**
* Signal dispatched when a looping animation finishes playing.
*/
public var onAnimationLoop:FlxTypedSignal<String->Void> = new FlxTypedSignal();
var currentAnimation:String;
var canPlayOtherAnims:Bool = true;
@@ -198,33 +201,44 @@ class FlxAtlasSprite extends FlxAnimate
goToFrameLabel(id);
fr = anim.getFrameLabel(id);
anim.curFrame += startFrame;
// Resume animation if it's paused.
anim.resume();
}
}
override public function update(elapsed:Float)
override public function update(elapsed:Float):Void
{
super.update(elapsed);
}
/**
* Returns true if the animation has finished playing.
* Never true if animation is configured to loop.
* @return Whether the animation has finished playing.
*/
public function isAnimationFinished():Bool
{
return this.anim.finished;
return isLoopComplete();
}
/**
* Returns true if the animation has reached the last frame.
* Can be true even if animation is configured to loop.
* @return Whether the animation has reached the last frame.
*/
public function isLoopComplete():Bool
{
if (this.anim == null) return false;
if (!this.anim.isPlaying) return false;
if (fr != null) return (anim.reversed && anim.curFrame < fr.index || !anim.reversed && anim.curFrame >= (fr.index + fr.duration));
if (fr != null)
{
var curFrame = anim.curFrame;
var startFrame = fr.index;
var endFrame = (fr.index + fr.duration);
return (anim.reversed) ? (curFrame < startFrame) : (curFrame >= endFrame);
}
return (anim.reversed && anim.curFrame == 0 || !(anim.reversed) && (anim.curFrame) >= (anim.length - 1));
}
@@ -252,7 +266,7 @@ class FlxAtlasSprite extends FlxAnimate
this.anim.goToFrameLabel(label);
}
function getFrameLabelNames(?layer:haxe.extern.EitherType<Int, String> = null)
function getFrameLabelNames(?layer:haxe.extern.EitherType<Int, String>):Array<String>
{
var labels = this.anim.getFrameLabels(layer);
var array = [];
@@ -295,16 +309,17 @@ class FlxAtlasSprite extends FlxAnimate
if (isLoopComplete())
{
anim.pause();
_onAnimationComplete();
if (looping)
{
anim.curFrame = (fr != null) ? fr.index : 0;
anim.resume();
_onAnimationLoop();
}
else if (fr != null && anim.curFrame != anim.length - 1)
{
anim.curFrame--;
_onAnimationComplete();
}
}
}
@@ -322,11 +337,32 @@ class FlxAtlasSprite extends FlxAnimate
}
}
function _onAnimationLoop():Void
{
if (currentAnimation != null)
{
onAnimationLoop.dispatch(currentAnimation);
}
else
{
onAnimationLoop.dispatch('');
}
}
var prevFrames:Map<Int, FlxFrame> = [];
public function replaceFrameGraphic(index:Int, ?graphic:FlxGraphicAsset):Void
{
if (graphic == null || !Assets.exists(graphic))
var cond = false;
if (graphic == null) cond = true;
else
{
if ((graphic is String)) cond = !Assets.exists(graphic)
else
cond = false;
}
if (cond)
{
var prevFrame:Null<FlxFrame> = prevFrames.get(index);
if (prevFrame == null) return;
@@ -1,7 +1,6 @@
package funkin.graphics.shaders;
import flixel.system.FlxAssets.FlxShader;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
class BlueFade extends FlxShader
@@ -0,0 +1,227 @@
package funkin.graphics.shaders;
import flixel.system.FlxAssets.FlxShader;
import flixel.util.FlxColor;
import flixel.FlxSprite;
import flixel.math.FlxAngle;
import flixel.graphics.frames.FlxFrame;
import openfl.display.BitmapData;
/*
A screenspace version of the DropShadowShader.. currently the only way to use this effect with
FlxAnimate :(
*/
class DropShadowScreenspace extends DropShadowShader
{
/*
The current zoom of the camera. Needed to figure out how much to multiply the drop shadow size.
*/
public var curZoom(default, set):Float;
function set_curZoom(val:Float):Float
{
curZoom = val;
zoom.value = [val];
return val;
}
@:glFragmentSource('
#pragma header
// This shader aims to mostly recreate how Adobe Animate/Flash handles drop shadows, but its main use here is for rim lighting.
// this shader also includes a recreation of the Animate/Flash "Adjust Color" filter,
// which was kindly provided and written by Rozebud https://github.com/ThatRozebudDude ( thank u rozebud :) )
// Adapted from Andrey-Postelzhuks shader found here: https://forum.unity.com/threads/hue-saturation-brightness-contrast-shader.260649/
// Hue rotation stuff is from here: https://www.w3.org/TR/filter-effects/#feColorMatrixElement
// equals (frame.left, frame.top, frame.right, frame.bottom)
uniform vec4 uFrameBounds;
uniform float ang;
uniform float dist;
uniform float str;
uniform float thr;
// need to account for rotated frames... oops
uniform float angOffset;
uniform sampler2D altMask;
uniform bool useMask;
uniform float thr2;
uniform vec3 dropColor;
uniform float hue;
uniform float saturation;
uniform float brightness;
uniform float contrast;
uniform float zoom;
uniform float AA_STAGES;
const vec3 grayscaleValues = vec3(0.3098039215686275, 0.607843137254902, 0.0823529411764706);
const float e = 2.718281828459045;
vec3 applyHueRotate(vec3 aColor, float aHue){
float angle = radians(aHue);
mat3 m1 = mat3(0.213, 0.213, 0.213, 0.715, 0.715, 0.715, 0.072, 0.072, 0.072);
mat3 m2 = mat3(0.787, -0.213, -0.213, -0.715, 0.285, -0.715, -0.072, -0.072, 0.928);
mat3 m3 = mat3(-0.213, 0.143, -0.787, -0.715, 0.140, 0.715, 0.928, -0.283, 0.072);
mat3 m = m1 + cos(angle) * m2 + sin(angle) * m3;
return m * aColor;
}
vec3 applySaturation(vec3 aColor, float value){
if(value > 0.0){ value = value * 3.0; }
value = (1.0 + (value / 100.0));
vec3 grayscale = vec3(dot(aColor, grayscaleValues));
return clamp(mix(grayscale, aColor, value), 0.0, 1.0);
}
vec3 applyContrast(vec3 aColor, float value){
value = (1.0 + (value / 100.0));
if(value > 1.0){
value = (((0.00852259 * pow(e, 4.76454 * (value - 1.0))) * 1.01) - 0.0086078159) * 10.0; //Just roll with it...
value += 1.0;
}
return clamp((aColor - 0.25) * value + 0.25, 0.0, 1.0);
}
vec3 applyHSBCEffect(vec3 color){
//Brightness
color = color + ((brightness) / 255.0);
//Hue
color = applyHueRotate(color, hue);
//Contrast
color = applyContrast(color, contrast);
//Saturation
color = applySaturation(color, saturation);
return color;
}
vec2 hash22(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.xx + p3.yz) * p3.zy);
}
float intensityPass(vec2 fragCoord, float curThreshold, bool useMask) {
vec4 col = texture2D(bitmap, fragCoord);
float maskIntensity = 0.0;
if(useMask == true){
maskIntensity = mix(0.0, 1.0, texture2D(altMask, fragCoord).b);
}
if(col.a == 0.0){
return 0.0;
}
float intensity = dot(col.rgb, vec3(0.3098, 0.6078, 0.0823));
intensity = maskIntensity > 0.0 ? float(intensity > thr2) : float(intensity > thr);
return intensity;
}
// essentially just stole this from the AngleMask shader but repurposed it to smooth
// the threshold because without any sort of smoothing it produces horrible edges
float antialias(vec2 fragCoord, float curThreshold, bool useMask) {
// In GLSL 100, we need to use constant loop bounds
// Well assume a reasonable maximum for AA_STAGES and use a fixed loop
// The actual number of iterations will be controlled by a condition inside
const int MAX_AA = 8; // This should be large enough for most uses
float AA_TOTAL_PASSES = AA_STAGES * AA_STAGES + 1.0;
const float AA_JITTER = 0.5;
// Run the shader multiple times with a random subpixel offset each time and average the results
float color = intensityPass(fragCoord, curThreshold, useMask);
for (int i = 0; i < MAX_AA * MAX_AA; i++) {
// Calculate x and y from i
int x = i / MAX_AA;
int y = i - (MAX_AA * int(i/MAX_AA)); // poor mans modulus
// Skip iterations beyond our desired AA_STAGES
if (float(x) >= AA_STAGES || float(y) >= AA_STAGES) {
continue;
}
vec2 offset = AA_JITTER * (2.0 * hash22(vec2(float(x), float(y))) - 1.0) / openfl_TextureSize.xy;
color += intensityPass(fragCoord + offset, curThreshold, useMask);
}
return color / AA_TOTAL_PASSES;
}
vec3 createDropShadow(vec3 col, float curThreshold, bool useMask) {
// essentially a mask so that areas under the threshold dont show the rimlight (mainly the outlines)
float intensity = antialias(openfl_TextureCoordv, curThreshold, useMask);
// the distance the dropshadow moves needs to be correctly scaled based on the texture size
vec2 imageRatio = vec2(1.0/openfl_TextureSize.x, 1.0/openfl_TextureSize.y);
// check the pixel in the direction and distance specified
vec2 checkedPixel = vec2(openfl_TextureCoordv.x + ((dist*zoom) * cos(ang + angOffset) * imageRatio.x), openfl_TextureCoordv.y - ((dist*zoom) * sin(ang + angOffset) * imageRatio.y));
// multiplier for the intensity of the drop shadow
float dropShadowAmount = 0.0;
dropShadowAmount = texture2D(bitmap, checkedPixel).a;
// add the dropshadow color based on the amount, strength, and intensity
col.rgb += dropColor.rgb * ((1.0 - (dropShadowAmount * str))*intensity);
return col;
}
void main()
{
vec4 col = texture2D(bitmap, openfl_TextureCoordv);
vec3 unpremultipliedColor = col.a > 0.0 ? col.rgb / col.a : col.rgb;
vec3 outColor = applyHSBCEffect(unpremultipliedColor);
outColor = createDropShadow(outColor, thr, useMask);
gl_FragColor = vec4(outColor.rgb * col.a, col.a);
}
')
override public function new()
{
super();
angle = 90;
strength = 1;
distance = 15;
threshold = 0.1;
baseHue = 0;
baseSaturation = 0;
baseBrightness = 0;
baseContrast = 0;
useAltMask = false;
color = 0xFFDFEF3C;
antialiasAmt = 2;
curZoom = 1;
angOffset.value = [0];
}
}
@@ -0,0 +1,451 @@
package funkin.graphics.shaders;
import flixel.system.FlxAssets.FlxShader;
import flixel.util.FlxColor;
import flixel.FlxSprite;
import flixel.math.FlxAngle;
import flixel.graphics.frames.FlxFrame;
import openfl.display.BitmapData;
/*
A shader that aims to *mostly recreate how Adobe Animate/Flash handles drop shadows, but its main use here is for rim lighting.
Has options for color, angle, distance, and a threshold to not cast the shadow on parts like outlines.
Can also be supplied a secondary mask which can then have an alternate threshold, for when sprites have too many conflicting colors
for the drop shadow to look right (e.g. the tankmen on GF's speakers).
Also has an Adjust Color shader in here so they can work together when needed.
*/
class DropShadowShader extends FlxShader
{
/*
The color of the drop shadow.
*/
public var color(default, set):FlxColor;
/*
The angle of the drop shadow.
for reference, depending on the angle, the affected side will be:
0 = RIGHT
90 = UP
180 = LEFT
270 = DOWN
*/
public var angle(default, set):Float;
/*
The distance or size of the drop shadow, in pixels,
relative to the texture itself... NOT the camera.
*/
public var distance(default, set):Float;
/*
The strength of the drop shadow.
Effectively just an alpha multiplier.
*/
public var strength(default, set):Float;
/*
The brightness threshold for the drop shadow.
Anything below this number will NOT be affected by the drop shadow shader.
A value of 0 effectively means theres no threshold, and vice versa.
*/
public var threshold(default, set):Float;
/*
The amount of antialias samples per-pixel,
used to smooth out any hard edges the brightness thresholding creates.
Defaults to 2, and 0 will remove any smoothing.
*/
public var antialiasAmt(default, set):Float;
/*
Whether the shader should try and use the alternate mask.
False by default.
*/
public var useAltMask(default, set):Bool;
/*
The image for the alternate mask.
At the moment, it uses the blue channel to specify what is or isnt going to use the alternate threshold.
(its kinda sloppy rn i need to make it work a little nicer)
TODO: maybe have a sort of "threshold intensity texture" as well? where higher/lower values indicate threshold strength..
*/
public var altMaskImage(default, set):BitmapData;
/*
An alternate brightness threshold for the drop shadow.
Anything below this number will NOT be affected by the drop shadow shader,
but ONLY when the pixel is within the mask.
*/
public var maskThreshold(default, set):Float;
/*
The FlxSprite that the shader should get the frame data from.
Needed to keep the drop shadow shader in the correct bounds and rotation.
*/
public var attachedSprite(default, set):FlxSprite;
/*
The hue component of the Adjust Color part of the shader.
*/
public var baseHue(default, set):Float;
/*
The saturation component of the Adjust Color part of the shader.
*/
public var baseSaturation(default, set):Float;
/*
The brightness component of the Adjust Color part of the shader.
*/
public var baseBrightness(default, set):Float;
/*
The contrast component of the Adjust Color part of the shader.
*/
public var baseContrast(default, set):Float;
/*
Sets all 4 adjust color values.
*/
public function setAdjustColor(b:Float, h:Float, c:Float, s:Float)
{
baseBrightness = b;
baseHue = h;
baseContrast = c;
baseSaturation = s;
}
function set_baseHue(val:Float):Float
{
baseHue = val;
hue.value = [val];
return val;
}
function set_baseSaturation(val:Float):Float
{
baseSaturation = val;
saturation.value = [val];
return val;
}
function set_baseBrightness(val:Float):Float
{
baseBrightness = val;
brightness.value = [val];
return val;
}
function set_baseContrast(val:Float):Float
{
baseContrast = val;
contrast.value = [val];
return val;
}
function set_threshold(val:Float):Float
{
threshold = val;
thr.value = [val];
return val;
}
function set_antialiasAmt(val:Float):Float
{
antialiasAmt = val;
AA_STAGES.value = [val];
return val;
}
function set_color(col:FlxColor):FlxColor
{
color = col;
dropColor.value = [color.red / 255, color.green / 255, color.blue / 255];
return color;
}
function set_angle(val:Float):Float
{
angle = val;
ang.value = [angle * FlxAngle.TO_RAD];
return angle;
}
function set_distance(val:Float):Float
{
distance = val;
dist.value = [val];
return val;
}
function set_strength(val:Float):Float
{
strength = val;
str.value = [val];
return val;
}
function set_attachedSprite(spr:FlxSprite):FlxSprite
{
attachedSprite = spr;
updateFrameInfo(attachedSprite.frame);
return spr;
}
/*
Loads an image for the mask.
While you *could* directly set the value of the mask, this function works for both HTML5 and desktop targets.
*/
public function loadAltMask(path:String)
{
#if html5
BitmapData.loadFromFile(path).onComplete(function(bmp:BitmapData) {
altMaskImage = bmp;
});
#else
altMaskImage = BitmapData.fromFile(path);
#end
}
/*
Should be called on the animation.callback of the attached sprite.
TODO: figure out why the reference to the attachedSprite breaks on web??
*/
public function onAttachedFrame(name, frameNum, frameIndex)
{
if (attachedSprite != null) updateFrameInfo(attachedSprite.frame);
}
/*
Updates the frame bounds and angle offset of the sprite for the shader.
*/
public function updateFrameInfo(frame:FlxFrame)
{
// NOTE: uv.width is actually the right pos and uv.height is the bottom pos
uFrameBounds.value = [frame.uv.x, frame.uv.y, frame.uv.width, frame.uv.height];
// if a frame is rotated the shader will look completely wrong lol
angOffset.value = [frame.angle * FlxAngle.TO_RAD];
}
function set_altMaskImage(_bitmapData:BitmapData):BitmapData
{
altMask.input = _bitmapData;
return _bitmapData;
}
function set_maskThreshold(val:Float):Float
{
maskThreshold = val;
thr2.value = [val];
return val;
}
function set_useAltMask(val:Bool):Bool
{
useAltMask = val;
useMask.value = [val];
return val;
}
@:glFragmentSource('
#pragma header
// This shader aims to mostly recreate how Adobe Animate/Flash handles drop shadows, but its main use here is for rim lighting.
// this shader also includes a recreation of the Animate/Flash "Adjust Color" filter,
// which was kindly provided and written by Rozebud https://github.com/ThatRozebudDude ( thank u rozebud :) )
// Adapted from Andrey-Postelzhuks shader found here: https://forum.unity.com/threads/hue-saturation-brightness-contrast-shader.260649/
// Hue rotation stuff is from here: https://www.w3.org/TR/filter-effects/#feColorMatrixElement
// equals (frame.left, frame.top, frame.right, frame.bottom)
uniform vec4 uFrameBounds;
uniform float ang;
uniform float dist;
uniform float str;
uniform float thr;
// need to account for rotated frames... oops
uniform float angOffset;
uniform sampler2D altMask;
uniform bool useMask;
uniform float thr2;
uniform vec3 dropColor;
uniform float hue;
uniform float saturation;
uniform float brightness;
uniform float contrast;
uniform float AA_STAGES;
const vec3 grayscaleValues = vec3(0.3098039215686275, 0.607843137254902, 0.0823529411764706);
const float e = 2.718281828459045;
vec3 applyHueRotate(vec3 aColor, float aHue){
float angle = radians(aHue);
mat3 m1 = mat3(0.213, 0.213, 0.213, 0.715, 0.715, 0.715, 0.072, 0.072, 0.072);
mat3 m2 = mat3(0.787, -0.213, -0.213, -0.715, 0.285, -0.715, -0.072, -0.072, 0.928);
mat3 m3 = mat3(-0.213, 0.143, -0.787, -0.715, 0.140, 0.715, 0.928, -0.283, 0.072);
mat3 m = m1 + cos(angle) * m2 + sin(angle) * m3;
return m * aColor;
}
vec3 applySaturation(vec3 aColor, float value){
if(value > 0.0){ value = value * 3.0; }
value = (1.0 + (value / 100.0));
vec3 grayscale = vec3(dot(aColor, grayscaleValues));
return clamp(mix(grayscale, aColor, value), 0.0, 1.0);
}
vec3 applyContrast(vec3 aColor, float value){
value = (1.0 + (value / 100.0));
if(value > 1.0){
value = (((0.00852259 * pow(e, 4.76454 * (value - 1.0))) * 1.01) - 0.0086078159) * 10.0; //Just roll with it...
value += 1.0;
}
return clamp((aColor - 0.25) * value + 0.25, 0.0, 1.0);
}
vec3 applyHSBCEffect(vec3 color){
//Brightness
color = color + ((brightness) / 255.0);
//Hue
color = applyHueRotate(color, hue);
//Contrast
color = applyContrast(color, contrast);
//Saturation
color = applySaturation(color, saturation);
return color;
}
vec2 hash22(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.xx + p3.yz) * p3.zy);
}
float intensityPass(vec2 fragCoord, float curThreshold, bool useMask) {
vec4 col = texture2D(bitmap, fragCoord);
float maskIntensity = 0.0;
if(useMask == true){
maskIntensity = mix(0.0, 1.0, texture2D(altMask, fragCoord).b);
}
if(col.a == 0.0){
return 0.0;
}
float intensity = dot(col.rgb, vec3(0.3098, 0.6078, 0.0823));
intensity = maskIntensity > 0.0 ? float(intensity > thr2) : float(intensity > thr);
return intensity;
}
// essentially just stole this from the AngleMask shader but repurposed it to smooth
// the threshold because without any sort of smoothing it produces horrible edges
float antialias(vec2 fragCoord, float curThreshold, bool useMask) {
// In GLSL 100, we need to use constant loop bounds
// Well assume a reasonable maximum for AA_STAGES and use a fixed loop
// The actual number of iterations will be controlled by a condition inside
const int MAX_AA = 8; // This should be large enough for most uses
float AA_TOTAL_PASSES = AA_STAGES * AA_STAGES + 1.0;
const float AA_JITTER = 0.5;
// Run the shader multiple times with a random subpixel offset each time and average the results
float color = intensityPass(fragCoord, curThreshold, useMask);
for (int i = 0; i < MAX_AA * MAX_AA; i++) {
// Calculate x and y from i
int x = i / MAX_AA;
int y = i - (MAX_AA * int(i/MAX_AA)); // poor mans modulus
// Skip iterations beyond our desired AA_STAGES
if (float(x) >= AA_STAGES || float(y) >= AA_STAGES) {
continue;
}
vec2 offset = AA_JITTER * (2.0 * hash22(vec2(float(x), float(y))) - 1.0) / openfl_TextureSize.xy;
color += intensityPass(fragCoord + offset, curThreshold, useMask);
}
return color / AA_TOTAL_PASSES;
}
vec3 createDropShadow(vec3 col, float curThreshold, bool useMask) {
// essentially a mask so that areas under the threshold dont show the rimlight (mainly the outlines)
float intensity = antialias(openfl_TextureCoordv, curThreshold, useMask);
// the distance the dropshadow moves needs to be correctly scaled based on the texture size
vec2 imageRatio = vec2(1.0/openfl_TextureSize.x, 1.0/openfl_TextureSize.y);
// check the pixel in the direction and distance specified
vec2 checkedPixel = vec2(openfl_TextureCoordv.x + (dist * cos(ang + angOffset) * imageRatio.x), openfl_TextureCoordv.y - (dist * sin(ang + angOffset) * imageRatio.y));
// multiplier for the intensity of the drop shadow
float dropShadowAmount = 0.0;
if(checkedPixel.x > uFrameBounds.x && checkedPixel.y > uFrameBounds.y && checkedPixel.x < uFrameBounds.z && checkedPixel.y < uFrameBounds.w){
dropShadowAmount = texture2D(bitmap, checkedPixel).a;
}
// add the dropshadow color based on the amount, strength, and intensity
col.rgb += dropColor.rgb * ((1.0 - (dropShadowAmount * str))*intensity);
return col;
}
void main()
{
vec4 col = texture2D(bitmap, openfl_TextureCoordv);
vec3 unpremultipliedColor = col.a > 0.0 ? col.rgb / col.a : col.rgb;
vec3 outColor = applyHSBCEffect(unpremultipliedColor);
outColor = createDropShadow(outColor, thr, useMask);
gl_FragColor = vec4(outColor.rgb * col.a, col.a);
}
')
public function new()
{
super();
angle = 0;
strength = 1;
distance = 15;
threshold = 0.1;
baseHue = 0;
baseSaturation = 0;
baseBrightness = 0;
baseContrast = 0;
antialiasAmt = 2;
useAltMask = false;
angOffset.value = [0];
}
}
+4 -4
View File
@@ -8,13 +8,13 @@ class HSVShader extends FlxRuntimeShader
public var saturation(default, set):Float;
public var value(default, set):Float;
public function new()
public function new(h:Float = 1, s:Float = 1, v:Float = 1)
{
super(Assets.getText(Paths.frag('hsv')));
FlxG.debugger.addTrackerProfile(new TrackerProfile(HSVShader, ['hue', 'saturation', 'value']));
hue = 1;
saturation = 1;
value = 1;
hue = h;
saturation = s;
value = v;
}
function set_hue(value:Float):Float
@@ -1,6 +1,5 @@
package funkin.graphics.shaders;
import flixel.system.FlxAssets.FlxShader;
import openfl.display.BitmapData;
import openfl.display.ShaderParameter;
import openfl.display.ShaderParameterType;
+11 -1
View File
@@ -1,7 +1,6 @@
package funkin.graphics.shaders;
import flixel.system.FlxAssets.FlxShader;
import flixel.util.FlxColor;
import openfl.display.BitmapData;
class TextureSwap extends FlxShader
@@ -9,6 +8,17 @@ class TextureSwap extends FlxShader
public var swappedImage(default, set):BitmapData;
public var amount(default, set):Float;
public function loadSwapImage(path:String)
{
#if html5
BitmapData.loadFromFile(path).onComplete(function(bmp:BitmapData) {
swappedImage = bmp;
});
#else
swappedImage = BitmapData.fromFile(path);
#end
}
function set_swappedImage(_bitmapData:BitmapData):BitmapData
{
image.input = _bitmapData;
@@ -1,6 +1,5 @@
package funkin.graphics.shaders;
import flixel.math.FlxPoint;
import flixel.system.FlxAssets.FlxShader;
class TitleOutline extends FlxShader
+2 -4
View File
@@ -1,9 +1,7 @@
package funkin.graphics.video;
import flixel.util.FlxColor;
import flixel.util.FlxSignal.FlxTypedSignal;
import funkin.audio.FunkinSound;
import openfl.display3D.textures.TextureBase;
import openfl.events.NetStatusEvent;
import openfl.media.SoundTransform;
import openfl.media.Video;
@@ -12,8 +10,8 @@ import openfl.net.NetStream;
/**
* Plays a video via a NetStream. Only works on HTML5.
* This does NOT replace hxCodec, nor does hxCodec replace this.
* hxCodec only works on desktop and does not work on HTML5!
* This does NOT replace hxvlc, nor does hxvlc replace this.
* hxvlc only works on desktop and does not work on HTML5!
*/
class FlxVideo extends FunkinSprite
{
@@ -1,34 +1,17 @@
package funkin.graphics.video;
#if hxCodec
import hxcodec.flixel.FlxVideoSprite;
#if hxvlc
import hxvlc.flixel.FlxVideoSprite;
/**
* Not to be confused with FlxVideo, this is a hxcodec based video class
* Not to be confused with FlxVideo, this is a hxvlc 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
+65 -24
View File
@@ -2,23 +2,17 @@ package funkin.input;
import flixel.input.gamepad.FlxGamepad;
import flixel.util.FlxDirectionFlags;
import flixel.FlxObject;
import flixel.input.FlxInput;
import flixel.input.FlxInput.FlxInputState;
import flixel.input.actions.FlxAction;
import flixel.input.actions.FlxActionInput;
import flixel.input.actions.FlxActionInputAnalog.FlxActionInputAnalogClickAndDragMouseMotion;
import flixel.input.actions.FlxActionInputDigital;
import flixel.input.actions.FlxActionManager;
import flixel.input.actions.FlxActionSet;
import flixel.input.android.FlxAndroidKey;
import flixel.input.gamepad.FlxGamepadButton;
import flixel.input.gamepad.FlxGamepadInputID;
import flixel.input.keyboard.FlxKey;
import flixel.input.mouse.FlxMouseButton.FlxMouseButtonID;
import flixel.math.FlxAngle;
import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import lime.ui.Haptic;
/**
@@ -67,6 +61,8 @@ class Controls extends FlxActionSet
var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT);
var _freeplay_right = new FunkinAction(Action.FREEPLAY_RIGHT);
var _freeplay_char_select = new FunkinAction(Action.FREEPLAY_CHAR_SELECT);
var _freeplay_jump_to_top = new FunkinAction(Action.FREEPLAY_JUMP_TO_TOP);
var _freeplay_jump_to_bottom = new FunkinAction(Action.FREEPLAY_JUMP_TO_BOTTOM);
var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE);
var _debug_menu = new FunkinAction(Action.DEBUG_MENU);
#if FEATURE_CHART_EDITOR
@@ -276,6 +272,16 @@ class Controls extends FlxActionSet
inline function get_FREEPLAY_CHAR_SELECT()
return _freeplay_char_select.check();
public var FREEPLAY_JUMP_TO_TOP(get, never):Bool;
inline function get_FREEPLAY_JUMP_TO_TOP()
return _freeplay_jump_to_top.check();
public var FREEPLAY_JUMP_TO_BOTTOM(get, never):Bool;
inline function get_FREEPLAY_JUMP_TO_BOTTOM()
return _freeplay_jump_to_bottom.check();
public var CUTSCENE_ADVANCE(get, never):Bool;
inline function get_CUTSCENE_ADVANCE()
@@ -337,6 +343,8 @@ class Controls extends FlxActionSet
add(_freeplay_left);
add(_freeplay_right);
add(_freeplay_char_select);
add(_freeplay_jump_to_top);
add(_freeplay_jump_to_bottom);
add(_cutscene_advance);
add(_debug_menu);
#if FEATURE_CHART_EDITOR add(_debug_chart); #end
@@ -409,6 +417,7 @@ class Controls extends FlxActionSet
public function getDialogueName(action:FlxActionDigital, ?ignoreSurrounding:Bool = false):String
{
if (action.inputs.length == 0) return 'N/A';
var input = action.inputs[0];
if (ignoreSurrounding == false)
{
@@ -462,6 +471,8 @@ class Controls extends FlxActionSet
case FREEPLAY_LEFT: _freeplay_left;
case FREEPLAY_RIGHT: _freeplay_right;
case FREEPLAY_CHAR_SELECT: _freeplay_char_select;
case FREEPLAY_JUMP_TO_TOP: _freeplay_jump_to_top;
case FREEPLAY_JUMP_TO_BOTTOM: _freeplay_jump_to_bottom;
case CUTSCENE_ADVANCE: _cutscene_advance;
case DEBUG_MENU: _debug_menu;
#if FEATURE_CHART_EDITOR case DEBUG_CHART: _debug_chart; #end
@@ -542,6 +553,10 @@ class Controls extends FlxActionSet
func(_freeplay_right, JUST_PRESSED);
case FREEPLAY_CHAR_SELECT:
func(_freeplay_char_select, JUST_PRESSED);
case FREEPLAY_JUMP_TO_TOP:
func(_freeplay_jump_to_top, JUST_PRESSED);
case FREEPLAY_JUMP_TO_BOTTOM:
func(_freeplay_jump_to_bottom, JUST_PRESSED);
case CUTSCENE_ADVANCE:
func(_cutscene_advance, JUST_PRESSED);
case DEBUG_MENU:
@@ -711,7 +726,7 @@ class Controls extends FlxActionSet
forEachBound(control, function(action, state) addKeys(action, keys, state));
}
public function bindSwipe(control:Control, swipeDir:Int = FlxDirectionFlags.UP, ?swpLength:Float = 90)
public function bindSwipe(control:Control, swipeDir:FlxDirectionFlags = FlxDirectionFlags.UP, ?swpLength:Float = 90)
{
forEachBound(control, function(action, press) action.add(new FlxActionInputDigitalMobileSwipeGameplay(swipeDir, press, swpLength)));
}
@@ -770,6 +785,8 @@ class Controls extends FlxActionSet
bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT));
bindKeys(Control.FREEPLAY_RIGHT, getDefaultKeybinds(scheme, Control.FREEPLAY_RIGHT));
bindKeys(Control.FREEPLAY_CHAR_SELECT, getDefaultKeybinds(scheme, Control.FREEPLAY_CHAR_SELECT));
bindKeys(Control.FREEPLAY_JUMP_TO_TOP, getDefaultKeybinds(scheme, Control.FREEPLAY_JUMP_TO_TOP));
bindKeys(Control.FREEPLAY_JUMP_TO_BOTTOM, getDefaultKeybinds(scheme, Control.FREEPLAY_JUMP_TO_BOTTOM));
bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE));
bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU));
#if FEATURE_CHART_EDITOR
@@ -810,6 +827,8 @@ class Controls extends FlxActionSet
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.FREEPLAY_JUMP_TO_TOP: return [HOME];
case Control.FREEPLAY_JUMP_TO_BOTTOM: return [END];
case Control.CUTSCENE_ADVANCE: return [Z, ENTER];
case Control.DEBUG_MENU: return [GRAVEACCENT];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
@@ -839,6 +858,8 @@ class Controls extends FlxActionSet
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.FREEPLAY_JUMP_TO_TOP: return [HOME];
case Control.FREEPLAY_JUMP_TO_BOTTOM: return [END];
case Control.CUTSCENE_ADVANCE: return [G, Z];
case Control.DEBUG_MENU: return [GRAVEACCENT];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
@@ -868,6 +889,8 @@ class Controls extends FlxActionSet
case Control.FREEPLAY_LEFT: return [];
case Control.FREEPLAY_RIGHT: return [];
case Control.FREEPLAY_CHAR_SELECT: return [];
case Control.FREEPLAY_JUMP_TO_TOP: return [];
case Control.FREEPLAY_JUMP_TO_BOTTOM: return [];
case Control.CUTSCENE_ADVANCE: return [ENTER];
case Control.DEBUG_MENU: return [];
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
@@ -983,6 +1006,9 @@ class Controls extends FlxActionSet
Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE),
Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT),
Control.FREEPLAY_RIGHT => getDefaultGamepadBinds(Control.FREEPLAY_RIGHT),
Control.FREEPLAY_CHAR_SELECT => getDefaultGamepadBinds(Control.FREEPLAY_CHAR_SELECT),
Control.FREEPLAY_JUMP_TO_TOP => getDefaultGamepadBinds(Control.FREEPLAY_JUMP_TO_TOP),
Control.FREEPLAY_JUMP_TO_BOTTOM => getDefaultGamepadBinds(Control.FREEPLAY_JUMP_TO_BOTTOM),
Control.VOLUME_UP => getDefaultGamepadBinds(Control.VOLUME_UP),
Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN),
Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE),
@@ -1033,11 +1059,17 @@ class Controls extends FlxActionSet
case Control.CUTSCENE_ADVANCE:
return [A];
case Control.FREEPLAY_FAVORITE:
[FlxGamepadInputID.BACK]; // Back (i.e. Select)
return [Y]; // Back (i.e. Select)
case Control.FREEPLAY_LEFT:
[LEFT_SHOULDER];
return [LEFT_SHOULDER];
case Control.FREEPLAY_RIGHT:
[RIGHT_SHOULDER];
return [RIGHT_SHOULDER];
case Control.FREEPLAY_CHAR_SELECT:
return [X];
case Control.FREEPLAY_JUMP_TO_TOP:
return [];
case Control.FREEPLAY_JUMP_TO_BOTTOM:
return [];
case Control.VOLUME_UP:
[];
case Control.VOLUME_DOWN:
@@ -1446,9 +1478,9 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital
var activateLength:Float = 90;
var hapticPressure:Int = 100;
public function new(swipeDir:Int = FlxDirectionFlags.ANY, Trigger:FlxInputState, ?swipeLength:Float = 90)
public function new(swipeDir:FlxDirectionFlags = FlxDirectionFlags.ANY, Trigger:FlxInputState, ?swipeLength:Float = 90)
{
super(OTHER, swipeDir, Trigger);
super(OTHER, swipeDir.toInt(), Trigger);
activateLength = swipeLength;
}
@@ -1530,16 +1562,21 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital
case JUST_PRESSED:
if (swp.touchLength >= activateLength)
{
switch (inputID)
if (inputID == FlxDirectionFlags.UP.toInt())
{
case FlxDirectionFlags.UP:
if (degAngle >= 45 && degAngle <= 90 + 45) return properTouch(swp);
case FlxDirectionFlags.DOWN:
if (-degAngle >= 45 && -degAngle <= 90 + 45) return properTouch(swp);
case FlxDirectionFlags.LEFT:
if (degAngle <= 45 && -degAngle <= 45) return properTouch(swp);
case FlxDirectionFlags.RIGHT:
if (degAngle >= 90 + 45 && degAngle <= -90 + -45) return properTouch(swp);
if (degAngle >= 45 && degAngle <= 90 + 45) return properTouch(swp);
}
else if (inputID == FlxDirectionFlags.DOWN.toInt())
{
if (-degAngle >= 45 && -degAngle <= 90 + 45) return properTouch(swp);
}
else if (inputID == FlxDirectionFlags.LEFT.toInt())
{
if (degAngle <= 45 && -degAngle <= 45) return properTouch(swp);
}
else if (inputID == FlxDirectionFlags.RIGHT.toInt())
{
if (degAngle >= 90 + 45 && degAngle <= -90 + -45) return properTouch(swp);
}
}
default:
@@ -1602,10 +1639,10 @@ enum Control
NOTE_UP;
NOTE_RIGHT;
// UI
UI_UP;
UI_LEFT;
UI_RIGHT;
UI_DOWN;
UI_UP;
UI_RIGHT;
RESET;
ACCEPT;
BACK;
@@ -1617,6 +1654,8 @@ enum Control
FREEPLAY_LEFT;
FREEPLAY_RIGHT;
FREEPLAY_CHAR_SELECT;
FREEPLAY_JUMP_TO_TOP;
FREEPLAY_JUMP_TO_BOTTOM;
// WINDOW
#if FEATURE_SCREENSHOTS WINDOW_SCREENSHOT; #end
WINDOW_FULLSCREEN;
@@ -1674,6 +1713,8 @@ enum abstract Action(String) to String from String
var FREEPLAY_LEFT = "freeplay_left";
var FREEPLAY_RIGHT = "freeplay_right";
var FREEPLAY_CHAR_SELECT = "freeplay_char_select";
var FREEPLAY_JUMP_TO_TOP = "freeplay_jump_to_top";
var FREEPLAY_JUMP_TO_BOTTOM = "freeplay_jump_to_bottom";
// VOLUME
var VOLUME_UP = "volume_up";
var VOLUME_DOWN = "volume_down";
+9 -1
View File
@@ -37,6 +37,9 @@ interface IStateChangingScriptedClass extends IScriptedClass
public function onSubStateOpenEnd(event:SubStateScriptEvent):Void;
public function onSubStateCloseBegin(event:SubStateScriptEvent):Void;
public function onSubStateCloseEnd(event:SubStateScriptEvent):Void;
public function onFocusLost(event:FocusScriptEvent):Void;
public function onFocusGained(event:FocusScriptEvent):Void;
}
/**
@@ -71,6 +74,11 @@ interface INoteScriptedClass extends IScriptedClass
* Called when EITHER player (usually the player) misses a note.
*/
public function onNoteMiss(event:NoteScriptEvent):Void;
/**
* Called when EITHER player (usually the player) drops a hold note.
*/
public function onNoteHoldDrop(event:HoldNoteScriptEvent):Void;
}
/**
@@ -140,7 +148,7 @@ interface IPlayStateScriptedClass extends INoteScriptedClass extends IBPMSyncedS
/**
* Called when the player restarts the song, either via pause menu or restarting after a game over.
*/
public function onSongRetry(event:ScriptEvent):Void;
public function onSongRetry(event:SongRetryEvent):Void;
/**
* Called when the player presses a key when no note is on the strumline.
+75 -11
View File
@@ -11,6 +11,7 @@ import funkin.play.notes.notekind.NoteKindManager;
import funkin.data.song.SongRegistry;
import funkin.data.freeplay.player.PlayerRegistry;
import funkin.data.stage.StageRegistry;
import funkin.data.stickers.StickerRegistry;
import funkin.data.freeplay.album.AlbumRegistry;
import funkin.modding.module.ModuleHandler;
import funkin.play.character.CharacterData.CharacterDataParser;
@@ -38,7 +39,7 @@ class PolymodHandler
* 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";
static final API_VERSION_RULE:String = ">=0.6.3 <0.7.0";
/**
* Where relative to the executable that mods are located.
@@ -79,8 +80,10 @@ class PolymodHandler
*/
public static function loadAllMods():Void
{
#if sys
// Create the mod root if it doesn't exist.
createModRoot();
#end
trace('Initializing Polymod (using all mods)...');
loadModsById(getAllModIds());
}
@@ -90,9 +93,10 @@ class PolymodHandler
*/
public static function loadEnabledMods():Void
{
#if sys
// Create the mod root if it doesn't exist.
createModRoot();
#end
trace('Initializing Polymod (using configured mods)...');
loadModsById(Save.instance.enabledModIds);
}
@@ -102,9 +106,10 @@ class PolymodHandler
*/
public static function loadNoMods():Void
{
#if sys
// Create the mod root if it doesn't exist.
createModRoot();
#end
// We still need to configure the debug print calls etc.
trace('Initializing Polymod (using no mods)...');
loadModsById([]);
@@ -151,11 +156,13 @@ class PolymodHandler
frameworkParams: buildFrameworkParams(),
// List of filenames to ignore in mods. Use the default list to ignore the metadata file, etc.
ignoredFiles: Polymod.getDefaultIgnoreList(),
ignoredFiles: buildIgnoreList(),
// Parsing rules for various data formats.
parseRules: buildParseRules(),
skipDependencyErrors: true,
// Parse hxc files and register the scripted classes in them.
useScriptedClasses: true,
loadScriptsAsync: #if html5 true #else false #end,
@@ -248,6 +255,9 @@ class PolymodHandler
Polymod.addImportAlias('lime.utils.Assets', funkin.Assets);
Polymod.addImportAlias('openfl.utils.Assets', funkin.Assets);
// `funkin.util.FileUtil` has unrestricted access to the file system.
Polymod.addImportAlias('funkin.util.FileUtil', funkin.util.FileUtilSandboxed);
// Add blacklisting for prohibited classes and packages.
// `Sys`
@@ -255,12 +265,12 @@ class PolymodHandler
Polymod.blacklistImport('Sys');
// `Reflect`
// Reflect.callMethod() can access blacklisted packages
Polymod.blacklistImport('Reflect');
// Reflect.callMethod() can access blacklisted packages, but some functions are whitelisted
Polymod.addImportAlias('Reflect', funkin.util.ReflectUtil);
// `Type`
// Type.createInstance(Type.resolveClass()) can access blacklisted packages
Polymod.blacklistImport('Type');
// Type.createInstance(Type.resolveClass()) can access blacklisted packages, but some functions are whitelisted
Polymod.addImportAlias('Type', funkin.util.ReflectUtil);
// `cpp.Lib`
// Lib.load() can load malicious DLLs
@@ -288,12 +298,21 @@ class PolymodHandler
Polymod.blacklistImport('openfl.utils.Assets');
Polymod.blacklistImport('openfl.Lib');
Polymod.blacklistImport('openfl.system.ApplicationDomain');
Polymod.blacklistImport('funkin.util.FunkinTypeResolver');
Polymod.blacklistImport('openfl.net.SharedObject');
// `openfl.desktop.NativeProcess`
// Can load native processes on the host operating system.
Polymod.blacklistImport('openfl.desktop.NativeProcess');
// `funkin.api.*`
// Contains functions which may allow for cheating and such.
for (cls in ClassMacro.listClassesInPackage('funkin.api'))
{
if (cls == null) continue;
var className:String = Type.getClassName(cls);
Polymod.blacklistImport(className);
}
// `polymod.*`
// Contains functions which may allow for un-blacklisting other modules.
for (cls in ClassMacro.listClassesInPackage('polymod'))
@@ -303,6 +322,24 @@ class PolymodHandler
Polymod.blacklistImport(className);
}
// `funkin.api.newgrounds.*`
// Contains functions which allow for cheating medals and leaderboards.
for (cls in ClassMacro.listClassesInPackage('funkin.api.newgrounds'))
{
if (cls == null) continue;
var className:String = Type.getClassName(cls);
Polymod.blacklistImport(className);
}
// `io.newgrounds.*`
// Contains functions which allow for cheating medals and leaderboards.
for (cls in ClassMacro.listClassesInPackage('io.newgrounds'))
{
if (cls == null) continue;
var className:String = Type.getClassName(cls);
Polymod.blacklistImport(className);
}
// `sys.*`
// Access to system utilities such as the file system.
for (cls in ClassMacro.listClassesInPackage('sys'))
@@ -313,6 +350,21 @@ class PolymodHandler
}
}
/**
* Build a list of file paths that will be ignored in mods.
*/
static function buildIgnoreList():Array<String>
{
var result = Polymod.getDefaultIgnoreList();
result.push('.git');
result.push('.gitignore');
result.push('.gitattributes');
result.push('README.md');
return result;
}
static function buildParseRules():polymod.format.ParseRules
{
var output:polymod.format.ParseRules = polymod.format.ParseRules.getDefault();
@@ -333,8 +385,19 @@ class PolymodHandler
{
return {
assetLibraryPaths: [
'default' => 'preload', 'shared' => 'shared', 'songs' => 'songs', 'videos' => 'videos', 'tutorial' => 'tutorial', 'week1' => 'week1',
'week2' => 'week2', 'week3' => 'week3', 'week4' => 'week4', 'week5' => 'week5', 'week6' => 'week6', 'week7' => 'week7', 'weekend1' => 'weekend1',
'default' => 'preload',
'shared' => 'shared',
'songs' => 'songs',
'videos' => 'videos',
'tutorial' => 'tutorial',
'week1' => 'week1',
'week2' => 'week2',
'week3' => 'week3',
'week4' => 'week4',
'week5' => 'week5',
'week6' => 'week6',
'week7' => 'week7',
'weekend1' => 'weekend1',
],
coreAssetRedirect: CORE_FOLDER,
}
@@ -425,6 +488,7 @@ class PolymodHandler
SpeakerRegistry.instance.loadEntries();
AlbumRegistry.instance.loadEntries();
StageRegistry.instance.loadEntries();
StickerRegistry.instance.loadEntries();
CharacterDataParser.loadCharacterCache(); // TODO: Migrate characters to BaseRegistry.
NoteKindManager.loadScripts();

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