mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-04-01 01:39:44 -04:00
Merge branch 'rewrite/master' into char-unlock-tinkers
This commit is contained in:
commit
d826f2a7bc
21 changed files with 290 additions and 108 deletions
CHANGELOG.mdartassets
docs
hmm.jsonsource
Main.hx
funkin
|
@ -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 f4cf1d3721155e16ab4e547b6baabc1238b66dae
|
||||
Subproject commit aede71ea384103393273fa72e8c02fa0f364da94
|
|
@ -14,7 +14,7 @@
|
|||
5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json
|
||||
6. Run `hmm install` to install all haxelibs of the current branch
|
||||
7. Run `haxelib run lime setup` to set up lime
|
||||
8. Platform setup
|
||||
8. Perform additional platform setup
|
||||
- For Windows, download the [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe)
|
||||
- When prompted, select "Individual Components" and make sure to download the following:
|
||||
- MSVC v143 VS 2022 C++ x64/x86 build tools
|
||||
|
@ -22,8 +22,24 @@
|
|||
- Mac: [`lime setup mac` Documentation](https://lime.openfl.org/docs/advanced-setup/macos/)
|
||||
- Linux: [`lime setup linux` Documentation](https://lime.openfl.org/docs/advanced-setup/linux/)
|
||||
- HTML5: Compiles without any extra setup
|
||||
9. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug`
|
||||
10. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State).
|
||||
9. If you are targeting for native, you may need to run `lime rebuild <PLATFORM>` and `lime rebuild <PLATFORM> -debug`
|
||||
10. `lime test <PLATFORM>` to build and launch the game for your platform (for example, `lime test windows`)
|
||||
|
||||
## Build Flags
|
||||
|
||||
There are several useful build flags you can add to a build to affect how it works. A full list can be found in `project.hxp`, but here's information on some of them:
|
||||
|
||||
- `-debug` to build the game in debug mode. This automatically enables several useful debug features.
|
||||
- This includes enabling in-game debug functions, disables compile-time optimizations, enabling asset redirection (see below), and enabling the VSCode debug server (which can slow the game on some machines but allows for powerful debugging through breakpoints).
|
||||
- `-DGITHUB_BUILD` will enable in-game debug functions (such as the ability to time travel in a song by pressing `PgUp`/`PgDn`), without enabling the other stuff
|
||||
- `-DFEATURE_POLYMOD_MODS` or `-DNO_FEATURE_POLYMOD_MODS` to forcibly enable or disable modding support.
|
||||
- `-DREDIRECT_ASSETS_FOLDER` or `-DNO_REDIRECT_ASSETS_FOLDER` to forcibly enable or disable asset redirection.
|
||||
- This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game
|
||||
- `-DFEATURE_DISCORD_RPC` or `-DNO_FEATURE_DISCORD_RPC` to forcibly enable or disable support for Discord Rich Presence.
|
||||
- `-DFEATURE_VIDEO_PLAYBACK` or `-DNO_FEATURE_VIDEO_PLAYBACK` to forcibly enable or disable video cutscene support.
|
||||
- `-DFEATURE_CHART_EDITOR` or `-DNO_FEATURE_CHART_EDITOR` to forcibly enable or disable the chart editor in the Debug menu.
|
||||
- `-DFEATURE_STAGE_EDITOR` to forcibly enable the experimental stage editor.
|
||||
- `-DFEATURE_GHOST_TAPPING` to forcibly enable an experimental gameplay change to the anti-mash system.
|
||||
|
||||
# Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB!
|
||||
|
||||
|
|
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,15 +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);
|
||||
lastTime = currTime + 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
|
||||
{
|
||||
|
@ -567,6 +569,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
|
||||
return sound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a string representation suitable for debugging.
|
||||
*/
|
||||
public override function toString():String
|
||||
{
|
||||
return 'FunkinSound(${this._label})';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -113,6 +113,11 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
|
|||
public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float)
|
||||
{
|
||||
forEachAlive(function(sound:FunkinSound) {
|
||||
if (sound.length < startTime)
|
||||
{
|
||||
// trace('Queuing sound (${sound.toString()} past its length! Skipping...)');
|
||||
return;
|
||||
}
|
||||
sound.play(forceRestart, startTime, endTime);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
*/
|
||||
public function hasAnimation(id:String):Bool
|
||||
{
|
||||
return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id) != null;
|
||||
return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,32 +154,27 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
{
|
||||
if (!anim.isPlaying)
|
||||
{
|
||||
if (fr != null) anim.curFrame = fr.index + startFrame;
|
||||
else
|
||||
anim.curFrame = startFrame;
|
||||
|
||||
// Resume animation if it's paused.
|
||||
anim.play('', restart, false, startFrame);
|
||||
anim.resume();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
else if (!hasAnimation(id))
|
||||
{
|
||||
// Skip if the animation doesn't exist
|
||||
if (!hasAnimation(id))
|
||||
{
|
||||
trace('Animation ' + id + ' not found');
|
||||
return;
|
||||
}
|
||||
trace('Animation ' + id + ' not found');
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentAnimation = id;
|
||||
anim.onComplete.removeAll();
|
||||
anim.onComplete.add(function() {
|
||||
if (loop)
|
||||
{
|
||||
this.anim.play(id, restart, false, startFrame);
|
||||
this.currentAnimation = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
onAnimationComplete.dispatch(id);
|
||||
}
|
||||
_onAnimationComplete();
|
||||
});
|
||||
|
||||
looping = loop;
|
||||
|
@ -190,6 +185,14 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
// Move to the first frame of the animation.
|
||||
// goToFrameLabel(id);
|
||||
trace('Playing animation $id');
|
||||
if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
|
||||
{
|
||||
this.anim.play(id, restart, false, startFrame);
|
||||
|
||||
this.currentAnimation = anim.curSymbol.name;
|
||||
|
||||
fr = null;
|
||||
}
|
||||
// Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
|
||||
if (getFrameLabelNames().indexOf(id) != -1)
|
||||
{
|
||||
|
@ -197,13 +200,6 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
fr = anim.getFrameLabel(id);
|
||||
anim.curFrame += startFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.anim.play(id, restart, false, startFrame);
|
||||
fr = null;
|
||||
}
|
||||
|
||||
this.currentAnimation = id;
|
||||
}
|
||||
|
||||
override public function update(elapsed:Float)
|
||||
|
@ -301,12 +297,13 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
{
|
||||
anim.pause();
|
||||
_onAnimationComplete();
|
||||
|
||||
if (looping)
|
||||
{
|
||||
anim.curFrame = (fr != null) ? fr.index : 0;
|
||||
anim.resume();
|
||||
}
|
||||
else
|
||||
else if (fr != null && anim.curFrame != anim.length - 1)
|
||||
{
|
||||
anim.curFrame--;
|
||||
}
|
||||
|
@ -320,6 +317,10 @@ class FlxAtlasSprite extends FlxAnimate
|
|||
{
|
||||
onAnimationComplete.dispatch(currentAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
onAnimationComplete.dispatch('');
|
||||
}
|
||||
}
|
||||
|
||||
var prevFrames:Map<Int, FlxFrame> = [];
|
||||
|
|
|
@ -395,20 +395,37 @@ class Controls extends FlxActionSet
|
|||
return result;
|
||||
}
|
||||
|
||||
public function getDialogueName(action:FlxActionDigital):String
|
||||
public function getDialogueName(action:FlxActionDigital, ?ignoreSurrounding:Bool = false):String
|
||||
{
|
||||
var input = action.inputs[0];
|
||||
return switch (input.device)
|
||||
if (ignoreSurrounding == false)
|
||||
{
|
||||
case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
|
||||
case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
|
||||
case device: throw 'unhandled device: $device';
|
||||
return switch (input.device)
|
||||
{
|
||||
case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
|
||||
case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
|
||||
case device: throw 'unhandled device: $device';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return switch (input.device)
|
||||
{
|
||||
case KEYBOARD: return '${(input.inputID : FlxKey)}';
|
||||
case GAMEPAD: return '${(input.inputID : FlxGamepadInputID)}';
|
||||
case device: throw 'unhandled device: $device';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getDialogueNameFromToken(token:String):String
|
||||
public function getDialogueNameFromToken(token:String, ?ignoreSurrounding:Bool = false):String
|
||||
{
|
||||
return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())));
|
||||
return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())), ignoreSurrounding);
|
||||
}
|
||||
|
||||
public function getDialogueNameFromControl(control:Control, ?ignoreSurrounding:Bool = false):String
|
||||
{
|
||||
return getDialogueName(getActionFromControl(control), ignoreSurrounding);
|
||||
}
|
||||
|
||||
function getActionFromControl(control:Control):FlxActionDigital
|
||||
|
|
|
@ -194,6 +194,7 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
// Animation is not looped.
|
||||
animation.onAnimationComplete.add((_name:String) -> {
|
||||
trace("AHAHAH 2");
|
||||
if (animation != null)
|
||||
{
|
||||
animation.anim.pause();
|
||||
|
@ -203,9 +204,10 @@ class ResultState extends MusicBeatSubState
|
|||
else if (animData.loopFrameLabel != null)
|
||||
{
|
||||
animation.onAnimationComplete.add((_name:String) -> {
|
||||
trace("AHAHAH 2");
|
||||
if (animation != null)
|
||||
{
|
||||
animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce!
|
||||
animation.playAnimation(animData.loopFrameLabel ?? '', true, false, true); // unpauses this anim, since it's on PlayOnce!
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -214,6 +216,7 @@ class ResultState extends MusicBeatSubState
|
|||
animation.onAnimationComplete.add((_name:String) -> {
|
||||
if (animation != null)
|
||||
{
|
||||
trace("AHAHAH");
|
||||
animation.anim.curFrame = animData.loopFrame ?? 0;
|
||||
animation.anim.play(); // unpauses this anim, since it's on PlayOnce!
|
||||
}
|
||||
|
@ -415,8 +418,7 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
restartTrack: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -426,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:
|
||||
{
|
||||
|
@ -1180,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:
|
||||
|
|
|
@ -349,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);
|
||||
|
@ -515,7 +518,7 @@ class CharSelectSubState extends MusicBeatSubState
|
|||
|
||||
syncLock = lock;
|
||||
|
||||
// sync = true;
|
||||
sync = true;
|
||||
|
||||
lock.onAnimationComplete.addOnce(function(_) {
|
||||
syncLock = null;
|
||||
|
|
|
@ -8,20 +8,22 @@ import hxcodec.flixel.FlxVideoSprite;
|
|||
#end
|
||||
import funkin.ui.MusicBeatSubState;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.save.Save;
|
||||
|
||||
/**
|
||||
* After about 2 minutes of inactivity on the title screen,
|
||||
* the game will enter the Attract state, as a reference to physical arcade machines.
|
||||
*
|
||||
* In the current version, this just plays the ~~Kickstarter trailer~~ Erect teaser, but this can be changed to
|
||||
* gameplay footage, a generic game trailer, or something more elaborate.
|
||||
* When you first enter the character select state, it will play an introductory video opening up the lights
|
||||
*/
|
||||
class IntroSubState extends MusicBeatSubState
|
||||
{
|
||||
static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
|
||||
static final LIGHTS_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
|
||||
|
||||
public override function create():Void
|
||||
{
|
||||
if (Save.instance.oldChar)
|
||||
{
|
||||
onLightsEnd();
|
||||
return;
|
||||
}
|
||||
// Pause existing music.
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
|
@ -30,14 +32,19 @@ class IntroSubState extends MusicBeatSubState
|
|||
}
|
||||
|
||||
#if html5
|
||||
trace('Playing web video ${ATTRACT_VIDEO_PATH}');
|
||||
playVideoHTML5(ATTRACT_VIDEO_PATH);
|
||||
trace('Playing web video ${LIGHTS_VIDEO_PATH}');
|
||||
playVideoHTML5(LIGHTS_VIDEO_PATH);
|
||||
#end
|
||||
|
||||
#if hxCodec
|
||||
trace('Playing native video ${ATTRACT_VIDEO_PATH}');
|
||||
playVideoNative(ATTRACT_VIDEO_PATH);
|
||||
trace('Playing native video ${LIGHTS_VIDEO_PATH}');
|
||||
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);
|
||||
}
|
||||
|
||||
#if html5
|
||||
|
@ -53,7 +60,7 @@ class IntroSubState extends MusicBeatSubState
|
|||
{
|
||||
vid.zIndex = 0;
|
||||
|
||||
vid.finishCallback = onAttractEnd;
|
||||
vid.finishCallback = onLightsEnd;
|
||||
|
||||
add(vid);
|
||||
}
|
||||
|
@ -77,7 +84,7 @@ class IntroSubState extends MusicBeatSubState
|
|||
if (vid != null)
|
||||
{
|
||||
vid.zIndex = 0;
|
||||
vid.bitmap.onEndReached.add(onAttractEnd);
|
||||
vid.bitmap.onEndReached.add(onLightsEnd);
|
||||
|
||||
add(vid);
|
||||
vid.play(filePath, false);
|
||||
|
@ -93,37 +100,33 @@ class IntroSubState extends MusicBeatSubState
|
|||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
onAttractEnd();
|
||||
}
|
||||
// if (!introSound.paused)
|
||||
// {
|
||||
// #if html5
|
||||
// @:privateAccess
|
||||
// vid.netStream.seek(introSound.time);
|
||||
// #elseif hxCodec
|
||||
// vid.bitmap.time = Std.int(introSound.time);
|
||||
// #end
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* When the attraction state ends (after the video ends or the user presses any button),
|
||||
* switch immediately to the title screen.
|
||||
* When the lights video finishes, it will close the substate
|
||||
*/
|
||||
function onAttractEnd():Void
|
||||
function onLightsEnd():Void
|
||||
{
|
||||
#if html5
|
||||
if (vid != null)
|
||||
{
|
||||
remove(vid);
|
||||
}
|
||||
#end
|
||||
|
||||
#if hxCodec
|
||||
if (vid != null)
|
||||
{
|
||||
#if hxCodec
|
||||
vid.stop();
|
||||
#end
|
||||
remove(vid);
|
||||
vid.destroy();
|
||||
vid = null;
|
||||
}
|
||||
#end
|
||||
|
||||
#if (html5 || hxCodec)
|
||||
vid.destroy();
|
||||
vid = null;
|
||||
#end
|
||||
FlxG.camera.zoom = 1;
|
||||
|
||||
close();
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
}
|
||||
else if (getCurrentAnimation() == animPrefixB)
|
||||
{
|
||||
trace("Loss Intro");
|
||||
var endFrame = playableCharData.getFistPumpIntroBadEndFrame();
|
||||
if (endFrame > -1 && anim.curFrame >= endFrame)
|
||||
{
|
||||
|
@ -166,6 +167,7 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
}
|
||||
else if (getCurrentAnimation() == animPrefixB)
|
||||
{
|
||||
trace("Loss GYATT");
|
||||
var endFrame = playableCharData.getFistPumpLoopBadEndFrame();
|
||||
if (endFrame > -1 && anim.curFrame >= endFrame)
|
||||
{
|
||||
|
@ -375,6 +377,13 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
|
||||
public function confirm():Void
|
||||
{
|
||||
// We really don't want to play anything but the new character animation here.
|
||||
if (PlayerRegistry.instance.hasNewCharacter())
|
||||
{
|
||||
currentState = NewUnlock;
|
||||
return;
|
||||
}
|
||||
|
||||
currentState = Confirm;
|
||||
}
|
||||
|
||||
|
@ -397,6 +406,13 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
|
||||
public function fistPumpIntro():Void
|
||||
{
|
||||
// We really don't want to play anything but the new character animation here.
|
||||
if (PlayerRegistry.instance.hasNewCharacter())
|
||||
{
|
||||
currentState = NewUnlock;
|
||||
return;
|
||||
}
|
||||
|
||||
currentState = FistPumpIntro;
|
||||
var animPrefix = playableCharData.getAnimationPrefix('fistPump');
|
||||
playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroStartFrame());
|
||||
|
@ -404,6 +420,13 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
|
||||
public function fistPump():Void
|
||||
{
|
||||
// We really don't want to play anything but the new character animation here.
|
||||
if (PlayerRegistry.instance.hasNewCharacter())
|
||||
{
|
||||
currentState = NewUnlock;
|
||||
return;
|
||||
}
|
||||
|
||||
currentState = FistPump;
|
||||
var animPrefix = playableCharData.getAnimationPrefix('fistPump');
|
||||
playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopStartFrame());
|
||||
|
@ -411,6 +434,13 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
|
||||
public function fistPumpLossIntro():Void
|
||||
{
|
||||
// We really don't want to play anything but the new character animation here.
|
||||
if (PlayerRegistry.instance.hasNewCharacter())
|
||||
{
|
||||
currentState = NewUnlock;
|
||||
return;
|
||||
}
|
||||
|
||||
currentState = FistPumpIntro;
|
||||
var animPrefix = playableCharData.getAnimationPrefix('loss');
|
||||
playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroBadStartFrame());
|
||||
|
@ -418,6 +448,13 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
|
||||
public function fistPumpLoss():Void
|
||||
{
|
||||
// We really don't want to play anything but the new character animation here.
|
||||
if (PlayerRegistry.instance.hasNewCharacter())
|
||||
{
|
||||
currentState = NewUnlock;
|
||||
return;
|
||||
}
|
||||
|
||||
currentState = FistPump;
|
||||
var animPrefix = playableCharData.getAnimationPrefix('loss');
|
||||
playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopBadStartFrame());
|
||||
|
|
|
@ -9,6 +9,7 @@ import flixel.group.FlxGroup.FlxTypedGroup;
|
|||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.input.touch.FlxTouch;
|
||||
import flixel.math.FlxAngle;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.system.debug.watch.Tracker.TrackerProfile;
|
||||
import flixel.text.FlxText;
|
||||
|
@ -180,6 +181,8 @@ class FreeplayState extends MusicBeatSubState
|
|||
var ostName:FlxText;
|
||||
var albumRoll:AlbumRoll;
|
||||
|
||||
var charSelectHint:FlxText;
|
||||
|
||||
var letterSort:LetterSort;
|
||||
var exitMovers:ExitMoverData = new Map();
|
||||
|
||||
|
@ -279,6 +282,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR);
|
||||
|
||||
ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48);
|
||||
charSelectHint = new FlxText(-40, 18, FlxG.width - 8 - 8, 'Press [ LOL ] to change characters', 32);
|
||||
|
||||
bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(styleData == null ? 'freeplay/freeplayBGdad' : styleData.getBgAssetGraphic());
|
||||
}
|
||||
|
@ -354,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);
|
||||
|
@ -498,7 +498,14 @@ class FreeplayState extends MusicBeatSubState
|
|||
ostName.alignment = RIGHT;
|
||||
ostName.visible = false;
|
||||
|
||||
exitMovers.set([overhangStuff, fnfFreeplay, ostName],
|
||||
charSelectHint.alignment = CENTER;
|
||||
charSelectHint.font = "5by7";
|
||||
charSelectHint.color = 0xFF5F5F5F;
|
||||
charSelectHint.text = 'Press [ ${controls.getDialogueNameFromControl(FREEPLAY_CHAR_SELECT, true)} ] to change characters';
|
||||
charSelectHint.y -= 100;
|
||||
FlxTween.tween(charSelectHint, {y: charSelectHint.y + 100}, 0.8, {ease: FlxEase.quartOut});
|
||||
|
||||
exitMovers.set([overhangStuff, fnfFreeplay, ostName, charSelectHint],
|
||||
{
|
||||
y: -overhangStuff.height,
|
||||
x: 0,
|
||||
|
@ -506,7 +513,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
wait: 0
|
||||
});
|
||||
|
||||
exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName],
|
||||
exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName, charSelectHint],
|
||||
{
|
||||
y: -300,
|
||||
speed: 0.8,
|
||||
|
@ -604,6 +611,11 @@ class FreeplayState extends MusicBeatSubState
|
|||
add(fnfFreeplay);
|
||||
add(ostName);
|
||||
|
||||
if (PlayerRegistry.instance.hasNewCharacter() == true)
|
||||
{
|
||||
add(charSelectHint);
|
||||
}
|
||||
|
||||
// be careful not to "add()" things in here unless it's to a group that's already added to the state
|
||||
// otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create())
|
||||
var onDJIntroDone = function() {
|
||||
|
@ -1348,10 +1360,19 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
var originalPos:FlxPoint = new FlxPoint();
|
||||
|
||||
var hintTimer:Float = 0;
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (charSelectHint != null)
|
||||
{
|
||||
hintTimer += elapsed * 2;
|
||||
var targetAmt:Float = (Math.sin(hintTimer) + 1) / 2;
|
||||
charSelectHint.alpha = FlxMath.lerp(0.3, 0.9, targetAmt);
|
||||
}
|
||||
|
||||
#if FEATURE_DEBUG_FUNCTIONS
|
||||
if (FlxG.keys.justPressed.P)
|
||||
{
|
||||
|
@ -1764,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))
|
||||
|
|
|
@ -358,6 +358,7 @@ class MainMenuState extends MusicBeatState
|
|||
// Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock
|
||||
// Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock
|
||||
// Ctrl+Alt+Shift+R = Score/Rank conflict test
|
||||
// Ctrl+Alt+Shift+N = Mark all characters as not seen
|
||||
// Ctrl+Alt+Shift+E = Dump save data
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P)
|
||||
|
@ -433,6 +434,15 @@ 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.oldChar = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E)
|
||||
{
|
||||
funkin.save.Save.instance.debug_dumpSave();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -273,8 +273,11 @@ class TitleState extends MusicBeatState
|
|||
}
|
||||
#end
|
||||
|
||||
if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico");
|
||||
|
||||
if (Save.instance.charactersSeen.contains("pico"))
|
||||
{
|
||||
Save.instance.charactersSeen.remove("pico");
|
||||
Save.instance.oldChar = false;
|
||||
}
|
||||
Conductor.instance.update();
|
||||
|
||||
/* if (FlxG.onMobile)
|
||||
|
|
Loading…
Add table
Reference in a new issue