diff --git a/alsoft.txt b/alsoft.txt
new file mode 100644
index 00000000..2f928c99
--- /dev/null
+++ b/alsoft.txt
@@ -0,0 +1,14 @@
+[general]
+sample-type=float32
+stereo-mode=speakers
+stereo-encoding=panpot
+hrtf=false
+cf_level=0
+resampler=fast_bsinc24
+front-stablizer=false
+output-limiter=false
+volume-adjust=0
+[decoder]
+hq-mode=false
+distance-comp=false
+nfc=false
\ No newline at end of file
diff --git a/assets/data/notes/Alt Anim Note.hx b/assets/data/notes/Alt Anim Note.hx
index b44b1398..ebc3e361 100644
--- a/assets/data/notes/Alt Anim Note.hx
+++ b/assets/data/notes/Alt Anim Note.hx
@@ -1,2 +1,2 @@
function onNoteHit(event) if (event.noteType == "Alt Anim Note") event.animSuffix = "-alt";
-function onPlayerMiss(event) if (event.noteType == "Alt Anim Note") event.animSuffix = "-alt";
\ No newline at end of file
+function onPlayerMiss(event) if (event.noteType == "Alt Anim Note") event.animSuffix = "miss-alt";
\ No newline at end of file
diff --git a/libs.xml b/libs.xml
index f932da09..570b451c 100644
--- a/libs.xml
+++ b/libs.xml
@@ -19,4 +19,5 @@
+
diff --git a/project.xml b/project.xml
index 6f01bc10..382ed9f6 100644
--- a/project.xml
+++ b/project.xml
@@ -67,6 +67,12 @@
+
+
+
@@ -139,6 +145,9 @@
+
+
+
@@ -150,6 +159,9 @@
+
+
+
@@ -175,6 +187,7 @@
+
diff --git a/source/funkin/backend/assets/Paths.hx b/source/funkin/backend/assets/Paths.hx
index 39783823..9486aed6 100644
--- a/source/funkin/backend/assets/Paths.hx
+++ b/source/funkin/backend/assets/Paths.hx
@@ -209,10 +209,10 @@ class Paths
* @param SkipAtlasCheck Whenever the atlas check should be skipped.
* @return FlxFramesCollection Frames
*/
- static function loadFrames(path:String, Unique:Bool = false, Key:String = null, SkipAtlasCheck:Bool = false):FlxFramesCollection {
+ static function loadFrames(path:String, Unique:Bool = false, Key:String = null, SkipAtlasCheck:Bool = false, SkipMultiCheck:Bool = false):FlxFramesCollection {
var noExt = Path.withoutExtension(path);
- if (Assets.exists('$noExt/1.png')) {
+ if (!SkipMultiCheck && Assets.exists('$noExt/1.png')) {
// MULTIPLE SPRITESHEETS!!
var graphic = FlxG.bitmap.add("flixel/images/logo/default.png", false, '$noExt/mult');
@@ -224,7 +224,7 @@ class Paths
var cur = 1;
var finalFrames = new MultiFramesCollection(graphic);
while(Assets.exists('$noExt/$cur.png')) {
- var spr = loadFrames('$noExt/$cur.png');
+ var spr = loadFrames('$noExt/$cur.png', false, null, false, true);
finalFrames.addFrames(spr);
cur++;
}
diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx
index 9183e4a4..bb0b4972 100644
--- a/source/funkin/backend/system/macros/Macros.hx
+++ b/source/funkin/backend/system/macros/Macros.hx
@@ -21,6 +21,7 @@ class Macros {
// OTHER LIBRARIES & STUFF
#if THREE_D_SUPPORT "away3d", "flx3d", #end
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
+ #if NAPE_ENABLED "nape", "flixel.addons.nape", #end
// BASE HAXE
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
])
diff --git a/source/funkin/backend/system/modules/ALSoftConfig.hx b/source/funkin/backend/system/modules/ALSoftConfig.hx
new file mode 100644
index 00000000..0b1b57a0
--- /dev/null
+++ b/source/funkin/backend/system/modules/ALSoftConfig.hx
@@ -0,0 +1,31 @@
+package funkin.backend.system.modules;
+
+import haxe.io.Path;
+
+/*
+ * A class that simply points OpenALSoft to a custom configuration file when
+ * the game starts up.
+ *
+ * The config overrides a few global OpenALSoft settings with the aim of
+ * improving audio quality on desktop targets.
+ */
+@:keepInit class ALSoftConfig
+{
+ #if desktop
+ static function __init__():Void
+ {
+ var origin:String = #if hl Sys.getCwd() #else Sys.programPath() #end;
+
+ var configPath:String = Path.directory(Path.withoutExtension(origin));
+ #if windows
+ configPath += "/plugins/alsoft.ini";
+ #elseif mac
+ configPath = Path.directory(configPath) + "/Resources/plugins/alsoft.conf";
+ #else
+ configPath += "/plugins/alsoft.conf";
+ #end
+
+ Sys.putEnv("ALSOFT_CONF", configPath);
+ }
+ #end
+}
\ No newline at end of file
diff --git a/source/funkin/editors/character/CharacterInfoScreen.hx b/source/funkin/editors/character/CharacterInfoScreen.hx
index 4f44dc81..1d7f313b 100644
--- a/source/funkin/editors/character/CharacterInfoScreen.hx
+++ b/source/funkin/editors/character/CharacterInfoScreen.hx
@@ -76,6 +76,9 @@ class CharacterInfoScreen extends UISubstateWindow {
add(iconColorWheel);
addLabelOn(iconColorWheel, "Icon Color");
+ if (character.iconColor != null)
+ iconColorWheel.colorChanged = true;
+
add(title = new UIText(spriteTextBox.x, spriteTextBox.y + 10 + 46 + 84, 0, "Character Data", 28));
positionXStepper = new UINumericStepper(title.x, title.y + title.height + 36, character.globalOffset.x, 0.001, 2, null, null, 84);
diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx
index f4d7c87e..96855473 100644
--- a/source/funkin/editors/charter/Charter.hx
+++ b/source/funkin/editors/charter/Charter.hx
@@ -1154,7 +1154,7 @@ class Charter extends UIState {
if (note.strumLineID == strumLineID)
selection.remove(note);
else i++;
- }
+ } else i++;
}
}
#end
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index bb458994..e26e2e3a 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -910,7 +910,7 @@ class PlayState extends MusicBeatState
var spr = event.spritePath;
if (!Assets.exists(spr)) spr = Paths.image('$spr');
- sprite = new FlxSprite().loadAnimatedGraphic(spr);
+ sprite = new FunkinSprite().loadAnimatedGraphic(spr);
sprite.scrollFactor.set();
sprite.scale.set(event.scale, event.scale);
sprite.updateHitbox();
@@ -1233,8 +1233,11 @@ class PlayState extends MusicBeatState
accFormat.format.color = curRating.color;
accuracyTxt.text = 'Accuracy:${accuracy < 0 ? "-%" : '${CoolUtil.quantize(accuracy * 100, 100)}%'} - ${curRating.rating}';
- accuracyTxt._formatRanges[0].range.start = accuracyTxt.text.length - curRating.rating.length;
- accuracyTxt._formatRanges[0].range.end = accuracyTxt.text.length;
+ for (i => frmtRange in accuracyTxt._formatRanges) if (frmtRange.format == accFormat) {
+ accuracyTxt._formatRanges[i].range.start = accuracyTxt.text.length - curRating.rating.length;
+ accuracyTxt._formatRanges[i].range.end = accuracyTxt.text.length;
+ break;
+ }
}
}
diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx
index b5880acc..1b0780dd 100644
--- a/source/funkin/game/StrumLine.hx
+++ b/source/funkin/game/StrumLine.hx
@@ -299,8 +299,10 @@ class StrumLine extends FlxTypedGroup {
* Creates a strum and returns the created strum (needs to be added manually).
* @param i Index of the strum
* @param animPrefix (Optional) Animation prefix (`left` = `arrowLEFT`, `left press`, `left confirm`).
+ * @param spritePath (Optional) The sprite's graphic path if you don't want the default one.
+ * @param playIntroAnimation (Optional) Whenever the intro animation should be played, by default might be `true` under certain conditions.
*/
- public function createStrum(i:Int, ?animPrefix:String) {
+ public function createStrum(i:Int, ?animPrefix:String, ?spritePath:String, ?playIntroAnimation:Bool) {
if (animPrefix == null)
animPrefix = strumAnimPrefix[i % strumAnimPrefix.length];
var babyArrow:Strum = new Strum(startingPos.x + ((Note.swagWidth * strumScale) * i), startingPos.y);
@@ -310,7 +312,8 @@ class StrumLine extends FlxTypedGroup {
babyArrow.scrollSpeed = data.scrollSpeed;
var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
- event.__doAnimation = !MusicBeatState.skipTransIn && (PlayState.instance != null ? PlayState.instance.introLength > 0 : true);
+ event.__doAnimation = playIntroAnimation == null ? (!MusicBeatState.skipTransIn && (PlayState.instance != null ? PlayState.instance.introLength > 0 : true)) : playIntroAnimation;
+ if (spritePath != null) event.sprite = spritePath;
event = PlayState.instance.scripts.event("onStrumCreation", event);
if (!event.cancelled) {
diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx
index ecf2fa7d..641b72b1 100644
--- a/source/funkin/menus/PauseSubState.hx
+++ b/source/funkin/menus/PauseSubState.hx
@@ -1,20 +1,20 @@
package funkin.menus;
-import funkin.editors.charter.Charter;
-import funkin.backend.scripting.events.MenuChangeEvent;
-import funkin.options.OptionsMenu;
-import funkin.backend.scripting.events.PauseCreationEvent;
-import funkin.backend.scripting.events.NameEvent;
-import funkin.backend.scripting.Script;
import flixel.sound.FlxSound;
-import flixel.text.FlxText;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
-import funkin.options.keybinds.KeybindsOptions;
-import funkin.menus.StoryMenuState;
+import funkin.backend.FunkinText;
+import funkin.backend.scripting.Script;
+import funkin.backend.scripting.events.MenuChangeEvent;
+import funkin.backend.scripting.events.NameEvent;
+import funkin.backend.scripting.events.PauseCreationEvent;
import funkin.backend.system.Conductor;
import funkin.backend.utils.FunkinParentDisabler;
+import funkin.editors.charter.Charter;
+import funkin.menus.StoryMenuState;
+import funkin.options.OptionsMenu;
import funkin.options.TreeMenu;
+import funkin.options.keybinds.KeybindsOptions;
class PauseSubState extends MusicBeatSubstate
{
@@ -22,6 +22,11 @@ class PauseSubState extends MusicBeatSubstate
var grpMenuShit:FlxTypedGroup;
+ var levelInfo:FunkinText;
+ var levelDifficulty:FunkinText;
+ var deathCounter:FunkinText;
+ var multiplayerText:FunkinText;
+
var menuItems:Array = ['Resume', 'Restart Song', 'Change Controls', 'Change Options', 'Exit to menu', "Exit to charter"];
var curSelected:Int = 0;
@@ -56,7 +61,6 @@ class PauseSubState extends MusicBeatSubstate
menuItems = event.options;
-
pauseMusic = FlxG.sound.load(Paths.music(event.music), 0, true);
pauseMusic.persist = false;
pauseMusic.group = FlxG.sound.defaultMusicGroup;
@@ -71,15 +75,13 @@ class PauseSubState extends MusicBeatSubstate
bg.scrollFactor.set();
add(bg);
- var levelInfo:FlxText = new FlxText(20, 15, 0, PlayState.SONG.meta.displayName, 32);
- var levelDifficulty:FlxText = new FlxText(20, 15, 0, PlayState.difficulty.toUpperCase(), 32);
- var deathCounter:FlxText = new FlxText(20, 15, 0, "Blue balled: " + PlayState.deathCounter, 32);
- var multiplayerText:FlxText = new FlxText(20, 15, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32);
+ levelInfo = new FunkinText(20, 15, 0, PlayState.SONG.meta.displayName, 32, false);
+ levelDifficulty = new FunkinText(20, 15, 0, PlayState.difficulty.toUpperCase(), 32, false);
+ deathCounter = new FunkinText(20, 15, 0, "Blue balled: " + PlayState.deathCounter, 32, false);
+ multiplayerText = new FunkinText(20, 15, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32, false);
for(k=>label in [levelInfo, levelDifficulty, deathCounter, multiplayerText]) {
label.scrollFactor.set();
- label.setFormat(Paths.font('vcr.ttf'), 32);
- label.updateHitbox();
label.alpha = 0;
label.x = FlxG.width - (label.width + 20);
label.y = 15 + (32 * k);
diff --git a/source/funkin/options/TreeMenu.hx b/source/funkin/options/TreeMenu.hx
index b0651fd2..3e05a4af 100644
--- a/source/funkin/options/TreeMenu.hx
+++ b/source/funkin/options/TreeMenu.hx
@@ -7,6 +7,7 @@ import flixel.tweens.FlxTween;
import funkin.menus.MainMenuState;
import flixel.util.typeLimit.OneOfTwo;
import funkin.options.type.OptionType;
+import funkin.options.type.TextOption;
import funkin.backend.system.framerate.Framerate;
class TreeMenu extends UIState {
@@ -18,13 +19,13 @@ class TreeMenu extends UIState {
public static var lastState:Class = null; // Static for fixing the softlock bugs when resetting the state - Nex
- public function new() {
+ public function new(scriptsAllowed:Bool = true, ?scriptName:String) {
if(lastState == null) lastState = Type.getClass(FlxG.state);
- super();
+ super(scriptsAllowed, scriptName);
}
public override function createPost() {
- if (main == null) throw "\"main\" variable has not been set in extended class!";
+ if (main == null) main = new OptionsScreen("Fallback Treemenu", "Please set the \"main\" variable in your extended class before createPost", [new TextOption("Oops! No Options", "This doesn't look like it was supposed to happen...", () -> FlxG.resetState() ) ]);
FlxG.camera.scroll.set(-FlxG.width, 0);
@@ -119,4 +120,4 @@ typedef OptionCategory = {
typedef OptionTypeDef = {
var type:Class;
var args:Array;
-}
\ No newline at end of file
+}