mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-27 10:05:41 -05:00
Merge branch 'rewrite/master' of https://github.com/ninjamuffin99/Funkin-secret into rewrite/feature/snapped-paste
This commit is contained in:
commit
937082fecf
37 changed files with 1784 additions and 521 deletions
14
.github/actions/setup-haxeshit/action.yml
vendored
14
.github/actions/setup-haxeshit/action.yml
vendored
|
@ -16,5 +16,17 @@ runs:
|
|||
haxelib git haxelib https://github.com/HaxeFoundation/haxelib.git development
|
||||
haxelib version
|
||||
haxelib --global install hmm
|
||||
haxelib --global run hmm install --quiet
|
||||
shell: bash
|
||||
- name: dependency install cache
|
||||
id: cache-hmm
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .haxelib
|
||||
key: ${{ runner.os }}-hmm-${{ hashFiles('**/hmm.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hmm-
|
||||
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
|
||||
name: hmm install
|
||||
run: |
|
||||
haxelib --global run hmm install
|
||||
shell: bash
|
||||
|
|
2
.github/actions/upload-itch/action.yml
vendored
2
.github/actions/upload-itch/action.yml
vendored
|
@ -40,5 +40,5 @@ runs:
|
|||
BUTLER_API_KEY: ${{inputs.butler-key}}
|
||||
run: |
|
||||
./butler login
|
||||
./butler push ${{inputs.build-dir}} ninja-muffin24/funkin-secret:${{inputs.target}}-${GITHUB_REF##*/}
|
||||
./butler push ${{inputs.build-dir}} ninja-muffin24/funkin-secret:${{inputs.target}}-${GITHUB_REF_NAME}
|
||||
shell: bash
|
5
.github/hooks/README.md
vendored
Normal file
5
.github/hooks/README.md
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Git Hooks
|
||||
These work even on Windows because of Git Bash.
|
||||
|
||||
## Setup
|
||||
`git config core.hooksPath .github/hooks`
|
2
.github/hooks/post-checkout
vendored
Normal file
2
.github/hooks/post-checkout
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
git submodule update --init --recursive
|
2
.github/hooks/post-merge
vendored
Normal file
2
.github/hooks/post-merge
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
git submodule update --init --recursive
|
5
.github/hooks/pre-push
vendored
Normal file
5
.github/hooks/pre-push
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
if git diff --cached --submodule | grep -q "^+"; then
|
||||
echo "WARNING: You have unpushed changes in submodules."
|
||||
exit 1
|
||||
fi
|
51
.github/workflows/build-shit.yml
vendored
51
.github/workflows/build-shit.yml
vendored
|
@ -26,9 +26,11 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
token: ${{ secrets.GH_RO_PAT }}
|
||||
- uses: ./.github/actions/setup-haxeshit
|
||||
- name: Build game
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libx11-dev xorg-dev libgl-dev libxi-dev libxext-dev libasound2-dev libxinerama-dev libxrandr-dev libgl1-mesa-dev
|
||||
haxelib run lime build html5 -release --times
|
||||
ls
|
||||
|
@ -48,28 +50,47 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
token: ${{ secrets.GH_RO_PAT }}
|
||||
- uses: ./.github/actions/setup-haxeshit
|
||||
- name: Make HXCPP cache dir
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}\\hxcpp_cache
|
||||
- name: Restore build cache
|
||||
id: cache-build-win
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
.haxelib
|
||||
export
|
||||
${{ runner.temp }}\\hxcpp_cache
|
||||
key: ${{ runner.os }}-build-win-${{ github.ref_name }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-win-
|
||||
- name: Build game
|
||||
run: |
|
||||
haxelib run lime build windows -release -DNO_REDIRECT_ASSETS_FOLDER
|
||||
dir
|
||||
env:
|
||||
HXCPP_COMPILE_CACHE: "${{ runner.temp }}\\hxcpp_cache"
|
||||
- uses: ./.github/actions/upload-itch
|
||||
with:
|
||||
butler-key: ${{ secrets.BUTLER_API_KEY }}
|
||||
build-dir: export/release/windows/bin
|
||||
target: win
|
||||
test-unit-win:
|
||||
needs: create-nightly-win
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- uses: ./.github/actions/setup-haxeshit
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd ./tests/unit/
|
||||
./start-win-native.bat
|
||||
# test-unit-win:
|
||||
# needs: create-nightly-win
|
||||
# runs-on: windows-latest
|
||||
# permissions:
|
||||
# contents: write
|
||||
# actions: write
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# with:
|
||||
# submodules: 'recursive'
|
||||
# token: ${{ secrets.GH_RO_PAT }}
|
||||
# - uses: ./.github/actions/setup-haxeshit
|
||||
# - name: Run unit tests
|
||||
# run: |
|
||||
# cd ./tests/unit/
|
||||
# ./start-win-native.bat
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ APIStuff.hx
|
|||
dump/
|
||||
export/
|
||||
RECOVER_*.fla
|
||||
shitAudio/
|
||||
|
|
17
Project.xml
17
Project.xml
|
@ -156,7 +156,6 @@
|
|||
<haxedef name="HXCPP_CHECK_POINTER" />
|
||||
<haxedef name="HXCPP_STACK_LINE" />
|
||||
<haxedef name="HXCPP_STACK_TRACE" />
|
||||
<haxedef name="openfl-enable-handle-error" />
|
||||
<!-- This macro allows addition of new functionality to existing Flixel. -->
|
||||
<haxeflag name="--macro" value="addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')" />
|
||||
<!--Place custom nodes like icons here (higher priority to override the HaxeFlixel icon)-->
|
||||
|
@ -196,6 +195,22 @@
|
|||
<haxedef name="REDIRECT_ASSETS_FOLDER" />
|
||||
</section>
|
||||
|
||||
|
||||
<section>
|
||||
<!--
|
||||
This flag enables the popup/crashlog error handler.
|
||||
However, it also messes with breakpoints on some platforms.
|
||||
-->
|
||||
<haxedef name="openfl-enable-handle-error" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<!-- TODO: Add a flag to Github Actions to turn this on or something. -->
|
||||
|
||||
<!-- Forces the version string to include the Git hash even on release builds (which are used for performance reasons). -->
|
||||
<haxedef name="FORCE_DEBUG_VERSION" />
|
||||
</section>
|
||||
|
||||
<!-- Run a script before and after building. -->
|
||||
<postbuild haxe="source/Prebuild.hx"/> -->
|
||||
<postbuild haxe="source/Postbuild.hx"/> -->
|
||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 2becb7e61458c1185bdf23abb87df505eec28676
|
||||
Subproject commit 8104d43e584a1f25e574438d7b21a7e671358969
|
4
hmm.json
4
hmm.json
|
@ -32,7 +32,7 @@
|
|||
"name": "flxanimate",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "a9136359271cae6ea3016b7fd9023c5c42562933",
|
||||
"ref": "dd2903f7dc7024335b981edf2a770760cec912e1",
|
||||
"url": "https://github.com/ninjamuffin99/flxanimate"
|
||||
},
|
||||
{
|
||||
|
@ -139,7 +139,7 @@
|
|||
"name": "openfl",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "d33d489a137ff8fdece4994cf1302f0b6334ed08",
|
||||
"ref": "de9395d2f367a80f93f082e1b639b9cde2258bf1",
|
||||
"url": "https://github.com/EliteMasterEric/openfl"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package funkin;
|
||||
|
||||
import funkin.shaderslmfao.HSVShader;
|
||||
import funkin.ui.StickerSubState;
|
||||
import flash.text.TextField;
|
||||
import flixel.FlxCamera;
|
||||
|
@ -12,6 +13,7 @@ import flixel.addons.ui.FlxInputText;
|
|||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.system.debug.watch.Tracker.TrackerProfile;
|
||||
import flixel.input.touch.FlxTouch;
|
||||
import flixel.math.FlxAngle;
|
||||
import flixel.math.FlxMath;
|
||||
|
@ -21,6 +23,7 @@ import flixel.tweens.FlxEase;
|
|||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.data.level.LevelRegistry;
|
||||
import flixel.util.FlxSpriteUtil;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.Controls.Control;
|
||||
|
@ -29,6 +32,7 @@ import funkin.freeplayStuff.DJBoyfriend;
|
|||
import funkin.freeplayStuff.FreeplayScore;
|
||||
import funkin.freeplayStuff.LetterSort;
|
||||
import funkin.freeplayStuff.SongMenuItem;
|
||||
import funkin.freeplayStuff.DifficultyStars;
|
||||
import funkin.play.HealthIcon;
|
||||
import funkin.play.PlayState;
|
||||
import funkin.shaderslmfao.AngleMask;
|
||||
|
@ -38,6 +42,7 @@ import funkin.play.PlayStatePlaylist;
|
|||
import funkin.play.song.Song;
|
||||
import lime.app.Future;
|
||||
import lime.utils.Assets;
|
||||
import funkin.graphics.adobeanimate.FlxAtlasSprite;
|
||||
|
||||
class FreeplayState extends MusicBeatSubState
|
||||
{
|
||||
|
@ -69,6 +74,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
var grpSongs:FlxTypedGroup<Alphabet>;
|
||||
var grpCapsules:FlxTypedGroup<SongMenuItem>;
|
||||
var curCapsule:SongMenuItem;
|
||||
var curPlaying:Bool = false;
|
||||
|
||||
var dj:DJBoyfriend;
|
||||
|
@ -114,44 +120,33 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
#if debug
|
||||
isDebug = true;
|
||||
addSong('Test', 'tutorial', 'bf-pixel');
|
||||
addSong('Pyro', 'weekend1', 'darnell');
|
||||
// addSong('Test', 'tutorial', 'bf-pixel');
|
||||
// addSong('Pyro', 'weekend1', 'darnell');
|
||||
#end
|
||||
|
||||
var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
||||
// var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
||||
|
||||
for (i in 0...initSonglist.length)
|
||||
{
|
||||
songs.push(new FreeplaySongData(initSonglist[i], 'tutorial', 'gf'));
|
||||
}
|
||||
// for (i in 0...initSonglist.length)
|
||||
// {
|
||||
// songs.push(new FreeplaySongData(initSonglist[i], 'tutorial', 'gf'));
|
||||
// }
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (!FlxG.sound.music.playing) FlxG.sound.playMusic(Paths.music('freakyMenu/freakyMenu'));
|
||||
}
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[2] || isDebug)
|
||||
addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 'week1', ['dad']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[2] || isDebug)
|
||||
addWeek(['Spookeez', 'South', 'Monster'], 'week2', ['spooky', 'spooky', 'monster']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[3] || isDebug)
|
||||
addWeek(['Pico', 'Philly-Nice', 'Blammed'], 'week3', ['pico']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[4] || isDebug)
|
||||
addWeek(['Satin-Panties', 'High', 'MILF'], 'week4', ['mom']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[5] || isDebug)
|
||||
addWeek(['Cocoa', 'Eggnog', 'Winter-Horrorland'], 'week5', ['parents-christmas', 'parents-christmas', 'monster-christmas']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[6] || isDebug)
|
||||
addWeek(['Senpai', 'Roses', 'Thorns'], 'week6', ['senpai', 'senpai', 'spirit']);
|
||||
|
||||
// if (StoryMenuState.weekUnlocked[7] || isDebug)
|
||||
addWeek(['Ugh', 'Guns', 'Stress'], 'week7', ['tankman']);
|
||||
|
||||
addWeek(["Darnell", "lit-up", "2hot", "blazin"], 'weekend1', ['darnell']);
|
||||
// programmatically adds the songs via LevelRegistry and SongRegistry
|
||||
for (coolWeek in LevelRegistry.instance.listBaseGameLevelIds())
|
||||
{
|
||||
for (coolSong in LevelRegistry.instance.parseEntryData(coolWeek).songs)
|
||||
{
|
||||
var metadata = SongRegistry.instance.parseEntryMetadata(coolSong);
|
||||
var char = metadata.playData.characters.opponent;
|
||||
var songName = metadata.songName;
|
||||
addSong(songName, coolWeek, char);
|
||||
}
|
||||
}
|
||||
|
||||
// LOAD MUSIC
|
||||
|
||||
|
@ -169,7 +164,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut});
|
||||
add(pinkBack);
|
||||
|
||||
var orangeBackShit:FlxSprite = new FlxSprite(84, FlxG.height * 0.68).makeGraphic(Std.int(pinkBack.width), 50, 0xFFffd400);
|
||||
var orangeBackShit:FlxSprite = new FlxSprite(84, 440).makeGraphic(Std.int(pinkBack.width), 75, 0xFFfeda00);
|
||||
add(orangeBackShit);
|
||||
|
||||
var alsoOrangeLOL:FlxSprite = new FlxSprite(0, orangeBackShit.y).makeGraphic(100, Std.int(orangeBackShit.height), 0xFFffd400);
|
||||
|
@ -191,9 +186,11 @@ class FreeplayState extends MusicBeatSubState
|
|||
add(grpTxtScrolls);
|
||||
grpTxtScrolls.visible = false;
|
||||
|
||||
var moreWays:BGScrollingText = new BGScrollingText(0, 200, "HOT BLOODED IN MORE WAYS THAN ONE", FlxG.width);
|
||||
FlxG.debugger.addTrackerProfile(new TrackerProfile(BGScrollingText, ["x", "y", "speed", "size"]));
|
||||
|
||||
var moreWays:BGScrollingText = new BGScrollingText(0, 160, "HOT BLOODED IN MORE WAYS THAN ONE", FlxG.width, true, 43);
|
||||
moreWays.funnyColor = 0xFFfff383;
|
||||
moreWays.speed = 4;
|
||||
moreWays.speed = 6.8;
|
||||
grpTxtScrolls.add(moreWays);
|
||||
|
||||
exitMovers.set([moreWays],
|
||||
|
@ -202,9 +199,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
speed: 0.4,
|
||||
});
|
||||
|
||||
var funnyScroll:BGScrollingText = new BGScrollingText(0, 250, "BOYFRIEND", FlxG.width / 2);
|
||||
var funnyScroll:BGScrollingText = new BGScrollingText(0, 220, "BOYFRIEND", FlxG.width / 2, false, 60);
|
||||
funnyScroll.funnyColor = 0xFFff9963;
|
||||
funnyScroll.speed = -1;
|
||||
funnyScroll.speed = -3.8;
|
||||
grpTxtScrolls.add(funnyScroll);
|
||||
|
||||
exitMovers.set([funnyScroll],
|
||||
|
@ -215,7 +212,8 @@ class FreeplayState extends MusicBeatSubState
|
|||
wait: 0
|
||||
});
|
||||
|
||||
var txtNuts:BGScrollingText = new BGScrollingText(0, 300, "PROTECT YO NUTS", FlxG.width / 2);
|
||||
var txtNuts:BGScrollingText = new BGScrollingText(0, 285, "PROTECT YO NUTS", FlxG.width / 2, true, 43);
|
||||
txtNuts.speed = 3.5;
|
||||
grpTxtScrolls.add(txtNuts);
|
||||
exitMovers.set([txtNuts],
|
||||
{
|
||||
|
@ -223,9 +221,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
speed: 0.4,
|
||||
});
|
||||
|
||||
var funnyScroll2:BGScrollingText = new BGScrollingText(0, 340, "BOYFRIEND", FlxG.width / 2);
|
||||
var funnyScroll2:BGScrollingText = new BGScrollingText(0, 335, "BOYFRIEND", FlxG.width / 2, false, 60);
|
||||
funnyScroll2.funnyColor = 0xFFff9963;
|
||||
funnyScroll2.speed = -1.2;
|
||||
funnyScroll2.speed = -3.8;
|
||||
grpTxtScrolls.add(funnyScroll2);
|
||||
|
||||
exitMovers.set([funnyScroll2],
|
||||
|
@ -234,9 +232,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
speed: 0.5,
|
||||
});
|
||||
|
||||
var moreWays2:BGScrollingText = new BGScrollingText(0, 400, "HOT BLOODED IN MORE WAYS THAN ONE", FlxG.width);
|
||||
var moreWays2:BGScrollingText = new BGScrollingText(0, 397, "HOT BLOODED IN MORE WAYS THAN ONE", FlxG.width, true, 43);
|
||||
moreWays2.funnyColor = 0xFFfff383;
|
||||
moreWays2.speed = 4.4;
|
||||
moreWays2.speed = 6.8;
|
||||
grpTxtScrolls.add(moreWays2);
|
||||
|
||||
exitMovers.set([moreWays2],
|
||||
|
@ -245,9 +243,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
speed: 0.4
|
||||
});
|
||||
|
||||
var funnyScroll3:BGScrollingText = new BGScrollingText(0, orangeBackShit.y, "BOYFRIEND", FlxG.width / 2);
|
||||
funnyScroll3.funnyColor = 0xFFff9963;
|
||||
funnyScroll3.speed = -0.8;
|
||||
var funnyScroll3:BGScrollingText = new BGScrollingText(0, orangeBackShit.y + 10, "BOYFRIEND", FlxG.width / 2, 60);
|
||||
funnyScroll3.funnyColor = 0xFFfea400;
|
||||
funnyScroll3.speed = -3.8;
|
||||
grpTxtScrolls.add(funnyScroll3);
|
||||
|
||||
exitMovers.set([funnyScroll3],
|
||||
|
@ -256,7 +254,8 @@ class FreeplayState extends MusicBeatSubState
|
|||
speed: 0.3
|
||||
});
|
||||
|
||||
dj = new DJBoyfriend(0, -100);
|
||||
// dj = new DJBoyfriend(0, -100);
|
||||
dj = new DJBoyfriend(640, 366);
|
||||
exitMovers.set([dj],
|
||||
{
|
||||
x: -dj.width * 1.6,
|
||||
|
@ -312,6 +311,49 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
grpDifficulties.group.members[curDifficulty].visible = true;
|
||||
|
||||
var albumArt:FlxAtlasSprite = new FlxAtlasSprite(640, 360, Paths.animateAtlas("freeplay/albumRoll"));
|
||||
albumArt.visible = false;
|
||||
add(albumArt);
|
||||
|
||||
exitMovers.set([albumArt],
|
||||
{
|
||||
x: FlxG.width,
|
||||
speed: 0.4,
|
||||
wait: 0
|
||||
});
|
||||
|
||||
var albumTitle:FlxSprite = new FlxSprite(947, 491).loadGraphic(Paths.image('freeplay/albumTitle-fnfvol1'));
|
||||
var albumArtist:FlxSprite = new FlxSprite(1010, 607).loadGraphic(Paths.image('freeplay/albumArtist-kawaisprite'));
|
||||
var difficultyStars:DifficultyStars = new DifficultyStars(140, 39);
|
||||
|
||||
difficultyStars.stars.visible = false;
|
||||
albumTitle.visible = false;
|
||||
albumArtist.visible = false;
|
||||
|
||||
exitMovers.set([albumTitle],
|
||||
{
|
||||
x: FlxG.width,
|
||||
speed: 0.2,
|
||||
wait: 0.1
|
||||
});
|
||||
|
||||
exitMovers.set([albumArtist],
|
||||
{
|
||||
x: FlxG.width * 1.1,
|
||||
speed: 0.2,
|
||||
wait: 0.2
|
||||
});
|
||||
exitMovers.set([difficultyStars],
|
||||
{
|
||||
x: FlxG.width * 1.2,
|
||||
speed: 0.2,
|
||||
wait: 0.3
|
||||
});
|
||||
|
||||
add(albumTitle);
|
||||
add(albumArtist);
|
||||
add(difficultyStars);
|
||||
|
||||
var overhangStuff:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 64, FlxColor.BLACK);
|
||||
overhangStuff.y -= overhangStuff.height;
|
||||
add(overhangStuff);
|
||||
|
@ -355,29 +397,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
txtCompletion.visible = false;
|
||||
add(txtCompletion);
|
||||
|
||||
exitMovers.set([fp, txtCompletion, fnfHighscoreSpr],
|
||||
{
|
||||
x: FlxG.width,
|
||||
speed: 0.3
|
||||
});
|
||||
|
||||
dj.onIntroDone.add(function() {
|
||||
FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut});
|
||||
|
||||
var diffSelLeft = new DifficultySelector(20, grpDifficulties.y - 10, false, controls);
|
||||
var diffSelRight = new DifficultySelector(325, grpDifficulties.y - 10, true, controls);
|
||||
|
||||
add(diffSelLeft);
|
||||
add(diffSelRight);
|
||||
|
||||
exitMovers.set([diffSelLeft, diffSelRight],
|
||||
{
|
||||
x: -diffSelLeft.width * 2,
|
||||
speed: 0.26
|
||||
});
|
||||
|
||||
var letterSort:LetterSort = new LetterSort(300, 100);
|
||||
var letterSort:LetterSort = new LetterSort(400, 75);
|
||||
add(letterSort);
|
||||
letterSort.visible = false;
|
||||
|
||||
exitMovers.set([letterSort],
|
||||
{
|
||||
|
@ -393,10 +415,51 @@ class FreeplayState extends MusicBeatSubState
|
|||
case "ALL":
|
||||
generateSongList(null, true);
|
||||
default:
|
||||
generateSongList({filterType: STARTSWITH, filterData: str}, true);
|
||||
generateSongList({filterType: REGEXP, filterData: str}, true);
|
||||
}
|
||||
};
|
||||
|
||||
exitMovers.set([fp, txtCompletion, fnfHighscoreSpr],
|
||||
{
|
||||
x: FlxG.width,
|
||||
speed: 0.3
|
||||
});
|
||||
|
||||
dj.onIntroDone.add(function() {
|
||||
// when boyfriend hits dat shiii
|
||||
//
|
||||
|
||||
albumArt.visible = true;
|
||||
albumArt.anim.play("");
|
||||
albumArt.anim.onComplete = function() {
|
||||
albumArt.anim.pause();
|
||||
};
|
||||
|
||||
new FlxTimer().start(1, function(_) {
|
||||
albumTitle.visible = true;
|
||||
});
|
||||
|
||||
new FlxTimer().start(35 / 24, function(_) {
|
||||
albumArtist.visible = true;
|
||||
difficultyStars.stars.visible = true;
|
||||
});
|
||||
|
||||
FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut});
|
||||
|
||||
var diffSelLeft = new DifficultySelector(20, grpDifficulties.y - 10, false, controls);
|
||||
var diffSelRight = new DifficultySelector(325, grpDifficulties.y - 10, true, controls);
|
||||
|
||||
add(diffSelLeft);
|
||||
add(diffSelRight);
|
||||
|
||||
letterSort.visible = true;
|
||||
|
||||
exitMovers.set([diffSelLeft, diffSelRight],
|
||||
{
|
||||
x: -diffSelLeft.width * 2,
|
||||
speed: 0.26
|
||||
});
|
||||
|
||||
new FlxTimer().start(1 / 24, function(handShit) {
|
||||
fnfHighscoreSpr.visible = true;
|
||||
fnfFreeplay.visible = true;
|
||||
|
@ -409,18 +472,18 @@ class FreeplayState extends MusicBeatSubState
|
|||
new FlxTimer().start(1.5 / 24, function(bold) {
|
||||
sillyStroke.width = 0;
|
||||
sillyStroke.height = 0;
|
||||
changeSelection();
|
||||
});
|
||||
});
|
||||
|
||||
pinkBack.color = 0xFFffd863;
|
||||
// fnfFreeplay.visible = true;
|
||||
bgDad.visible = true;
|
||||
orangeBackShit.visible = true;
|
||||
alsoOrangeLOL.visible = true;
|
||||
grpTxtScrolls.visible = true;
|
||||
});
|
||||
|
||||
generateSongList();
|
||||
generateSongList(null, false);
|
||||
|
||||
// FlxG.sound.playMusic(Paths.music('title'), 0);
|
||||
// FlxG.sound.music.fadeIn(2, 0, 0.8);
|
||||
|
@ -466,9 +529,12 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
public function generateSongList(?filterStuff:SongFilter, force:Bool = false)
|
||||
{
|
||||
curSelected = 0;
|
||||
curSelected = 1;
|
||||
|
||||
grpCapsules.clear();
|
||||
for (cap in grpCapsules.members)
|
||||
cap.kill();
|
||||
|
||||
// grpCapsules.clear();
|
||||
|
||||
// var regexp:EReg = regexp;
|
||||
var tempSongs:Array<FreeplaySongData> = songs;
|
||||
|
@ -477,6 +543,13 @@ class FreeplayState extends MusicBeatSubState
|
|||
{
|
||||
switch (filterStuff.filterType)
|
||||
{
|
||||
case REGEXP:
|
||||
// filterStuff.filterData has a string with the first letter of the sorting range, and the second one
|
||||
// this creates a filter to return all the songs that start with a letter between those two
|
||||
var filterRegexp = new EReg("^[" + filterStuff.filterData + "].*", "i");
|
||||
tempSongs = tempSongs.filter(str -> {
|
||||
return filterRegexp.match(str.songName);
|
||||
});
|
||||
case STARTSWITH:
|
||||
tempSongs = tempSongs.filter(str -> {
|
||||
return str.songName.toLowerCase().startsWith(filterStuff.filterData);
|
||||
|
@ -492,54 +565,48 @@ class FreeplayState extends MusicBeatSubState
|
|||
}
|
||||
}
|
||||
|
||||
var hsvShader:HSVShader = new HSVShader();
|
||||
|
||||
var randomCapsule:SongMenuItem = grpCapsules.recycle(SongMenuItem);
|
||||
randomCapsule.init(FlxG.width, 0, "Random");
|
||||
randomCapsule.onConfirm = function() {
|
||||
capsuleOnConfirmRandom(randomCapsule);
|
||||
};
|
||||
randomCapsule.y = randomCapsule.intendedY(0) + 10;
|
||||
randomCapsule.targetPos.x = randomCapsule.x;
|
||||
randomCapsule.alpha = 0.5;
|
||||
randomCapsule.songText.visible = false;
|
||||
randomCapsule.favIcon.visible = false;
|
||||
randomCapsule.initJumpIn(0, force);
|
||||
randomCapsule.hsvShader = hsvShader;
|
||||
grpCapsules.add(randomCapsule);
|
||||
|
||||
for (i in 0...tempSongs.length)
|
||||
{
|
||||
var funnyMenu:SongMenuItem = new SongMenuItem(FlxG.width, (i * 150) + 160, tempSongs[i].songName);
|
||||
var funnyMenu:SongMenuItem = grpCapsules.recycle(SongMenuItem);
|
||||
funnyMenu.init(FlxG.width, 0, tempSongs[i].songName);
|
||||
if (tempSongs[i].songCharacter != null) funnyMenu.setCharacter(tempSongs[i].songCharacter);
|
||||
funnyMenu.onConfirm = function() {
|
||||
capsuleOnConfirmDefault(funnyMenu);
|
||||
};
|
||||
funnyMenu.y = funnyMenu.intendedY(i + 1) + 10;
|
||||
funnyMenu.targetPos.x = funnyMenu.x;
|
||||
funnyMenu.ID = i;
|
||||
funnyMenu.alpha = 0.5;
|
||||
funnyMenu.capsule.alpha = 0.5;
|
||||
funnyMenu.songText.visible = false;
|
||||
funnyMenu.favIcon.visible = tempSongs[i].isFav;
|
||||
|
||||
funnyMenu.hsvShader = hsvShader;
|
||||
// fp.updateScore(0);
|
||||
|
||||
var maxTimer:Float = Math.min(i, 4);
|
||||
|
||||
new FlxTimer().start((1 / 24) * maxTimer, function(doShit) {
|
||||
funnyMenu.doJumpIn = true;
|
||||
});
|
||||
|
||||
new FlxTimer().start((0.09 * maxTimer) + 0.85, function(lerpTmr) {
|
||||
funnyMenu.doLerp = true;
|
||||
});
|
||||
|
||||
if (!force)
|
||||
{
|
||||
new FlxTimer().start(((0.20 * maxTimer) / (1 + maxTimer)) + 0.75, function(swagShi) {
|
||||
funnyMenu.songText.visible = true;
|
||||
funnyMenu.alpha = 1;
|
||||
});
|
||||
}
|
||||
if (i < 8) funnyMenu.initJumpIn(Math.min(i, 4), force);
|
||||
else
|
||||
{
|
||||
funnyMenu.songText.visible = true;
|
||||
funnyMenu.alpha = 1;
|
||||
}
|
||||
funnyMenu.forcePosition();
|
||||
|
||||
grpCapsules.add(funnyMenu);
|
||||
|
||||
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, tempSongs[i].songName, true, false);
|
||||
songText.x += 100;
|
||||
songText.isMenuItem = true;
|
||||
songText.targetY = i;
|
||||
|
||||
// grpSongs.add(songText);
|
||||
|
||||
// songText.x += 40;
|
||||
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
|
||||
// songText.screenCenter(X);
|
||||
}
|
||||
|
||||
FlxG.console.registerFunction("changeSelection", changeSelection);
|
||||
|
||||
changeSelection();
|
||||
changeDiff();
|
||||
}
|
||||
|
@ -576,6 +643,8 @@ class FreeplayState extends MusicBeatSubState
|
|||
var spamTimer:Float = 0;
|
||||
var spamming:Bool = false;
|
||||
|
||||
var busy:Bool = false; // Set to true once the user has pressed enter to select a song.
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
@ -623,11 +692,13 @@ class FreeplayState extends MusicBeatSubState
|
|||
fp.updateScore(Std.int(lerpScore));
|
||||
|
||||
txtCompletion.text = Math.floor(lerpCompletion * 100) + "%";
|
||||
// trace(Highscore.getCompletion(songs[curSelected].songName, curDifficulty));
|
||||
|
||||
// trace(intendedScore);
|
||||
// trace(lerpScore);
|
||||
// Highscore.getAllScores();
|
||||
handleInputs(elapsed);
|
||||
}
|
||||
|
||||
function handleInputs(elapsed:Float):Void
|
||||
{
|
||||
if (busy) return;
|
||||
|
||||
var upP = controls.UI_UP_P;
|
||||
var downP = controls.UI_DOWN_P;
|
||||
|
@ -830,66 +901,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
{
|
||||
// if (Assets.exists())
|
||||
|
||||
var poop:String = songs[curSelected].songName.toLowerCase();
|
||||
|
||||
// does not work properly, always just accidentally sets it to normal anyways!
|
||||
/* if (!Assets.exists(Paths.json(songs[curSelected].songName + '/' + poop)))
|
||||
{
|
||||
// defaults to normal if HARD / EASY doesn't exist
|
||||
// does not account if NORMAL doesn't exist!
|
||||
FlxG.log.warn("CURRENT DIFFICULTY IS NOT CHARTED, DEFAULTING TO NORMAL!");
|
||||
poop = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), 1);
|
||||
curDifficulty = 1;
|
||||
}*/
|
||||
|
||||
PlayStatePlaylist.isStoryMode = false;
|
||||
var songId:String = songs[curSelected].songName.toLowerCase();
|
||||
var targetSong:Song = SongRegistry.instance.fetchEntry(songId);
|
||||
var targetDifficulty:String = switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
'easy';
|
||||
case 1:
|
||||
'normal';
|
||||
case 2:
|
||||
'hard';
|
||||
default: 'normal';
|
||||
};
|
||||
|
||||
// TODO: Implement additional difficulties into the interface properly.
|
||||
if (FlxG.keys.pressed.E)
|
||||
{
|
||||
targetDifficulty = 'erect';
|
||||
}
|
||||
|
||||
// TODO: Implement Pico into the interface properly.
|
||||
var targetCharacter:String = 'bf';
|
||||
if (FlxG.keys.pressed.P)
|
||||
{
|
||||
targetCharacter = 'pico';
|
||||
}
|
||||
|
||||
PlayStatePlaylist.campaignId = songs[curSelected].levelId;
|
||||
|
||||
// Visual and audio effects.
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
dj.confirm();
|
||||
|
||||
if (targetSong != null)
|
||||
{
|
||||
// Load and cache the song's charts.
|
||||
// TODO: Do this in the loading state.
|
||||
targetSong.cacheCharts(true);
|
||||
}
|
||||
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer) {
|
||||
LoadingState.loadAndSwitchState(new PlayState(
|
||||
{
|
||||
targetSong: targetSong,
|
||||
targetDifficulty: targetDifficulty,
|
||||
targetCharacter: targetCharacter,
|
||||
}), true);
|
||||
});
|
||||
grpCapsules.members[curSelected].onConfirm();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -941,45 +953,133 @@ class FreeplayState extends MusicBeatSubState
|
|||
}
|
||||
}
|
||||
|
||||
function capsuleOnConfirmRandom(cap:SongMenuItem):Void
|
||||
{
|
||||
trace("RANDOM SELECTED");
|
||||
|
||||
busy = true;
|
||||
}
|
||||
|
||||
function capsuleOnConfirmDefault(cap:SongMenuItem):Void
|
||||
{
|
||||
// var poop:String = songs[curSelected].songName.toLowerCase();
|
||||
|
||||
// does not work properly, always just accidentally sets it to normal anyways!
|
||||
/* if (!Assets.exists(Paths.json(songs[curSelected].songName + '/' + poop)))
|
||||
{
|
||||
// defaults to normal if HARD / EASY doesn't exist
|
||||
// does not account if NORMAL doesn't exist!
|
||||
FlxG.log.warn("CURRENT DIFFICULTY IS NOT CHARTED, DEFAULTING TO NORMAL!");
|
||||
poop = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), 1);
|
||||
curDifficulty = 1;
|
||||
}*/
|
||||
|
||||
busy = true;
|
||||
|
||||
PlayStatePlaylist.isStoryMode = false;
|
||||
|
||||
var songId:String = cap.songTitle.toLowerCase();
|
||||
var targetSong:Song = SongRegistry.instance.fetchEntry(songId);
|
||||
var targetDifficulty:String = switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
'easy';
|
||||
case 1:
|
||||
'normal';
|
||||
case 2:
|
||||
'hard';
|
||||
default: 'normal';
|
||||
};
|
||||
|
||||
// TODO: Implement additional difficulties into the interface properly.
|
||||
if (FlxG.keys.pressed.E)
|
||||
{
|
||||
targetDifficulty = 'erect';
|
||||
}
|
||||
|
||||
// TODO: Implement Pico into the interface properly.
|
||||
var targetCharacter:String = 'bf';
|
||||
if (FlxG.keys.pressed.P)
|
||||
{
|
||||
targetCharacter = 'pico';
|
||||
}
|
||||
|
||||
PlayStatePlaylist.campaignId = songs[curSelected].levelId;
|
||||
|
||||
// Visual and audio effects.
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
dj.confirm();
|
||||
|
||||
// Load and cache the song's charts.
|
||||
// TODO: Do this in the loading state.
|
||||
targetSong.cacheCharts(true);
|
||||
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer) {
|
||||
LoadingState.loadAndSwitchState(new PlayState(
|
||||
{
|
||||
targetSong: targetSong,
|
||||
targetDifficulty: targetDifficulty,
|
||||
targetCharacter: targetCharacter,
|
||||
}), true);
|
||||
});
|
||||
}
|
||||
|
||||
function changeSelection(change:Int = 0)
|
||||
{
|
||||
// fp.updateScore(12345);
|
||||
|
||||
NGio.logEvent('Fresh');
|
||||
|
||||
// NGio.logEvent('Fresh');
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
|
||||
// FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName));
|
||||
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected < 0) curSelected = grpCapsules.members.length - 1;
|
||||
if (curSelected >= grpCapsules.members.length) curSelected = 0;
|
||||
if (curSelected < 0) curSelected = grpCapsules.countLiving() - 1;
|
||||
if (curSelected >= grpCapsules.countLiving()) curSelected = 0;
|
||||
|
||||
// selector.y = (70 * curSelected) + 30;
|
||||
|
||||
// intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty);
|
||||
|
||||
if (songs[curSelected] != null)
|
||||
{
|
||||
intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty);
|
||||
intendedCompletion = Highscore.getCompletion(songs[curSelected].songName, curDifficulty);
|
||||
}
|
||||
else
|
||||
{
|
||||
intendedScore = 0;
|
||||
intendedCompletion = 0;
|
||||
}
|
||||
|
||||
// lerpScore = 0;
|
||||
|
||||
#if PRELOAD_ALL
|
||||
// FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
|
||||
#end
|
||||
|
||||
var bullShit:Int = 0;
|
||||
|
||||
for (index => capsule in grpCapsules.members)
|
||||
{
|
||||
capsule.selected = false;
|
||||
index += 1;
|
||||
|
||||
capsule.targetPos.y = ((index - curSelected) * 150) + 160;
|
||||
capsule.selected = index == curSelected + 1;
|
||||
|
||||
capsule.targetPos.y = capsule.intendedY(index - curSelected);
|
||||
capsule.targetPos.x = 270 + (60 * (Math.sin(index - curSelected)));
|
||||
// capsule.targetPos.x = 320 + (40 * (index - curSelected));
|
||||
|
||||
if (index < curSelected) capsule.targetPos.y -= 100; // another 100 for good measure
|
||||
}
|
||||
|
||||
if (grpCapsules.members.length > 0) grpCapsules.members[curSelected].selected = true;
|
||||
if (grpCapsules.countLiving() > 0)
|
||||
{
|
||||
if (curSelected == 0)
|
||||
{
|
||||
FlxG.sound.playMusic(Paths.music('freeplay/freeplayRandom'), 0);
|
||||
FlxG.sound.music.fadeIn(2, 0, 0.8);
|
||||
}
|
||||
grpCapsules.members[curSelected].selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1119,10 @@ class DifficultySelector extends FlxSprite
|
|||
|
||||
whiteShader.colorSet = true;
|
||||
|
||||
scale.x = scale.y = 0.5;
|
||||
|
||||
new FlxTimer().start(2 / 24, function(tmr) {
|
||||
scale.x = scale.y = 1;
|
||||
whiteShader.colorSet = false;
|
||||
updateHitbox();
|
||||
});
|
||||
|
@ -1035,6 +1138,7 @@ typedef SongFilter =
|
|||
enum abstract FilterType(String)
|
||||
{
|
||||
var STARTSWITH;
|
||||
var REGEXP;
|
||||
var FAVORITE;
|
||||
var ALL;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ class Paths
|
|||
return getPath(file, type, library);
|
||||
}
|
||||
|
||||
public static inline function animateAtlas(path:String, library:String)
|
||||
public static inline function animateAtlas(path:String, ?library:String)
|
||||
{
|
||||
return getLibraryPathForce('images/$path', library);
|
||||
return getLibraryPath('images/$path', library);
|
||||
}
|
||||
|
||||
inline static public function txt(key:String, ?library:String)
|
||||
|
|
|
@ -150,6 +150,11 @@ class PauseSubState extends MusicBeatSubState
|
|||
|
||||
super.update(elapsed);
|
||||
|
||||
handleInputs();
|
||||
}
|
||||
|
||||
function handleInputs():Void
|
||||
{
|
||||
var upP = controls.UI_UP_P;
|
||||
var downP = controls.UI_DOWN_P;
|
||||
var accepted = controls.ACCEPT;
|
||||
|
@ -229,9 +234,14 @@ class PauseSubState extends MusicBeatSubState
|
|||
FlxTransitionableState.skipNextTransIn = true;
|
||||
FlxTransitionableState.skipNextTransOut = true;
|
||||
|
||||
if (PlayStatePlaylist.isStoryMode) openSubState(new funkin.ui.StickerSubState(null, STORY));
|
||||
if (PlayStatePlaylist.isStoryMode)
|
||||
{
|
||||
openSubState(new funkin.ui.StickerSubState(null, STORY));
|
||||
}
|
||||
else
|
||||
{
|
||||
openSubState(new funkin.ui.StickerSubState(null, FREEPLAY));
|
||||
}
|
||||
|
||||
case 'Exit to Chart Editor':
|
||||
this.close();
|
||||
|
|
49
source/funkin/audio/FlxStreamSound.hx
Normal file
49
source/funkin/audio/FlxStreamSound.hx
Normal file
|
@ -0,0 +1,49 @@
|
|||
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;
|
||||
#if (openfl >= "8.0.0")
|
||||
import openfl.utils.AssetType;
|
||||
#end
|
||||
|
||||
/**
|
||||
* a FlxSound that just overrides loadEmbedded to allow for "streamed" sounds to load with better performance!
|
||||
*/
|
||||
class FlxStreamSound extends FlxSound
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
override public function loadEmbedded(EmbeddedSound:FlxSoundAsset, Looped:Bool = false, AutoDestroy:Bool = false, ?OnComplete:Void->Void):FlxSound
|
||||
{
|
||||
if (EmbeddedSound == null) return this;
|
||||
|
||||
cleanup(true);
|
||||
|
||||
if ((EmbeddedSound is Sound))
|
||||
{
|
||||
_sound = EmbeddedSound;
|
||||
}
|
||||
else if ((EmbeddedSound is Class))
|
||||
{
|
||||
_sound = Type.createInstance(EmbeddedSound, []);
|
||||
}
|
||||
else if ((EmbeddedSound is String))
|
||||
{
|
||||
if (Assets.exists(EmbeddedSound, AssetType.SOUND)
|
||||
|| Assets.exists(EmbeddedSound, AssetType.MUSIC)) _sound = Assets.getMusic(EmbeddedSound);
|
||||
else
|
||||
FlxG.log.error('Could not find a Sound asset with an ID of \'$EmbeddedSound\'.');
|
||||
}
|
||||
|
||||
// NOTE: can't pull ID3 info from embedded sound currently
|
||||
return init(Looped, AutoDestroy, OnComplete);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import flixel.math.FlxMath;
|
|||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxSort;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
// its kinda like marqeee html lol!
|
||||
class BGScrollingText extends FlxSpriteGroup
|
||||
|
@ -16,36 +17,53 @@ class BGScrollingText extends FlxSpriteGroup
|
|||
public var widthShit:Float = FlxG.width;
|
||||
public var placementOffset:Float = 20;
|
||||
public var speed:Float = 1;
|
||||
public var size(default, set):Int = 48;
|
||||
|
||||
public var funnyColor(default, set):Int = 0xFFFFFFFF;
|
||||
|
||||
public function new(x:Float, y:Float, text:String, widthShit:Float = 100)
|
||||
public function new(x:Float, y:Float, text:String, widthShit:Float = 100, ?bold:Bool = false, ?size:Int = 48)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
this.widthShit = widthShit;
|
||||
if (size != null) this.size = size;
|
||||
|
||||
grpTexts = new FlxTypedSpriteGroup<FlxText>();
|
||||
add(grpTexts);
|
||||
|
||||
var testText:FlxText = new FlxText(0, 0, 0, text, 48);
|
||||
var testText:FlxText = new FlxText(0, 0, 0, text, this.size);
|
||||
testText.font = "5by7";
|
||||
testText.bold = bold;
|
||||
testText.updateHitbox();
|
||||
grpTexts.add(testText);
|
||||
|
||||
var needed:Int = Math.ceil(widthShit / testText.frameWidth);
|
||||
var needed:Int = Math.ceil(widthShit / testText.frameWidth) + 1;
|
||||
|
||||
for (i in 0...needed)
|
||||
{
|
||||
var lmfao:Int = i + 1;
|
||||
|
||||
var coolText:FlxText = new FlxText((lmfao * testText.frameWidth) + (lmfao * 20), 0, 0, text, 48);
|
||||
var coolText:FlxText = new FlxText((lmfao * testText.frameWidth) + (lmfao * 20), 0, 0, text, this.size);
|
||||
|
||||
coolText.font = "5by7";
|
||||
coolText.bold = bold;
|
||||
coolText.updateHitbox();
|
||||
grpTexts.add(coolText);
|
||||
}
|
||||
}
|
||||
|
||||
function set_size(value:Int):Int
|
||||
{
|
||||
if (grpTexts != null)
|
||||
{
|
||||
grpTexts.forEach(function(txt:FlxText) {
|
||||
txt.size = value;
|
||||
});
|
||||
}
|
||||
this.size = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
function set_funnyColor(col:Int):Int
|
||||
{
|
||||
grpTexts.forEach(function(txt) {
|
||||
|
@ -55,7 +73,7 @@ class BGScrollingText extends FlxSpriteGroup
|
|||
return col;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
override public function update(elapsed:Float)
|
||||
{
|
||||
for (txt in grpTexts.group)
|
||||
{
|
||||
|
@ -66,14 +84,16 @@ class BGScrollingText extends FlxSpriteGroup
|
|||
if (txt.x < -txt.frameWidth)
|
||||
{
|
||||
txt.x = grpTexts.group.members[grpTexts.length - 1].x + grpTexts.group.members[grpTexts.length - 1].frameWidth + placementOffset;
|
||||
|
||||
sortTextShit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (txt.x > widthShit)
|
||||
if (txt.x > txt.frameWidth * 2)
|
||||
{
|
||||
txt.x = grpTexts.group.members[0].x - grpTexts.group.members[0].frameWidth - placementOffset;
|
||||
|
||||
sortTextShit();
|
||||
}
|
||||
}
|
||||
|
|
49
source/funkin/freeplayStuff/CapsuleText.hx
Normal file
49
source/funkin/freeplayStuff/CapsuleText.hx
Normal file
|
@ -0,0 +1,49 @@
|
|||
package funkin.freeplayStuff;
|
||||
|
||||
import openfl.filters.BitmapFilterQuality;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import funkin.shaderslmfao.GaussianBlurShader;
|
||||
|
||||
class CapsuleText extends FlxSpriteGroup
|
||||
{
|
||||
public var blurredText:FlxText;
|
||||
|
||||
var whiteText:FlxText;
|
||||
|
||||
public var text(default, set):String;
|
||||
|
||||
public function new(x:Float, y:Float, songTitle:String, size:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
blurredText = initText(songTitle, size);
|
||||
blurredText.shader = new GaussianBlurShader(1);
|
||||
whiteText = initText(songTitle, size);
|
||||
// whiteText.shader = new GaussianBlurShader(0.3);
|
||||
text = songTitle;
|
||||
|
||||
blurredText.color = 0xFF00ccff;
|
||||
whiteText.color = 0xFFFFFFFF;
|
||||
add(blurredText);
|
||||
add(whiteText);
|
||||
}
|
||||
|
||||
function initText(songTitle, size:Float):FlxText
|
||||
{
|
||||
var text:FlxText = new FlxText(0, 0, 0, songTitle, Std.int(size));
|
||||
text.font = "5by7";
|
||||
return text;
|
||||
}
|
||||
|
||||
function set_text(value:String):String
|
||||
{
|
||||
blurredText.text = value;
|
||||
whiteText.text = value;
|
||||
whiteText.textField.filters = [
|
||||
new openfl.filters.GlowFilter(0x00ccff, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM),
|
||||
// new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW)
|
||||
];
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -3,8 +3,12 @@ package funkin.freeplayStuff;
|
|||
import flixel.FlxSprite;
|
||||
import flixel.util.FlxSignal;
|
||||
import funkin.util.assets.FlxAnimationUtil;
|
||||
import funkin.graphics.adobeanimate.FlxAtlasSprite;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.audio.FlxStreamSound;
|
||||
|
||||
class DJBoyfriend extends FlxSprite
|
||||
class DJBoyfriend extends FlxAtlasSprite
|
||||
{
|
||||
// Represents the sprite's current status.
|
||||
// Without state machines I would have driven myself crazy years ago.
|
||||
|
@ -20,20 +24,55 @@ class DJBoyfriend extends FlxSprite
|
|||
// TODO: Switch this class to use SwagSprite instead.
|
||||
public var animOffsets:Map<String, Array<Dynamic>>;
|
||||
|
||||
static final SPOOK_PERIOD:Float = 180.0;
|
||||
var gotSpooked:Bool = false;
|
||||
|
||||
static final SPOOK_PERIOD:Float = 120.0;
|
||||
static final TV_PERIOD:Float = 180.0;
|
||||
|
||||
// Time since dad last SPOOKED you.
|
||||
var timeSinceSpook:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
super(x, y, Paths.animateAtlas("freeplay/freeplay-boyfriend", "preload"));
|
||||
|
||||
animOffsets = new Map<String, Array<Dynamic>>();
|
||||
|
||||
setupAnimations();
|
||||
anim.callback = function(name, number) {
|
||||
switch (name)
|
||||
{
|
||||
case "Boyfriend DJ watchin tv OG":
|
||||
if (number == 85) runTvLogic();
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
animation.finishCallback = onFinishAnim;
|
||||
setupAnimations();
|
||||
trace(listAnimations());
|
||||
|
||||
FlxG.debugger.track(this);
|
||||
FlxG.console.registerObject("dj", this);
|
||||
|
||||
anim.onComplete = onFinishAnim;
|
||||
|
||||
FlxG.console.registerFunction("tv", function() {
|
||||
currentState = TV;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
[remote hand under,boyfriend top head,brim piece,arm cringe l,red lazer,dj arm in,bf fist pump arm,hand raised right,forearm left,fist shaking,bf smile eyes closed face,arm cringe r,bf clenched face,face shrug,boyfriend falling,blue tint 1,shirt sleeve,bf clenched fist,head BF relaxed,blue tint 2,hand down left,blue tint 3,blue tint 4,head less smooshed,blue tint 5,boyfriend freeplay,BF head slight turn,blue tint 6,arm shrug l,blue tint 7,shoulder raised w sleeve,blue tint 8,fist pump face,blue tint 9,foot rested light,hand turnaround,arm chill right,Boyfriend DJ,arm shrug r,head back bf,hat top piece,dad bod,face surprise snap,Boyfriend DJ fist pump,office chair,foot rested right,chest down,office chair upright,body chill,bf dj afk,head mouth open dad,BF Head defalt HAIR BLOWING,hand shrug l,face piece,foot wag,turn table,shoulder up left,turntable lights,boyfriend dj body shirt blowing,body chunk turned,hand down right,dj arm out,hand shrug r,body chest out,rave hand,palm,chill face default,head back semi bf,boyfriend bottom head,DJ arm,shoulder right dad,bf surprise,boyfriend dj body,hs1,Boyfriend DJ watchin tv OG,spinning disk,hs2,arm chill left,boyfriend dj intro,hs3,hs4,chill face extra,hs5,remote hand upright,hs6,pant over table,face surprise,bf arm peace,arm turnaround,bf eyes 1,arm slammed table,eye squit,leg BF,head mid piece,arm backing,arm swoopin in,shoe right lowering,forearm right,hand out,blue tint 10,body falling back,remote thumb press,shoulder,hair spike single,bf bent
|
||||
arm,crt,foot raised right,dad hand,chill face 1,chill face 2,clenched fist,head SMOOSHED,shoulder left dad,df1,body chunk upright,df2,df3,df4,hat front piece,df5,foot rested right 2,hand in,arm spun,shoe raised left,bf 1 finger hand,bf mouth 1,Boyfriend DJ confirm,forearm down ,hand raised left,remote thumb up]
|
||||
*/
|
||||
override public function listAnimations():Array<String>
|
||||
{
|
||||
var anims:Array<String> = [];
|
||||
@:privateAccess
|
||||
for (animKey in anim.symbolDictionary)
|
||||
{
|
||||
anims.push(animKey.name);
|
||||
}
|
||||
return anims;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
|
@ -44,51 +83,68 @@ class DJBoyfriend extends FlxSprite
|
|||
{
|
||||
case Intro:
|
||||
// Play the intro animation then leave this state immediately.
|
||||
if (getCurrentAnimation() != 'intro') playAnimation('intro', true);
|
||||
if (getCurrentAnimation() != 'boyfriend dj intro') playFlashAnimation('boyfriend dj intro', true);
|
||||
timeSinceSpook = 0;
|
||||
case Idle:
|
||||
// We are in this state the majority of the time.
|
||||
if (getCurrentAnimation() != 'idle' || animation.finished)
|
||||
if (getCurrentAnimation() != 'Boyfriend DJ' || anim.finished)
|
||||
{
|
||||
if (timeSinceSpook > SPOOK_PERIOD)
|
||||
if (timeSinceSpook > SPOOK_PERIOD && !gotSpooked)
|
||||
{
|
||||
currentState = Spook;
|
||||
}
|
||||
else if (timeSinceSpook > TV_PERIOD)
|
||||
{
|
||||
currentState = TV;
|
||||
}
|
||||
else
|
||||
{
|
||||
playAnimation('idle', false);
|
||||
playFlashAnimation('Boyfriend DJ', false);
|
||||
}
|
||||
}
|
||||
timeSinceSpook += elapsed;
|
||||
case Confirm:
|
||||
if (getCurrentAnimation() != 'confirm') playAnimation('confirm', false);
|
||||
if (getCurrentAnimation() != 'Boyfriend DJ confirm') playFlashAnimation('Boyfriend DJ confirm', false);
|
||||
timeSinceSpook = 0;
|
||||
case Spook:
|
||||
if (getCurrentAnimation() != 'spook')
|
||||
if (getCurrentAnimation() != 'bf dj afk')
|
||||
{
|
||||
onSpook.dispatch();
|
||||
playAnimation('spook', false);
|
||||
playFlashAnimation('bf dj afk', false);
|
||||
}
|
||||
timeSinceSpook = 0;
|
||||
case TV:
|
||||
if (getCurrentAnimation() != 'Boyfriend DJ watchin tv OG') playFlashAnimation('Boyfriend DJ watchin tv OG', true);
|
||||
timeSinceSpook = 0;
|
||||
default:
|
||||
// I shit myself.
|
||||
}
|
||||
}
|
||||
|
||||
function onFinishAnim(name:String):Void
|
||||
function onFinishAnim():Void
|
||||
{
|
||||
var name = anim.curSymbol.name;
|
||||
switch (name)
|
||||
{
|
||||
case "intro":
|
||||
case "boyfriend dj intro":
|
||||
// trace('Finished intro');
|
||||
currentState = Idle;
|
||||
onIntroDone.dispatch();
|
||||
case "idle":
|
||||
case "Boyfriend DJ":
|
||||
// trace('Finished idle');
|
||||
case "spook":
|
||||
case "bf dj afk":
|
||||
// trace('Finished spook');
|
||||
currentState = Idle;
|
||||
case "confirm":
|
||||
case "Boyfriend DJ confirm":
|
||||
|
||||
case "Boyfriend DJ watchin tv OG":
|
||||
var frame:Int = FlxG.random.bool(33) ? 112 : 166;
|
||||
if (FlxG.random.bool(10))
|
||||
{
|
||||
frame = 60;
|
||||
// boyfriend switches channel code?
|
||||
}
|
||||
anim.play("Boyfriend DJ watchin tv OG", true, false, frame);
|
||||
// trace('Finished confirm');
|
||||
}
|
||||
}
|
||||
|
@ -100,19 +156,66 @@ class DJBoyfriend extends FlxSprite
|
|||
|
||||
function setupAnimations():Void
|
||||
{
|
||||
frames = FlxAnimationUtil.combineFramesCollections(Paths.getSparrowAtlas('freeplay/bfFreeplay'), Paths.getSparrowAtlas('freeplay/bf-freeplay-afk'));
|
||||
// frames = FlxAnimationUtil.combineFramesCollections(Paths.getSparrowAtlas('freeplay/bfFreeplay'), Paths.getSparrowAtlas('freeplay/bf-freeplay-afk'));
|
||||
|
||||
animation.addByPrefix('intro', "boyfriend dj intro", 24, false);
|
||||
addOffset('intro', 0, 0);
|
||||
// animation.addByPrefix('intro', "boyfriend dj intro", 24, false);
|
||||
addOffset('boyfriend dj intro', 8, 3);
|
||||
|
||||
animation.addByPrefix('idle', "Boyfriend DJ0", 24, false);
|
||||
addOffset('idle', -4, -426);
|
||||
// animation.addByPrefix('idle', "Boyfriend DJ0", 24, false);
|
||||
addOffset('Boyfriend DJ', 0, 0);
|
||||
|
||||
animation.addByPrefix('confirm', "Boyfriend DJ confirm", 24, false);
|
||||
addOffset('confirm', 40, -451);
|
||||
// animation.addByPrefix('confirm', "Boyfriend DJ confirm", 24, false);
|
||||
addOffset('Boyfriend DJ confirm', 0, 0);
|
||||
|
||||
animation.addByPrefix('spook', "bf dj afk0", 24, false);
|
||||
addOffset('spook', -3, -272);
|
||||
// animation.addByPrefix('spook', "bf dj afk0", 24, false);
|
||||
addOffset('bf dj afk', 0, 0);
|
||||
}
|
||||
|
||||
var cartoonSnd:FlxStreamSound;
|
||||
|
||||
public var playingCartoon:Bool = false;
|
||||
|
||||
public function runTvLogic()
|
||||
{
|
||||
if (cartoonSnd == null)
|
||||
{
|
||||
// tv is OFF, but getting turned on
|
||||
FlxG.sound.play(Paths.sound('tv_on'));
|
||||
|
||||
cartoonSnd = new FlxStreamSound();
|
||||
FlxG.sound.defaultSoundGroup.add(cartoonSnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// plays it smidge after the click
|
||||
new FlxTimer().start(0.1, function(_) {
|
||||
FlxG.sound.play(Paths.sound('channel_switch'));
|
||||
});
|
||||
}
|
||||
// cartoonSnd.loadEmbedded(Paths.sound("cartoons/peck"));
|
||||
// cartoonSnd.play();
|
||||
|
||||
loadCartoon();
|
||||
}
|
||||
|
||||
function loadCartoon()
|
||||
{
|
||||
cartoonSnd.loadEmbedded(Paths.sound(getRandomFlashToon()), false, false, function() {
|
||||
anim.play("Boyfriend DJ watchin tv OG", true, false, 60);
|
||||
});
|
||||
cartoonSnd.play(true, FlxG.random.float(0, cartoonSnd.length));
|
||||
}
|
||||
|
||||
var cartoonList:Array<String> = openfl.utils.Assets.list().filter(function(path) return path.startsWith("assets/sounds/cartoons/"));
|
||||
|
||||
function getRandomFlashToon():String
|
||||
{
|
||||
var randomFile = FlxG.random.getObject(cartoonList);
|
||||
|
||||
randomFile = randomFile.replace("assets/sounds/", "");
|
||||
randomFile = randomFile.substring(0, randomFile.length - 4);
|
||||
|
||||
return randomFile;
|
||||
}
|
||||
|
||||
public function confirm():Void
|
||||
|
@ -125,15 +228,15 @@ class DJBoyfriend extends FlxSprite
|
|||
animOffsets[name] = [x, y];
|
||||
}
|
||||
|
||||
public function getCurrentAnimation():String
|
||||
override public function getCurrentAnimation():String
|
||||
{
|
||||
if (this.animation == null || this.animation.curAnim == null) return "";
|
||||
return this.animation.curAnim.name;
|
||||
if (this.anim == null || this.anim.curSymbol == null) return "";
|
||||
return this.anim.curSymbol.name;
|
||||
}
|
||||
|
||||
public function playAnimation(AnimName:String, Force:Bool = false, Reversed:Bool = false, Frame:Int = 0):Void
|
||||
public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void
|
||||
{
|
||||
animation.play(AnimName, Force, Reversed, Frame);
|
||||
anim.play(id, Force, Reverse, Frame);
|
||||
applyAnimOffset();
|
||||
}
|
||||
|
||||
|
@ -156,4 +259,5 @@ enum DJBoyfriendState
|
|||
Idle;
|
||||
Confirm;
|
||||
Spook;
|
||||
TV;
|
||||
}
|
||||
|
|
106
source/funkin/freeplayStuff/DifficultyStars.hx
Normal file
106
source/funkin/freeplayStuff/DifficultyStars.hx
Normal file
|
@ -0,0 +1,106 @@
|
|||
package funkin.freeplayStuff;
|
||||
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import funkin.graphics.adobeanimate.FlxAtlasSprite;
|
||||
import funkin.shaderslmfao.HSVShader;
|
||||
|
||||
class DifficultyStars extends FlxSpriteGroup
|
||||
{
|
||||
/**
|
||||
* Internal handler var for difficulty... ranges from 0... to 15
|
||||
* 0 is 1 star... 15 is 0 stars!
|
||||
*/
|
||||
var curDifficulty(default, set):Int = 0;
|
||||
|
||||
/**
|
||||
* Range between 0 and 15
|
||||
*/
|
||||
public var difficulty(default, set):Int = 1;
|
||||
|
||||
public var stars:FlxAtlasSprite;
|
||||
|
||||
var flames:FreeplayFlames;
|
||||
|
||||
var hsvShader:HSVShader;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
hsvShader = new HSVShader();
|
||||
|
||||
flames = new FreeplayFlames(0, 0);
|
||||
add(flames);
|
||||
|
||||
stars = new FlxAtlasSprite(0, 0, Paths.animateAtlas("freeplay/freeplayStars"));
|
||||
stars.anim.play("diff stars");
|
||||
add(stars);
|
||||
|
||||
stars.shader = hsvShader;
|
||||
|
||||
for (memb in flames.members)
|
||||
memb.shader = hsvShader;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
// "loops" the current animation
|
||||
// for clarity, the animation file looks like
|
||||
// frame : stars
|
||||
// 0-99: 1 star
|
||||
// 100-199: 2 stars
|
||||
// ......
|
||||
// 1300-1499: 15 stars
|
||||
// 1500 : 0 stars
|
||||
if (curDifficulty < 15 && stars.anim.curFrame >= (curDifficulty + 1) * 100)
|
||||
{
|
||||
stars.anim.play("diff stars", true, false, curDifficulty * 100);
|
||||
}
|
||||
}
|
||||
|
||||
function set_difficulty(value:Int):Int
|
||||
{
|
||||
difficulty = value;
|
||||
|
||||
if (difficulty <= 0)
|
||||
{
|
||||
difficulty = 0;
|
||||
curDifficulty = 15;
|
||||
}
|
||||
else if (difficulty <= 15)
|
||||
{
|
||||
difficulty = value;
|
||||
curDifficulty = difficulty - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
difficulty = 15;
|
||||
curDifficulty = difficulty - 1;
|
||||
}
|
||||
|
||||
if (difficulty > 10) flames.flameCount = difficulty - 10;
|
||||
else
|
||||
flames.flameCount = 0;
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
function set_curDifficulty(value:Int):Int
|
||||
{
|
||||
curDifficulty = value;
|
||||
if (curDifficulty == 15)
|
||||
{
|
||||
stars.anim.play("diff stars", true, false, 1500);
|
||||
stars.anim.pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
stars.anim.curFrame = Std.int(curDifficulty * 100);
|
||||
stars.anim.play("diff stars", true, false, curDifficulty * 100);
|
||||
}
|
||||
|
||||
return curDifficulty;
|
||||
}
|
||||
}
|
117
source/funkin/freeplayStuff/FreeplayFlames.hx
Normal file
117
source/funkin/freeplayStuff/FreeplayFlames.hx
Normal file
|
@ -0,0 +1,117 @@
|
|||
package funkin.freeplayStuff;
|
||||
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
class FreeplayFlames extends FlxSpriteGroup
|
||||
{
|
||||
var flameX(default, set):Float = 917;
|
||||
var flameY(default, set):Float = 103;
|
||||
var flameSpreadX(default, set):Float = 29;
|
||||
var flameSpreadY(default, set):Float = 6;
|
||||
|
||||
public var flameCount(default, set):Int = 0;
|
||||
|
||||
var flameTimer:Float = 0.25;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
for (i in 0...5)
|
||||
{
|
||||
var flame:FlxSprite = new FlxSprite(flameX + (flameSpreadX * i), flameY + (flameSpreadY * i));
|
||||
flame.frames = Paths.getSparrowAtlas("freeplay/freeplayFlame");
|
||||
flame.animation.addByPrefix("flame", "fire loop", FlxG.random.int(23, 25), false);
|
||||
flame.animation.play("flame");
|
||||
flame.visible = false;
|
||||
flameCount = 0;
|
||||
|
||||
// sets the loop... maybe better way to do this lol!
|
||||
flame.animation.finishCallback = function(_) {
|
||||
flame.animation.play("flame", true, false, 2);
|
||||
};
|
||||
add(flame);
|
||||
}
|
||||
}
|
||||
|
||||
var properPositions:Bool = false;
|
||||
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
// doesn't work in create()/new() for some reason
|
||||
// so putting it here bwah!
|
||||
if (!properPositions)
|
||||
{
|
||||
setFlamePositions();
|
||||
properPositions = true;
|
||||
}
|
||||
}
|
||||
|
||||
function set_flameCount(value:Int):Int
|
||||
{
|
||||
this.flameCount = value;
|
||||
var visibleCount:Int = 0;
|
||||
for (i in 0...5)
|
||||
{
|
||||
if (members[i] == null) continue;
|
||||
var flame:FlxSprite = members[i];
|
||||
if (i < flameCount)
|
||||
{
|
||||
if (!flame.visible)
|
||||
{
|
||||
new FlxTimer().start(flameTimer * visibleCount, function(_) {
|
||||
flame.animation.play("flame", true);
|
||||
flame.visible = true;
|
||||
});
|
||||
visibleCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flame.visible = false;
|
||||
}
|
||||
}
|
||||
return this.flameCount;
|
||||
}
|
||||
|
||||
function setFlamePositions()
|
||||
{
|
||||
for (i in 0...5)
|
||||
{
|
||||
var flame:FlxSprite = members[i];
|
||||
flame.x = flameX + (flameSpreadX * i);
|
||||
flame.y = flameY + (flameSpreadY * i);
|
||||
}
|
||||
}
|
||||
|
||||
function set_flameX(value:Float):Float
|
||||
{
|
||||
this.flameX = value;
|
||||
setFlamePositions();
|
||||
return this.flameX;
|
||||
}
|
||||
|
||||
function set_flameY(value:Float):Float
|
||||
{
|
||||
this.flameY = value;
|
||||
setFlamePositions();
|
||||
return this.flameY;
|
||||
}
|
||||
|
||||
function set_flameSpreadX(value:Float):Float
|
||||
{
|
||||
this.flameSpreadX = value;
|
||||
setFlamePositions();
|
||||
return this.flameSpreadX;
|
||||
}
|
||||
|
||||
function set_flameSpreadY(value:Float):Float
|
||||
{
|
||||
this.flameSpreadY = value;
|
||||
setFlamePositions();
|
||||
return this.flameSpreadY;
|
||||
}
|
||||
}
|
|
@ -4,38 +4,68 @@ import flixel.FlxSprite;
|
|||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.graphics.adobeanimate.FlxAtlasSprite;
|
||||
|
||||
class LetterSort extends FlxTypedSpriteGroup<FreeplayLetter>
|
||||
class LetterSort extends FlxTypedSpriteGroup<FlxSprite>
|
||||
{
|
||||
public var letters:Array<FreeplayLetter> = [];
|
||||
|
||||
var curSelection:Int = 0;
|
||||
// starts at 2, cuz that's the middle letter on start (accounting for fav and #, it should begin at ALL filter)
|
||||
var curSelection:Int = 2;
|
||||
|
||||
public var changeSelectionCallback:String->Void;
|
||||
|
||||
var leftArrow:FlxSprite;
|
||||
var rightArrow:FlxSprite;
|
||||
var grpSeperators:Array<FlxSprite> = [];
|
||||
|
||||
public function new(x, y)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
var leftArrow:FreeplayLetter = new FreeplayLetter(-20, 0);
|
||||
leftArrow.animation.play("arrow");
|
||||
leftArrow = new FlxSprite(-20, 15).loadGraphic(Paths.image("freeplay/miniArrow"));
|
||||
// leftArrow.animation.play("arrow");
|
||||
leftArrow.flipX = true;
|
||||
add(leftArrow);
|
||||
|
||||
for (i in 0...6)
|
||||
for (i in 0...5)
|
||||
{
|
||||
var letter:FreeplayLetter = new FreeplayLetter(i * 80, 0, i);
|
||||
letter.x += 50;
|
||||
letter.y += 50;
|
||||
letter.ogY = y;
|
||||
// letter.visible = false;
|
||||
add(letter);
|
||||
|
||||
letters.push(letter);
|
||||
|
||||
if (i == 3) letter.alpha = 0.6;
|
||||
if (i != 2) letter.scale.x = letter.scale.y = 0.8;
|
||||
|
||||
var sep:FreeplayLetter = new FreeplayLetter((i * 80) + 50, 0);
|
||||
sep.animation.play("seperator");
|
||||
var darkness:Float = Math.abs(i - 2) / 6;
|
||||
|
||||
letter.color = letter.color.getDarkened(darkness);
|
||||
|
||||
// don't put the last seperator
|
||||
if (i == 4) continue;
|
||||
|
||||
var sep:FlxSprite = new FlxSprite((i * 80) + 55, 20).loadGraphic(Paths.image("freeplay/seperator"));
|
||||
// sep.animation.play("seperator");
|
||||
sep.color = letter.color.getDarkened(darkness);
|
||||
add(sep);
|
||||
|
||||
grpSeperators.push(sep);
|
||||
}
|
||||
|
||||
// changeSelection(-3);
|
||||
rightArrow = new FlxSprite(380, 15).loadGraphic(Paths.image("freeplay/miniArrow"));
|
||||
|
||||
// rightArrow.animation.play("arrow");
|
||||
add(rightArrow);
|
||||
|
||||
changeSelection(0);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
|
@ -48,53 +78,168 @@ class LetterSort extends FlxTypedSpriteGroup<FreeplayLetter>
|
|||
|
||||
public function changeSelection(diff:Int = 0)
|
||||
{
|
||||
var ezTimer:Int->FlxSprite->Float->Void = function(frameNum:Int, spr:FlxSprite, offsetNum:Float) {
|
||||
new FlxTimer().start(frameNum / 24, function(_) {
|
||||
spr.offset.x = offsetNum;
|
||||
});
|
||||
};
|
||||
|
||||
var positions:Array<Float> = [-10, -22, 2, 0];
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
for (sep in grpSeperators)
|
||||
{
|
||||
ezTimer(0, sep, positions[0]);
|
||||
ezTimer(1, sep, positions[1]);
|
||||
ezTimer(2, sep, positions[2]);
|
||||
ezTimer(3, sep, positions[3]);
|
||||
}
|
||||
|
||||
for (index => letter in letters)
|
||||
{
|
||||
letter.offset.x = positions[0];
|
||||
|
||||
new FlxTimer().start(1 / 24, function(_) {
|
||||
letter.offset.x = positions[1];
|
||||
if (index == 0) letter.visible = false;
|
||||
});
|
||||
|
||||
new FlxTimer().start(2 / 24, function(_) {
|
||||
letter.offset.x = positions[2];
|
||||
if (index == 0.) letter.visible = true;
|
||||
});
|
||||
|
||||
if (index == 2)
|
||||
{
|
||||
ezTimer(3, letter, 0);
|
||||
// letter.offset.x = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
ezTimer(3, letter, positions[3]);
|
||||
}
|
||||
|
||||
leftArrow.offset.x = 3;
|
||||
new FlxTimer().start(2 / 24, function(_) {
|
||||
leftArrow.offset.x = 0;
|
||||
});
|
||||
}
|
||||
else if (diff > 0)
|
||||
{
|
||||
for (sep in grpSeperators)
|
||||
{
|
||||
ezTimer(0, sep, -positions[0]);
|
||||
ezTimer(1, sep, -positions[1]);
|
||||
ezTimer(2, sep, -positions[2]);
|
||||
ezTimer(3, sep, -positions[3]);
|
||||
}
|
||||
// same timing and functions and shit as the left one... except to the right!!
|
||||
|
||||
for (index => letter in letters)
|
||||
{
|
||||
letter.offset.x = -positions[0];
|
||||
|
||||
new FlxTimer().start(1 / 24, function(_) {
|
||||
letter.offset.x = -positions[1];
|
||||
if (index == 0) letter.visible = false;
|
||||
});
|
||||
|
||||
new FlxTimer().start(2 / 24, function(_) {
|
||||
letter.offset.x = -positions[2];
|
||||
if (index == 0) letter.visible = true;
|
||||
});
|
||||
|
||||
if (index == 2)
|
||||
{
|
||||
ezTimer(3, letter, 0);
|
||||
// letter.offset.x = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
ezTimer(3, letter, -positions[3]);
|
||||
}
|
||||
|
||||
rightArrow.offset.x = -3;
|
||||
new FlxTimer().start(2 / 24, function(_) {
|
||||
rightArrow.offset.x = 0;
|
||||
});
|
||||
}
|
||||
|
||||
curSelection += diff;
|
||||
if (curSelection < 0) curSelection = letters[0].arr.length - 1;
|
||||
if (curSelection >= letters[0].arr.length) curSelection = 0;
|
||||
|
||||
for (letter in letters)
|
||||
letter.changeLetter(diff);
|
||||
letter.changeLetter(diff, curSelection);
|
||||
|
||||
if (changeSelectionCallback != null) changeSelectionCallback(letters[3].arr[letters[3].curLetter]); // bullshit and long lol!
|
||||
if (changeSelectionCallback != null) changeSelectionCallback(letters[2].arr[letters[2].curLetter]); // bullshit and long lol!
|
||||
}
|
||||
}
|
||||
|
||||
class FreeplayLetter extends FlxSprite
|
||||
class FreeplayLetter extends FlxAtlasSprite
|
||||
{
|
||||
public var arr:Array<String> = [];
|
||||
|
||||
public var curLetter:Int = 0;
|
||||
|
||||
public var ogY:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float, ?letterInd:Int)
|
||||
{
|
||||
super(x, y);
|
||||
super(x, y, Paths.animateAtlas("freeplay/sortedLetters"));
|
||||
// frames = Paths.getSparrowAtlas("freeplay/letterStuff");
|
||||
// this.anim.play("AB");
|
||||
// trace(this.anim.symbolDictionary);
|
||||
|
||||
frames = Paths.getSparrowAtlas("freeplay/letterStuff");
|
||||
|
||||
var alphabet:String = "abcdefghijklmnopqrstuvwxyz";
|
||||
arr = alphabet.split("");
|
||||
arr.insert(0, "#");
|
||||
var alphabet:String = "AB-CD-EH-I L-MN-OR-s-t-UZ";
|
||||
arr = alphabet.split("-");
|
||||
arr.insert(0, "ALL");
|
||||
arr.insert(0, "fav");
|
||||
arr.insert(0, "#");
|
||||
|
||||
for (str in arr)
|
||||
{
|
||||
animation.addByPrefix(str, str + " "); // string followed by a space! intentional!
|
||||
}
|
||||
// trace(arr);
|
||||
|
||||
animation.addByPrefix("arrow", "mini arrow");
|
||||
animation.addByPrefix("seperator", "seperator");
|
||||
// for (str in arr)
|
||||
// {
|
||||
// animation.addByPrefix(str, str + " "); // string followed by a space! intentional!
|
||||
// }
|
||||
|
||||
// animation.addByPrefix("arrow", "mini arrow");
|
||||
// animation.addByPrefix("seperator", "seperator");
|
||||
|
||||
if (letterInd != null)
|
||||
{
|
||||
animation.play(arr[letterInd]);
|
||||
this.anim.play(arr[letterInd] + " move");
|
||||
this.anim.pause();
|
||||
curLetter = letterInd;
|
||||
}
|
||||
}
|
||||
|
||||
public function changeLetter(diff:Int = 0)
|
||||
public function changeLetter(diff:Int = 0, ?curSelection:Int)
|
||||
{
|
||||
curLetter += diff;
|
||||
|
||||
if (curLetter < 0) curLetter = arr.length - 1;
|
||||
if (curLetter >= arr.length) curLetter = 0;
|
||||
|
||||
animation.play(arr[curLetter]);
|
||||
var animName:String = arr[curLetter] + " move";
|
||||
|
||||
switch (arr[curLetter])
|
||||
{
|
||||
case "I L":
|
||||
animName = "IL move";
|
||||
case "s":
|
||||
animName = "S move";
|
||||
case "t":
|
||||
animName = "T move";
|
||||
}
|
||||
|
||||
this.anim.play(animName);
|
||||
if (curSelection != curLetter)
|
||||
{
|
||||
this.anim.pause();
|
||||
}
|
||||
// updateHitbox();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package funkin.freeplayStuff;
|
||||
|
||||
import funkin.shaderslmfao.HSVShader;
|
||||
import funkin.shaderslmfao.GaussianBlurShader;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
|
@ -7,17 +10,29 @@ import flixel.group.FlxSpriteGroup;
|
|||
import flixel.math.FlxMath;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.shaderslmfao.Grayscale;
|
||||
|
||||
class SongMenuItem extends FlxSpriteGroup
|
||||
{
|
||||
var capsule:FlxSprite;
|
||||
public var capsule:FlxSprite;
|
||||
|
||||
public var selected(default, set):Bool = false;
|
||||
var pixelIcon:FlxSprite;
|
||||
|
||||
public var selected(default, set):Bool;
|
||||
|
||||
public var songTitle:String = "Test";
|
||||
|
||||
public var songText:FlxText;
|
||||
public var songText:CapsuleText;
|
||||
public var favIcon:FlxSprite;
|
||||
public var ranking:FlxSprite;
|
||||
|
||||
var ranks:Array<String> = ["fail", "average", "great", "excellent", "perfect"];
|
||||
|
||||
// lol...
|
||||
var diffRanks:Array<String> = [
|
||||
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "14", "15"
|
||||
];
|
||||
|
||||
public var targetPos:FlxPoint = new FlxPoint();
|
||||
public var doLerp:Bool = false;
|
||||
|
@ -25,7 +40,12 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
|
||||
public var doJumpOut:Bool = false;
|
||||
|
||||
public function new(x:Float, y:Float, song:String)
|
||||
public var onConfirm:Void->Void;
|
||||
public var diffGrayscale:Grayscale;
|
||||
|
||||
public var hsvShader(default, set):HSVShader;
|
||||
|
||||
public function new(x:Float, y:Float, song:String, ?character:String)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
|
@ -38,19 +58,144 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
// capsule.animation
|
||||
add(capsule);
|
||||
|
||||
songText = new FlxText(120, 40, 0, songTitle, 40);
|
||||
songText.font = "5by7";
|
||||
songText.color = 0xFF43C1EA;
|
||||
add(songText);
|
||||
// doesn't get added, simply is here to help with visibility of things for the pop in!
|
||||
grpHide = new FlxGroup();
|
||||
|
||||
favIcon = new FlxSprite(440, 40);
|
||||
var rank:String = FlxG.random.getObject(ranks);
|
||||
|
||||
ranking = new FlxSprite(capsule.width * 0.84, 30);
|
||||
ranking.loadGraphic(Paths.image("freeplay/ranks/" + rank));
|
||||
ranking.scale.x = ranking.scale.y = realScaled;
|
||||
ranking.alpha = 0.75;
|
||||
ranking.origin.set(capsule.origin.x - ranking.x, capsule.origin.y - ranking.y);
|
||||
add(ranking);
|
||||
grpHide.add(ranking);
|
||||
|
||||
diffGrayscale = new Grayscale(1);
|
||||
|
||||
var diffRank = new FlxSprite(145, 90).loadGraphic(Paths.image("freeplay/diffRankings/diff" + FlxG.random.getObject(diffRanks)));
|
||||
diffRank.shader = diffGrayscale;
|
||||
diffRank.visible = false;
|
||||
add(diffRank);
|
||||
diffRank.origin.set(capsule.origin.x - diffRank.x, capsule.origin.y - diffRank.y);
|
||||
grpHide.add(diffRank);
|
||||
|
||||
switch (rank)
|
||||
{
|
||||
case "perfect":
|
||||
ranking.x -= 10;
|
||||
}
|
||||
|
||||
songText = new CapsuleText(capsule.width * 0.26, 45, songTitle, Std.int(40 * realScaled));
|
||||
add(songText);
|
||||
grpHide.add(songText);
|
||||
|
||||
pixelIcon = new FlxSprite(155, 15);
|
||||
pixelIcon.makeGraphic(32, 32, 0x00000000);
|
||||
pixelIcon.antialiasing = false;
|
||||
pixelIcon.active = false;
|
||||
add(pixelIcon);
|
||||
grpHide.add(pixelIcon);
|
||||
|
||||
if (character != null) setCharacter(character);
|
||||
|
||||
favIcon = new FlxSprite(400, 40);
|
||||
favIcon.frames = Paths.getSparrowAtlas('freeplay/favHeart');
|
||||
favIcon.animation.addByPrefix('fav', "favorite heart", 24, false);
|
||||
favIcon.animation.play('fav');
|
||||
favIcon.setGraphicSize(60, 60);
|
||||
favIcon.setGraphicSize(50, 50);
|
||||
favIcon.visible = false;
|
||||
add(favIcon);
|
||||
// grpHide.add(favIcon);
|
||||
|
||||
selected = selected; // just to kickstart the set_selected
|
||||
setVisibleGrp(false);
|
||||
}
|
||||
|
||||
function set_hsvShader(value:HSVShader):HSVShader
|
||||
{
|
||||
this.hsvShader = value;
|
||||
capsule.shader = hsvShader;
|
||||
songText.shader = hsvShader;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function textAppear()
|
||||
{
|
||||
songText.scale.x = 1.7;
|
||||
songText.scale.y = 0.2;
|
||||
|
||||
new FlxTimer().start(1 / 24, function(_) {
|
||||
songText.scale.x = 0.4;
|
||||
songText.scale.y = 1.4;
|
||||
});
|
||||
|
||||
new FlxTimer().start(2 / 24, function(_) {
|
||||
songText.scale.x = songText.scale.y = 1;
|
||||
});
|
||||
}
|
||||
|
||||
function setVisibleGrp(value:Bool)
|
||||
{
|
||||
for (spr in grpHide.members)
|
||||
{
|
||||
spr.visible = value;
|
||||
}
|
||||
|
||||
if (value) textAppear();
|
||||
|
||||
selectedAlpha();
|
||||
}
|
||||
|
||||
public function init(x:Float, y:Float, song:String, ?character:String)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.songTitle = song;
|
||||
songText.text = this.songTitle;
|
||||
if (character != null) setCharacter(character);
|
||||
|
||||
selected = selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the character displayed next to this song in the freeplay menu.
|
||||
* @param char The character ID used by this song.
|
||||
* If the character has no freeplay icon, a warning will be thrown and nothing will display.
|
||||
*/
|
||||
public function setCharacter(char:String)
|
||||
{
|
||||
var charPath:String = "freeplay/icons/";
|
||||
|
||||
trace(char);
|
||||
|
||||
switch (char)
|
||||
{
|
||||
case "monster-christmas":
|
||||
charPath += "monsterpixel";
|
||||
case "mom-car":
|
||||
charPath += "mommypixel";
|
||||
case "dad":
|
||||
charPath += "daddypixel";
|
||||
case "darnell-blazin":
|
||||
charPath += "darnellpixel";
|
||||
case "senpai-angry":
|
||||
charPath += "senpaipixel";
|
||||
default:
|
||||
charPath += char + "pixel";
|
||||
}
|
||||
|
||||
if (!openfl.utils.Assets.exists(Paths.image(charPath)))
|
||||
{
|
||||
trace('[WARN] Character ${char} has no freeplay icon.');
|
||||
return;
|
||||
}
|
||||
|
||||
pixelIcon.loadGraphic(Paths.image(charPath));
|
||||
pixelIcon.scale.x = pixelIcon.scale.y = 2;
|
||||
pixelIcon.origin.x = 100;
|
||||
// pixelIcon.origin.x = capsule.origin.x;
|
||||
// pixelIcon.offset.x -= pixelIcon.origin.x;
|
||||
}
|
||||
|
||||
var frameInTicker:Float = 0;
|
||||
|
@ -63,6 +208,63 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
var xPosLerpLol:Array<Float> = [0.9, 0.4, 0.16, 0.16, 0.22, 0.22, 0.245]; // NUMBERS ARE JANK CUZ THE SCALING OR WHATEVER
|
||||
var xPosOutLerpLol:Array<Float> = [0.245, 0.75, 0.98, 0.98, 1.2]; // NUMBERS ARE JANK CUZ THE SCALING OR WHATEVER
|
||||
|
||||
public var realScaled:Float = 0.8;
|
||||
|
||||
public function initJumpIn(maxTimer:Float, ?force:Bool):Void
|
||||
{
|
||||
frameInTypeBeat = 0;
|
||||
|
||||
new FlxTimer().start((1 / 24) * maxTimer, function(doShit) {
|
||||
doJumpIn = true;
|
||||
});
|
||||
|
||||
new FlxTimer().start((0.09 * maxTimer) + 0.85, function(lerpTmr) {
|
||||
doLerp = true;
|
||||
});
|
||||
|
||||
if (force)
|
||||
{
|
||||
visible = true;
|
||||
capsule.alpha = 1;
|
||||
setVisibleGrp(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
new FlxTimer().start((xFrames.length / 24) * 2.5, function(_) {
|
||||
visible = true;
|
||||
capsule.alpha = 1;
|
||||
setVisibleGrp(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var grpHide:FlxGroup;
|
||||
|
||||
public function forcePosition()
|
||||
{
|
||||
visible = true;
|
||||
capsule.alpha = 1;
|
||||
selectedAlpha();
|
||||
doLerp = true;
|
||||
doJumpIn = false;
|
||||
doJumpOut = false;
|
||||
|
||||
frameInTypeBeat = xFrames.length;
|
||||
frameOutTypeBeat = 0;
|
||||
|
||||
capsule.scale.x = xFrames[frameInTypeBeat - 1];
|
||||
capsule.scale.y = 1 / xFrames[frameInTypeBeat - 1];
|
||||
// x = FlxG.width * xPosLerpLol[Std.int(Math.min(frameInTypeBeat - 1, xPosLerpLol.length - 1))];
|
||||
|
||||
x = targetPos.x;
|
||||
y = targetPos.y;
|
||||
|
||||
capsule.scale.x *= realScaled;
|
||||
capsule.scale.y *= realScaled;
|
||||
|
||||
setVisibleGrp(true);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (doJumpIn)
|
||||
|
@ -73,10 +275,13 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
{
|
||||
frameInTicker = 0;
|
||||
|
||||
scale.x = xFrames[frameInTypeBeat];
|
||||
scale.y = 1 / xFrames[frameInTypeBeat];
|
||||
capsule.scale.x = xFrames[frameInTypeBeat];
|
||||
capsule.scale.y = 1 / xFrames[frameInTypeBeat];
|
||||
x = FlxG.width * xPosLerpLol[Std.int(Math.min(frameInTypeBeat, xPosLerpLol.length - 1))];
|
||||
|
||||
capsule.scale.x *= realScaled;
|
||||
capsule.scale.y *= realScaled;
|
||||
|
||||
frameInTypeBeat += 1;
|
||||
}
|
||||
}
|
||||
|
@ -89,10 +294,13 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
{
|
||||
frameOutTicker = 0;
|
||||
|
||||
scale.x = xFrames[frameOutTypeBeat];
|
||||
scale.y = 1 / xFrames[frameOutTypeBeat];
|
||||
capsule.scale.x = xFrames[frameOutTypeBeat];
|
||||
capsule.scale.y = 1 / xFrames[frameOutTypeBeat];
|
||||
x = FlxG.width * xPosOutLerpLol[Std.int(Math.min(frameOutTypeBeat, xPosOutLerpLol.length - 1))];
|
||||
|
||||
capsule.scale.x *= realScaled;
|
||||
capsule.scale.y *= realScaled;
|
||||
|
||||
frameOutTypeBeat += 1;
|
||||
}
|
||||
}
|
||||
|
@ -106,14 +314,29 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public function intendedY(index:Int):Float
|
||||
{
|
||||
return (index * ((height * realScaled) + 10)) + 120;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merely a helper function to call set_selected, to make sure that the alpha is correct on the rankings/selections
|
||||
*/
|
||||
public function selectedAlpha():Void
|
||||
{
|
||||
selected = selected;
|
||||
}
|
||||
|
||||
function set_selected(value:Bool):Bool
|
||||
{
|
||||
// trace(value);
|
||||
|
||||
// cute one liners, lol!
|
||||
diffGrayscale.setAmount(value ? 0 : 0.8);
|
||||
songText.alpha = value ? 1 : 0.6;
|
||||
songText.blurredText.visible = value ? true : false;
|
||||
capsule.offset.x = value ? 0 : -5;
|
||||
capsule.animation.play(value ? "selected" : "unselected");
|
||||
ranking.alpha = value ? 1 : 0.7;
|
||||
ranking.color = value ? 0xFFFFFFFF : 0xFFAAAAAA;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,41 +511,7 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
NoteSplash.buildSplashFrames();
|
||||
|
||||
// Returns null if the song failed to load or doesn't have the selected difficulty.
|
||||
if (currentSong == null || currentChart == null)
|
||||
{
|
||||
// We have encountered a critical error. Prevent Flixel from trying to run any gameplay logic.
|
||||
criticalFailure = true;
|
||||
|
||||
// Choose an error message.
|
||||
var message:String = 'There was a critical error. Click OK to return to the main menu.';
|
||||
if (currentSong == null)
|
||||
{
|
||||
message = 'The was a critical error loading this song\'s chart. Click OK to return to the main menu.';
|
||||
}
|
||||
else if (currentDifficulty == null)
|
||||
{
|
||||
message = 'The was a critical error selecting a difficulty for this song. Click OK to return to the main menu.';
|
||||
}
|
||||
else if (currentSong.getDifficulty(currentDifficulty) == null)
|
||||
{
|
||||
message = 'The was a critical error retrieving data for this song on "$currentDifficulty" difficulty. Click OK to return to the main menu.';
|
||||
}
|
||||
|
||||
// Display a popup. This blocks the application until the user clicks OK.
|
||||
lime.app.Application.current.window.alert(message, 'Error loading PlayState');
|
||||
|
||||
// Force the user back to the main menu.
|
||||
if (isSubState)
|
||||
{
|
||||
this.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!assertChartExists()) return;
|
||||
|
||||
if (false)
|
||||
{
|
||||
|
@ -660,6 +626,47 @@ class PlayState extends MusicBeatSubState
|
|||
initialized = true;
|
||||
}
|
||||
|
||||
function assertChartExists():Bool
|
||||
{
|
||||
// Returns null if the song failed to load or doesn't have the selected difficulty.
|
||||
if (currentSong == null || currentChart == null)
|
||||
{
|
||||
// We have encountered a critical error. Prevent Flixel from trying to run any gameplay logic.
|
||||
criticalFailure = true;
|
||||
|
||||
// Choose an error message.
|
||||
var message:String = 'There was a critical error. Click OK to return to the main menu.';
|
||||
if (currentSong == null)
|
||||
{
|
||||
message = 'The was a critical error loading this song\'s chart. Click OK to return to the main menu.';
|
||||
}
|
||||
else if (currentDifficulty == null)
|
||||
{
|
||||
message = 'The was a critical error selecting a difficulty for this song. Click OK to return to the main menu.';
|
||||
}
|
||||
else if (currentSong.getDifficulty(currentDifficulty) == null)
|
||||
{
|
||||
message = 'The was a critical error retrieving data for this song on "$currentDifficulty" difficulty. Click OK to return to the main menu.';
|
||||
}
|
||||
|
||||
// Display a popup. This blocks the application until the user clicks OK.
|
||||
lime.app.Application.current.window.alert(message, 'Error loading PlayState');
|
||||
|
||||
// Force the user back to the main menu.
|
||||
if (isSubState)
|
||||
{
|
||||
this.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
if (criticalFailure) return;
|
||||
|
@ -672,6 +679,8 @@ class PlayState extends MusicBeatSubState
|
|||
// Handle restarting the song when needed (player death or pressing Retry)
|
||||
if (needsReset)
|
||||
{
|
||||
if (!assertChartExists()) return;
|
||||
|
||||
dispatchEvent(new ScriptEvent(ScriptEvent.SONG_RETRY));
|
||||
|
||||
resetCamera();
|
||||
|
@ -686,8 +695,10 @@ class PlayState extends MusicBeatSubState
|
|||
// Reset music properly.
|
||||
|
||||
FlxG.sound.music.pause();
|
||||
vocals.pause();
|
||||
FlxG.sound.music.time = (startTimestamp);
|
||||
|
||||
vocals = currentChart.buildVocals();
|
||||
vocals.pause();
|
||||
vocals.time = 0;
|
||||
|
||||
FlxG.sound.music.volume = 1;
|
||||
|
@ -1879,6 +1890,7 @@ class PlayState extends MusicBeatSubState
|
|||
{
|
||||
// Grant the player health.
|
||||
health += Constants.HEALTH_HOLD_BONUS_PER_SECOND * elapsed;
|
||||
songScore += Std.int(Constants.SCORE_HOLD_BONUS_PER_SECOND * elapsed);
|
||||
}
|
||||
|
||||
// TODO: Potential penalty for dropping a hold note?
|
||||
|
@ -1999,103 +2011,6 @@ class PlayState extends MusicBeatSubState
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle player inputs.
|
||||
*/
|
||||
function keyShit(test:Bool):Void
|
||||
{
|
||||
// control arrays, order L D R U
|
||||
var holdArray:Array<Bool> = [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
|
||||
var pressArray:Array<Bool> = [
|
||||
controls.NOTE_LEFT_P,
|
||||
controls.NOTE_DOWN_P,
|
||||
controls.NOTE_UP_P,
|
||||
controls.NOTE_RIGHT_P
|
||||
];
|
||||
var releaseArray:Array<Bool> = [
|
||||
controls.NOTE_LEFT_R,
|
||||
controls.NOTE_DOWN_R,
|
||||
controls.NOTE_UP_R,
|
||||
controls.NOTE_RIGHT_R
|
||||
];
|
||||
|
||||
// if (pressArray.contains(true))
|
||||
// {
|
||||
// var lol:Array<Int> = cast pressArray;
|
||||
// inputSpitter.push(Std.int(Conductor.songPosition) + ' ' + lol.join(' '));
|
||||
// }
|
||||
|
||||
// HOLDS, check for sustain notes
|
||||
if (holdArray.contains(true) && generatedMusic)
|
||||
{
|
||||
/*
|
||||
activeNotes.forEachAlive(function(daNote:Note) {
|
||||
if (daNote.isSustainNote && daNote.canBeHit && daNote.mustPress && holdArray[daNote.data.noteData]) goodNoteHit(daNote);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// PRESSES, check for note hits
|
||||
if (pressArray.contains(true) && generatedMusic)
|
||||
{
|
||||
Haptic.vibrate(100, 100);
|
||||
|
||||
if (currentStage != null && currentStage.getBoyfriend() != null)
|
||||
{
|
||||
currentStage.getBoyfriend().holdTimer = 0;
|
||||
}
|
||||
|
||||
var possibleNotes:Array<NoteSprite> = []; // notes that can be hit
|
||||
var directionList:Array<Int> = []; // directions that can be hit
|
||||
var dumbNotes:Array<NoteSprite> = []; // notes to kill later
|
||||
|
||||
for (note in dumbNotes)
|
||||
{
|
||||
FlxG.log.add('killing dumb ass note at ' + note.noteData.time);
|
||||
note.kill();
|
||||
// activeNotes.remove(note, true);
|
||||
note.destroy();
|
||||
}
|
||||
|
||||
possibleNotes.sort((a, b) -> Std.int(a.noteData.time - b.noteData.time));
|
||||
|
||||
if (perfectMode)
|
||||
{
|
||||
goodNoteHit(possibleNotes[0], null);
|
||||
}
|
||||
else if (possibleNotes.length > 0)
|
||||
{
|
||||
for (shit in 0...pressArray.length)
|
||||
{ // if a direction is hit that shouldn't be
|
||||
if (pressArray[shit] && !directionList.contains(shit)) ghostNoteMiss(shit);
|
||||
}
|
||||
for (coolNote in possibleNotes)
|
||||
{
|
||||
if (pressArray[coolNote.noteData.getDirection()]) goodNoteHit(coolNote, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// HNGGG I really want to add an option for ghost tapping
|
||||
// L + ratio
|
||||
for (shit in 0...pressArray.length)
|
||||
if (pressArray[shit]) ghostNoteMiss(shit, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStage == null) return;
|
||||
|
||||
for (keyId => isPressed in pressArray)
|
||||
{
|
||||
if (playerStrumline == null) continue;
|
||||
|
||||
var dir:NoteDirection = Strumline.DIRECTIONS[keyId];
|
||||
|
||||
if (isPressed && !playerStrumline.isConfirm(dir)) playerStrumline.playPress(dir);
|
||||
if (!holdArray[keyId]) playerStrumline.playStatic(dir);
|
||||
}
|
||||
}
|
||||
|
||||
function goodNoteHit(note:NoteSprite, input:PreciseInputEvent):Void
|
||||
{
|
||||
var event:NoteScriptEvent = new NoteScriptEvent(ScriptEvent.NOTE_HIT, note, Highscore.tallies.combo + 1, true);
|
||||
|
@ -2104,19 +2019,16 @@ class PlayState extends MusicBeatSubState
|
|||
// Calling event.cancelEvent() skips all the other logic! Neat!
|
||||
if (event.eventCanceled) return;
|
||||
|
||||
if (!note.isHoldNote)
|
||||
{
|
||||
Highscore.tallies.combo++;
|
||||
Highscore.tallies.totalNotesHit++;
|
||||
|
||||
if (Highscore.tallies.combo > Highscore.tallies.maxCombo) Highscore.tallies.maxCombo = Highscore.tallies.combo;
|
||||
|
||||
popUpScore(note, input);
|
||||
}
|
||||
|
||||
playerStrumline.hitNote(note);
|
||||
|
||||
if (note.holdNoteSprite != null)
|
||||
if (note.isHoldNote && note.holdNoteSprite != null)
|
||||
{
|
||||
playerStrumline.playNoteHoldCover(note.holdNoteSprite);
|
||||
}
|
||||
|
|
|
@ -649,6 +649,8 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
|
|||
}
|
||||
boppers = [];
|
||||
|
||||
if (group != null)
|
||||
{
|
||||
for (sprite in this.group)
|
||||
{
|
||||
if (sprite != null)
|
||||
|
@ -659,6 +661,8 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
|
|||
}
|
||||
}
|
||||
group.clear();
|
||||
}
|
||||
|
||||
if (debugIconGroup != null && debugIconGroup.group != null)
|
||||
{
|
||||
debugIconGroup.kill();
|
||||
|
|
23
source/funkin/shaderslmfao/BlendModesShader.hx
Normal file
23
source/funkin/shaderslmfao/BlendModesShader.hx
Normal file
|
@ -0,0 +1,23 @@
|
|||
package funkin.shaderslmfao;
|
||||
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import funkin.Paths;
|
||||
import openfl.utils.Assets;
|
||||
import openfl.display.BitmapData;
|
||||
|
||||
class BlendModesShader extends FlxRuntimeShader
|
||||
{
|
||||
public var camera:BitmapData;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super(Assets.getText(Paths.frag('blendModes')));
|
||||
}
|
||||
|
||||
public function setCamera(camera:BitmapData):Void
|
||||
{
|
||||
this.camera = camera;
|
||||
|
||||
this.setBitmapData('camera', camera);
|
||||
}
|
||||
}
|
25
source/funkin/shaderslmfao/GaussianBlurShader.hx
Normal file
25
source/funkin/shaderslmfao/GaussianBlurShader.hx
Normal file
|
@ -0,0 +1,25 @@
|
|||
package funkin.shaderslmfao;
|
||||
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import funkin.Paths;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
/**
|
||||
* Note... not actually gaussian!
|
||||
*/
|
||||
class GaussianBlurShader extends FlxRuntimeShader
|
||||
{
|
||||
public var amount:Float;
|
||||
|
||||
public function new(amount:Float = 1.0)
|
||||
{
|
||||
super(Assets.getText(Paths.frag("gaussianBlur")));
|
||||
setAmount(amount);
|
||||
}
|
||||
|
||||
public function setAmount(value:Float):Void
|
||||
{
|
||||
this.amount = value;
|
||||
this.setFloat("amount", amount);
|
||||
}
|
||||
}
|
22
source/funkin/shaderslmfao/Grayscale.hx
Normal file
22
source/funkin/shaderslmfao/Grayscale.hx
Normal file
|
@ -0,0 +1,22 @@
|
|||
package funkin.shaderslmfao;
|
||||
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import funkin.Paths;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
class Grayscale extends FlxRuntimeShader
|
||||
{
|
||||
public var amount:Float = 1;
|
||||
|
||||
public function new(amount:Float = 1)
|
||||
{
|
||||
super(Assets.getText(Paths.frag("grayscale")));
|
||||
setAmount(amount);
|
||||
}
|
||||
|
||||
public function setAmount(value:Float):Void
|
||||
{
|
||||
amount = value;
|
||||
this.setFloat("amount", amount);
|
||||
}
|
||||
}
|
44
source/funkin/shaderslmfao/HSVShader.hx
Normal file
44
source/funkin/shaderslmfao/HSVShader.hx
Normal file
|
@ -0,0 +1,44 @@
|
|||
package funkin.shaderslmfao;
|
||||
|
||||
import flixel.addons.display.FlxRuntimeShader;
|
||||
import funkin.Paths;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
class HSVShader extends FlxRuntimeShader
|
||||
{
|
||||
public var hue(default, set):Float;
|
||||
public var saturation(default, set):Float;
|
||||
public var value(default, set):Float;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super(Assets.getText(Paths.frag('hsv')));
|
||||
hue = 1;
|
||||
saturation = 1;
|
||||
value = 1;
|
||||
}
|
||||
|
||||
function set_hue(value:Float):Float
|
||||
{
|
||||
this.setFloat('hue', value);
|
||||
this.hue = value;
|
||||
|
||||
return this.hue;
|
||||
}
|
||||
|
||||
function set_saturation(value:Float):Float
|
||||
{
|
||||
this.setFloat('sat', value);
|
||||
this.saturation = value;
|
||||
|
||||
return this.saturation;
|
||||
}
|
||||
|
||||
function set_value(value:Float):Float
|
||||
{
|
||||
this.setFloat('val', value);
|
||||
this.value = value;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,9 @@ import openfl.geom.Matrix;
|
|||
import openfl.display.Sprite;
|
||||
import openfl.display.Bitmap;
|
||||
|
||||
using Lambda;
|
||||
using StringTools;
|
||||
|
||||
class StickerSubState extends MusicBeatSubState
|
||||
{
|
||||
public var grpStickers:FlxTypedGroup<StickerSprite>;
|
||||
|
@ -26,10 +29,60 @@ class StickerSubState extends MusicBeatSubState
|
|||
|
||||
var nextState:NEXTSTATE = FREEPLAY;
|
||||
|
||||
// what "folders" to potentially load from (as of writing only "keys" exist)
|
||||
var soundSelections:Array<String> = [];
|
||||
// what "folder" was randomly selected
|
||||
var soundSelection:String = "";
|
||||
var sounds:Array<String> = [];
|
||||
|
||||
public function new(?oldStickers:Array<StickerSprite>, ?nextState:NEXTSTATE = FREEPLAY):Void
|
||||
{
|
||||
super();
|
||||
|
||||
// todo still
|
||||
// make sure that ONLY plays mp3/ogg files
|
||||
// if there's no mp3/ogg file, then it regenerates/reloads the random folder
|
||||
|
||||
var assetsInList = openfl.utils.Assets.list();
|
||||
|
||||
var soundFilterFunc = function(a:String) {
|
||||
return a.startsWith('assets/shared/sounds/stickersounds/');
|
||||
};
|
||||
|
||||
soundSelections = assetsInList.filter(soundFilterFunc);
|
||||
soundSelections = soundSelections.map(function(a:String) {
|
||||
return a.replace('assets/shared/sounds/stickersounds/', '').split('/')[0];
|
||||
});
|
||||
|
||||
// cracked cleanup... yuchh...
|
||||
for (i in soundSelections)
|
||||
{
|
||||
while (soundSelections.contains(i))
|
||||
{
|
||||
soundSelections.remove(i);
|
||||
}
|
||||
soundSelections.push(i);
|
||||
}
|
||||
|
||||
trace(soundSelections);
|
||||
|
||||
soundSelection = FlxG.random.getObject(soundSelections);
|
||||
|
||||
var filterFunc = function(a:String) {
|
||||
return a.startsWith('assets/shared/sounds/stickersounds/' + soundSelection + '/');
|
||||
};
|
||||
var assetsInList3 = openfl.utils.Assets.list();
|
||||
sounds = assetsInList3.filter(filterFunc);
|
||||
for (i in 0...sounds.length)
|
||||
{
|
||||
sounds[i] = sounds[i].replace('assets/shared/sounds/', '');
|
||||
sounds[i] = sounds[i].substring(0, sounds[i].lastIndexOf('.'));
|
||||
}
|
||||
|
||||
trace(sounds);
|
||||
|
||||
// trace(assetsInList);
|
||||
|
||||
this.nextState = nextState;
|
||||
|
||||
grpStickers = new FlxTypedGroup<StickerSprite>();
|
||||
|
@ -66,6 +119,8 @@ class StickerSubState extends MusicBeatSubState
|
|||
{
|
||||
new FlxTimer().start(sticker.timing, _ -> {
|
||||
sticker.visible = false;
|
||||
var daSound:String = FlxG.random.getObject(sounds);
|
||||
FlxG.sound.play(Paths.sound(daSound));
|
||||
|
||||
if (ind == grpStickers.members.length - 1)
|
||||
{
|
||||
|
@ -151,7 +206,11 @@ class StickerSubState extends MusicBeatSubState
|
|||
sticker.timing = FlxMath.remapToRange(ind, 0, grpStickers.members.length, 0, 0.9);
|
||||
|
||||
new FlxTimer().start(sticker.timing, _ -> {
|
||||
if (grpStickers == null) return;
|
||||
|
||||
sticker.visible = true;
|
||||
var daSound:String = FlxG.random.getObject(sounds);
|
||||
FlxG.sound.play(Paths.sound(daSound));
|
||||
|
||||
var frameTimer:Int = FlxG.random.int(0, 2);
|
||||
|
||||
|
@ -212,10 +271,10 @@ class StickerSubState extends MusicBeatSubState
|
|||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (FlxG.keys.justPressed.ANY)
|
||||
{
|
||||
regenStickers();
|
||||
}
|
||||
// if (FlxG.keys.justPressed.ANY)
|
||||
// {
|
||||
// regenStickers();
|
||||
// }
|
||||
}
|
||||
|
||||
var switchingState:Bool = false;
|
||||
|
|
|
@ -89,6 +89,7 @@ class ChartEditorDialogHandler
|
|||
linkCreateBasic.onClick = function(_event) {
|
||||
// Hide the welcome dialog
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.stopWelcomeMusic();
|
||||
|
||||
//
|
||||
// Create Song Wizard
|
||||
|
@ -114,6 +115,7 @@ class ChartEditorDialogHandler
|
|||
linkImportChartLegacy.onClick = function(_event) {
|
||||
// Hide the welcome dialog
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.stopWelcomeMusic();
|
||||
|
||||
// Open the "Import Chart" dialog
|
||||
openImportChartWizard(state, 'legacy', false);
|
||||
|
@ -124,6 +126,7 @@ class ChartEditorDialogHandler
|
|||
buttonBrowse.onClick = function(_event) {
|
||||
// Hide the welcome dialog
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.stopWelcomeMusic();
|
||||
|
||||
// Open the "Open Chart" dialog
|
||||
openBrowseWizard(state, false);
|
||||
|
@ -152,6 +155,7 @@ class ChartEditorDialogHandler
|
|||
linkTemplateSong.text = songName;
|
||||
linkTemplateSong.onClick = function(_event) {
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.stopWelcomeMusic();
|
||||
|
||||
// Load song from template
|
||||
ChartEditorImportExportHandler.loadSongAsTemplate(state, targetSongId);
|
||||
|
@ -160,6 +164,7 @@ class ChartEditorDialogHandler
|
|||
splashTemplateContainer.addComponent(linkTemplateSong);
|
||||
}
|
||||
|
||||
state.fadeInWelcomeMusic();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
@ -552,11 +557,9 @@ class ChartEditorDialogHandler
|
|||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false);
|
||||
if (dialog == null) throw 'Could not locate Song Metadata dialog';
|
||||
|
||||
var dialogContainer:Null<Dialog> = dialog.findComponent('metadataDialog', Dialog);
|
||||
if (dialogContainer == null) throw 'Could not locate metadataDialog in Song Metadata dialog';
|
||||
if (targetVariation != Constants.DEFAULT_VARIATION)
|
||||
{
|
||||
dialogContainer.title = 'New Chart - Provide Song Metadata (${targetVariation.toTitleCase()})';
|
||||
dialog.title = 'New Chart - Provide Song Metadata (${targetVariation.toTitleCase()})';
|
||||
}
|
||||
|
||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||
|
|
|
@ -137,10 +137,10 @@ class ChartEditorImportExportHandler
|
|||
|
||||
/**
|
||||
* @param force Whether to force the export without prompting the user for a file location.
|
||||
* @param tmp If true, save to the temporary directory instead of the local `backup` directory.
|
||||
*/
|
||||
public static function exportAllSongData(state:ChartEditorState, force:Bool = false, tmp:Bool = false):Void
|
||||
public static function exportAllSongData(state:ChartEditorState, force:Bool = false):Void
|
||||
{
|
||||
var tmp = false;
|
||||
var zipEntries:Array<haxe.zip.Entry> = [];
|
||||
|
||||
for (variation in state.availableVariations)
|
||||
|
@ -154,9 +154,9 @@ class ChartEditorImportExportHandler
|
|||
if (variationId == '')
|
||||
{
|
||||
var variationMetadata:Null<SongMetadata> = state.songMetadata.get(variation);
|
||||
if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', SerializerUtil.toJSON(variationMetadata)));
|
||||
if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize()));
|
||||
var variationChart:Null<SongChartData> = state.songChartData.get(variation);
|
||||
if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', SerializerUtil.toJSON(variationChart)));
|
||||
if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -727,6 +727,16 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
var downKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.DOWN);
|
||||
|
||||
/**
|
||||
* Variable used to track how long the user has been holding the W keybind.
|
||||
*/
|
||||
var wKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.W);
|
||||
|
||||
/**
|
||||
* Variable used to track how long the user has been holding the S keybind.
|
||||
*/
|
||||
var sKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.S);
|
||||
|
||||
/**
|
||||
* Variable used to track how long the user has been holding the page-up keybind.
|
||||
*/
|
||||
|
@ -788,6 +798,11 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* The chill audio track that plays when you open the Chart Editor.
|
||||
*/
|
||||
public var welcomeMusic:FlxSound = new FlxSound();
|
||||
|
||||
/**
|
||||
* The audio track for the instrumental.
|
||||
* Replaced when switching instrumentals.
|
||||
|
@ -1234,6 +1249,9 @@ class ChartEditorState extends HaxeUIState
|
|||
// Get rid of any music from the previous state.
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
// Play the welcome music.
|
||||
setupWelcomeMusic();
|
||||
|
||||
buildDefaultSongData();
|
||||
|
||||
buildBackground();
|
||||
|
@ -1258,6 +1276,26 @@ class ChartEditorState extends HaxeUIState
|
|||
ChartEditorDialogHandler.openWelcomeDialog(this, false);
|
||||
}
|
||||
|
||||
function setupWelcomeMusic()
|
||||
{
|
||||
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
|
||||
this.welcomeMusic.looped = true;
|
||||
// this.welcomeMusic.play();
|
||||
// fadeInWelcomeMusic();
|
||||
}
|
||||
|
||||
public function fadeInWelcomeMusic():Void
|
||||
{
|
||||
this.welcomeMusic.play();
|
||||
this.welcomeMusic.fadeIn(4, 0, 1.0);
|
||||
}
|
||||
|
||||
public function stopWelcomeMusic():Void
|
||||
{
|
||||
// this.welcomeMusic.fadeOut(4, 0);
|
||||
this.welcomeMusic.pause();
|
||||
}
|
||||
|
||||
function buildDefaultSongData():Void
|
||||
{
|
||||
selectedVariation = Constants.DEFAULT_VARIATION;
|
||||
|
@ -1596,6 +1634,7 @@ class ChartEditorState extends HaxeUIState
|
|||
addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this));
|
||||
addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true));
|
||||
addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true));
|
||||
addUIClickListener('menubarItemExit', _ -> quitChartEditor());
|
||||
|
||||
addUIClickListener('menubarItemUndo', _ -> undoLastCommand());
|
||||
|
||||
|
@ -1661,16 +1700,20 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
addUIClickListener('menubarItemSelectNone', _ -> performCommand(new DeselectAllItemsCommand(currentNoteSelection, currentEventSelection)));
|
||||
|
||||
// TODO: Implement these.
|
||||
// addUIClickListener('menubarItemSelectRegion', _ -> doSomething());
|
||||
// addUIClickListener('menubarItemSelectBeforeCursor', _ -> doSomething());
|
||||
// addUIClickListener('menubarItemSelectAfterCursor', _ -> doSomething());
|
||||
|
||||
addUIClickListener('menubarItemPlaytestFull', _ -> testSongInPlayState(false));
|
||||
addUIClickListener('menubarItemPlaytestMinimal', _ -> testSongInPlayState(true));
|
||||
|
||||
addUIChangeListener('menubarItemInputStyleGroup', function(event:UIEvent) {
|
||||
trace('Change input style: ${event.target}');
|
||||
addUIClickListener('menuBarItemNoteSnapDecrease', _ -> noteSnapQuantIndex--);
|
||||
addUIClickListener('menuBarItemNoteSnapIncrease', _ -> noteSnapQuantIndex++);
|
||||
|
||||
addUIChangeListener('menuBarItemInputStyleNone', function(event:UIEvent) {
|
||||
currentLiveInputStyle = None;
|
||||
});
|
||||
addUIChangeListener('menuBarItemInputStyleNumberKeys', function(event:UIEvent) {
|
||||
currentLiveInputStyle = NumberKeys;
|
||||
});
|
||||
addUIChangeListener('menuBarItemInputStyleWASD', function(event:UIEvent) {
|
||||
currentLiveInputStyle = WASD;
|
||||
});
|
||||
|
||||
addUIClickListener('menubarItemAbout', _ -> ChartEditorDialogHandler.openAboutDialog(this));
|
||||
|
@ -1773,6 +1816,8 @@ class ChartEditorState extends HaxeUIState
|
|||
add(redoKeyHandler);
|
||||
add(upKeyHandler);
|
||||
add(downKeyHandler);
|
||||
add(wKeyHandler);
|
||||
add(sKeyHandler);
|
||||
add(pageUpKeyHandler);
|
||||
add(pageDownKeyHandler);
|
||||
}
|
||||
|
@ -1799,7 +1844,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// Auto-save to local storage.
|
||||
#else
|
||||
// Auto-save to temp file.
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true, true);
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true);
|
||||
#end
|
||||
}
|
||||
|
||||
|
@ -1821,6 +1866,13 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
// Override F4 behavior to include the autosave.
|
||||
if (FlxG.keys.justPressed.F4)
|
||||
{
|
||||
quitChartEditor();
|
||||
return;
|
||||
}
|
||||
|
||||
// dispatchEvent gets called here.
|
||||
super.update(elapsed);
|
||||
|
||||
|
@ -1900,20 +1952,33 @@ class ChartEditorState extends HaxeUIState
|
|||
// Mouse Wheel = Scroll
|
||||
if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
scrollAmount = -10 * FlxG.mouse.wheel;
|
||||
scrollAmount = -50 * FlxG.mouse.wheel;
|
||||
shouldPause = true;
|
||||
}
|
||||
|
||||
// Up Arrow = Scroll Up
|
||||
if (upKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD)
|
||||
if (upKeyHandler.activated && currentLiveInputStyle == None)
|
||||
{
|
||||
scrollAmount = -GRID_SIZE * 0.25 * 5.0;
|
||||
scrollAmount = -GRID_SIZE * 0.25 * 25.0;
|
||||
shouldPause = true;
|
||||
}
|
||||
// Down Arrow = Scroll Down
|
||||
if (downKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD)
|
||||
if (downKeyHandler.activated && currentLiveInputStyle == None)
|
||||
{
|
||||
scrollAmount = GRID_SIZE * 0.25 * 5.0;
|
||||
scrollAmount = GRID_SIZE * 0.25 * 25.0;
|
||||
shouldPause = true;
|
||||
}
|
||||
|
||||
// W = Scroll Up (doesn't work with Ctrl+Scroll)
|
||||
if (wKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
scrollAmount = -GRID_SIZE * 0.25 * 25.0;
|
||||
shouldPause = true;
|
||||
}
|
||||
// S = Scroll Down (doesn't work with Ctrl+Scroll)
|
||||
if (sKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
scrollAmount = GRID_SIZE * 0.25 * 25.0;
|
||||
shouldPause = true;
|
||||
}
|
||||
|
||||
|
@ -1978,7 +2043,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// SHIFT + Scroll = Scroll Fast
|
||||
if (FlxG.keys.pressed.SHIFT)
|
||||
{
|
||||
scrollAmount *= 5;
|
||||
scrollAmount *= 2;
|
||||
}
|
||||
// CONTROL + Scroll = Scroll Precise
|
||||
if (FlxG.keys.pressed.CONTROL)
|
||||
|
@ -2048,6 +2113,8 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
|
||||
function handleSnap():Void
|
||||
{
|
||||
if (currentLiveInputStyle == None)
|
||||
{
|
||||
if (FlxG.keys.justPressed.LEFT && !FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
|
@ -2059,6 +2126,7 @@ class ChartEditorState extends HaxeUIState
|
|||
noteSnapQuantIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle display of the mouse cursor.
|
||||
|
@ -3044,10 +3112,16 @@ class ChartEditorState extends HaxeUIState
|
|||
// CTRL + Q = Quit to Menu
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q)
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
quitChartEditor();
|
||||
}
|
||||
}
|
||||
|
||||
function quitChartEditor():Void
|
||||
{
|
||||
autoSave();
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle keybinds for edit menu items.
|
||||
*/
|
||||
|
@ -3147,6 +3221,8 @@ class ChartEditorState extends HaxeUIState
|
|||
* Handle keybinds for View menu items.
|
||||
*/
|
||||
function handleViewKeybinds():Void
|
||||
{
|
||||
if (currentLiveInputStyle == None)
|
||||
{
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT)
|
||||
{
|
||||
|
@ -3156,6 +3232,8 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
incrementDifficulty(1);
|
||||
}
|
||||
// Would bind Ctrl+A and Ctrl+D here, but they are already bound to Select All and Select None.
|
||||
}
|
||||
}
|
||||
|
||||
function incrementDifficulty(change:Int):Void
|
||||
|
@ -3261,7 +3339,7 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
function handleTestKeybinds():Void
|
||||
{
|
||||
if (!isHaxeUIDialogOpen && FlxG.keys.justPressed.ENTER)
|
||||
if (!isHaxeUIDialogOpen && !isCursorOverHaxeUI && FlxG.keys.justPressed.ENTER)
|
||||
{
|
||||
var minimal = FlxG.keys.pressed.SHIFT;
|
||||
testSongInPlayState(minimal);
|
||||
|
@ -3853,25 +3931,26 @@ class ChartEditorState extends HaxeUIState
|
|||
switch (currentLiveInputStyle)
|
||||
{
|
||||
case LiveInputStyle.WASD:
|
||||
if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(0);
|
||||
if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(1);
|
||||
if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(2);
|
||||
if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(3);
|
||||
if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(4);
|
||||
if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(5);
|
||||
if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(6);
|
||||
if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(7);
|
||||
|
||||
if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(4);
|
||||
if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(5);
|
||||
if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(6);
|
||||
if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(7);
|
||||
if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(0);
|
||||
if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(1);
|
||||
if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(2);
|
||||
if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(3);
|
||||
case LiveInputStyle.NumberKeys:
|
||||
if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(0);
|
||||
if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(1);
|
||||
if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(2);
|
||||
if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(3);
|
||||
// Flipped because Dad is on the left but represents data 0-3.
|
||||
if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(4);
|
||||
if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(5);
|
||||
if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(6);
|
||||
if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(7);
|
||||
|
||||
if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(4);
|
||||
if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(5);
|
||||
if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(6);
|
||||
if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(7);
|
||||
if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(0);
|
||||
if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(1);
|
||||
if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(2);
|
||||
if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(3);
|
||||
case LiveInputStyle.None:
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -3880,13 +3959,25 @@ class ChartEditorState extends HaxeUIState
|
|||
function placeNoteAtPlayhead(column:Int):Void
|
||||
{
|
||||
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
|
||||
var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / (16 / noteSnapQuant);
|
||||
var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio;
|
||||
var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep));
|
||||
var playheadPosMs:Float = playheadPosStep * Conductor.stepLengthMs * (16 / noteSnapQuant);
|
||||
var playheadPosSnappedMs:Float = playheadPosStep * Conductor.stepLengthMs * noteSnapRatio;
|
||||
|
||||
var newNoteData:SongNoteData = new SongNoteData(playheadPosMs, column, 0, selectedNoteKind);
|
||||
// Look for notes within 1 step of the playhead.
|
||||
var notesAtPos:Array<SongNoteData> = SongDataUtils.getNotesInTimeRange(currentSongChartNoteData, playheadPosSnappedMs,
|
||||
playheadPosSnappedMs + Conductor.stepLengthMs * noteSnapRatio);
|
||||
notesAtPos = SongDataUtils.getNotesWithData(notesAtPos, [column]);
|
||||
|
||||
if (notesAtPos.length == 0)
|
||||
{
|
||||
var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, selectedNoteKind);
|
||||
performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL));
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('Already a note there.');
|
||||
}
|
||||
}
|
||||
|
||||
function set_scrollPositionInPixels(value:Float):Float
|
||||
{
|
||||
|
@ -3944,6 +4035,8 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
public function testSongInPlayState(minimal:Bool = false):Void
|
||||
{
|
||||
autoSave();
|
||||
|
||||
var startTimestamp:Float = 0;
|
||||
if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs;
|
||||
|
||||
|
|
74
source/funkin/ui/title/FlxSpriteOverlay.hx
Normal file
74
source/funkin/ui/title/FlxSpriteOverlay.hx
Normal file
|
@ -0,0 +1,74 @@
|
|||
package funkin.ui.title;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import funkin.shaderslmfao.BlendModesShader;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
||||
|
||||
class FlxSpriteOverlay extends FlxSprite
|
||||
{
|
||||
var blendShader:BlendModesShader;
|
||||
var dipshitBitmap:BitmapData;
|
||||
var temp:FlxSprite;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
temp = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, 0xFF000000);
|
||||
blendShader = new BlendModesShader();
|
||||
dipshitBitmap = new BitmapData(2180, 1720, true, 0xFFCC00CC);
|
||||
}
|
||||
|
||||
override function drawComplex(camera:FlxCamera):Void
|
||||
{
|
||||
_frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY());
|
||||
_matrix.translate(-origin.x, -origin.y);
|
||||
_matrix.scale(scale.x, scale.y);
|
||||
if (bakedRotationAngle <= 0)
|
||||
{
|
||||
updateTrig();
|
||||
if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle);
|
||||
}
|
||||
getScreenPosition(_point, camera).subtractPoint(offset);
|
||||
_point.add(origin.x, origin.y);
|
||||
_matrix.translate(_point.x, _point.y);
|
||||
if (isPixelPerfectRender(camera))
|
||||
{
|
||||
_matrix.tx = Math.floor(_matrix.tx);
|
||||
_matrix.ty = Math.floor(_matrix.ty);
|
||||
}
|
||||
|
||||
var sprRect = getScreenBounds();
|
||||
|
||||
// dipshitBitmap.draw(camera.canvas, camera.canvas.transform.matrix);
|
||||
// blendShader.setCamera(dipshitBitmap);
|
||||
|
||||
// FlxG.bitmapLog.add(dipshitBitmap);
|
||||
|
||||
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader);
|
||||
}
|
||||
|
||||
function copyToFlash(rect):openfl.geom.Rectangle
|
||||
{
|
||||
var flashRect = new openfl.geom.Rectangle();
|
||||
flashRect.x = rect.x;
|
||||
flashRect.y = rect.y;
|
||||
flashRect.width = rect.width;
|
||||
flashRect.height = rect.height;
|
||||
return flashRect;
|
||||
}
|
||||
|
||||
override public function isSimpleRender(?camera:FlxCamera):Bool
|
||||
{
|
||||
if (FlxG.renderBlit)
|
||||
{
|
||||
return super.isSimpleRender(camera);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import openfl.events.MouseEvent;
|
|||
import openfl.events.NetStatusEvent;
|
||||
import openfl.media.Video;
|
||||
import openfl.net.NetStream;
|
||||
import openfl.display.BlendMode;
|
||||
|
||||
#if desktop
|
||||
#end
|
||||
|
@ -101,7 +102,7 @@ class TitleState extends MusicBeatState
|
|||
var logoBl:FlxSprite;
|
||||
var outlineShaderShit:TitleOutline;
|
||||
|
||||
var gfDance:FlxSprite;
|
||||
var gfDance:FlxSpriteOverlay;
|
||||
var danceLeft:Bool = false;
|
||||
var titleText:FlxSprite;
|
||||
var maskShader = new LeftMaskShader();
|
||||
|
@ -124,13 +125,11 @@ class TitleState extends MusicBeatState
|
|||
|
||||
outlineShaderShit = new TitleOutline();
|
||||
|
||||
gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07);
|
||||
gfDance = new FlxSpriteOverlay(FlxG.width * 0.4, FlxG.height * 0.07);
|
||||
gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle');
|
||||
gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
|
||||
add(gfDance);
|
||||
|
||||
// maskShader.swagSprX = gfDance.x;
|
||||
// maskShader.swagMaskX = gfDance.x + 200;
|
||||
// maskShader.frameUV = gfDance.frame.uv;
|
||||
|
@ -142,6 +141,8 @@ class TitleState extends MusicBeatState
|
|||
|
||||
add(logoBl);
|
||||
|
||||
add(gfDance);
|
||||
|
||||
titleText = new FlxSprite(100, FlxG.height * 0.8);
|
||||
titleText.frames = Paths.getSparrowAtlas('titleEnter');
|
||||
titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24);
|
||||
|
@ -245,6 +246,8 @@ class TitleState extends MusicBeatState
|
|||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
FlxG.bitmapLog.add(FlxG.camera.buffer);
|
||||
|
||||
#if HAS_PITCH
|
||||
if (FlxG.keys.pressed.UP) FlxG.sound.music.pitch += 0.5 * elapsed;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class Constants
|
|||
*/
|
||||
public static final VERSION_SUFFIX:String = ' PROTOTYPE';
|
||||
|
||||
#if debug
|
||||
#if (debug || FORCE_DEBUG_VERSION)
|
||||
static function get_VERSION():String
|
||||
{
|
||||
return 'v${Application.current.meta.get('version')} (${GIT_BRANCH} : ${GIT_HASH})' + VERSION_SUFFIX;
|
||||
|
@ -71,7 +71,7 @@ class Constants
|
|||
*/
|
||||
// ==============================
|
||||
|
||||
#if debug
|
||||
#if (debug || FORCE_DEBUG_VERSION)
|
||||
/**
|
||||
* The current Git branch.
|
||||
*/
|
||||
|
@ -324,10 +324,15 @@ class Constants
|
|||
public static final HEALTH_MINE_PENALTY:Float = 15.0 / 100.0 * HEALTH_MAX; // 15.0%
|
||||
|
||||
/**
|
||||
* If true, the player will not receive the ghost miss penalty if there are no notes within the hit window.
|
||||
* This is the thing people have been begging for forever lolol.
|
||||
* SCORE VALUES
|
||||
*/
|
||||
public static final GHOST_TAPPING:Bool = false;
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* The amount of score the player gains for every send they hold a hold note.
|
||||
* A fraction of this value is granted every frame.
|
||||
*/
|
||||
public static final SCORE_HOLD_BONUS_PER_SECOND:Float = 250.0;
|
||||
|
||||
/**
|
||||
* FILE EXTENSIONS
|
||||
|
@ -367,6 +372,12 @@ class Constants
|
|||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* If true, the player will not receive the ghost miss penalty if there are no notes within the hit window.
|
||||
* This is the thing people have been begging for forever lolol.
|
||||
*/
|
||||
public static final GHOST_TAPPING:Bool = false;
|
||||
|
||||
/**
|
||||
* The separator between an asset library and the asset path.
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package funkin.util.macro;
|
||||
|
||||
#if debug
|
||||
#if (debug || FORCE_DEBUG_VERSION)
|
||||
class GitCommit
|
||||
{
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue