diff --git a/.gitignore b/.gitignore
index 9f24f450e..8a4d131df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,4 @@ export/
.vscode/
APIStuff.hx
.DS_STORE
-
-example_mods/enaSkin/
-
-example_mods/tricky/
+RECOVER_*.fla
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 4afcd170e..9a277f85c 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,6 +12,21 @@
"name": "Haxe Eval",
"type": "haxe-eval",
"request": "launch"
- }
+ },
+ {
+ "name": "HTML5 Debug",
+ "type": "chrome",
+ "request": "launch",
+ "url": "http://127.0.0.1:3001",
+ "sourceMaps": true,
+ "webRoot": "${workspaceFolder}",
+ "preLaunchTask": "debug: html"
+ },
+ {
+ "name": "Mac (Debug)",
+ "type": "hxcpp",
+ "request": "launch",
+ "program": "${workspaceRoot}/export/debug/macos/bin/Funkin.app/Contents/MacOS/Funkin",
+ "preLaunchTask": "debug: mac"
]
}
diff --git a/Project.xml b/Project.xml
index 4c6ad39a6..81f017853 100644
--- a/Project.xml
+++ b/Project.xml
@@ -96,7 +96,13 @@
-
+
@@ -192,7 +198,7 @@
-
+
diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json
index ccd7405d8..4c7fd742e 100644
--- a/example_mods/introMod/_polymod_meta.json
+++ b/example_mods/introMod/_polymod_meta.json
@@ -1,7 +1,9 @@
{
"title": "Intro Mod",
"description": "An introductory mod.",
- "author": "MasterEric",
+ "contributors": [{
+ "name": "MasterEric"
+ }],
"api_version": "0.1.0",
"mod_version": "1.0.0",
"license": "Apache-2.0"
diff --git a/example_mods/testing123/_polymod_meta.json b/example_mods/testing123/_polymod_meta.json
index 0c134dd9f..1a7766820 100644
--- a/example_mods/testing123/_polymod_meta.json
+++ b/example_mods/testing123/_polymod_meta.json
@@ -1,7 +1,9 @@
{
"title": "Testing123",
"description": "Newgrounds? More like OLDGROUNDS lol.",
- "author": "MasterEric",
+ "contributors": [{
+ "name": "MasterEric"
+ }],
"api_version": "0.1.0",
"mod_version": "1.0.0",
"license": "Apache-2.0"
diff --git a/source/Main.hx b/source/Main.hx
index 32b7433f3..191ebef53 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -1,9 +1,9 @@
package;
-import funkin.InitState;
-import funkin.MemoryCounter;
import flixel.FlxGame;
import flixel.FlxState;
+import funkin.InitState;
+import funkin.MemoryCounter;
import openfl.Lib;
import openfl.display.FPS;
import openfl.display.Sprite;
@@ -37,13 +37,7 @@ class Main extends Sprite
{
super();
- // TODO: Ideally this should change to utilize a user interface.
- // 1. Call PolymodHandler.getAllMods(). This gives you an array of ModMetadata items,
- // each of which contains information about the mod including an icon.
- // 2. Provide an interface to enable, disable, and reorder enabled mods.
- // A design similar to that of Minecraft resource packs would be intuitive.
- // 3. The interface should save (to the save file) and output an ordered array of mod IDs.
- // 4. Replace the call to PolymodHandler.loadAllMods() with a call to PolymodHandler.loadModsById(ids:Array).
+ // TODO: Replace this with loadEnabledMods().
funkin.modding.PolymodHandler.loadAllMods();
if (stage != null)
diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx
index bacde05e8..7f37eff18 100644
--- a/source/funkin/FreeplayState.hx
+++ b/source/funkin/FreeplayState.hx
@@ -1,6 +1,5 @@
package funkin;
-import funkin.Controls.Control;
import flash.text.TextField;
import flixel.FlxCamera;
import flixel.FlxGame;
@@ -21,17 +20,18 @@ import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import flixel.util.FlxSpriteUtil;
import flixel.util.FlxTimer;
+import funkin.Controls.Control;
import funkin.freeplayStuff.BGScrollingText;
import funkin.freeplayStuff.DJBoyfriend;
import funkin.freeplayStuff.FreeplayScore;
import funkin.freeplayStuff.SongMenuItem;
import funkin.play.HealthIcon;
-import lime.app.Future;
-import lime.utils.Assets;
+import funkin.play.PlayState;
import funkin.shaderslmfao.AngleMask;
import funkin.shaderslmfao.PureColor;
import funkin.shaderslmfao.StrokeShader;
-import funkin.play.PlayState;
+import lime.app.Future;
+import lime.utils.Assets;
using StringTools;
@@ -499,6 +499,9 @@ class FreeplayState extends MusicBeatSubstate
if (controls.BACK)
{
FlxG.sound.play(Paths.sound('cancelMenu'));
+
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new MainMenuState());
}
diff --git a/source/funkin/GameOverSubstate.hx b/source/funkin/GameOverSubstate.hx
index fe957af25..113e64b63 100644
--- a/source/funkin/GameOverSubstate.hx
+++ b/source/funkin/GameOverSubstate.hx
@@ -1,17 +1,14 @@
package funkin;
-import funkin.modding.events.ScriptEventDispatcher;
-import funkin.modding.events.ScriptEvent;
-import funkin.play.character.BaseCharacter;
import flixel.FlxObject;
-import flixel.FlxSubState;
-import flixel.math.FlxPoint;
import flixel.system.FlxSound;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
-import haxe.display.Display;
-import funkin.ui.PreferencesMenu;
+import funkin.modding.events.ScriptEvent;
+import funkin.modding.events.ScriptEventDispatcher;
import funkin.play.PlayState;
+import funkin.play.character.BaseCharacter;
+import funkin.ui.PreferencesMenu;
using StringTools;
diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx
index f7ec0ff4b..bfde8c327 100644
--- a/source/funkin/InitState.hx
+++ b/source/funkin/InitState.hx
@@ -1,9 +1,5 @@
package funkin;
-import funkin.play.character.CharacterData.CharacterDataParser;
-import funkin.modding.module.ModuleHandler;
-import funkin.play.stage.StageData;
-import funkin.charting.ChartingState;
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.transition.TransitionData;
@@ -11,12 +7,17 @@ import flixel.graphics.FlxGraphic;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.util.FlxColor;
-import openfl.display.BitmapData;
+import funkin.charting.ChartingState;
+import funkin.modding.module.ModuleHandler;
import funkin.play.PicoFight;
+import funkin.play.PlayState;
+import funkin.play.character.CharacterData.CharacterDataParser;
+import funkin.play.stage.StageData;
import funkin.ui.PreferencesMenu;
+import funkin.ui.animDebugShit.DebugBoundingState;
import funkin.ui.stageBuildShit.StageBuilderState;
import funkin.util.macro.MacroUtil;
-import funkin.play.PlayState;
+import openfl.display.BitmapData;
using StringTools;
@@ -178,7 +179,11 @@ class InitState extends FlxTransitionableState
#elseif FIGHT
FlxG.switchState(new PicoFight());
#elseif ANIMDEBUG
+<<<<<<< HEAD
FlxG.switchState(new funkin.ui.animDebugShit.DebugBoundingState());
+=======
+ FlxG.switchState(new DebugBoundingState());
+>>>>>>> origin/feature/scripted-modules
#elseif NETTEST
FlxG.switchState(new netTest.NetTest());
#else
diff --git a/source/funkin/LoadingState.hx b/source/funkin/LoadingState.hx
index bbe20ff2d..ad649bb03 100644
--- a/source/funkin/LoadingState.hx
+++ b/source/funkin/LoadingState.hx
@@ -2,9 +2,9 @@ package funkin;
import flixel.FlxSprite;
import flixel.FlxState;
-import flixel.graphics.frames.FlxAtlasFrames;
import flixel.math.FlxMath;
import flixel.util.FlxTimer;
+import funkin.play.PlayState;
import haxe.io.Path;
import lime.app.Future;
import lime.app.Promise;
@@ -12,7 +12,6 @@ import lime.utils.AssetLibrary;
import lime.utils.AssetManifest;
import lime.utils.Assets as LimeAssets;
import openfl.utils.Assets;
-import funkin.play.PlayState;
class LoadingState extends MusicBeatState
{
@@ -21,7 +20,6 @@ class LoadingState extends MusicBeatState
var target:FlxState;
var stopMusic = false;
var callbacks:MultiCallback;
-
var danceLeft = false;
var loadBar:FlxSprite;
@@ -123,13 +121,7 @@ class LoadingState extends MusicBeatState
if (!super.beatHit())
return false;
- // logo.animation.play('bump');
danceLeft = !danceLeft;
- /*
- if (danceLeft)
- gfDance.animation.play('danceRight');
- else
- gfDance.animation.play('danceLeft'); */
return true;
}
diff --git a/source/funkin/MainMenuState.hx b/source/funkin/MainMenuState.hx
index 39eeb87e7..1f99b067f 100644
--- a/source/funkin/MainMenuState.hx
+++ b/source/funkin/MainMenuState.hx
@@ -1,10 +1,10 @@
package funkin;
-import flixel.addons.transition.FlxTransitionableState;
-import flixel.effects.FlxFlicker;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.effects.FlxFlicker;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.input.touch.FlxTouch;
@@ -14,13 +14,13 @@ import flixel.tweens.FlxTween;
import flixel.ui.FlxButton;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
+import funkin.NGio;
import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
import funkin.modding.module.ModuleHandler;
-import funkin.NGio;
import funkin.shaderslmfao.ScreenWipeShader;
import funkin.ui.AtlasMenuList;
-import funkin.ui.MenuList;
import funkin.ui.MenuList.MenuItem;
+import funkin.ui.MenuList;
import funkin.ui.OptionsState;
import funkin.ui.PreferencesMenu;
import funkin.ui.Prompt;
@@ -35,8 +35,8 @@ using StringTools;
import Discord.DiscordClient;
#end
#if newgrounds
-import io.newgrounds.NG;
import funkin.ui.NgPrompt;
+import io.newgrounds.NG;
#end
class MainMenuState extends MusicBeatState
@@ -104,14 +104,9 @@ class MainMenuState extends MusicBeatState
}
});
- menuItems.enabled = false; // disable for intro
-
- createMenuItem('storymode', 'mainmenu/storymode', function()
- {
- startExitState(new StoryMenuState());
- });
-
- createMenuItem('freeplay', 'mainmenu/freeplay', function()
+ menuItems.enabled = true; // can move on intro
+ menuItems.createItem('story mode', function() startExitState(new StoryMenuState()));
+ menuItems.createItem('freeplay', function()
{
persistentDraw = true;
persistentUpdate = false;
@@ -184,7 +179,7 @@ class MainMenuState extends MusicBeatState
{
super.finishTransIn();
- menuItems.enabled = true;
+ // menuItems.enabled = true;
// #if newgrounds
// if (NGio.savedSessionFailed)
diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/MusicBeatState.hx
index a11d468ca..5e86ea022 100644
--- a/source/funkin/MusicBeatState.hx
+++ b/source/funkin/MusicBeatState.hx
@@ -1,18 +1,18 @@
package funkin;
-import flixel.util.FlxSort;
-import funkin.util.SortUtil;
-import funkin.play.stage.StageData.StageDataParser;
-import funkin.play.character.CharacterData.CharacterDataParser;
import flixel.FlxState;
import flixel.FlxSubState;
-import flixel.util.FlxColor;
+import flixel.addons.ui.FlxUIState;
import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import flixel.util.FlxSort;
+import funkin.Conductor.BPMChangeEvent;
+import funkin.modding.PolymodHandler;
import funkin.modding.events.ScriptEvent;
import funkin.modding.module.ModuleHandler;
-import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
-import funkin.Conductor.BPMChangeEvent;
-import flixel.addons.ui.FlxUIState;
+import funkin.play.character.CharacterData.CharacterDataParser;
+import funkin.play.stage.StageData.StageDataParser;
+import funkin.util.SortUtil;
/**
* MusicBeatState actually represents the core utility FlxState of the game.
@@ -68,6 +68,8 @@ class MusicBeatState extends FlxUIState
if (oldStep != curStep && curStep >= 0)
stepHit();
+ FlxG.watch.addQuick("songPos", Conductor.songPosition);
+
dispatchEvent(new UpdateScriptEvent(elapsed));
}
@@ -97,20 +99,7 @@ class MusicBeatState extends FlxUIState
function debug_refreshModules()
{
- // Forcibly clear scripts so that scripts can be edited.
- ModuleHandler.clearModuleCache();
- polymod.hscript.PolymodScriptClass.clearScriptClasses();
-
- // Forcibly reload Polymod so it finds any new files.
- polymod.Polymod.reload();
-
- // Reload scripted classes so stages and modules will update.
- polymod.hscript.PolymodScriptClass.registerAllScriptClasses();
-
- // Reload the stages in cache. This might cause a lag spike but who cares this is a debug utility.
- StageDataParser.loadStageCache();
- CharacterDataParser.loadCharacterCache();
- ModuleHandler.loadModuleCache();
+ PolymodHandler.forceReloadAssets();
// Restart the current state, so old data is cleared.
FlxG.resetState();
diff --git a/source/funkin/MusicBeatSubstate.hx b/source/funkin/MusicBeatSubstate.hx
index 12cb56cff..db20bce34 100644
--- a/source/funkin/MusicBeatSubstate.hx
+++ b/source/funkin/MusicBeatSubstate.hx
@@ -1,9 +1,9 @@
package funkin;
-import funkin.modding.module.ModuleHandler;
-import funkin.modding.events.ScriptEvent;
-import funkin.Conductor.BPMChangeEvent;
import flixel.FlxSubState;
+import funkin.Conductor.BPMChangeEvent;
+import funkin.modding.events.ScriptEvent;
+import funkin.modding.module.ModuleHandler;
/**
* MusicBeatSubstate reincorporates the functionality of MusicBeatState into an FlxSubState.
diff --git a/source/funkin/Note.hx b/source/funkin/Note.hx
index 32a5b19a8..433a1e727 100644
--- a/source/funkin/Note.hx
+++ b/source/funkin/Note.hx
@@ -80,8 +80,8 @@ class Note extends FlxSprite
public static var RED_NOTE:Int = 3;
// SCORING STUFF
- public static var safeFrames:Int = 10;
- public static var HIT_WINDOW:Float = (safeFrames / 60) * 1000; // 166.67 ms hit window
+ public static var HIT_WINDOW:Float = (10 / 60) * 1000; // 166.67 ms hit window (10 frames at 60fps)
+ // thresholds are fractions of HIT_WINDOW ^^
// anything above bad threshold is shit
public static var BAD_THRESHOLD:Float = 0.8; // 125ms , 8 frames
public static var GOOD_THRESHOLD:Float = 0.55; // 91.67ms , 5.5 frames
diff --git a/source/funkin/NoteSplash.hx b/source/funkin/NoteSplash.hx
index 64169c48b..3e4d3a3b5 100644
--- a/source/funkin/NoteSplash.hx
+++ b/source/funkin/NoteSplash.hx
@@ -22,6 +22,8 @@ class NoteSplash extends FlxSprite
setupNoteSplash(x, y, noteData);
+ antialiasing = true;
+
// alpha = 0.75;
}
diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx
index 81e6fb9f5..8a9648795 100644
--- a/source/funkin/PauseSubState.hx
+++ b/source/funkin/PauseSubState.hx
@@ -1,6 +1,5 @@
package funkin;
-import funkin.Controls.Control;
import flixel.FlxSprite;
import flixel.FlxSubState;
import flixel.addons.transition.FlxTransitionableState;
@@ -11,6 +10,7 @@ import flixel.text.FlxText;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
+import funkin.Controls.Control;
import funkin.play.PlayState;
class PauseSubState extends MusicBeatSubstate
@@ -33,43 +33,53 @@ class PauseSubState extends MusicBeatSubstate
var practiceText:FlxText;
+ var exitingToMenu:Bool = false;
+ var bg:FlxSprite;
+ var metaDataGrp:FlxTypedGroup;
+
public function new(x:Float, y:Float)
{
super();
menuItems = pauseOG;
- pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
+ if (PlayState.storyWeek == 6) // consistent with logic that decides asset lib!!
+ pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast-pixel'), true, true);
+ else
+ pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
pauseMusic.volume = 0;
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
FlxG.sound.list.add(pauseMusic);
- var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
bg.alpha = 0;
bg.scrollFactor.set();
add(bg);
+ metaDataGrp = new FlxTypedGroup();
+ add(metaDataGrp);
+
var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32);
levelInfo.text += PlayState.currentSong.song;
levelInfo.scrollFactor.set();
levelInfo.setFormat(Paths.font("vcr.ttf"), 32);
levelInfo.updateHitbox();
- add(levelInfo);
+ metaDataGrp.add(levelInfo);
var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32);
levelDifficulty.text += CoolUtil.difficultyString();
levelDifficulty.scrollFactor.set();
levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32);
levelDifficulty.updateHitbox();
- add(levelDifficulty);
+ metaDataGrp.add(levelDifficulty);
var deathCounter:FlxText = new FlxText(20, 15 + 64, 0, "", 32);
deathCounter.text = "Blue balled: " + PlayState.deathCounter;
deathCounter.scrollFactor.set();
deathCounter.setFormat(Paths.font('vcr.ttf'), 32);
deathCounter.updateHitbox();
- add(deathCounter);
+ metaDataGrp.add(deathCounter);
practiceText = new FlxText(20, 15 + 64 + 32, 0, "PRACTICE MODE", 32);
practiceText.scrollFactor.set();
@@ -77,7 +87,7 @@ class PauseSubState extends MusicBeatSubstate
practiceText.updateHitbox();
practiceText.x = FlxG.width - (practiceText.width + 20);
practiceText.visible = PlayState.isPracticeMode;
- add(practiceText);
+ metaDataGrp.add(practiceText);
levelDifficulty.alpha = 0;
levelInfo.alpha = 0;
@@ -130,71 +140,103 @@ class PauseSubState extends MusicBeatSubstate
var downP = controls.UI_DOWN_P;
var accepted = controls.ACCEPT;
- if (upP)
+ #if debug
+ // to pause the game and get screenshots easy, press H on pause menu!
+ if (FlxG.keys.justPressed.H)
{
- changeSelection(-1);
+ bg.visible = !bg.visible;
+ grpMenuShit.visible = !grpMenuShit.visible;
+ metaDataGrp.visible = !metaDataGrp.visible;
}
- if (downP)
- {
- changeSelection(1);
- }
-
- var androidPause:Bool = false;
-
- #if android
- androidPause = FlxG.android.justPressed.BACK;
#end
- if (androidPause)
- close();
-
- if (accepted)
+ if (!exitingToMenu)
{
- var daSelected:String = menuItems[curSelected];
-
- switch (daSelected)
+ if (upP)
{
- case "Resume":
- close();
- case "EASY" | 'NORMAL' | "HARD":
- PlayState.currentSong = SongLoad.loadFromJson(PlayState.currentSong.song.toLowerCase(), PlayState.currentSong.song.toLowerCase());
- SongLoad.curDiff = daSelected.toLowerCase();
-
- PlayState.storyDifficulty = curSelected;
-
- PlayState.needsReset = true;
-
- close();
-
- case 'Toggle Practice Mode':
- PlayState.isPracticeMode = !PlayState.isPracticeMode;
- practiceText.visible = PlayState.isPracticeMode;
-
- case 'Change Difficulty':
- menuItems = difficultyChoices;
- regenMenu();
- case 'BACK':
- menuItems = pauseOG;
- regenMenu();
- case "Restart Song":
- PlayState.needsReset = true;
-
- close();
- // FlxG.resetState();
- case "Exit to menu":
- PlayState.seenCutscene = false;
- PlayState.deathCounter = 0;
- if (PlayState.isStoryMode)
- FlxG.switchState(new StoryMenuState());
- else
- FlxG.switchState(new FreeplayState());
+ changeSelection(-1);
+ }
+ if (downP)
+ {
+ changeSelection(1);
}
- }
- if (FlxG.keys.justPressed.J)
- {
- // for reference later!
- // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
+ var androidPause:Bool = false;
+
+ #if android
+ androidPause = FlxG.android.justPressed.BACK;
+ #end
+
+ if (androidPause)
+ close();
+
+ if (accepted)
+ {
+ var daSelected:String = menuItems[curSelected];
+
+ switch (daSelected)
+ {
+ case "Resume":
+ close();
+ case "EASY" | 'NORMAL' | "HARD":
+ PlayState.currentSong = SongLoad.loadFromJson(PlayState.currentSong.song.toLowerCase(), PlayState.currentSong.song.toLowerCase());
+ SongLoad.curDiff = daSelected.toLowerCase();
+
+ PlayState.storyDifficulty = curSelected;
+
+ PlayState.needsReset = true;
+
+ close();
+
+ case 'Toggle Practice Mode':
+ PlayState.isPracticeMode = !PlayState.isPracticeMode;
+ practiceText.visible = PlayState.isPracticeMode;
+
+ case 'Change Difficulty':
+ menuItems = difficultyChoices;
+ regenMenu();
+ case 'BACK':
+ menuItems = pauseOG;
+ regenMenu();
+ case "Restart Song":
+ PlayState.needsReset = true;
+
+ close();
+ // FlxG.resetState();
+ case "Exit to menu":
+ exitingToMenu = true;
+ PlayState.seenCutscene = false;
+ PlayState.deathCounter = 0;
+
+ for (item in grpMenuShit.members)
+ {
+ item.targetY = -3;
+ item.alpha = 0.6;
+ }
+
+ FlxTween.tween(bg, {alpha: 1}, 0.4, {
+ ease: FlxEase.quartInOut,
+ onComplete: function(_)
+ {
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
+
+ FlxG.cameras.list[1].alpha = 0; // bullshit for the UI camera???
+
+ if (PlayState.isStoryMode)
+ FlxG.switchState(new StoryMenuState());
+ else
+ FlxG.switchState(new FreeplayState());
+ }
+ });
+ }
+ }
+
+ if (FlxG.keys.justPressed.J)
+ {
+ // for reference later!
+ // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
+ }
}
}
@@ -216,12 +258,9 @@ class PauseSubState extends MusicBeatSubstate
if (curSelected >= menuItems.length)
curSelected = 0;
- var bullShit:Int = 0;
-
- for (item in grpMenuShit.members)
+ for (index => item in grpMenuShit.members)
{
- item.targetY = bullShit - curSelected;
- bullShit++;
+ item.targetY = index - curSelected;
item.alpha = 0.6;
// item.setGraphicSize(Std.int(item.width * 0.8));
diff --git a/source/funkin/TitleState.hx b/source/funkin/TitleState.hx
index df91a5841..6dfd5c8b7 100644
--- a/source/funkin/TitleState.hx
+++ b/source/funkin/TitleState.hx
@@ -1,48 +1,32 @@
package funkin;
-import funkin.ui.AtlasText.BoldText;
-import funkin.audiovis.SpectogramSprite;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.group.FlxGroup;
-import flixel.input.android.FlxAndroidKey;
-import flixel.input.android.FlxAndroidKeys;
import flixel.input.gamepad.FlxGamepad;
-import flixel.input.gamepad.id.SwitchJoyconLeftID;
-import flixel.math.FlxPoint;
-import flixel.math.FlxRect;
-import flixel.text.FlxText;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
-import lime.app.Application;
-import lime.graphics.Image;
-import lime.media.AudioContext;
-import lime.ui.Window;
-import openfl.Assets;
-import openfl.display.Sprite;
-import openfl.events.AsyncErrorEvent;
-import openfl.events.Event;
-import openfl.events.MouseEvent;
-import openfl.events.NetStatusEvent;
-import openfl.media.Video;
-import openfl.net.NetConnection;
-import openfl.net.NetStream;
+import funkin.audiovis.SpectogramSprite;
import funkin.shaderslmfao.BuildingShaders;
import funkin.shaderslmfao.ColorSwap;
import funkin.shaderslmfao.TitleOutline;
-import funkin.ui.PreferencesMenu;
+import funkin.ui.AtlasText;
+import funkin.util.Constants;
+import openfl.Assets;
+import openfl.display.Sprite;
+import openfl.events.AsyncErrorEvent;
+import openfl.events.MouseEvent;
+import openfl.events.NetStatusEvent;
+import openfl.media.Video;
+import openfl.net.NetStream;
using StringTools;
#if desktop
-import sys.FileSystem;
-import sys.io.File;
-import sys.thread.Thread;
#end
-
class TitleState extends MusicBeatState
{
public static var initialized:Bool = false;
@@ -74,33 +58,33 @@ class TitleState extends MusicBeatState
super.create();
/*
- #elseif web
+ #elseif web
- if (!initialized)
- {
+ if (!initialized)
+ {
- video = new Video();
- FlxG.stage.addChild(video);
+ video = new Video();
+ FlxG.stage.addChild(video);
- var netConnection = new NetConnection();
- netConnection.connect(null);
+ var netConnection = new NetConnection();
+ netConnection.connect(null);
- netStream = new NetStream(netConnection);
- netStream.client = {onMetaData: client_onMetaData};
- netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
- netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
- // netStream.addEventListener(NetStatusEvent.NET_STATUS) // netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
+ netStream = new NetStream(netConnection);
+ netStream.client = {onMetaData: client_onMetaData};
+ netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
+ netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
+ // netStream.addEventListener(NetStatusEvent.NET_STATUS) // netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
- overlay = new Sprite();
- overlay.graphics.beginFill(0, 0.5);
- overlay.graphics.drawRect(0, 0, 1280, 720);
- overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
+ overlay = new Sprite();
+ overlay.graphics.beginFill(0, 0.5);
+ overlay.graphics.drawRect(0, 0, 1280, 720);
+ overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
- overlay.buttonMode = true;
- // FlxG.stage.addChild(overlay);
+ overlay.buttonMode = true;
+ // FlxG.stage.addChild(overlay);
- }
+ }
*/
// netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
@@ -159,9 +143,9 @@ class TitleState extends MusicBeatState
{
FlxG.sound.playMusic(Paths.music('freakyMenu'), 0);
FlxG.sound.music.fadeIn(4, 0, 0.7);
+ Conductor.bpm = Constants.FREAKY_MENU_BPM;
}
- Conductor.bpm = 102;
persistentUpdate = true;
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
@@ -290,13 +274,13 @@ class TitleState extends MusicBeatState
#end
/* if (FlxG.onMobile)
+ {
+ if (gfDance != null)
{
- if (gfDance != null)
- {
- gfDance.x = (FlxG.width / 2) + (FlxG.accelerometer.x * (FlxG.width / 2));
- // gfDance.y = (FlxG.height / 2) + (FlxG.accelerometer.y * (FlxG.height / 2));
- }
+ gfDance.x = (FlxG.width / 2) + (FlxG.accelerometer.x * (FlxG.width / 2));
+ // gfDance.y = (FlxG.height / 2) + (FlxG.accelerometer.y * (FlxG.height / 2));
}
+ }
*/
if (FlxG.keys.justPressed.I)
{
@@ -313,37 +297,37 @@ class TitleState extends MusicBeatState
}
/*
- FlxG.watch.addQuick('cur display', FlxG.stage.window.display.id);
- if (FlxG.keys.justPressed.Y)
+ FlxG.watch.addQuick('cur display', FlxG.stage.window.display.id);
+ if (FlxG.keys.justPressed.Y)
+ {
+ // trace(FlxG.stage.window.display.name);
+
+ if (FlxG.gamepads.firstActive != null)
{
- // trace(FlxG.stage.window.display.name);
-
- if (FlxG.gamepads.firstActive != null)
- {
- trace(FlxG.gamepads.firstActive.model);
- FlxG.gamepads.firstActive.id
- }
- else
- trace('gamepad null');
-
- // FlxG.stage.window.title = Std.string(FlxG.random.int(0, 20000));
- // FlxG.stage.window.setIcon(Image.fromFile('assets/images/icon16.png'));
- // FlxG.stage.window.readPixels;
-
- if (FlxG.stage.window.width == Std.int(FlxG.stage.window.display.bounds.width))
- {
- FlxG.stage.window.width = 1280;
- FlxG.stage.window.height = 720;
- FlxG.stage.window.y = 30;
- }
- else
- {
- FlxG.stage.window.width = Std.int(FlxG.stage.window.display.bounds.width);
- FlxG.stage.window.height = Std.int(FlxG.stage.window.display.bounds.height);
- FlxG.stage.window.x = Std.int(FlxG.stage.window.display.bounds.x);
- FlxG.stage.window.y = Std.int(FlxG.stage.window.display.bounds.y);
- }
+ trace(FlxG.gamepads.firstActive.model);
+ FlxG.gamepads.firstActive.id
}
+ else
+ trace('gamepad null');
+
+ // FlxG.stage.window.title = Std.string(FlxG.random.int(0, 20000));
+ // FlxG.stage.window.setIcon(Image.fromFile('assets/images/icon16.png'));
+ // FlxG.stage.window.readPixels;
+
+ if (FlxG.stage.window.width == Std.int(FlxG.stage.window.display.bounds.width))
+ {
+ FlxG.stage.window.width = 1280;
+ FlxG.stage.window.height = 720;
+ FlxG.stage.window.y = 30;
+ }
+ else
+ {
+ FlxG.stage.window.width = Std.int(FlxG.stage.window.display.bounds.width);
+ FlxG.stage.window.height = Std.int(FlxG.stage.window.display.bounds.height);
+ FlxG.stage.window.x = Std.int(FlxG.stage.window.display.bounds.x);
+ FlxG.stage.window.y = Std.int(FlxG.stage.window.display.bounds.y);
+ }
+ }
*/
#if debug
@@ -434,16 +418,16 @@ class TitleState extends MusicBeatState
if (pressedEnter && !skippedIntro && initialized)
skipIntro();
/*
- #if web
- if (!initialized && controls.ACCEPT)
- {
- // netStream.dispose();
- // FlxG.stage.removeChild(video);
+ #if web
+ if (!initialized && controls.ACCEPT)
+ {
+ // netStream.dispose();
+ // FlxG.stage.removeChild(video);
- startIntro();
- skipIntro();
- }
- #end
+ startIntro();
+ skipIntro();
+ }
+ #end
*/
if (controls.UI_LEFT)
@@ -509,7 +493,7 @@ class TitleState extends MusicBeatState
for (i in 0...textArray.length)
{
- var money:BoldText = new BoldText(0, 0, textArray[i]);
+ var money:AtlasText = new AtlasText(0, 0, textArray[i], AtlasFont.BOLD);
money.screenCenter(X);
money.y += (i * 60) + 200;
// credGroup.add(money);
@@ -524,10 +508,9 @@ class TitleState extends MusicBeatState
lime.ui.Haptic.vibrate(100, 100);
- var coolText:BoldText = new BoldText(0, 0, text);
+ var coolText:AtlasText = new AtlasText(0, 0, text, AtlasFont.BOLD);
coolText.screenCenter(X);
coolText.y += (textGroup.length * 60) + 200;
- // credGroup.add(coolText);
textGroup.add(coolText);
}
diff --git a/source/funkin/VoicesGroup.hx b/source/funkin/VoicesGroup.hx
index bb9dd419f..ae34bb0c6 100644
--- a/source/funkin/VoicesGroup.hx
+++ b/source/funkin/VoicesGroup.hx
@@ -38,6 +38,31 @@ class VoicesGroup extends FlxTypedGroup
}
}
+ /**
+ * Finds the largest deviation from the desired time inside this VoicesGroup.
+ *
+ * @param targetTime The time to check against.
+ * If none is provided, it checks the time of all members against the first member of this VoicesGroup.
+ * @return The largest deviation from the target time found.
+ */
+ public function checkSyncError(?targetTime:Float):Float
+ {
+ var error:Float = 0;
+
+ forEachAlive(function(snd)
+ {
+ if (targetTime == null)
+ targetTime = snd.time;
+ else
+ {
+ var diff:Float = snd.time - targetTime;
+ if (Math.abs(diff) > Math.abs(error))
+ error = diff;
+ }
+ });
+ return error;
+ }
+
// prob a better / cleaner way to do all these forEach stuff?
public function pause()
{
diff --git a/source/funkin/animate/ParseAnimate.hx b/source/funkin/animate/ParseAnimate.hx
index 9c2fa17a4..c41aba0f7 100644
--- a/source/funkin/animate/ParseAnimate.hx
+++ b/source/funkin/animate/ParseAnimate.hx
@@ -4,7 +4,9 @@ import haxe.format.JsonParser;
import openfl.Assets;
import openfl.geom.Matrix3D;
import openfl.geom.Matrix;
+#if sys
import sys.io.File;
+#end
/**
* Generally designed / written in a way that can be easily taken out of FNF and used elsewhere
diff --git a/source/funkin/charting/ChartingState.hx b/source/funkin/charting/ChartingState.hx
index 507d8dec6..ba34f2281 100644
--- a/source/funkin/charting/ChartingState.hx
+++ b/source/funkin/charting/ChartingState.hx
@@ -1,14 +1,6 @@
package funkin.charting;
-import funkin.Conductor.BPMChangeEvent;
-import funkin.Note.NoteData;
-import funkin.Section.SwagSection;
-import funkin.SongLoad.SwagSong;
-import funkin.audiovis.ABotVis;
-import funkin.audiovis.PolygonSpectogram;
-import funkin.audiovis.SpectogramSprite;
import flixel.FlxSprite;
-import funkin.play.HealthIcon;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.ui.FlxInputText;
@@ -24,14 +16,22 @@ import flixel.system.FlxSound;
import flixel.text.FlxText;
import flixel.ui.FlxButton;
import flixel.util.FlxColor;
+import funkin.Conductor.BPMChangeEvent;
+import funkin.Note.NoteData;
+import funkin.Section.SwagSection;
+import funkin.SongLoad.SwagSong;
+import funkin.audiovis.ABotVis;
+import funkin.audiovis.PolygonSpectogram;
+import funkin.audiovis.SpectogramSprite;
+import funkin.play.HealthIcon;
+import funkin.play.PlayState;
+import funkin.rendering.MeshRender;
import haxe.Json;
import lime.media.AudioBuffer;
import lime.utils.Assets;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import openfl.net.FileReference;
-import funkin.rendering.MeshRender;
-import funkin.play.PlayState;
using Lambda;
using StringTools;
@@ -976,9 +976,9 @@ class ChartingState extends MusicBeatState
_song.bpm = tempBpm;
/* if (FlxG.keys.justPressed.UP)
- Conductor.bpm += 1;
+ Conductor.bpm = Conductor.bpm + 1;
if (FlxG.keys.justPressed.DOWN)
- Conductor.bpm -= 1; */
+ Conductor.bpm = Conductor.bpm - 1; */
var shiftThing:Int = 1;
if (FlxG.keys.pressed.SHIFT)
diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx
index 882dc86fe..1fe2b0682 100644
--- a/source/funkin/modding/PolymodHandler.hx
+++ b/source/funkin/modding/PolymodHandler.hx
@@ -1,10 +1,9 @@
package funkin.modding;
-import polymod.Polymod.ModMetadata;
+import funkin.modding.module.ModuleHandler;
+import funkin.play.stage.StageData;
import polymod.Polymod;
-import polymod.backends.OpenFLBackend;
import polymod.backends.PolymodAssets.PolymodAssetType;
-import polymod.format.ParseRules.LinesParseFormat;
import polymod.format.ParseRules.TextFileFormat;
class PolymodHandler
@@ -31,6 +30,15 @@ class PolymodHandler
loadModsById(getAllModIds());
}
+ /**
+ * Loads the game with configured mods enabled with Polymod.
+ */
+ public static function loadEnabledMods()
+ {
+ trace("Initializing Polymod (using configured mods)...");
+ loadModsById(getEnabledModIds());
+ }
+
/**
* Loads the game without any mods enabled with Polymod.
*/
@@ -167,4 +175,61 @@ class PolymodHandler
var modIds = [for (i in getAllMods()) i.id];
return modIds;
}
+
+ public static function setEnabledMods(newModList:Array):Void
+ {
+ FlxG.save.data.enabledMods = newModList;
+ // Make sure to COMMIT the changes.
+ FlxG.save.flush();
+ }
+
+ /**
+ * Returns the list of enabled mods.
+ * @return Array
+ */
+ public static function getEnabledModIds():Array
+ {
+ if (FlxG.save.data.enabledMods == null)
+ {
+ // NOTE: If the value is null, the enabled mod list is unconfigured.
+ // Currently, we default to disabling newly installed mods.
+ // If we want to auto-enable new mods, but otherwise leave the configured list in place,
+ // we will need some custom logic.
+ FlxG.save.data.enabledMods = [];
+ }
+ return FlxG.save.data.enabledMods;
+ }
+
+ public static function getEnabledMods():Array
+ {
+ var modIds = getEnabledModIds();
+ var modMetadata = getAllMods();
+ var enabledMods = [];
+ for (item in modMetadata)
+ {
+ if (modIds.indexOf(item.id) != -1)
+ {
+ enabledMods.push(item);
+ }
+ }
+ return enabledMods;
+ }
+
+ public static function forceReloadAssets()
+ {
+ // Forcibly clear scripts so that scripts can be edited.
+ ModuleHandler.clearModuleCache();
+ polymod.hscript.PolymodScriptClass.clearScriptClasses();
+
+ // Forcibly reload Polymod so it finds any new files.
+ loadEnabledMods();
+
+ // Reload scripted classes so stages and modules will update.
+ polymod.hscript.PolymodScriptClass.registerAllScriptClasses();
+
+ // Reload the stages in cache.
+ // TODO: Currently this causes lag since you're reading a lot of files, how to fix?
+ StageDataParser.loadStageCache();
+ ModuleHandler.loadModuleCache();
+ }
}
diff --git a/source/funkin/modding/events/ScriptEventDispatcher.hx b/source/funkin/modding/events/ScriptEventDispatcher.hx
index bfb62b9d1..474d1a18c 100644
--- a/source/funkin/modding/events/ScriptEventDispatcher.hx
+++ b/source/funkin/modding/events/ScriptEventDispatcher.hx
@@ -1,7 +1,7 @@
package funkin.modding.events;
-import funkin.modding.IScriptedClass;
import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
+import funkin.modding.IScriptedClass;
/**
* Utility functions to assist with handling scripted classes.
diff --git a/source/funkin/modding/module/Module.hx b/source/funkin/modding/module/Module.hx
index 74f04c3bd..d337ad719 100644
--- a/source/funkin/modding/module/Module.hx
+++ b/source/funkin/modding/module/Module.hx
@@ -1,13 +1,8 @@
package funkin.modding.module;
-import funkin.modding.events.ScriptEvent;
-import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
-import funkin.modding.events.ScriptEvent.KeyboardInputScriptEvent;
-import funkin.modding.events.ScriptEvent.NoteScriptEvent;
-import funkin.modding.events.ScriptEvent.SongTimeScriptEvent;
-import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
import funkin.modding.IScriptedClass.IStateChangingScriptedClass;
+import funkin.modding.events.ScriptEvent;
/**
* A module is a scripted class which receives all events without requiring a specific context.
diff --git a/source/funkin/play/PicoFight.hx b/source/funkin/play/PicoFight.hx
index 016fada3f..a5dddac3a 100644
--- a/source/funkin/play/PicoFight.hx
+++ b/source/funkin/play/PicoFight.hx
@@ -1,14 +1,13 @@
package funkin.play;
-import funkin.Note.NoteData;
-import funkin.audiovis.PolygonSpectogram;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.addons.effects.FlxTrail;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.util.FlxColor;
-import flixel.util.FlxTimer;
+import funkin.Note.NoteData;
+import funkin.audiovis.PolygonSpectogram;
class PicoFight extends MusicBeatState
{
@@ -202,7 +201,6 @@ class PicoFight extends MusicBeatState
picoHealth += 1;
makeNotes();
-
return true;
}
}
diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx
index 09cdc0c06..87e8d9e69 100644
--- a/source/funkin/play/PlayState.hx
+++ b/source/funkin/play/PlayState.hx
@@ -1,12 +1,12 @@
package funkin.play;
-import funkin.play.character.BaseCharacter;
-import flixel.addons.transition.FlxTransitionableState;
import flixel.FlxCamera;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxSubState;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup;
import flixel.math.FlxMath;
import flixel.math.FlxPoint;
@@ -18,22 +18,27 @@ import flixel.ui.FlxBar;
import flixel.util.FlxColor;
import flixel.util.FlxSort;
import flixel.util.FlxTimer;
-import funkin.charting.ChartingState;
-import funkin.modding.events.ScriptEvent;
-import funkin.modding.events.ScriptEvent.SongTimeScriptEvent;
-import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
-import funkin.modding.events.ScriptEventDispatcher;
-import funkin.modding.IHook;
-import funkin.modding.module.ModuleHandler;
import funkin.Note;
-import funkin.play.character.CharacterData;
-import funkin.play.stage.Stage;
-import funkin.play.HealthIcon;
-import funkin.play.stage.StageData;
-import funkin.play.Strumline.StrumlineArrow;
-import funkin.play.Strumline.StrumlineStyle;
+import funkin.Note;
+import funkin.Section.SwagSection;
import funkin.Section.SwagSection;
import funkin.SongLoad.SwagSong;
+import funkin.SongLoad.SwagSong;
+import funkin.charting.ChartingState;
+import funkin.modding.IHook;
+import funkin.modding.IHook;
+import funkin.modding.events.ScriptEvent;
+import funkin.modding.events.ScriptEventDispatcher;
+import funkin.modding.module.ModuleHandler;
+import funkin.play.HealthIcon;
+import funkin.play.Strumline.StrumlineArrow;
+import funkin.play.Strumline.StrumlineArrow;
+import funkin.play.Strumline.StrumlineStyle;
+import funkin.play.Strumline.StrumlineStyle;
+import funkin.play.character.BaseCharacter;
+import funkin.play.character.CharacterData;
+import funkin.play.stage.Stage;
+import funkin.play.stage.StageData;
import funkin.ui.PopUpStuff;
import funkin.ui.PreferencesMenu;
import funkin.util.Constants;
@@ -838,7 +843,7 @@ class PlayState extends MusicBeatState implements IHook
var gottaHitNote:Bool = section.mustHitSection;
- if (songNotes.highStakes)
+ if (songNotes.highStakes) // noteData > 3
gottaHitNote = !section.mustHitSection;
var oldNote:Note;
@@ -848,7 +853,9 @@ class PlayState extends MusicBeatState implements IHook
oldNote = null;
var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote);
- swagNote.data = songNotes;
+ // swagNote.data = songNotes;
+ swagNote.data.sustainLength = songNotes.sustainLength;
+ swagNote.data.altNote = songNotes.altNote;
swagNote.scrollFactor.set(0, 0);
var susLength:Float = swagNote.data.sustainLength;
@@ -950,6 +957,7 @@ class PlayState extends MusicBeatState implements IHook
vocals.pause();
FlxG.sound.music.time = 0;
+
regenNoteData(); // loads the note data from start
health = 1;
songScore = 0;
@@ -1597,7 +1605,7 @@ class PlayState extends MusicBeatState implements IHook
}
}
- if (PlayState.instance.currentStage == null)
+ if (PlayState.instance == null || PlayState.instance.currentStage == null)
return;
for (keyId => isPressed in pressArray)
@@ -1709,9 +1717,8 @@ class PlayState extends MusicBeatState implements IHook
if (!super.stepHit())
return false;
- if (!isInCutscene
- && Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 20
- || (currentSong.needsVoices && Math.abs(vocals.time - (Conductor.songPosition - Conductor.offset)) > 20))
+ if (Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 20
+ || Math.abs(vocals.checkSyncError(Conductor.songPosition - Conductor.offset)) > 20)
{
resyncVocals();
}
diff --git a/source/funkin/play/VanillaCutscenes.hx b/source/funkin/play/VanillaCutscenes.hx
index 9cbcd8736..71587eeb9 100644
--- a/source/funkin/play/VanillaCutscenes.hx
+++ b/source/funkin/play/VanillaCutscenes.hx
@@ -1,10 +1,12 @@
package funkin.play;
-import flixel.util.FlxTimer;
-import flixel.tweens.FlxTween;
-import flixel.tweens.FlxEase;
-import flixel.util.FlxColor;
import flixel.FlxSprite;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
/**
* Static methods for playing cutscenes in the PlayState.
@@ -43,8 +45,8 @@ class VanillaCutscenes
PlayState.instance.add(blackScreen);
#if html5
- vid:FlxVideo = new FlxVideo(path);
- vid.finishCallback = finishVideoCutscene();
+ var vid:FlxVideo = new FlxVideo(path);
+ vid.finishCallback = finishVideoCutscene;
#else
finishVideoCutscene();
#end
diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx
index 0b026ed22..dfb91607c 100644
--- a/source/funkin/play/stage/Bopper.hx
+++ b/source/funkin/play/stage/Bopper.hx
@@ -1,12 +1,8 @@
package funkin.play.stage;
-import funkin.modding.events.ScriptEvent;
-import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
-import funkin.modding.events.ScriptEvent.NoteScriptEvent;
-import funkin.modding.events.ScriptEvent.SongTimeScriptEvent;
-import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
-import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
import flixel.FlxSprite;
+import funkin.modding.IScriptedClass.IPlayStateScriptedClass;
+import funkin.modding.events.ScriptEvent;
/**
* A Bopper is a stage prop which plays a dance animation.
@@ -97,14 +93,14 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
{
if (danceEvery > 0 && event.beat % danceEvery == 0)
{
- dance();
+ dance(true);
}
}
/**
* Called every `danceEvery` beats of the song.
*/
- function dance(force:Bool = false):Void
+ public function dance(force:Bool = false):Void
{
if (this.animation == null)
{
@@ -120,17 +116,17 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
{
if (hasDanced)
{
- playAnimation('danceRight$idleSuffix');
+ playAnimation('danceRight$idleSuffix', force);
}
else
{
- playAnimation('danceLeft$idleSuffix');
+ playAnimation('danceLeft$idleSuffix', force);
}
hasDanced = !hasDanced;
}
else
{
- playAnimation('idle$idleSuffix');
+ playAnimation('idle$idleSuffix', force);
}
}
@@ -213,7 +209,6 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
public function setAnimationOffsets(name:String, xOffset:Float, yOffset:Float):Void
{
animationOffsets.set(name, [xOffset, yOffset]);
- applyAnimationOffsets(name);
}
/**
diff --git a/source/funkin/play/stage/ScriptedBopper.hx b/source/funkin/play/stage/ScriptedBopper.hx
index 4dd98e82c..405ef57f6 100644
--- a/source/funkin/play/stage/ScriptedBopper.hx
+++ b/source/funkin/play/stage/ScriptedBopper.hx
@@ -2,7 +2,5 @@ package funkin.play.stage;
import funkin.modding.IHook;
-//
-// @:hscriptClass
-// @:keep
-// class ScriptedBopper extends Bopper implements IHook {}
+@:hscriptClass
+class ScriptedBopper extends Bopper implements IHook {}
diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx
index 2b8c46acb..8e2713b2c 100644
--- a/source/funkin/play/stage/Stage.hx
+++ b/source/funkin/play/stage/Stage.hx
@@ -1,20 +1,16 @@
package funkin.play.stage;
-import funkin.util.assets.FlxAnimationUtil;
-import funkin.play.character.BaseCharacter;
-import funkin.modding.events.ScriptEventDispatcher;
-import funkin.modding.events.ScriptEvent;
-import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
-import funkin.modding.events.ScriptEvent.KeyboardInputScriptEvent;
-import funkin.modding.IScriptedClass;
import flixel.FlxSprite;
import flixel.group.FlxSpriteGroup;
-import flixel.math.FlxPoint;
import flixel.util.FlxSort;
import funkin.modding.IHook;
-import funkin.play.character.BaseCharacter.CharacterType;
+import funkin.modding.IScriptedClass;
+import funkin.modding.events.ScriptEvent;
+import funkin.modding.events.ScriptEventDispatcher;
+import funkin.play.character.Character.CharacterType;
import funkin.play.stage.StageData.StageDataParser;
import funkin.util.SortUtil;
+import funkin.util.assets.FlxAnimationUtil;
/**
* A Stage is a group of objects rendered in the PlayState.
@@ -149,6 +145,18 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
if (Std.isOfType(propSprite, Bopper))
{
cast(propSprite, Bopper).setAnimationOffsets(propAnim.name, propAnim.offsets[0], propAnim.offsets[1]);
+<<<<<<< HEAD
+=======
+ }
+ }
+ default: // "sparrow"
+ FlxAnimationUtil.addAtlasAnimations(propSprite, dataProp.animations);
+ if (Std.isOfType(propSprite, Bopper))
+ {
+ for (propAnim in dataProp.animations)
+ {
+ cast(propSprite, Bopper).setAnimationOffsets(propAnim.name, propAnim.offsets[0], propAnim.offsets[1]);
+>>>>>>> origin/feature/scripted-modules
}
}
default: // "sparrow"
@@ -427,33 +435,45 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
for (prop in this.namedProps)
{
- remove(prop);
- prop.kill();
- prop.destroy();
+ if (prop != null)
+ {
+ remove(prop);
+ prop.kill();
+ prop.destroy();
+ }
}
namedProps.clear();
for (char in this.characters)
{
- remove(char);
- char.kill();
- char.destroy();
+ if (char != null)
+ {
+ remove(char);
+ char.kill();
+ char.destroy();
+ }
}
characters.clear();
for (bopper in boppers)
{
- remove(bopper);
- bopper.kill();
- bopper.destroy();
+ if (bopper != null)
+ {
+ remove(bopper);
+ bopper.kill();
+ bopper.destroy();
+ }
}
boppers = [];
for (sprite in this.group)
{
- remove(sprite);
- sprite.kill();
- sprite.destroy();
+ if (sprite != null)
+ {
+ sprite.kill();
+ sprite.destroy();
+ remove(sprite);
+ }
}
group.clear();
}
@@ -497,9 +517,6 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
public function onCountdownEnd(event:CountdownScriptEvent) {}
- /**
- * A function that should get called every frame.
- */
public function onUpdate(event:UpdateScriptEvent) {}
public function onNoteHit(event:NoteScriptEvent) {}
diff --git a/source/funkin/play/stage/StageData.hx b/source/funkin/play/stage/StageData.hx
index 4e240b8b6..dc5538bac 100644
--- a/source/funkin/play/stage/StageData.hx
+++ b/source/funkin/play/stage/StageData.hx
@@ -1,7 +1,7 @@
package funkin.play.stage;
-import funkin.util.VersionUtil;
import flixel.util.typeLimit.OneOfTwo;
+import funkin.util.VersionUtil;
import funkin.util.assets.DataAssets;
import haxe.Json;
import openfl.Assets;
diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx
index 3006f3994..b07aca240 100644
--- a/source/funkin/ui/AtlasText.hx
+++ b/source/funkin/ui/AtlasText.hx
@@ -1,19 +1,10 @@
package funkin.ui;
import flixel.FlxSprite;
-import flixel.group.FlxSpriteGroup;
import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxSpriteGroup;
import flixel.util.FlxStringUtil;
-@:forward
-abstract BoldText(AtlasText) from AtlasText to AtlasText
-{
- inline public function new(x = 0.0, y = 0.0, text:String)
- {
- this = new AtlasText(x, y, text, AtlasFont.BOLD);
- }
-}
-
/**
* AtlasText is an improved version of Alphabet and FlxBitmapText.
* It supports animations on the letters, and is less buggy than Alphabet.
diff --git a/source/funkin/ui/ControlsMenu.hx b/source/funkin/ui/ControlsMenu.hx
index 62445be96..e5e3e44b0 100644
--- a/source/funkin/ui/ControlsMenu.hx
+++ b/source/funkin/ui/ControlsMenu.hx
@@ -1,6 +1,5 @@
package funkin.ui;
-import funkin.Controls;
import flixel.FlxCamera;
import flixel.FlxObject;
import flixel.FlxSprite;
@@ -8,6 +7,7 @@ import flixel.group.FlxGroup;
import flixel.input.actions.FlxActionInput;
import flixel.input.gamepad.FlxGamepadInputID;
import flixel.input.keyboard.FlxKey;
+import funkin.Controls;
import funkin.ui.AtlasText;
import funkin.ui.MenuList;
import funkin.ui.TextMenuList;
@@ -87,20 +87,20 @@ class ControlsMenu extends funkin.ui.OptionsState.Page
if (currentHeader != "UI_" && name.indexOf("UI_") == 0)
{
currentHeader = "UI_";
- headers.add(new BoldText(0, y, "UI")).screenCenter(X);
+ headers.add(new AtlasText(0, y, "UI", AtlasFont.BOLD)).screenCenter(X);
y += spacer;
}
else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0)
{
currentHeader = "NOTE_";
- headers.add(new BoldText(0, y, "NOTES")).screenCenter(X);
+ headers.add(new AtlasText(0, y, "NOTES", AtlasFont.BOLD)).screenCenter(X);
y += spacer;
}
if (currentHeader != null && name.indexOf(currentHeader) == 0)
name = name.substr(currentHeader.length);
- var label = labels.add(new BoldText(150, y, name));
+ var label = labels.add(new AtlasText(150, y, name, AtlasFont.BOLD));
label.alpha = 0.6;
for (i in 0...COLUMNS)
createItem(label.x + 400 + i * 300, y, control, i);
diff --git a/source/funkin/ui/OptionsState.hx b/source/funkin/ui/OptionsState.hx
index 32b511d3e..3a74ef3f8 100644
--- a/source/funkin/ui/OptionsState.hx
+++ b/source/funkin/ui/OptionsState.hx
@@ -5,9 +5,9 @@ import flixel.FlxSubState;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup;
import flixel.util.FlxSignal;
+import funkin.util.Constants;
+import funkin.util.WindowUtil;
-// typedef OptionsState = OptionsMenu_old;
-// class OptionsState_new extends MusicBeatState
class OptionsState extends MusicBeatState
{
var pages = new Map();
@@ -30,17 +30,12 @@ class OptionsState extends MusicBeatState
var options = addPage(Options, new OptionsMenu(false));
var preferences = addPage(Preferences, new PreferencesMenu());
var controls = addPage(Controls, new ControlsMenu());
- // var colors = addPage(Colors, new ColorsMenu());
-
- var mods = addPage(Mods, new ModMenu());
if (options.hasMultipleOptions())
{
options.onExit.add(exitToMainMenu);
controls.onExit.add(switchPage.bind(Options));
- // colors.onExit.add(switchPage.bind(Options));
preferences.onExit.add(switchPage.bind(Options));
- mods.onExit.add(switchPage.bind(Options));
}
else
{
@@ -66,12 +61,18 @@ class OptionsState extends MusicBeatState
function setPage(name:PageName)
{
if (pages.exists(currentName))
+ {
currentPage.exists = false;
+ currentPage.visible = false;
+ }
currentName = name;
if (pages.exists(currentName))
+ {
currentPage.exists = true;
+ currentPage.visible = true;
+ }
}
override function finishTransIn()
@@ -90,7 +91,7 @@ class OptionsState extends MusicBeatState
function exitToMainMenu()
{
currentPage.enabled = false;
- // Todo animate?
+ // TODO: Animate this transition?
FlxG.switchState(new MainMenuState());
}
}
@@ -174,7 +175,6 @@ class OptionsMenu extends Page
createItem("PREFERENCES", function() switchPage(Preferences));
createItem("CONTROLS", function() switchPage(Controls));
// createItem("COLORS", function() switchPage(Colors));
- createItem("MODS", function() switchPage(Mods));
#if CAN_OPEN_LINKS
if (showDonate)
@@ -218,11 +218,7 @@ class OptionsMenu extends Page
#if CAN_OPEN_LINKS
function selectDonate()
{
- #if linux
- Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]);
- #else
- FlxG.openURL('https://ninja-muffin24.itch.io/funkin');
- #end
+ WindowUtil.openURL(Constants.URL_ITCH);
}
#end
diff --git a/source/funkin/ui/PreferencesMenu.hx b/source/funkin/ui/PreferencesMenu.hx
index a5aa4e368..94158bcce 100644
--- a/source/funkin/ui/PreferencesMenu.hx
+++ b/source/funkin/ui/PreferencesMenu.hx
@@ -4,8 +4,8 @@ import flixel.FlxCamera;
import flixel.FlxObject;
import flixel.FlxSprite;
import funkin.ui.AtlasText.AtlasFont;
-import funkin.ui.TextMenuList.TextMenuItem;
import funkin.ui.OptionsState.Page;
+import funkin.ui.TextMenuList.TextMenuItem;
class PreferencesMenu extends Page
{
diff --git a/source/funkin/ui/Prompt.hx b/source/funkin/ui/Prompt.hx
index 1679d3886..76d85744b 100644
--- a/source/funkin/ui/Prompt.hx
+++ b/source/funkin/ui/Prompt.hx
@@ -1,12 +1,12 @@
package funkin.ui;
import flixel.FlxSprite;
-import flixel.graphics.frames.FlxAtlasFrames;
-import flixel.text.FlxText;
-import flixel.util.FlxColor;
-import funkin.ui.AtlasText;
+import funkin.ui.AtlasText.AtlasFont;
import funkin.ui.MenuList;
+/**
+ * Opens a yes/no dialog box as a substate over the current state.
+ */
class Prompt extends flixel.FlxSubState
{
inline static var MARGIN = 100;
@@ -26,7 +26,7 @@ class Prompt extends flixel.FlxSubState
buttons = new TextMenuList(Horizontal);
- field = new BoldText(text);
+ field = new AtlasText(text, AtlasFont.BOLD);
field.scrollFactor.set(0, 0);
}
diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx
index af775babe..a93578c20 100644
--- a/source/funkin/util/Constants.hx
+++ b/source/funkin/util/Constants.hx
@@ -1,7 +1,7 @@
package funkin.util;
-import lime.app.Application;
import flixel.util.FlxColor;
+import lime.app.Application;
class Constants
{
@@ -18,6 +18,8 @@ class Constants
public static final VERSION_SUFFIX = ' PROTOTYPE';
public static var VERSION(get, null):String;
+ public static final FREAKY_MENU_BPM = 102;
+
#if debug
public static final GIT_HASH = funkin.util.macro.GitCommit.getGitCommitHash();
diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx
index a5c7e71f4..57e1f80ed 100644
--- a/source/funkin/util/VersionUtil.hx
+++ b/source/funkin/util/VersionUtil.hx
@@ -1,7 +1,7 @@
package funkin.util;
-import thx.semver.VersionRule;
import thx.semver.Version;
+import thx.semver.VersionRule;
/**
* Remember, increment the patch version (1.0.x) if you make a bugfix,
diff --git a/source/funkin/util/assets/FlxAnimationUtil.hx b/source/funkin/util/assets/FlxAnimationUtil.hx
index ac07e6065..d40dfa73c 100644
--- a/source/funkin/util/assets/FlxAnimationUtil.hx
+++ b/source/funkin/util/assets/FlxAnimationUtil.hx
@@ -1,7 +1,7 @@
package funkin.util.assets;
-import funkin.play.AnimationData;
import flixel.FlxSprite;
+import funkin.play.AnimationData;
class FlxAnimationUtil
{