Merge remote-tracking branch 'origin/feature/scripted-modules' into feature/scripted-characters

This commit is contained in:
Eric Myllyoja 2022-04-18 20:39:41 -04:00
commit 43dbce2be1
38 changed files with 491 additions and 377 deletions

5
.gitignore vendored
View file

@ -2,7 +2,4 @@ export/
.vscode/
APIStuff.hx
.DS_STORE
example_mods/enaSkin/
example_mods/tricky/
RECOVER_*.fla

17
.vscode/launch.json vendored
View file

@ -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"
]
}

View file

@ -96,7 +96,13 @@
<!-- <assets path='example_mods' rename='mods' embed='false'/> -->
<assets path='example_mods' rename='mods' embed='false' exclude="*.md" />
<!--
AUTOMATICALLY MOVING EXAMPLE MODS INTO THE BUILD CAUSES ISSUES
Currently, this line will add the mod files to the library manifest,
which causes issues if the mod is not enabled.
If we can exclude the `mods` folder from the manifest, we can re-enable this line.
<assets path='example_mods' rename='mods' embed='false' exclude="*.md" />
-->
<assets path='art/readme.txt' rename='do NOT readme.txt' />
<assets path="CHANGELOG.md" rename='changelog.txt' />
@ -192,7 +198,7 @@
<haxeflag name="--macro" value="include('funkin')" />
<!-- Necessary to provide stack traces for HScript. -->
<haxedef name="hscriptPos" />
<haxedef name="hscriptPos" />
<haxedef name="HXCPP_CHECK_POINTER" />
<haxedef name="HXCPP_STACK_LINE" />

View file

@ -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"

View file

@ -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"

View file

@ -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<String>).
// TODO: Replace this with loadEnabledMods().
funkin.modding.PolymodHandler.loadAllMods();
if (stage != null)

View file

@ -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());
}

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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)

View file

@ -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();

View file

@ -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.

View file

@ -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

View file

@ -22,6 +22,8 @@ class NoteSplash extends FlxSprite
setupNoteSplash(x, y, noteData);
antialiasing = true;
// alpha = 0.75;
}

View file

@ -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<FlxSprite>;
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<FlxSprite>();
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));

View file

@ -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);
}

View file

@ -38,6 +38,31 @@ class VoicesGroup extends FlxTypedGroup<FlxSound>
}
}
/**
* 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()
{

View file

@ -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

View file

@ -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)

View file

@ -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<String>):Void
{
FlxG.save.data.enabledMods = newModList;
// Make sure to COMMIT the changes.
FlxG.save.flush();
}
/**
* Returns the list of enabled mods.
* @return Array<String>
*/
public static function getEnabledModIds():Array<String>
{
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<ModMetadata>
{
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();
}
}

View file

@ -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.

View file

@ -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.

View file

@ -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;
}
}

View file

@ -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();
}

View file

@ -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

View file

@ -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);
}
/**

View file

@ -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 {}

View file

@ -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) {}

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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<PageName, Page>();
@ -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

View file

@ -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
{

View file

@ -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);
}

View file

@ -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();

View file

@ -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,

View file

@ -1,7 +1,7 @@
package funkin.util.assets;
import funkin.play.AnimationData;
import flixel.FlxSprite;
import funkin.play.AnimationData;
class FlxAnimationUtil
{