diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 71089ba04..f6f5c3250 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -3,13 +3,18 @@ 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: diff --git a/.github/ISSUE_TEMPLATE/charting.yml b/.github/ISSUE_TEMPLATE/charting.yml index a56afc543..e86b73c12 100644 --- a/.github/ISSUE_TEMPLATE/charting.yml +++ b/.github/ISSUE_TEMPLATE/charting.yml @@ -3,13 +3,18 @@ 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 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: diff --git a/.github/ISSUE_TEMPLATE/compiling.yml b/.github/ISSUE_TEMPLATE/compiling.yml index cab9b34cd..6dd9e4cf9 100644 --- a/.github/ISSUE_TEMPLATE/compiling.yml +++ b/.github/ISSUE_TEMPLATE/compiling.yml @@ -1,23 +1,31 @@ -name: Compiling Report +name: Compiling Help description: Report an issue with compiling the game. labels: ["type: compilation help", "status: pending triage"] -title: "Compiling Report: " +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 properly named my issue + - 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 to/for? + description: Which platform are you compiling for? options: - Web/HTML5 - - Desktop + - Desktop (Windows) + - Desktop (Mac) + - Desktop (Linux) - Other validations: required: true @@ -32,7 +40,7 @@ body: - type: markdown attributes: - value: "## Describe your compiling error." + value: "## Describe your compiling issue." - type: markdown attributes: @@ -40,8 +48,16 @@ body: - type: textarea attributes: - label: Description (include any images, videos, errors of terminal or console, error logs) - 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... + 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 diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index a91f670d0..f315fcc2c 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -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: diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index dfb4ace95..ac0e758c8 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -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: diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml index 1de00e62f..9b2f338ce 100644 --- a/.github/changed-lines-count-labeler.yml +++ b/.github/changed-lines-count-labeler.yml @@ -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 diff --git a/.github/label-actions.yml b/.github/label-actions.yml index a99d17660..ef7448ab2 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -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' diff --git a/.github/labeler.yml b/.github/labeler.yml index 9cf784f4c..414df5a31 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -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' diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8e8a45e19..15e94daa5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ - + ## Does this PR close any issues? If so, link them below. ## Briefly describe the issue(s) fixed. diff --git a/.github/workflows/label-pull-request-on-create.yml b/.github/workflows/label-pull-request-on-create.yml new file mode 100644 index 000000000..94620657d --- /dev/null +++ b/.github/workflows/label-pull-request-on-create.yml @@ -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" diff --git a/README.md b/README.md index 29077d7f1..6c12bfd08 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 000000000..b25cbb190 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,244 @@ +# 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. + +# 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.5.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^_ | +| 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 | +| Adjusted Difficulty Ratings | https://github.com/FunkinCrew/Funkin/issues/2781#issuecomment-2172053144 | +| Countdown after Unpausing | https://github.com/FunkinCrew/Funkin/issues/2721#issuecomment-2159330106 | +| 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. + +**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! + +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. + +## 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 look like a 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). + +Here are some guidelines for writing comments in your code: +- Leave comments only when you believe a piece of code warrants explanation. +- 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 Comments +#### DO NOT: +```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 whole 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(); + } +``` + +#### DO: +```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(); + } +``` + +## 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. + +# Closing +Thank you for reading the Contributing Guide. +We look forward to seeing your contributions to the game! diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 54ba396c4..fd2bee464 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -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,7 +23,7 @@ - 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**. diff --git a/source/Main.hx b/source/Main.hx index 1e1f8832d..c0a85d315 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -107,7 +107,7 @@ class Main extends Sprite 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; diff --git a/source/funkin/Assets.hx b/source/funkin/Assets.hx index 967e4b0ca..6b1131691 100644 --- a/source/funkin/Assets.hx +++ b/source/funkin/Assets.hx @@ -144,16 +144,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 { return openfl.utils.Assets.loadLibrary(name); diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index 0578c37ef..37977dbf4 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -157,6 +157,25 @@ 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; + } + public static var unlockedFramerate(get, set):Bool; static function get_unlockedFramerate():Bool @@ -231,6 +250,8 @@ class Preferences #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 diff --git a/source/funkin/data/stage/StageData.hx b/source/funkin/data/stage/StageData.hx index 5ac22ca90..56fd9ebd8 100644 --- a/source/funkin/data/stage/StageData.hx +++ b/source/funkin/data/stage/StageData.hx @@ -171,7 +171,7 @@ 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] */ @@ -261,4 +261,32 @@ typedef StageDataCharacter = */ @:optional var cameraOffsets:Array; + + /** + * 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 [0, 0] + */ + @:optional + @:default([0, 0]) + var scroll:Array; + + /** + * 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; }; diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 5fe22be9a..65b697e32 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -61,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 @@ -270,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() @@ -331,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 @@ -456,6 +470,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 @@ -536,6 +552,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: @@ -764,6 +784,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 @@ -804,6 +826,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 @@ -833,6 +857,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 @@ -862,6 +888,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 @@ -978,6 +1006,8 @@ class Controls extends FlxActionSet 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), @@ -1035,6 +1065,10 @@ class Controls extends FlxActionSet 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: @@ -1619,6 +1653,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; @@ -1676,6 +1712,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"; diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index abca8a7ee..665cf00d6 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -290,7 +290,7 @@ 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. diff --git a/source/funkin/play/ResultScore.hx b/source/funkin/play/ResultScore.hx index 23e6c8d32..c5713b7b0 100644 --- a/source/funkin/play/ResultScore.hx +++ b/source/funkin/play/ResultScore.hx @@ -50,12 +50,12 @@ class ResultScore extends FlxTypedSpriteGroup public function animateNumbers():Void { - for (i in group.members.length-scoreStart...group.members.length) + for (i in group.members.length - scoreStart...group.members.length) { - // if(i.finalDigit == 10) continue; + // if(i.finalDigit == 10) continue; - new FlxTimer().start((i-1)/24, _ -> { - group.members[i].finalDelay = scoreStart - (i-1); + new FlxTimer().start((i - 1) / 24, _ -> { + group.members[i].finalDelay = scoreStart - (i - 1); group.members[i].playAnim(); group.members[i].shuffle(); }); @@ -97,10 +97,13 @@ class ScoreNum extends FlxSprite { if (val >= 0 && animation.curAnim != null && animation.curAnim.name != numToString[val]) { - if(glow){ + if (glow) + { animation.play(numToString[val], true, false, 0); glow = false; - }else{ + } + else + { animation.play(numToString[val], true, false, 4); } updateHitbox(); @@ -108,18 +111,18 @@ class ScoreNum extends FlxSprite switch (val) { case 1: - // offset.x -= 15; + // offset.x -= 15; case 5: - // set offsets - // offset.x += 0; - // offset.y += 10; + // set offsets + // offset.x += 0; + // offset.y += 10; case 7: - // offset.y += 6; + // offset.y += 6; case 4: - // offset.y += 5; + // offset.y += 5; case 9: - // offset.y += 5; + // offset.y += 5; default: centerOffsets(false); } @@ -144,44 +147,45 @@ class ScoreNum extends FlxSprite "ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "DISABLED" ]; - function finishShuffleTween():Void{ - + function finishShuffleTween():Void + { var tweenFunction = function(x) { var digitRounded = Math.floor(x); - //if(digitRounded == finalDigit) glow = true; + // if(digitRounded == finalDigit) glow = true; digit = digitRounded; }; - finalTween = FlxTween.num(0.0, finalDigit, 23/24, { - ease: FlxEase.quadOut, - onComplete: function (input) { - new FlxTimer().start((finalDelay)/24, _ -> { - animation.play(animation.curAnim.name, true, false, 0); - }); - // fuck - } - }, tweenFunction); + finalTween = FlxTween.num(0.0, finalDigit, 23 / 24, + { + ease: FlxEase.quadOut, + onComplete: function(input) { + new FlxTimer().start((finalDelay) / 24, _ -> { + animation.play(animation.curAnim.name, true, false, 0); + }); + // fuck + } + }, tweenFunction); } - function shuffleProgress(shuffleTimer:FlxTimer):Void { var tempDigit:Int = digit; tempDigit += 1; - if(tempDigit > 9) tempDigit = 0; - if(tempDigit < 0) tempDigit = 0; + if (tempDigit > 9) tempDigit = 0; + if (tempDigit < 0) tempDigit = 0; digit = tempDigit; if (shuffleTimer.loops > 0 && shuffleTimer.loopsLeft == 0) { - //digit = finalDigit; + // digit = finalDigit; finishShuffleTween(); } } - public function shuffle():Void{ - var duration:Float = 41/24; - var interval:Float = 1/24; + public function shuffle():Void + { + var duration:Float = 41 / 24; + var interval:Float = 1 / 24; shuffleTimer = new FlxTimer().start(interval, shuffleProgress, Std.int(duration / interval)); } diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index c485a6d34..ea93ab7a1 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -282,8 +282,7 @@ class ResultState extends MusicBeatSubState songName.shader = maskShaderSongName; difficulty.shader = maskShaderDifficulty; - // maskShaderSongName.swagMaskX = difficulty.x - 15; - maskShaderDifficulty.swagMaskX = difficulty.x - 15; + maskShaderDifficulty.swagMaskX = difficulty.x - 30; var blackTopBar:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/topBarBlack")); blackTopBar.y = -blackTopBar.height; diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 85dfa6360..73d0aa522 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -26,7 +26,7 @@ typedef StagePropGroup = FlxTypedSpriteGroup; /** * A Stage is a group of objects rendered in the PlayState. * - * A Stage is comprised of one or more props, each of which is a FlxSprite. + * A Stage is comprised of one or more props, each of which is an FlxSprite. */ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements IRegistryEntry { @@ -453,6 +453,12 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements character.cameraFocusPoint.x += stageCharData.cameraOffsets[0]; character.cameraFocusPoint.y += stageCharData.cameraOffsets[1]; + character.scrollFactor.x = stageCharData.scroll[0]; + character.scrollFactor.y = stageCharData.scroll[1]; + + character.alpha = stageCharData.alpha; + character.angle = stageCharData.angle; + #if FEATURE_DEBUG_FUNCTIONS // Draw the debug icon at the character's feet. if (charType == BF || charType == DAD) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 42146f0a4..4d2bab9d0 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -102,6 +102,7 @@ class Save debugDisplay: false, autoPause: true, strumlineBackgroundOpacity: 0, + autoFullscreen: false, inputOffset: 0, audioVisualOffset: 0, unlockedFramerate: false, @@ -1364,7 +1365,13 @@ typedef SaveDataOptions = var strumlineBackgroundOpacity:Int; /** - * Offset the users inputs by this many ms. + * If enabled, the game will automatically launch in fullscreen on startup. + * @default `true` + */ + var autoFullscreen:Bool; + + /** + * Offset the user's inputs by this many ms. * @default `0` */ var inputOffset:Int; diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 507a7ce44..6e3ea3bbe 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -469,7 +469,10 @@ class CharSelectSubState extends MusicBeatSubState } else { - if (availableChars.exists(i)) nonLocks.push(i); + var playableCharacterId:String = availableChars.get(i); + var player:Null = PlayerRegistry.instance.fetchEntry(playableCharacterId); + var isPlayerUnlocked:Bool = player?.isUnlocked() ?? false; + if (availableChars.exists(i) && isPlayerUnlocked) nonLocks.push(i); var temp:Lock = new Lock(0, 0, i); temp.ID = 1; diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 16da8caad..e1f21f5b0 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -396,6 +396,11 @@ class DebugBoundingState extends FlxState onionSkinChar.visible = !onionSkinChar.visible; } + if (FlxG.keys.justPressed.G) + { + swagChar.flipX = !swagChar.flipX; + } + // Plays the idle animation if (FlxG.keys.justPressed.SPACE) { diff --git a/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx b/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx index cb0fa7b28..8d6b3605c 100644 --- a/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx +++ b/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx @@ -22,6 +22,8 @@ class CapsuleOptionsMenu extends FlxSpriteGroup var currentInstrumental:FlxText; + var busy:Bool = false; + public function new(parent:FreeplayState, x:Float = 0, y:Float = 0, instIds:Array):Void { super(x, y); @@ -66,24 +68,34 @@ class CapsuleOptionsMenu extends FlxSpriteGroup destroy(); return; } - @:privateAccess - if (parent.controls.BACK) + var changedInst = false; + + if (!busy) { - close(); - return; + @:privateAccess + if (parent.controls.BACK) + { + close(); + return; + } + + if (parent.getControls().UI_LEFT_P) + { + currentInstrumentalIndex = (currentInstrumentalIndex + 1) % instrumentalIds.length; + changedInst = true; + } + if (parent.getControls().UI_RIGHT_P) + { + currentInstrumentalIndex = (currentInstrumentalIndex - 1 + instrumentalIds.length) % instrumentalIds.length; + changedInst = true; + } + if (parent.getControls().ACCEPT) + { + busy = true; + onConfirm(instrumentalIds[currentInstrumentalIndex] ?? ''); + } } - var changedInst = false; - if (parent.getControls().UI_LEFT_P) - { - currentInstrumentalIndex = (currentInstrumentalIndex + 1) % instrumentalIds.length; - changedInst = true; - } - if (parent.getControls().UI_RIGHT_P) - { - currentInstrumentalIndex = (currentInstrumentalIndex - 1 + instrumentalIds.length) % instrumentalIds.length; - changedInst = true; - } if (!changedInst && currentInstrumental.text == '') changedInst = true; if (changedInst) @@ -91,11 +103,6 @@ class CapsuleOptionsMenu extends FlxSpriteGroup currentInstrumental.text = instrumentalIds[currentInstrumentalIndex].toTitleCase() ?? ''; if (currentInstrumental.text == '') currentInstrumental.text = 'Default'; } - - if (parent.getControls().ACCEPT) - { - onConfirm(instrumentalIds[currentInstrumentalIndex] ?? ''); - } } public function close():Void diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 91ebef25d..f8939984e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1391,6 +1391,16 @@ class FreeplayState extends MusicBeatSubState } } + if (controls.FREEPLAY_JUMP_TO_TOP && !busy) + { + changeSelection(-curSelected); + } + + if (controls.FREEPLAY_JUMP_TO_BOTTOM && !busy) + { + changeSelection(grpCapsules.countLiving() - curSelected - 1); + } + lerpScore = MathUtil.smoothLerp(lerpScore, intendedScore, elapsed, 0.5); lerpCompletion = MathUtil.smoothLerp(lerpCompletion, intendedCompletion, elapsed, 0.5); diff --git a/source/funkin/ui/options/ControlsMenu.hx b/source/funkin/ui/options/ControlsMenu.hx index b67e9d92e..1eb9dc211 100644 --- a/source/funkin/ui/options/ControlsMenu.hx +++ b/source/funkin/ui/options/ControlsMenu.hx @@ -49,6 +49,10 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page var currentDevice:Device = Keys; var deviceListSelected:Bool = false; + static final CONTROL_BASE_X = 50; + static final CONTROL_MARGIN_X = 700; + static final CONTROL_SPACING_X = 300; + public function new() { super(); @@ -141,10 +145,10 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length); var formatName = name.replace('_', ' '); - var label = labels.add(new AtlasText(100, y, formatName, AtlasFont.BOLD)); + var label = labels.add(new AtlasText(CONTROL_BASE_X, y, formatName, AtlasFont.BOLD)); label.alpha = 0.6; for (i in 0...COLUMNS) - createItem(label.x + 550 + i * 400, y, control, i); + createItem(label.x + CONTROL_MARGIN_X + i * CONTROL_SPACING_X, y, control, i); y += spacer; } diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 77007952b..ad4ddabc9 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -115,6 +115,9 @@ class PreferencesMenu extends Page createPrefItemCheckbox('Auto Pause', 'If enabled, game automatically pauses when it loses focus.', function(value:Bool):Void { Preferences.autoPause = value; }, Preferences.autoPause); + createPrefItemCheckbox('Launch in Fullscreen', 'Automatically launch the game in fullscreen on startup', function(value:Bool):Void { + Preferences.autoFullscreen = value; + }, Preferences.autoFullscreen); #if web createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void { diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 247b56934..93bc7ed96 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -28,6 +28,10 @@ import openfl.net.NetStream; #if FEATURE_NEWGROUNDS import funkin.api.newgrounds.Medals; #end +import funkin.ui.freeplay.FreeplayState; +import funkin.api.newgrounds.NGio; +import openfl.display.BlendMode; +import funkin.save.Save; #if desktop #end @@ -47,10 +51,6 @@ class TitleState extends MusicBeatState var lastBeat:Int = 0; var swagShader:ColorSwap; - var video:Video; - var netStream:NetStream; - var overlay:Sprite; - override public function create():Void { super.create(); @@ -62,7 +62,6 @@ class TitleState extends MusicBeatState // DEBUG BULLSHIT - // netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown); if (!initialized) new FlxTimer().start(1, function(tmr:FlxTimer) { startIntro(); }); @@ -70,42 +69,6 @@ class TitleState extends MusicBeatState startIntro(); } - function client_onMetaData(metaData:Dynamic) - { - video.attachNetStream(netStream); - - video.width = video.videoWidth; - video.height = video.videoHeight; - // video. - } - - function netStream_onAsyncError(event:AsyncErrorEvent):Void - { - trace("Error loading video"); - } - - function netConnection_onNetStatus(event:NetStatusEvent):Void - { - if (event.info.code == 'NetStream.Play.Complete') - { - // netStream.dispose(); - // FlxG.stage.removeChild(video); - - startIntro(); - } - - trace(event.toString()); - } - - function overlay_onMouseDown(event:MouseEvent):Void - { - netStream.soundTransform.volume = 0.2; - netStream.soundTransform.pan = -1; - // netStream.play(Paths.file('music/kickstarterTrailer.mp4')); - - FlxG.stage.removeChild(overlay); - } - var logoBl:FlxSprite; var outlineShaderShit:TitleOutline;