diff --git a/Project.xml b/Project.xml
index de9ba048..53928e72 100644
--- a/Project.xml
+++ b/Project.xml
@@ -76,7 +76,7 @@
-
+
diff --git a/art/teaser discord.png b/art/teaser discord.png
new file mode 100644
index 00000000..cf57c69c
Binary files /dev/null and b/art/teaser discord.png differ
diff --git a/art/teaser.png b/art/teaser.png
new file mode 100644
index 00000000..0b3be839
Binary files /dev/null and b/art/teaser.png differ
diff --git a/assets/data/characters/tankman.xml b/assets/data/characters/tankman.xml
index e31636b4..3dd2f589 100644
--- a/assets/data/characters/tankman.xml
+++ b/assets/data/characters/tankman.xml
@@ -1,11 +1,13 @@
-
+
+
+
-
+
-
+
diff --git a/assets/data/freeplaySonglist.json b/assets/data/freeplaySonglist.json
new file mode 100644
index 00000000..cf387481
--- /dev/null
+++ b/assets/data/freeplaySonglist.json
@@ -0,0 +1,129 @@
+{
+ "addOGSongs": false,
+ "songs": [
+ {
+ "name": "Tutorial",
+ "icon": "gf",
+ "color": "#9271FD"
+ },
+
+
+ {
+ "name": "Bopeebo",
+ "icon": "dad",
+ "color": "#9271FD"
+ },
+ {
+ "name": "Fresh",
+ "icon": "dad",
+ "color": "#9271FD"
+ },
+ {
+ "name": "Dadbattle",
+ "icon": "dad",
+ "color": "#9271FD"
+ },
+
+
+ {
+ "name": "Spookeez",
+ "icon": "spooky",
+ "color": "#223344"
+ },
+ {
+ "name": "South",
+ "icon": "spooky",
+ "color": "#223344"
+ },
+ {
+ "name": "Monster",
+ "icon": "monster",
+ "color": "#223344"
+ },
+
+
+ {
+ "name": "Pico",
+ "icon": "pico",
+ "color": "#941653"
+ },
+ {
+ "name": "Philly Nice",
+ "icon": "pico",
+ "color": "#941653"
+ },
+ {
+ "name": "Blammed",
+ "icon": "pico",
+ "color": "#941653"
+ },
+
+
+ {
+ "name": "Satin Panties",
+ "icon": "mom",
+ "color": "#FC96D7"
+ },
+ {
+ "name": "High",
+ "icon": "mom",
+ "color": "#FC96D7"
+ },
+ {
+ "name": "MILF",
+ "icon": "mom",
+ "color": "#FC96D7"
+ },
+
+
+ {
+ "name": "Cocoa",
+ "icon": "parents-christmas",
+ "color": "#A0D1FF"
+ },
+ {
+ "name": "Eggnog",
+ "icon": "parents-christmas",
+ "color": "#A0D1FF"
+ },
+ {
+ "name": "Winter Horrorland",
+ "icon": "monster",
+ "color": "#A0D1FF"
+ },
+
+
+ {
+ "name": "Senpai",
+ "icon": "senpai",
+ "color": "#FF78BF"
+ },
+ {
+ "name": "Roses",
+ "icon": "senpai",
+ "color": "#FF78BF"
+ },
+ {
+ "name": "Thorns",
+ "icon": "spirit",
+ "color": "#FF78BF"
+ },
+
+
+ {
+ "name": "Ugh",
+ "icon": "tankman",
+ "color": "#F6B604"
+ },
+ {
+ "name": "Guns",
+ "icon": "tankman",
+ "color": "#F6B604"
+ },
+ {
+ "name": "Stress",
+ "icon": "tankman",
+ "color": "#F6B604"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/data/freeplaySonglist.txt b/assets/data/freeplaySonglist.txt
deleted file mode 100644
index 1b5bac2c..00000000
--- a/assets/data/freeplaySonglist.txt
+++ /dev/null
@@ -1 +0,0 @@
-Tutorial
\ No newline at end of file
diff --git a/assets/data/stages/mall-evil.xml b/assets/data/stages/mall-evil.xml
index 8d72a943..1085d4bf 100644
--- a/assets/data/stages/mall-evil.xml
+++ b/assets/data/stages/mall-evil.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/stages/tank.hx b/assets/data/stages/tank.hx
new file mode 100644
index 00000000..8de3c2ca
--- /dev/null
+++ b/assets/data/stages/tank.hx
@@ -0,0 +1,9 @@
+var tankAngle:Float = FlxG.random.int(-90, 45);
+var tankSpeed:Float = FlxG.random.float(5, 7);
+
+function update(elapsed:Float) {
+ tankAngle += elapsed * tankSpeed;
+ tankRolling.angle = tankAngle - 90 + 15;
+ tankRolling.x = 400 + (1500 * Math.cos(Math.PI / 180 * (1 * tankAngle + 180)));
+ tankRolling.y = 1300 + (1100 * Math.sin(Math.PI / 180 * (1 * tankAngle + 180)));
+}
\ No newline at end of file
diff --git a/assets/data/stages/tank.xml b/assets/data/stages/tank.xml
new file mode 100644
index 00000000..8ca44fb1
--- /dev/null
+++ b/assets/data/stages/tank.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/stages/tank/tankRolling.png b/assets/images/stages/tank/tankRolling.png
index 706d20d9..24c7d69f 100644
Binary files a/assets/images/stages/tank/tankRolling.png and b/assets/images/stages/tank/tankRolling.png differ
diff --git a/assets/images/stages/tank/tankRolling.xml b/assets/images/stages/tank/tankRolling.xml
index 6993b1da..f3125783 100644
--- a/assets/images/stages/tank/tankRolling.xml
+++ b/assets/images/stages/tank/tankRolling.xml
@@ -2,5 +2,7 @@
-
+
+
+
diff --git a/buildnumber.txt b/buildnumber.txt
index 34578cc4..680cc9c3 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-239
\ No newline at end of file
+263
\ No newline at end of file
diff --git a/source/Alphabet.hx b/source/Alphabet.hx
index 77ac5dc8..43f46b17 100644
--- a/source/Alphabet.hx
+++ b/source/Alphabet.hx
@@ -224,8 +224,8 @@ class Alphabet extends FlxSpriteGroup
{
var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
- y = FlxMath.lerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
- x = FlxMath.lerp(x, (targetY * 20) + 90, 0.16);
+ y = CoolUtil.fpsLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
+ x = CoolUtil.fpsLerp(x, (targetY * 20) + 90, 0.16);
}
super.update(elapsed);
diff --git a/source/Discord.hx b/source/Discord.hx
index dbd80057..b8d68606 100644
--- a/source/Discord.hx
+++ b/source/Discord.hx
@@ -11,7 +11,8 @@ class DiscordClient
{
trace("Discord Client starting...");
DiscordRpc.start({
- clientID: "814588678700924999",
+ // clientID: "814588678700924999",
+ clientID: "1027994136193810442",
onReady: onReady,
onError: onError,
onDisconnected: onDisconnected
diff --git a/source/funkin/data/FreeplaySonglist.hx b/source/funkin/data/FreeplaySonglist.hx
new file mode 100644
index 00000000..33471f5f
--- /dev/null
+++ b/source/funkin/data/FreeplaySonglist.hx
@@ -0,0 +1,74 @@
+package funkin.data;
+
+import flixel.util.FlxColor;
+import openfl.utils.Assets;
+import funkin.menus.FreeplayState;
+import haxe.Json;
+
+class FreeplaySonglist {
+ public var addOGSongs:Bool = false;
+ public var songs:Array = [];
+
+ public function new() {
+
+ }
+
+ private function _addJSONSongs(songs:Array) {
+ if (songs != null && songs is Array) {
+ for(e in songs) {
+ if (e is Dynamic) {
+ if (e.name == null) continue;
+ if (e.icon == null) e.icon = "bf";
+ if (e.color == null) e.color = FreeplayState.defaultColor;
+ this.songs.push(new SongMetadata(e.name,
+ CoolUtil.getDefault(e.icon, "bf"),
+ CoolUtil.getDefault(CoolUtil.getColorFromDynamic(e.color), FreeplayState.defaultColor)));
+ }
+ }
+ }
+ }
+
+ public static function get() {
+ var songList = new FreeplaySonglist();
+
+ var jsonPath = Paths.json("freeplaySonglist");
+ var baseJsonPath = Paths.getPath('data/freeplaySonglist.json', TEXT, null, true);
+
+ try {
+ var json:FreeplayJSON = Json.parse(Assets.getText(jsonPath));
+ var addOGSongs = CoolUtil.getDefault(json.addOGSongs, true);
+ songList._addJSONSongs(json.songs);
+ if (addOGSongs && (jsonPath != baseJsonPath)) {
+ var json:FreeplayJSON = Json.parse(Assets.getText(baseJsonPath));
+ songList._addJSONSongs(json.songs);
+ }
+ }
+
+ return songList;
+ }
+}
+
+typedef FreeplayJSON = {
+ public var addOGSongs:Null;
+ public var songs:Array;
+}
+
+typedef FreeplaySong = {
+ public var name:String;
+ public var icon:String;
+ public var color:Dynamic;
+}
+
+class SongMetadata
+{
+ public var songName:String = "";
+ public var color:FlxColor = FreeplayState.defaultColor;
+ public var songCharacter:String = "";
+
+ public function new(song:String, songCharacter:String, color:FlxColor)
+ {
+ this.songName = song;
+ this.color = color;
+ this.songCharacter = songCharacter;
+ }
+}
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index bcac0ba4..26447162 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -783,8 +783,8 @@ class PlayState extends MusicBeatState
// FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight);
// TODO: FPS-compatible lerping
- iconP1.scale.set(FlxMath.lerp(iconP1.scale.x, 1, 0.33), FlxMath.lerp(iconP1.scale.y, 1, 0.33));
- iconP2.scale.set(FlxMath.lerp(iconP2.scale.x, 1, 0.33), FlxMath.lerp(iconP2.scale.y, 1, 0.33));
+ iconP1.scale.set(lerp(iconP1.scale.x, 1, 0.33), lerp(iconP1.scale.y, 1, 0.33));
+ iconP2.scale.set(lerp(iconP2.scale.x, 1, 0.33), lerp(iconP2.scale.y, 1, 0.33));
iconP1.updateHitbox();
iconP2.updateHitbox();
@@ -894,8 +894,8 @@ class PlayState extends MusicBeatState
if (camZooming)
{
- FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95);
- camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95);
+ FlxG.camera.zoom = lerp(defaultCamZoom, FlxG.camera.zoom, 0.95);
+ camHUD.zoom = lerp(1, camHUD.zoom, 0.95);
}
FlxG.watch.addQuick("beatShit", curBeat);
diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx
index 6306ccf4..484995c5 100644
--- a/source/funkin/game/Stage.hx
+++ b/source/funkin/game/Stage.hx
@@ -67,6 +67,15 @@ class Stage extends FlxBasic implements IBeatReceiver {
if (node.has.scroll) {
var scroll:Null = Std.parseFloat(node.att.scroll);
if (scroll != null) spr.scrollFactor.set(scroll, scroll);
+ } else {
+ if (node.has.scrollx) {
+ var scroll:Null = Std.parseFloat(node.att.scrollx);
+ if (scroll != null) spr.scrollFactor.x = scroll;
+ }
+ if (node.has.scrolly) {
+ var scroll:Null = Std.parseFloat(node.att.scrolly);
+ if (scroll != null) spr.scrollFactor.y = scroll;
+ }
}
if (node.has.scale) {
var scale:Null = Std.parseFloat(node.att.scale);
diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx
index 8a14070b..7dedd698 100644
--- a/source/funkin/menus/FreeplayState.hx
+++ b/source/funkin/menus/FreeplayState.hx
@@ -6,6 +6,7 @@ import Discord.DiscordClient;
import flash.text.TextField;
import flixel.FlxG;
import flixel.FlxSprite;
+import flixel.FlxState;
import flixel.addons.display.FlxGridOverlay;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
@@ -13,11 +14,22 @@ import flixel.text.FlxText;
import flixel.util.FlxColor;
import lime.utils.Assets;
import funkin.system.Song;
+import funkin.data.FreeplaySonglist;
using StringTools;
class FreeplayState extends MusicBeatState
{
+ /**
+ * Default background colors for songs without bg color
+ */
+ public inline static var defaultColor:FlxColor = 0xFF9271FD;
+
+ /**
+ * How much time a song stays selected until it autoplays.
+ */
+ public inline static var timeUntilAutoplay:Float = 1;
+
var songs:Array = [];
var selector:FlxText;
@@ -29,6 +41,11 @@ class FreeplayState extends MusicBeatState
var lerpScore:Int = 0;
var intendedScore:Int = 0;
+ var songList:FreeplaySonglist;
+ var scoreBG:FlxSprite;
+
+ var bg:FlxSprite;
+
private var grpSongs:FlxTypedGroup;
private var curPlaying:Bool = false;
@@ -36,20 +53,10 @@ class FreeplayState extends MusicBeatState
override function create()
{
- var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
+ var initSonglist = CoolUtil.coolTextFile(Paths.json('freeplaySonglist'));
- for (i in 0...initSonglist.length)
- {
- songs.push(new SongMetadata(initSonglist[i], 1, 'gf'));
- }
-
- /*
- if (FlxG.sound.music != null)
- {
- if (!FlxG.sound.music.playing)
- FlxG.sound.playMusic(Paths.music('freakyMenu'));
- }
- */
+ songList = FreeplaySonglist.get();
+ songs = songList.songs;
#if desktop
// Updating Discord Rich Presence
@@ -62,19 +69,11 @@ class FreeplayState extends MusicBeatState
isDebug = true;
#end
- addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']);
- addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky']);
- addWeek(['Pico', 'Philly Nice', 'Blammed'], 3, ['pico']);
- addWeek(['Satin Panties', 'High', 'Milf'], 4, ['mom']);
- addWeek(['Cocoa', 'Eggnog', 'Winter Horrorland'], 5, ['parents-christmas', 'parents-christmas', 'monster']);
- addWeek(['Senpai', 'Roses', 'Thorns'], 6, ['senpai', 'senpai', 'spirit']);
- addWeek(['Ugh', 'Guns', 'Stress'], 7, ['tankman']);
-
- // LOAD MUSIC
-
// LOAD CHARACTERS
- var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuBGBlue'));
+ bg = new FlxSprite(0, 0, Paths.image('menuDesat'));
+ if (songs.length > 0)
+ bg.color = songs[0].color;
add(bg);
grpSongs = new FlxTypedGroup();
@@ -104,7 +103,7 @@ class FreeplayState extends MusicBeatState
scoreText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT);
// scoreText.alignment = RIGHT;
- var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 66, 0xFF000000);
+ scoreBG = new FlxSprite(scoreText.x - 6, 0).makeGraphic(1, 1, 0xFF000000);
scoreBG.alpha = 0.6;
add(scoreBG);
@@ -146,26 +145,13 @@ class FreeplayState extends MusicBeatState
super.create();
}
+
- public function addSong(songName:String, weekNum:Int, songCharacter:String)
- {
- songs.push(new SongMetadata(songName, weekNum, songCharacter));
- }
-
- public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array)
- {
- if (songCharacters == null)
- songCharacters = ['bf'];
-
- var num:Int = 0;
- for (song in songs)
- {
- addSong(song, weekNum, songCharacters[num]);
-
- if (songCharacters.length != 1)
- num++;
- }
- }
+ #if PRELOAD_ALL
+ var autoplayElapsed:Float = 0;
+ var songInstPlaying:Bool = false;
+ var curPlayingInst:String = null;
+ #end
override function update(elapsed:Float)
{
@@ -176,12 +162,32 @@ class FreeplayState extends MusicBeatState
FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
}
- lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.4));
+ lerpScore = Math.floor(lerp(lerpScore, intendedScore, 0.4));
if (Math.abs(lerpScore - intendedScore) <= 10)
lerpScore = intendedScore;
scoreText.text = "PERSONAL BEST:" + lerpScore;
+ scoreText.x = FlxG.width - scoreText.width - 4;
+ scoreBG.scale.set(scoreText.width + 8, 66);
+ scoreBG.updateHitbox();
+ scoreBG.x = FlxG.width - scoreBG.width;
+ diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2));
+
+ bg.color = CoolUtil.lerpColor(bg.color, songs[curSelected].color, 0.0625);
+
+
+ // putting it before so that its actually smooth
+ updateOptionsAlpha();
+
+ #if PRELOAD_ALL
+ autoplayElapsed += elapsed;
+ if (!songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) {
+ if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].songName)))
+ FlxG.sound.playMusic(curPlayingInst, 0);
+ songInstPlaying = true;
+ }
+ #end
var upP = controls.UP_P;
var downP = controls.DOWN_P;
@@ -212,7 +218,7 @@ class FreeplayState extends MusicBeatState
PlayState.SONG = Song.loadFromJson(songs[curSelected].songName, CoolUtil.difficultyString());
PlayState.isStoryMode = false;
- PlayState.storyWeek = songs[curSelected].week;
+ // PlayState.storyWeek = songs[curSelected].week;
trace('CUR WEEK' + PlayState.storyWeek);
LoadingState.loadAndSwitchState(new PlayState());
}
@@ -234,11 +240,11 @@ class FreeplayState extends MusicBeatState
switch (curDifficulty)
{
case 0:
- diffText.text = "EASY";
+ diffText.text = "< EASY >";
case 1:
- diffText.text = 'NORMAL';
+ diffText.text = '< NORMAL >';
case 2:
- diffText.text = "HARD";
+ diffText.text = "< HARD >";
}
}
@@ -259,16 +265,19 @@ class FreeplayState extends MusicBeatState
intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty);
// lerpScore = 0;
#end
-
+
#if PRELOAD_ALL
- FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
+ autoplayElapsed = 0;
+ songInstPlaying = false;
#end
+ }
+ function updateOptionsAlpha() {
var bullShit:Int = 0;
for (i in 0...iconArray.length)
{
- iconArray[i].alpha = 0.6;
+ iconArray[i].alpha = lerp(iconArray[i].alpha, songInstPlaying ? 0.45 : 0.6, 0.25);
}
iconArray[curSelected].alpha = 1;
@@ -278,7 +287,7 @@ class FreeplayState extends MusicBeatState
item.targetY = bullShit - curSelected;
bullShit++;
- item.alpha = 0.6;
+ item.alpha = lerp(item.alpha, songInstPlaying ? 0.45 : 0.6, 0.25);
// item.setGraphicSize(Std.int(item.width * 0.8));
if (item.targetY == 0)
@@ -288,18 +297,4 @@ class FreeplayState extends MusicBeatState
}
}
}
-}
-
-class SongMetadata
-{
- public var songName:String = "";
- public var week:Int = 0;
- public var songCharacter:String = "";
-
- public function new(song:String, week:Int, songCharacter:String)
- {
- this.songName = song;
- this.week = week;
- this.songCharacter = songCharacter;
- }
-}
+}
\ No newline at end of file
diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx
index 6c9b42e8..02c45e41 100644
--- a/source/funkin/menus/MainMenuState.hx
+++ b/source/funkin/menus/MainMenuState.hx
@@ -6,6 +6,7 @@ import Discord.DiscordClient;
import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
+import flixel.FlxState;
import flixel.addons.transition.FlxTransitionableState;
import flixel.effects.FlxFlicker;
import flixel.graphics.frames.FlxAtlasFrames;
@@ -156,39 +157,27 @@ class MainMenuState extends MusicBeatState
menuItems.forEach(function(spr:FlxSprite)
{
- if (curSelected != spr.ID)
+ if (spr.ID != curSelected) return;
+ FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker)
{
- FlxTween.tween(spr, {alpha: 0}, 0.4, {
- ease: FlxEase.quadOut,
- onComplete: function(twn:FlxTween)
- {
- spr.kill();
- }
- });
- }
- else
- {
- FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker)
+ var daChoice:String = optionShit[curSelected];
+
+ switch (daChoice)
{
- var daChoice:String = optionShit[curSelected];
+ case 'story mode':
+ FlxG.switchState(new StoryMenuState());
+ trace("Story Menu Selected");
+ case 'freeplay':
+ FlxG.switchState(new FreeplayState());
- switch (daChoice)
- {
- case 'story mode':
- FlxG.switchState(new StoryMenuState());
- trace("Story Menu Selected");
- case 'freeplay':
- FlxG.switchState(new FreeplayState());
+ trace("Freeplay Menu Selected");
- trace("Freeplay Menu Selected");
-
- case 'options':
- FlxTransitionableState.skipNextTransIn = true;
- FlxTransitionableState.skipNextTransOut = true;
- // FlxG.switchState(new OptionsMenu());
- }
- });
- }
+ case 'options':
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
+ // FlxG.switchState(new OptionsMenu());
+ }
+ });
});
}
}
@@ -202,6 +191,15 @@ class MainMenuState extends MusicBeatState
});
}
+
+ public override function switchTo(nextState:FlxState):Bool {
+ try {
+ menuItems.forEach(function(spr:FlxSprite) {
+ FlxTween.tween(spr, {alpha: 0}, 0.5, {ease: FlxEase.quintOut});
+ });
+ }
+ return super.switchTo(nextState);
+ }
function changeItem(huh:Int = 0)
{
curSelected += huh;
diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx
index b6893976..938195e3 100644
--- a/source/funkin/menus/StoryMenuState.hx
+++ b/source/funkin/menus/StoryMenuState.hx
@@ -226,7 +226,7 @@ class StoryMenuState extends MusicBeatState
override function update(elapsed:Float)
{
// scoreText.setFormat('VCR OSD Mono', 32);
- lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.5));
+ lerpScore = Math.floor(lerp(lerpScore, intendedScore, 0.5));
scoreText.text = "WEEK SCORE:" + lerpScore;
diff --git a/source/funkin/system/CoolUtil.hx b/source/funkin/system/CoolUtil.hx
index d920dfb6..8764c9a7 100644
--- a/source/funkin/system/CoolUtil.hx
+++ b/source/funkin/system/CoolUtil.hx
@@ -2,6 +2,9 @@ package funkin.system;
import lime.utils.Assets;
import flixel.animation.FlxAnimation;
+import flixel.util.FlxColor;
+import flixel.math.FlxMath;
+import flixel.FlxG;
using StringTools;
@@ -9,6 +12,108 @@ class CoolUtil
{
public static var difficultyArray:Array = ['EASY', "NORMAL", "HARD"];
+ /**
+ * Returns `v` if not null, `defaultValue` otherwise.
+ * @param v The value
+ * @param defaultValue The default value
+ * @return T The return value
+ */
+ public static function getDefault(v:T, defaultValue:T):T {
+ return v == null ? defaultValue : v;
+ }
+
+ public static function fpsLerp(v1:Float, v2:Float, ratio:Float):Float {
+ return FlxMath.lerp(v1, v2, getFPSRatio(ratio));
+ }
+ /**
+ * Lerps from color1 into color2 in a cool way 😎
+ * @param color1 Color 1
+ * @param color2 Color 2
+ * @param ratio Ratio
+ * @param fpsSensitive Whenever the ratio should be case sentivive (adapted when game is running at 120 instead of 60)
+ */
+ public static function lerpColor(color1:FlxColor, color2:FlxColor, ratio:Float, fpsSensitive:Bool = false) {
+ var h1 = color1.hue;
+ var s1 = color1.saturation;
+ var b1 = color1.brightness;
+
+ var h2 = color2.hue;
+ var s2 = color2.saturation;
+ var b2 = color2.brightness;
+
+ if (!fpsSensitive)
+ ratio = getFPSRatio(ratio);
+
+ if (Math.abs(h1-h2) > 180) h1 += 360;
+
+ if (Math.abs(h1 - h2) > 90 || s2 < 0.125 || s1 < 0.125) {
+ // classic r,g,b lerp
+ var r1 = color1.redFloat;
+ var g1 = color1.greenFloat;
+ var b1 = color1.blueFloat;
+
+ var r2 = color2.redFloat;
+ var g2 = color2.greenFloat;
+ var b2 = color2.blueFloat;
+
+ return FlxColor.fromRGBFloat(
+ FlxMath.lerp(r1, r2, ratio),
+ FlxMath.lerp(g1, g2, ratio),
+ FlxMath.lerp(b1, b2, ratio));
+ }
+
+
+ return FlxColor.fromHSB(
+ FlxMath.lerp(h1, h2, ratio),
+ FlxMath.lerp(s1, s2, ratio),
+ FlxMath.lerp(b1, b2, ratio));
+ }
+
+ /**
+ * Modifies a lerp ratio based on current FPS to keep a stable speed on higher framerate.
+ * @param ratio Ratio
+ * @return Float FPS-Modified Ratio
+ */
+ public static function getFPSRatio(ratio:Float) {
+ return FlxMath.bound(ratio * 60 * FlxG.elapsed, 0, 1);
+ }
+ /**
+ * Tries to get a color from a `Dynamic` variable.
+ * @param c `Dynamic` color.
+ * @return Null The result color
+ */
+ public static function getColorFromDynamic(c:Dynamic):Null {
+ // -1
+ if (c is Int) return c;
+
+ // -1.0
+ if (c is Float) return Std.int(c);
+
+ // "#FFFFFF"
+ if (c is String) return FlxColor.fromString(c);
+
+ // [255, 255, 255]
+ if (c is Array) {
+ var r:Int = 0;
+ var g:Int = 0;
+ var b:Int = 0;
+ var a:Int = 255;
+ var array:Array = cast c;
+ for(k=>e in array) {
+ if (e is Int || e is Float) {
+ switch(k) {
+ case 0: r = Std.int(e);
+ case 1: g = Std.int(e);
+ case 2: b = Std.int(e);
+ case 3: a = Std.int(e);
+ }
+ }
+ }
+ return FlxColor.fromRGB(r, g, b, a);
+ }
+ return null;
+ }
+
public static function difficultyString():String
{
return difficultyArray[PlayState.storyDifficulty];
diff --git a/source/funkin/system/MusicBeatState.hx b/source/funkin/system/MusicBeatState.hx
index 84c8f031..2b685b13 100644
--- a/source/funkin/system/MusicBeatState.hx
+++ b/source/funkin/system/MusicBeatState.hx
@@ -7,6 +7,7 @@ import flixel.FlxG;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.ui.FlxUIState;
import flixel.math.FlxRect;
+import flixel.math.FlxMath;
import flixel.util.FlxTimer;
class MusicBeatState extends FlxUIState
@@ -78,4 +79,11 @@ class MusicBeatState extends FlxUIState
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
}
+
+ public function lerp(v1:Float, v2:Float, ratio:Float, fpsSensitive:Bool = false) {
+ if (fpsSensitive)
+ return FlxMath.lerp(v1, v2, ratio);
+ else
+ return CoolUtil.fpsLerp(v1, v2, ratio);
+ }
}
diff --git a/source/funkin/system/MusicBeatSubstate.hx b/source/funkin/system/MusicBeatSubstate.hx
index 4ba4da15..0d646d41 100644
--- a/source/funkin/system/MusicBeatSubstate.hx
+++ b/source/funkin/system/MusicBeatSubstate.hx
@@ -4,6 +4,7 @@ import funkin.system.Conductor.BPMChangeEvent;
import funkin.system.Conductor;
import flixel.FlxG;
import flixel.FlxSubState;
+import flixel.math.FlxMath;
class MusicBeatSubstate extends FlxSubState
{
@@ -63,4 +64,11 @@ class MusicBeatSubstate extends FlxSubState
{
//do literally nothing dumbass
}
+
+ public function lerp(v1:Float, v2:Float, ratio:Float, fpsSensitive:Bool = false) {
+ if (fpsSensitive)
+ return FlxMath.lerp(v1, v2, ratio);
+ else
+ return CoolUtil.fpsLerp(v1, v2, ratio);
+ }
}
diff --git a/source/funkin/system/Paths.hx b/source/funkin/system/Paths.hx
index 565a06a2..7281b047 100644
--- a/source/funkin/system/Paths.hx
+++ b/source/funkin/system/Paths.hx
@@ -18,7 +18,7 @@ class Paths
inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end;
private static var __useSourceAssets = false;
- static function getPath(file:String, type:AssetType, library:Null, skipModsVerification:Bool = false)
+ public static function getPath(file:String, type:AssetType, library:Null, skipModsVerification:Bool = false)
{
if (library != null && library.startsWith("mods/")) {
library = library.toLowerCase();