mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-11-29 15:56:06 +00:00
Merge branch 'rewrite/master' into pico-cutscene-tweaks
This commit is contained in:
commit
e2a51def65
|
|
@ -29,8 +29,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Implemented support for a new Instrumental Selector in Freeplay
|
||||
- Beating a Pico remix lets you use that instrumental when playing as Boyfriend
|
||||
- Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes
|
||||
- Week 1 Erect Stage
|
||||
- Week 2 Erect Stage
|
||||
- Week 3 Erect Stage
|
||||
- Week 4 Erect Stage
|
||||
- Week 5 Erect Stage
|
||||
- Weekend 1 Erect Stage
|
||||
- Implemented alternate animations and music for Pico in the results screen.
|
||||
- These display on Pico remixes, as well as when playing Weekend 1.
|
||||
- Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1)
|
||||
- Implemented a new Strumline Background option, to display a darkened background behind the strumline with your choice of opacity.
|
||||
- Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand)
|
||||
## Changed
|
||||
- Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo.
|
||||
|
|
|
|||
2
art
2
art
|
|
@ -1 +1 @@
|
|||
Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9
|
||||
Subproject commit 0dee03f11afc01c2883da223fa10405f7011dd33
|
||||
2
assets
2
assets
|
|
@ -1 +1 @@
|
|||
Subproject commit 350910d8094853d11deb2ee27cacbe3ada27af32
|
||||
Subproject commit 86a0a01e188a80a51b88a0a4188609f2db452bab
|
||||
2
hmm.json
2
hmm.json
|
|
@ -194,7 +194,7 @@
|
|||
"name": "polymod",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "96cfc5fa693b017e47f7cb13b765cc68698fa6b6",
|
||||
"ref": "0fbdf27fe124549730accd540cec8a183f8652c0",
|
||||
"url": "https://github.com/larsiusprime/polymod"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,14 +67,9 @@ class Main extends Sprite
|
|||
function init(?event:Event):Void
|
||||
{
|
||||
#if web
|
||||
untyped js.Syntax.code("
|
||||
window.requestAnimationFrame = function(callback, element) {
|
||||
var currTime = new Date().getTime();
|
||||
var timeToCall = 0;
|
||||
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
||||
timeToCall);
|
||||
return id;
|
||||
}");
|
||||
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
|
||||
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
|
||||
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
|
||||
#end
|
||||
|
||||
if (hasEventListener(Event.ADDED_TO_STAGE))
|
||||
|
|
|
|||
|
|
@ -128,6 +128,48 @@ class Preferences
|
|||
return value;
|
||||
}
|
||||
|
||||
public static var unlockedFramerate(get, set):Bool;
|
||||
|
||||
static function get_unlockedFramerate():Bool
|
||||
{
|
||||
return Save?.instance?.options?.unlockedFramerate;
|
||||
}
|
||||
|
||||
static function set_unlockedFramerate(value:Bool):Bool
|
||||
{
|
||||
if (value != Save.instance.options.unlockedFramerate)
|
||||
{
|
||||
#if web
|
||||
toggleFramerateCap(value);
|
||||
#end
|
||||
}
|
||||
|
||||
var save:Save = Save.instance;
|
||||
save.options.unlockedFramerate = value;
|
||||
save.flush();
|
||||
return value;
|
||||
}
|
||||
|
||||
#if web
|
||||
// We create a haxe version of this just for readability.
|
||||
// We use these to override `window.requestAnimationFrame` in Javascript to uncap the framerate / "animation" request rate
|
||||
// Javascript is crazy since u can just do stuff like that lol
|
||||
|
||||
public static function unlockedFramerateFunction(callback, element)
|
||||
{
|
||||
var currTime = Date.now().getTime();
|
||||
var timeToCall = 0;
|
||||
var id = js.Browser.window.setTimeout(function() {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
return id;
|
||||
}
|
||||
|
||||
// Lime already implements their own little framerate cap, so we can just use that
|
||||
// This also gets set in the init function in Main.hx, since we need to definitely override it
|
||||
public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
|
||||
#end
|
||||
|
||||
/**
|
||||
* Loads the user's preferences from the save data and apply them.
|
||||
*/
|
||||
|
|
@ -137,6 +179,17 @@ class Preferences
|
|||
FlxG.autoPause = Preferences.autoPause;
|
||||
// Apply the debugDisplay setting (enables the FPS and RAM display).
|
||||
toggleDebugDisplay(Preferences.debugDisplay);
|
||||
#if web
|
||||
toggleFramerateCap(Preferences.unlockedFramerate);
|
||||
#end
|
||||
}
|
||||
|
||||
static function toggleFramerateCap(unlocked:Bool):Void
|
||||
{
|
||||
#if web
|
||||
var framerateFunction = unlocked ? unlockedFramerateFunction : lockedFramerateFunction;
|
||||
untyped js.Syntax.code("window.requestAnimationFrame = framerateFunction;");
|
||||
#end
|
||||
}
|
||||
|
||||
static function toggleDebugDisplay(show:Bool):Void
|
||||
|
|
|
|||
|
|
@ -340,6 +340,8 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
if (songMusicData != null)
|
||||
{
|
||||
Conductor.instance.mapTimeChanges(songMusicData.timeChanges);
|
||||
|
||||
if (songMusicData.looped != null && params.loop == null) params.loop = songMusicData.looped;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -185,11 +185,12 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
// Move to the first frame of the animation.
|
||||
// goToFrameLabel(id);
|
||||
trace('Playing animation $id');
|
||||
if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
|
||||
if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
|
||||
{
|
||||
this.anim.play(id, restart, false, startFrame);
|
||||
|
||||
if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame);
|
||||
this.currentAnimation = anim.curSymbol.name;
|
||||
|
||||
fr = null;
|
||||
}
|
||||
// Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
|
||||
|
|
@ -316,6 +317,10 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
{
|
||||
onAnimationComplete.dispatch(currentAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
onAnimationComplete.dispatch('');
|
||||
}
|
||||
}
|
||||
|
||||
var prevFrames:Map<Int, FlxFrame> = [];
|
||||
|
|
|
|||
|
|
@ -418,8 +418,7 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
restartTrack: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -429,8 +428,7 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
restartTrack: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -577,19 +577,6 @@ enum abstract ScoringRank(String)
|
|||
}
|
||||
}
|
||||
|
||||
public function shouldMusicLoop():Bool
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD | PERFECT | EXCELLENT | GREAT | GOOD:
|
||||
return true;
|
||||
case SHIT:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getHorTextAsset()
|
||||
{
|
||||
switch (abstract)
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ class Save
|
|||
autoPause: true,
|
||||
inputOffset: 0,
|
||||
audioVisualOffset: 0,
|
||||
unlockedFramerate: false,
|
||||
|
||||
controls:
|
||||
{
|
||||
|
|
@ -407,6 +408,9 @@ class Save
|
|||
return data.unlocks.charactersSeen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks whether the player has seen the spotlight animation, which should only display once per save file ever.
|
||||
*/
|
||||
public var oldChar(get, set):Bool;
|
||||
|
||||
function get_oldChar():Bool
|
||||
|
|
@ -416,7 +420,9 @@ class Save
|
|||
|
||||
function set_oldChar(value:Bool):Bool
|
||||
{
|
||||
return data.unlocks.oldChar = value;
|
||||
data.unlocks.oldChar = value;
|
||||
flush();
|
||||
return data.unlocks.oldChar;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -425,7 +431,11 @@ class Save
|
|||
*/
|
||||
public function addCharacterSeen(character:String):Void
|
||||
{
|
||||
if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character);
|
||||
if (!data.unlocks.charactersSeen.contains(character))
|
||||
{
|
||||
data.unlocks.charactersSeen.push(character);
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1171,6 +1181,12 @@ typedef SaveDataOptions =
|
|||
*/
|
||||
var audioVisualOffset:Int;
|
||||
|
||||
/**
|
||||
* If we want the framerate to be unlocked on HTML5.
|
||||
* @default `false
|
||||
*/
|
||||
var unlockedFramerate:Bool;
|
||||
|
||||
var controls:
|
||||
{
|
||||
var p1:
|
||||
|
|
|
|||
|
|
@ -71,12 +71,17 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
var availableChars:Map<Int, String> = new Map<Int, String>();
|
||||
var pressedSelect:Bool = false;
|
||||
var selectTimer:FlxTimer = new FlxTimer();
|
||||
|
||||
var selectSound:FunkinSound;
|
||||
var unlockSound:FunkinSound;
|
||||
var lockedSound:FunkinSound;
|
||||
var introSound:FunkinSound;
|
||||
var staticSound:FunkinSound;
|
||||
|
||||
var charSelectCam:FunkinCamera;
|
||||
|
||||
var selectedBizz:Array<BitmapFilter> = [
|
||||
new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 21, 1, false, false, false),
|
||||
new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 19, 1, false, false, false),
|
||||
new DropShadowFilter(5, 45, 0x000000, 1, 2, 2, 1, 1, false, false, false)
|
||||
];
|
||||
|
||||
|
|
@ -125,7 +130,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
add(bg);
|
||||
|
||||
var crowd:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/crowd"));
|
||||
crowd.anim.play("");
|
||||
crowd.anim.play();
|
||||
crowd.scrollFactor.set(0.3, 0.3);
|
||||
add(crowd);
|
||||
|
||||
|
|
@ -224,7 +229,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
// FlxG.debugger.track(bfChill, "bf chill");
|
||||
// FlxG.debugger.track(playerChill, "player");
|
||||
// FlxG.debugger.track(nametag, "nametag");
|
||||
FlxG.debugger.track(selectSound, "selectSound");
|
||||
// FlxG.debugger.track(selectSound, "selectSound");
|
||||
// FlxG.debugger.track(chooseDipshit, "choose dipshit");
|
||||
// FlxG.debugger.track(barthing, "barthing");
|
||||
// FlxG.debugger.track(fgBlur, "fgBlur");
|
||||
|
|
@ -289,6 +294,26 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
FlxG.sound.defaultSoundGroup.add(unlockSound);
|
||||
FlxG.sound.list.add(unlockSound);
|
||||
|
||||
lockedSound = new FunkinSound();
|
||||
lockedSound.loadEmbedded(Paths.sound('CS_locked'));
|
||||
lockedSound.pitch = 1;
|
||||
|
||||
lockedSound.volume = 1.;
|
||||
|
||||
FlxG.sound.defaultSoundGroup.add(lockedSound);
|
||||
FlxG.sound.list.add(lockedSound);
|
||||
|
||||
staticSound = new FunkinSound();
|
||||
staticSound.loadEmbedded(Paths.sound('static loop'));
|
||||
staticSound.pitch = 1;
|
||||
|
||||
staticSound.looped = true;
|
||||
|
||||
staticSound.volume = 0.6;
|
||||
|
||||
FlxG.sound.defaultSoundGroup.add(staticSound);
|
||||
FlxG.sound.list.add(staticSound);
|
||||
|
||||
// playing it here to preload it. not doing this makes a super awkward pause at the end of the intro
|
||||
// TODO: probably make an intro thing for funkinSound itself that preloads the next audio?
|
||||
FunkinSound.playMusic('stayFunky',
|
||||
|
|
@ -324,6 +349,9 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
// FlxG.camera.follow(camFollow, LOCKON, 0.01);
|
||||
FlxG.camera.follow(camFollow, LOCKON);
|
||||
|
||||
var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader);
|
||||
FlxG.camera.filters = [fadeShaderFilter];
|
||||
|
||||
var temp:FlxSprite = new FlxSprite();
|
||||
temp.loadGraphic(Paths.image('charSelect/placement'));
|
||||
add(temp);
|
||||
|
|
@ -356,10 +384,24 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
blackScreen.y = -(FlxG.height * 0.5);
|
||||
add(blackScreen);
|
||||
|
||||
introSound = new FunkinSound();
|
||||
introSound.loadEmbedded(Paths.sound('CS_Lights'));
|
||||
introSound.pitch = 1;
|
||||
introSound.volume = 0;
|
||||
|
||||
FlxG.sound.defaultSoundGroup.add(introSound);
|
||||
FlxG.sound.list.add(introSound);
|
||||
|
||||
openSubState(new IntroSubState());
|
||||
subStateClosed.addOnce((_) -> {
|
||||
remove(blackScreen);
|
||||
if (!Save.instance.oldChar) camera.flash();
|
||||
if (!Save.instance.oldChar)
|
||||
{
|
||||
camera.flash();
|
||||
|
||||
introSound.volume = 1;
|
||||
introSound.play(true);
|
||||
}
|
||||
checkNewChar();
|
||||
|
||||
Save.instance.oldChar = true;
|
||||
|
|
@ -368,7 +410,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
|
||||
function checkNewChar():Void
|
||||
{
|
||||
if (nonLocks.length > 0) selectTimer.start(0.5, (_) -> {
|
||||
if (nonLocks.length > 0) selectTimer.start(2, (_) -> {
|
||||
unLock();
|
||||
});
|
||||
else
|
||||
|
|
@ -503,7 +545,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
updateIconPositions();
|
||||
playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death")
|
||||
{
|
||||
sync = false;
|
||||
// sync = false;
|
||||
playerChillOut.visible = false;
|
||||
playerChillOut.switchChar(char);
|
||||
});
|
||||
|
|
@ -513,6 +555,9 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
{
|
||||
pressedSelect = false;
|
||||
@:bypassAccessor curChar = char;
|
||||
|
||||
staticSound.stop();
|
||||
|
||||
FunkinSound.playMusic('stayFunky',
|
||||
{
|
||||
startingVolume: 1,
|
||||
|
|
@ -565,7 +610,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
function syncAudio(elapsed:Float):Void
|
||||
{
|
||||
@:privateAccess
|
||||
if (sync && !unlockSound.paused)
|
||||
if (sync && unlockSound.time > 0)
|
||||
{
|
||||
// if (playerChillOut.anim.framerate > 0)
|
||||
// {
|
||||
|
|
@ -576,12 +621,12 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
playerChillOut.anim._tick = 0;
|
||||
if (syncLock != null) syncLock.anim._tick = 0;
|
||||
|
||||
if ((unlockSound.time - audioBizz) >= (delay * 1000))
|
||||
if ((unlockSound.time - audioBizz) >= ((delay) * 100))
|
||||
{
|
||||
if (syncLock != null) syncLock.anim._tick = delay;
|
||||
|
||||
playerChillOut.anim._tick = delay;
|
||||
audioBizz += delay * 1000;
|
||||
audioBizz += delay * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -728,8 +773,11 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
cursorY = -1;
|
||||
}
|
||||
|
||||
if (availableChars.exists(getCurrentSelected()) && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()]))
|
||||
if (autoFollow
|
||||
&& availableChars.exists(getCurrentSelected())
|
||||
&& Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()]))
|
||||
{
|
||||
gfChill.visible = true;
|
||||
curChar = availableChars.get(getCurrentSelected());
|
||||
|
||||
if (!pressedSelect && controls.ACCEPT)
|
||||
|
|
@ -746,7 +794,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1, {ease: FlxEase.quadInOut});
|
||||
FlxTween.tween(FlxG.sound.music, {volume: 0.0}, 1.5, {ease: FlxEase.quadInOut});
|
||||
playerChill.playAnimation("select");
|
||||
gfChill.playAnimation("confirm");
|
||||
gfChill.playAnimation("confirm", true, false, true);
|
||||
pressedSelect = true;
|
||||
selectTimer.start(1.5, (_) -> {
|
||||
// pressedSelect = false;
|
||||
|
|
@ -774,17 +822,22 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
{
|
||||
ease: FlxEase.quartInOut,
|
||||
onComplete: (_) -> {
|
||||
playerChill.playAnimation("idle", true, false, true);
|
||||
gfChill.playAnimation("idle", true, false, true);
|
||||
if (playerChill.getCurrentAnimation() == "deselect loop start" || playerChill.getCurrentAnimation() == "deselect")
|
||||
{
|
||||
playerChill.playAnimation("idle", true, false, true);
|
||||
gfChill.playAnimation("idle", true, false, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
selectTimer.cancel();
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (autoFollow)
|
||||
{
|
||||
curChar = "locked";
|
||||
|
||||
gfChill.visible = false;
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
cursorDenied.visible = true;
|
||||
|
|
@ -792,6 +845,9 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
cursorDenied.y = cursor.y - 4;
|
||||
|
||||
playerChill.playAnimation("cannot select Label", true);
|
||||
|
||||
lockedSound.play(true);
|
||||
|
||||
cursorDenied.animation.play("idle", true);
|
||||
cursorDenied.animation.finishCallback = (_) -> {
|
||||
cursorDenied.visible = false;
|
||||
|
|
@ -948,7 +1004,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
memb.scale.set(2.6, 2.6);
|
||||
}
|
||||
if (pressedSelect && memb.animation.curAnim.name == "idle") memb.animation.play("confirm");
|
||||
if (!pressedSelect && memb.animation.curAnim.name != "idle")
|
||||
if (autoFollow && !pressedSelect && memb.animation.curAnim.name != "idle")
|
||||
{
|
||||
memb.animation.play("confirm", false, true);
|
||||
member.animation.finishCallback = (_) -> {
|
||||
|
|
@ -981,6 +1037,10 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
|
||||
curChar = value;
|
||||
|
||||
if (value == "locked") staticSound.play();
|
||||
else
|
||||
staticSound.stop();
|
||||
|
||||
nametag.switchChar(value);
|
||||
playerChill.visible = false;
|
||||
playerChillOut.visible = true;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ class IntroSubState extends MusicBeatSubState
|
|||
{
|
||||
static final LIGHTS_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
|
||||
|
||||
var introSound:FunkinSound = null;
|
||||
|
||||
public override function create():Void
|
||||
{
|
||||
if (Save.instance.oldChar)
|
||||
|
|
@ -43,19 +41,10 @@ class IntroSubState extends MusicBeatSubState
|
|||
playVideoNative(LIGHTS_VIDEO_PATH);
|
||||
#end
|
||||
|
||||
// Im TOO lazy to even care, so uh, yep
|
||||
FlxG.camera.zoom = 0.66666666666666666666666666666667;
|
||||
vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom));
|
||||
vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75);
|
||||
|
||||
introSound = new FunkinSound();
|
||||
introSound.loadEmbedded(Paths.sound('CS_Lights'));
|
||||
introSound.pitch = 1;
|
||||
|
||||
FlxG.sound.defaultSoundGroup.add(introSound);
|
||||
FlxG.sound.list.add(introSound);
|
||||
|
||||
introSound.play(true);
|
||||
// // Im TOO lazy to even care, so uh, yep
|
||||
// FlxG.camera.zoom = 0.66666666666666666666666666666667;
|
||||
// vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom));
|
||||
// vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75);
|
||||
}
|
||||
|
||||
#if html5
|
||||
|
|
|
|||
|
|
@ -358,10 +358,6 @@ class FreeplayState extends MusicBeatSubState
|
|||
if (availableDifficultiesForSong.length == 0) continue;
|
||||
|
||||
songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations));
|
||||
for (difficulty in availableDifficultiesForSong)
|
||||
{
|
||||
diffIdsTotal.pushUnique(difficulty);
|
||||
}
|
||||
for (difficulty in unsuffixedDifficulties)
|
||||
{
|
||||
diffIdsTotal.pushUnique(difficulty);
|
||||
|
|
@ -1789,12 +1785,13 @@ class FreeplayState extends MusicBeatSubState
|
|||
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
|
||||
intendedScore = songScore?.score ?? 0;
|
||||
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
|
||||
rememberedDifficulty = currentDifficulty;
|
||||
rememberedDifficulty = suffixedDifficulty;
|
||||
}
|
||||
else
|
||||
{
|
||||
intendedScore = 0;
|
||||
intendedCompletion = 0.0;
|
||||
rememberedDifficulty = currentDifficulty;
|
||||
}
|
||||
|
||||
if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion))
|
||||
|
|
|
|||
|
|
@ -437,7 +437,10 @@ class MainMenuState extends MusicBeatState
|
|||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.N)
|
||||
{
|
||||
@:privateAccess
|
||||
funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"];
|
||||
{
|
||||
funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"];
|
||||
funkin.save.Save.instance.data.unlocks.oldChar = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,12 @@ class PreferencesMenu extends Page
|
|||
createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void {
|
||||
Preferences.autoPause = value;
|
||||
}, Preferences.autoPause);
|
||||
|
||||
#if web
|
||||
createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void {
|
||||
Preferences.unlockedFramerate = value;
|
||||
}, Preferences.unlockedFramerate);
|
||||
#end
|
||||
}
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
|
|
|
|||
Loading…
Reference in a new issue