mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-03-21 01:19:26 +00:00
Work in progress on fixing Week 6
This commit is contained in:
parent
12a48b9b86
commit
13d6ba378e
|
@ -1,66 +0,0 @@
|
|||
package flixel.tweens.misc;
|
||||
|
||||
/**
|
||||
* Tweens the background color of a state.
|
||||
* Tweens the red, green, blue, and/or alpha values of the color.
|
||||
*
|
||||
* @see `flixel.tweens.misc.ColorTween` for something that operates on sprites!
|
||||
*/
|
||||
class BackgroundColorTween extends FlxTween
|
||||
{
|
||||
public var color(default, null):FlxColor;
|
||||
|
||||
var startColor:FlxColor;
|
||||
var endColor:FlxColor;
|
||||
|
||||
/**
|
||||
* State object whose color to tween
|
||||
*/
|
||||
public var targetState(default, null):FlxState;
|
||||
|
||||
/**
|
||||
* Clean up references
|
||||
*/
|
||||
override public function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
targetState = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tweens the color to a new color and an alpha to a new alpha.
|
||||
*
|
||||
* @param duration Duration of the tween.
|
||||
* @param fromColor Start color.
|
||||
* @param toColor End color.
|
||||
* @param targetState Optional sprite object whose color to tween.
|
||||
* @return The tween for chaining.
|
||||
*/
|
||||
public function tween(duration:Float, fromColor:FlxColor, toColor:FlxColor, ?targetState:FlxSprite):ColorTween
|
||||
{
|
||||
this.color = startColor = fromColor;
|
||||
this.endColor = toColor;
|
||||
this.duration = duration;
|
||||
this.targetState = targetState;
|
||||
this.start();
|
||||
return this;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
color = FlxColor.interpolate(startColor, endColor, scale);
|
||||
|
||||
if (targetState != null)
|
||||
{
|
||||
targetState.bgColor = color;
|
||||
// Alpha should apply inherently.
|
||||
// targetState.alpha = color.alphaFloat;
|
||||
}
|
||||
}
|
||||
|
||||
override function isTweenOf(object:Dynamic, ?field:String):Bool
|
||||
{
|
||||
return targetState == object && (field == null || field == "color");
|
||||
}
|
||||
}
|
|
@ -203,6 +203,9 @@ class InitState extends FlxState
|
|||
// Plugins provide a useful interface for globally active Flixel objects,
|
||||
// that receive update events regardless of the current state.
|
||||
// TODO: Move scripted Module behavior to a Flixel plugin.
|
||||
#if debug
|
||||
funkin.util.plugins.MemoryGCPlugin.initialize();
|
||||
#end
|
||||
funkin.util.plugins.EvacuateDebugPlugin.initialize();
|
||||
funkin.util.plugins.ForceCrashPlugin.initialize();
|
||||
funkin.util.plugins.ReloadAssetsDebugPlugin.initialize();
|
||||
|
|
|
@ -25,6 +25,9 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
{
|
||||
static final MAX_VOLUME:Float = 2.0;
|
||||
|
||||
/**
|
||||
* Using `FunkinSound.load` will override a dead instance from here rather than creating a new one, if possible!
|
||||
*/
|
||||
static var cache(default, null):FlxTypedGroup<FunkinSound> = new FlxTypedGroup<FunkinSound>();
|
||||
|
||||
public var muted(default, set):Bool = false;
|
||||
|
@ -264,6 +267,8 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
|
|||
{
|
||||
var sound:FunkinSound = cache.recycle(construct);
|
||||
|
||||
// Load the sound.
|
||||
// Sets `exists = true` as a side effect.
|
||||
sound.loadEmbedded(embeddedSound, looped, autoDestroy, onComplete);
|
||||
|
||||
if (embeddedSound is String)
|
||||
|
|
|
@ -80,8 +80,9 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
|
|||
|
||||
// We have to play, then pause the sound to set the time,
|
||||
// else the sound will restart immediately when played.
|
||||
result.play(true, 0.0);
|
||||
result.pause();
|
||||
// TODO: Past me experienced that issue but present me didn't? Investigate.
|
||||
// result.play(true, 0.0);
|
||||
// result.pause();
|
||||
result.time = this.time;
|
||||
|
||||
result.onComplete = function() {
|
||||
|
|
|
@ -40,6 +40,15 @@ class FlxVideo extends FlxBasic
|
|||
netStream.play(videoPath);
|
||||
}
|
||||
|
||||
public function restartVideo():Void
|
||||
{
|
||||
// Seek to the beginning of the video.
|
||||
if (netStream != null)
|
||||
{
|
||||
netStream.seek(0);
|
||||
}
|
||||
}
|
||||
|
||||
public function finishVideo():Void
|
||||
{
|
||||
netStream.dispose();
|
||||
|
|
|
@ -15,7 +15,6 @@ using funkin.util.tools.ArraySortTools;
|
|||
using funkin.util.tools.ArrayTools;
|
||||
using funkin.util.tools.DynamicTools;
|
||||
using funkin.util.tools.FloatTools;
|
||||
using funkin.util.tools.FlxTweenTools;
|
||||
using funkin.util.tools.Int64Tools;
|
||||
using funkin.util.tools.IntTools;
|
||||
using funkin.util.tools.IteratorTools;
|
||||
|
|
|
@ -58,12 +58,11 @@ class Controls extends FlxActionSet
|
|||
var _back = new FlxActionDigital(Action.BACK);
|
||||
var _pause = new FlxActionDigital(Action.PAUSE);
|
||||
var _reset = new FlxActionDigital(Action.RESET);
|
||||
var _screenshot = new FlxActionDigital(Action.SCREENSHOT);
|
||||
var _cutscene_advance = new FlxActionDigital(Action.CUTSCENE_ADVANCE);
|
||||
var _cutscene_skip = new FlxActionDigital(Action.CUTSCENE_SKIP);
|
||||
var _debug_menu = new FlxActionDigital(Action.DEBUG_MENU);
|
||||
var _debug_chart = new FlxActionDigital(Action.DEBUG_CHART);
|
||||
var _debug_stage = new FlxActionDigital(Action.DEBUG_STAGE);
|
||||
var _screenshot = new FlxActionDigital(Action.SCREENSHOT);
|
||||
var _volume_up = new FlxActionDigital(Action.VOLUME_UP);
|
||||
var _volume_down = new FlxActionDigital(Action.VOLUME_DOWN);
|
||||
var _volume_mute = new FlxActionDigital(Action.VOLUME_MUTE);
|
||||
|
@ -208,16 +207,21 @@ class Controls extends FlxActionSet
|
|||
inline function get_PAUSE()
|
||||
return _pause.check();
|
||||
|
||||
public var RESET(get, never):Bool;
|
||||
|
||||
inline function get_RESET()
|
||||
return _reset.check();
|
||||
|
||||
public var SCREENSHOT(get, never):Bool;
|
||||
|
||||
inline function get_SCREENSHOT()
|
||||
return _screenshot.check();
|
||||
|
||||
public var CUTSCENE_ADVANCE(get, never):Bool;
|
||||
|
||||
inline function get_CUTSCENE_ADVANCE()
|
||||
return _cutscene_advance.check();
|
||||
|
||||
public var CUTSCENE_SKIP(get, never):Bool;
|
||||
|
||||
inline function get_CUTSCENE_SKIP()
|
||||
return _cutscene_skip.check();
|
||||
|
||||
public var DEBUG_MENU(get, never):Bool;
|
||||
|
||||
inline function get_DEBUG_MENU()
|
||||
|
@ -233,11 +237,6 @@ class Controls extends FlxActionSet
|
|||
inline function get_DEBUG_STAGE()
|
||||
return _debug_stage.check();
|
||||
|
||||
public var SCREENSHOT(get, never):Bool;
|
||||
|
||||
inline function get_SCREENSHOT()
|
||||
return _screenshot.check();
|
||||
|
||||
public var VOLUME_UP(get, never):Bool;
|
||||
|
||||
inline function get_VOLUME_UP()
|
||||
|
@ -253,11 +252,6 @@ class Controls extends FlxActionSet
|
|||
inline function get_VOLUME_MUTE()
|
||||
return _volume_mute.check();
|
||||
|
||||
public var RESET(get, never):Bool;
|
||||
|
||||
inline function get_RESET()
|
||||
return _reset.check();
|
||||
|
||||
public function new(name, scheme:KeyboardScheme = null)
|
||||
{
|
||||
super(name);
|
||||
|
@ -289,16 +283,15 @@ class Controls extends FlxActionSet
|
|||
add(_accept);
|
||||
add(_back);
|
||||
add(_pause);
|
||||
add(_reset);
|
||||
add(_screenshot);
|
||||
add(_cutscene_advance);
|
||||
add(_cutscene_skip);
|
||||
add(_debug_menu);
|
||||
add(_debug_chart);
|
||||
add(_debug_stage);
|
||||
add(_screenshot);
|
||||
add(_volume_up);
|
||||
add(_volume_down);
|
||||
add(_volume_mute);
|
||||
add(_reset);
|
||||
|
||||
for (action in digitalActions)
|
||||
byName[action.name] = action;
|
||||
|
@ -383,12 +376,11 @@ class Controls extends FlxActionSet
|
|||
case BACK: _back;
|
||||
case PAUSE: _pause;
|
||||
case RESET: _reset;
|
||||
case SCREENSHOT: _screenshot;
|
||||
case CUTSCENE_ADVANCE: _cutscene_advance;
|
||||
case CUTSCENE_SKIP: _cutscene_skip;
|
||||
case DEBUG_MENU: _debug_menu;
|
||||
case DEBUG_CHART: _debug_chart;
|
||||
case DEBUG_STAGE: _debug_stage;
|
||||
case SCREENSHOT: _screenshot;
|
||||
case VOLUME_UP: _volume_up;
|
||||
case VOLUME_DOWN: _volume_down;
|
||||
case VOLUME_MUTE: _volume_mute;
|
||||
|
@ -449,26 +441,24 @@ class Controls extends FlxActionSet
|
|||
func(_back, JUST_PRESSED);
|
||||
case PAUSE:
|
||||
func(_pause, JUST_PRESSED);
|
||||
case RESET:
|
||||
func(_reset, JUST_PRESSED);
|
||||
case SCREENSHOT:
|
||||
func(_screenshot, JUST_PRESSED);
|
||||
case CUTSCENE_ADVANCE:
|
||||
func(_cutscene_advance, JUST_PRESSED);
|
||||
case CUTSCENE_SKIP:
|
||||
func(_cutscene_skip, PRESSED);
|
||||
case DEBUG_MENU:
|
||||
func(_debug_menu, JUST_PRESSED);
|
||||
case DEBUG_CHART:
|
||||
func(_debug_chart, JUST_PRESSED);
|
||||
case DEBUG_STAGE:
|
||||
func(_debug_stage, JUST_PRESSED);
|
||||
case SCREENSHOT:
|
||||
func(_screenshot, JUST_PRESSED);
|
||||
case VOLUME_UP:
|
||||
func(_volume_up, JUST_PRESSED);
|
||||
case VOLUME_DOWN:
|
||||
func(_volume_down, JUST_PRESSED);
|
||||
case VOLUME_MUTE:
|
||||
func(_volume_mute, JUST_PRESSED);
|
||||
case RESET:
|
||||
func(_reset, JUST_PRESSED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,13 +644,12 @@ class Controls extends FlxActionSet
|
|||
bindKeys(Control.ACCEPT, getDefaultKeybinds(scheme, Control.ACCEPT));
|
||||
bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK));
|
||||
bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE));
|
||||
bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET));
|
||||
bindKeys(Control.SCREENSHOT, getDefaultKeybinds(scheme, Control.SCREENSHOT));
|
||||
bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE));
|
||||
bindKeys(Control.CUTSCENE_SKIP, getDefaultKeybinds(scheme, Control.CUTSCENE_SKIP));
|
||||
bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU));
|
||||
bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART));
|
||||
bindKeys(Control.DEBUG_STAGE, getDefaultKeybinds(scheme, Control.DEBUG_STAGE));
|
||||
bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET));
|
||||
bindKeys(Control.SCREENSHOT, getDefaultKeybinds(scheme, Control.SCREENSHOT));
|
||||
bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP));
|
||||
bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN));
|
||||
bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE));
|
||||
|
@ -683,16 +672,15 @@ class Controls extends FlxActionSet
|
|||
case Control.ACCEPT: return [Z, SPACE, ENTER];
|
||||
case Control.BACK: return [X, BACKSPACE, ESCAPE];
|
||||
case Control.PAUSE: return [P, ENTER, ESCAPE];
|
||||
case Control.RESET: return [R];
|
||||
case Control.SCREENSHOT: return [F3]; // TODO: Change this back to PrintScreen
|
||||
case Control.CUTSCENE_ADVANCE: return [Z, ENTER];
|
||||
case Control.CUTSCENE_SKIP: return [P, ESCAPE];
|
||||
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
||||
case Control.DEBUG_CHART: return [];
|
||||
case Control.DEBUG_STAGE: return [];
|
||||
case Control.SCREENSHOT: return [F3]; // TODO: Change this back to PrintScreen
|
||||
case Control.VOLUME_UP: return [PLUS, NUMPADPLUS];
|
||||
case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS];
|
||||
case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO];
|
||||
case Control.RESET: return [R];
|
||||
}
|
||||
case Duo(true):
|
||||
switch (control) {
|
||||
|
@ -707,16 +695,15 @@ class Controls extends FlxActionSet
|
|||
case Control.ACCEPT: return [G, Z];
|
||||
case Control.BACK: return [H, X];
|
||||
case Control.PAUSE: return [ONE];
|
||||
case Control.RESET: return [R];
|
||||
case Control.SCREENSHOT: return [PRINTSCREEN];
|
||||
case Control.CUTSCENE_ADVANCE: return [G, Z];
|
||||
case Control.CUTSCENE_SKIP: return [ONE];
|
||||
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
||||
case Control.DEBUG_CHART: return [];
|
||||
case Control.DEBUG_STAGE: return [];
|
||||
case Control.SCREENSHOT: return [PRINTSCREEN];
|
||||
case Control.VOLUME_UP: return [PLUS];
|
||||
case Control.VOLUME_DOWN: return [MINUS];
|
||||
case Control.VOLUME_MUTE: return [ZERO];
|
||||
case Control.RESET: return [R];
|
||||
}
|
||||
case Duo(false):
|
||||
switch (control) {
|
||||
|
@ -731,16 +718,15 @@ class Controls extends FlxActionSet
|
|||
case Control.ACCEPT: return [ENTER];
|
||||
case Control.BACK: return [ESCAPE];
|
||||
case Control.PAUSE: return [ONE];
|
||||
case Control.RESET: return [R];
|
||||
case Control.SCREENSHOT: return [PRINTSCREEN];
|
||||
case Control.CUTSCENE_ADVANCE: return [ENTER];
|
||||
case Control.CUTSCENE_SKIP: return [ONE];
|
||||
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
||||
case Control.DEBUG_CHART: return [];
|
||||
case Control.DEBUG_STAGE: return [];
|
||||
case Control.SCREENSHOT: return [PRINTSCREEN];
|
||||
case Control.VOLUME_UP: return [NUMPADPLUS];
|
||||
case Control.VOLUME_DOWN: return [NUMPADMINUS];
|
||||
case Control.VOLUME_MUTE: return [NUMPADZERO];
|
||||
case Control.RESET: return [R];
|
||||
}
|
||||
default:
|
||||
// Fallthrough.
|
||||
|
@ -843,15 +829,14 @@ class Controls extends FlxActionSet
|
|||
Control.NOTE_LEFT => getDefaultGamepadBinds(Control.NOTE_LEFT),
|
||||
Control.NOTE_RIGHT => getDefaultGamepadBinds(Control.NOTE_RIGHT),
|
||||
Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE),
|
||||
Control.RESET => getDefaultGamepadBinds(Control.RESET),
|
||||
// Control.SCREENSHOT => [],
|
||||
// Control.VOLUME_UP => [RIGHT_SHOULDER],
|
||||
// Control.VOLUME_DOWN => [LEFT_SHOULDER],
|
||||
// Control.VOLUME_MUTE => [RIGHT_TRIGGER],
|
||||
Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE),
|
||||
Control.CUTSCENE_SKIP => getDefaultGamepadBinds(Control.CUTSCENE_SKIP),
|
||||
// Control.DEBUG_MENU
|
||||
// Control.DEBUG_CHART
|
||||
Control.RESET => getDefaultGamepadBinds(Control.RESET)
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -868,15 +853,14 @@ class Controls extends FlxActionSet
|
|||
case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT];
|
||||
case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT];
|
||||
case Control.PAUSE: return [START];
|
||||
case Control.RESET: return [RIGHT_SHOULDER];
|
||||
case Control.SCREENSHOT: return [];
|
||||
case Control.VOLUME_UP: return [];
|
||||
case Control.VOLUME_DOWN: return [];
|
||||
case Control.VOLUME_MUTE: return [];
|
||||
case Control.CUTSCENE_ADVANCE: return [A];
|
||||
case Control.CUTSCENE_SKIP: return [START];
|
||||
case Control.DEBUG_MENU: return [];
|
||||
case Control.DEBUG_CHART: return [];
|
||||
case Control.RESET: return [RIGHT_SHOULDER];
|
||||
default:
|
||||
// Fallthrough.
|
||||
}
|
||||
|
@ -1228,14 +1212,13 @@ enum Control
|
|||
UI_RIGHT;
|
||||
UI_DOWN;
|
||||
RESET;
|
||||
SCREENSHOT;
|
||||
ACCEPT;
|
||||
BACK;
|
||||
PAUSE;
|
||||
// CUTSCENE
|
||||
CUTSCENE_ADVANCE;
|
||||
CUTSCENE_SKIP;
|
||||
// SCREENSHOT
|
||||
SCREENSHOT;
|
||||
// VOLUME
|
||||
VOLUME_UP;
|
||||
VOLUME_DOWN;
|
||||
|
@ -1279,15 +1262,14 @@ abstract Action(String) to String from String
|
|||
var BACK = "back";
|
||||
var PAUSE = "pause";
|
||||
var RESET = "reset";
|
||||
// SCREENSHOT
|
||||
var SCREENSHOT = "screenshot";
|
||||
// CUTSCENE
|
||||
var CUTSCENE_ADVANCE = "cutscene_advance";
|
||||
var CUTSCENE_SKIP = "cutscene_skip";
|
||||
// VOLUME
|
||||
var VOLUME_UP = "volume_up";
|
||||
var VOLUME_DOWN = "volume_down";
|
||||
var VOLUME_MUTE = "volume_mute";
|
||||
// SCREENSHOT
|
||||
var SCREENSHOT = "screenshot";
|
||||
// DEBUG
|
||||
var DEBUG_MENU = "debug_menu";
|
||||
var DEBUG_CHART = "debug_chart";
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
package funkin.play;
|
||||
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.FlxG;
|
||||
import flixel.util.FlxTimer;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.graphics.FunkinSprite;
|
||||
import funkin.play.cutscene.VideoCutscene;
|
||||
import funkin.play.PlayState;
|
||||
import funkin.ui.AtlasText;
|
||||
import funkin.ui.MusicBeatSubState;
|
||||
import funkin.ui.transition.StickerSubState;
|
||||
|
||||
typedef PauseSubStateParams =
|
||||
{
|
||||
?mode:PauseMode,
|
||||
|
@ -10,29 +29,36 @@ typedef PauseSubStateParams =
|
|||
*/
|
||||
class PauseSubState extends MusicBeatSubState
|
||||
{
|
||||
static final PAUSE_MENU_ENTRIES_STANDARD = [
|
||||
static final PAUSE_MENU_ENTRIES_STANDARD:Array<PauseMenuEntry> = [
|
||||
{text: 'Resume', callback: resume},
|
||||
{text: 'Restart Song', callback: restartPlayState},
|
||||
{text: 'Change Difficulty', callback: switchMode.bind(_, Difficulty)},
|
||||
{text: 'Enable Practice Mode', callback: enablePracticeMode, filter: () -> (PlayState.instance?.isPracticeMode ?? true)},
|
||||
{text: 'Enable Practice Mode', callback: enablePracticeMode, filter: () -> !(PlayState.instance?.isPracticeMode ?? false)},
|
||||
{text: 'Exit to Menu', callback: quitToMenu},
|
||||
];
|
||||
|
||||
static final PAUSE_MENU_ENTRIES_CHARTING = [
|
||||
static final PAUSE_MENU_ENTRIES_CHARTING:Array<PauseMenuEntry> = [
|
||||
{text: 'Resume', callback: resume},
|
||||
{text: 'Restart Song', callback: restartPlayState},
|
||||
{text: 'Return to Chart Editor', callback: quitToChartEditor},
|
||||
];
|
||||
|
||||
static final PAUSE_MENU_ENTRIES_DIFFICULTY = [
|
||||
static final PAUSE_MENU_ENTRIES_DIFFICULTY:Array<PauseMenuEntry> = [
|
||||
{text: 'Back', callback: switchMode.bind(_, Standard)}
|
||||
// Other entries are added dynamically.
|
||||
];
|
||||
|
||||
static final PAUSE_MENU_ENTRIES_CUTSCENE = [
|
||||
static final PAUSE_MENU_ENTRIES_VIDEO_CUTSCENE:Array<PauseMenuEntry> = [
|
||||
{text: 'Resume', callback: resume},
|
||||
{text: 'Restart Cutscene', callback: restartCutscene},
|
||||
{text: 'Skip Cutscene', callback: skipCutscene},
|
||||
{text: 'Restart Cutscene', callback: restartVideoCutscene},
|
||||
{text: 'Skip Cutscene', callback: skipVideoCutscene},
|
||||
{text: 'Exit to Menu', callback: quitToMenu},
|
||||
];
|
||||
|
||||
static final PAUSE_MENU_ENTRIES_CONVERSATION:Array<PauseMenuEntry> = [
|
||||
{text: 'Resume', callback: resume},
|
||||
{text: 'Restart Dialogue', callback: restartConversation},
|
||||
{text: 'Skip Dialogue', callback: skipConversation},
|
||||
{text: 'Exit to Menu', callback: quitToMenu},
|
||||
];
|
||||
|
||||
|
@ -42,15 +68,21 @@ class PauseSubState extends MusicBeatSubState
|
|||
public static var musicSuffix:String = '';
|
||||
|
||||
// Status
|
||||
var menuEntries:Array<PauseMenuEntry>;
|
||||
var currentMenuEntries:Array<PauseMenuEntry>;
|
||||
var currentEntry:Int = 0;
|
||||
var currentMode:PauseMode;
|
||||
var allowInput:Bool = true;
|
||||
|
||||
/**
|
||||
* Disallow input until the transition in is complete!
|
||||
* This prevents the pause menu from immediately closing.
|
||||
*/
|
||||
public var allowInput:Bool = false;
|
||||
|
||||
// Graphics
|
||||
var metadata:FlxTypedGroup<FlxText>;
|
||||
var background:FunkinSprite;
|
||||
var metadata:FlxTypedSpriteGroup<FlxText>;
|
||||
var metadataPractice:FlxText;
|
||||
var menuEntryText:FlxTypedGroup<AtlasText>;
|
||||
var menuEntryText:FlxTypedSpriteGroup<AtlasText>;
|
||||
|
||||
// Audio
|
||||
var pauseMusic:FunkinSound;
|
||||
|
@ -58,9 +90,7 @@ class PauseSubState extends MusicBeatSubState
|
|||
public function new(?params:PauseSubStateParams)
|
||||
{
|
||||
super();
|
||||
this.currentMode = params?.mode ?? PauseMode.Standard;
|
||||
|
||||
this.bgColor = FlxColor.TRANSPARENT; // Transparent, fades into black later.
|
||||
this.currentMode = params?.mode ?? Standard;
|
||||
}
|
||||
|
||||
public override function create():Void
|
||||
|
@ -69,8 +99,16 @@ class PauseSubState extends MusicBeatSubState
|
|||
|
||||
startPauseMusic();
|
||||
|
||||
buildBackground();
|
||||
|
||||
buildMetadata();
|
||||
|
||||
menuEntryText = new FlxTypedSpriteGroup<AtlasText>();
|
||||
menuEntryText.scrollFactor.set(0, 0);
|
||||
add(menuEntryText);
|
||||
|
||||
regenerateMenu();
|
||||
|
||||
transitionIn();
|
||||
}
|
||||
|
||||
|
@ -81,47 +119,69 @@ class PauseSubState extends MusicBeatSubState
|
|||
handleInputs();
|
||||
}
|
||||
|
||||
public override function destroy():Void
|
||||
{
|
||||
super.destroy();
|
||||
pauseMusic.stop();
|
||||
}
|
||||
|
||||
function startPauseMusic():Void
|
||||
{
|
||||
pauseMusic = FunkinSound.load(Paths.music('breakfast-pixel'), true, true);
|
||||
pauseMusic = FunkinSound.load(Paths.music('breakfast$musicSuffix'), true, true);
|
||||
|
||||
// Start playing at a random point in the song.
|
||||
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
|
||||
pauseMusic.fadeIn(MUSIC_FADE_IN_TIME, 0, MUSIC_FINAL_VOLUME);
|
||||
}
|
||||
|
||||
function buildBackground():Void
|
||||
{
|
||||
// Using state.bgColor causes bugs!
|
||||
background = new FunkinSprite(0, 0);
|
||||
background.makeSolidColor(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
background.alpha = 0.0;
|
||||
background.scrollFactor.set(0, 0);
|
||||
background.updateHitbox();
|
||||
add(background);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the metadata in the top right.
|
||||
*/
|
||||
function buildMetadata():Void
|
||||
{
|
||||
metadata = new FlxTypedGroup<FlxSprite>();
|
||||
metadata = new FlxTypedSpriteGroup<FlxText>();
|
||||
metadata.scrollFactor.set(0, 0);
|
||||
add(metadata);
|
||||
|
||||
var metadataSong:FlxText = new FlxText(20, 15, 0, 'Song Name - Artist');
|
||||
var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name - Artist');
|
||||
metadataSong.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
if (PlayState.instance?.currentChart != null)
|
||||
{
|
||||
metadataSong.text += '${PlayState.instance.currentChart.songName} - ${PlayState.instance.currentChart.songArtist}';
|
||||
metadataSong.text = '${PlayState.instance.currentChart.songName} - ${PlayState.instance.currentChart.songArtist}';
|
||||
}
|
||||
metadataSong.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataSong);
|
||||
|
||||
var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, 0, 'Difficulty');
|
||||
var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, FlxG.width - 40, 'Difficulty: ');
|
||||
metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
if (PlayState.instance?.currentDifficulty != null)
|
||||
{
|
||||
metadataDifficulty.text += PlayState.instance.currentDifficulty.toTitleCase();
|
||||
}
|
||||
metadataDifficulty.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataDifficulty);
|
||||
|
||||
var metadataDeaths:FlxText = new FlxText(20, 15 + 64, 0, '0 Blue Balls');
|
||||
var metadataDeaths:FlxText = new FlxText(20, 15 + 64, FlxG.width - 40, '0 Blue Balls');
|
||||
metadataDeaths.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
metadataDeaths.text = '${PlayState.instance?.deathCounter} Blue Balls';
|
||||
metadataDeaths.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataDeaths);
|
||||
|
||||
metadataPractice = new FlxText(20, 15 + 96, 0, 'PRACTICE MODE');
|
||||
metadataPractice = new FlxText(20, 15 + 96, FlxG.width - 40, 'PRACTICE MODE');
|
||||
metadataPractice.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false;
|
||||
metadataPractice.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataPractice);
|
||||
}
|
||||
|
||||
|
@ -149,30 +209,45 @@ class PauseSubState extends MusicBeatSubState
|
|||
trace('DIFFICULTIES: ${difficultiesInVariation}');
|
||||
for (difficulty in difficultiesInVariation)
|
||||
{
|
||||
difficulties.push({text: difficulty.toTitleCase(), callback: () -> changeDifficulty(this, difficulty)});
|
||||
entries.push({text: difficulty.toTitleCase(), callback: (state) -> changeDifficulty(state, difficulty)});
|
||||
}
|
||||
}
|
||||
|
||||
// Add the back button.
|
||||
currentMenuEntries = entries.concat(PAUSE_MENU_ENTRIES_DIFFICULTY.clone());
|
||||
case PauseMode.Conversation:
|
||||
currentMenuEntries = PAUSE_MENU_ENTRIES_CONVERSATION.clone();
|
||||
case PauseMode.Cutscene:
|
||||
currentMenuEntries = PAUSE_MENU_ENTRIES_CUTSCENE.clone();
|
||||
currentMenuEntries = PAUSE_MENU_ENTRIES_VIDEO_CUTSCENE.clone();
|
||||
}
|
||||
|
||||
// Render out the entries depending on the mode.
|
||||
for (entryIndex in 0...entries)
|
||||
var entryIndex:Int = 0;
|
||||
var toRemove = [];
|
||||
for (entry in currentMenuEntries)
|
||||
{
|
||||
var entry:PauseMenuEntry = entries[entryIndex];
|
||||
if (entry == null || (entry.filter != null && !entry.filter()))
|
||||
{
|
||||
// Remove entries that should be hidden.
|
||||
toRemove.push(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle visible entries.
|
||||
var yPos:Float = 70 * entryIndex + 30;
|
||||
var text:AtlasText = new AtlasText(0, yPos, entry.text, AtlasFont.BOLD);
|
||||
text.scrollFactor.set(0, 0);
|
||||
text.alpha = 0;
|
||||
menuEntryText.add(text);
|
||||
|
||||
// Remove entries that should be hidden.
|
||||
if (entry.filter != null && !entry.filter()) currentMenuEntries.remove(entry);
|
||||
entry.sprite = text;
|
||||
|
||||
var yPos:Float = 70 * entryIndex + 30;
|
||||
var text:AtlasText = new AtlasText(0, yPos, entry.text, AtlasFont.BOLD);
|
||||
text.alpha = 0;
|
||||
menuEntryText.add(text);
|
||||
|
||||
entry.sprite = text;
|
||||
entryIndex++;
|
||||
}
|
||||
}
|
||||
for (entry in toRemove)
|
||||
{
|
||||
currentMenuEntries.remove(entry);
|
||||
}
|
||||
|
||||
metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false;
|
||||
|
@ -182,15 +257,19 @@ class PauseSubState extends MusicBeatSubState
|
|||
|
||||
function transitionIn():Void
|
||||
{
|
||||
FlxTween.globalManager.bgColor(this, 0.4, FlxColor.fromRGB(0, 0, 0, 0.0), FlxColor.fromRGB(0, 0, 0, 0.6), {ease: FlxEase.quartInOut});
|
||||
FlxTween.tween(background, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut});
|
||||
|
||||
// Animate each element a little bit downwards.
|
||||
var delay:Float = 0.3;
|
||||
var delay:Float = 0.1;
|
||||
for (child in metadata.members)
|
||||
{
|
||||
FlxTween.tween(child, {alpha: 1, y: child.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: delay});
|
||||
delay += 0.2;
|
||||
delay += 0.05;
|
||||
}
|
||||
|
||||
new FlxTimer().start(0.2, (_) -> {
|
||||
allowInput = true;
|
||||
});
|
||||
}
|
||||
|
||||
function handleInputs():Void
|
||||
|
@ -205,22 +284,24 @@ class PauseSubState extends MusicBeatSubState
|
|||
{
|
||||
changeSelection(1);
|
||||
}
|
||||
if (controls.PAUSE)
|
||||
{
|
||||
resume(this);
|
||||
}
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
menuEntries[currentEntry].callback(this);
|
||||
currentMenuEntries[currentEntry].callback(this);
|
||||
}
|
||||
else if (controls.PAUSE)
|
||||
{
|
||||
resume(this);
|
||||
}
|
||||
|
||||
#if (debug || FORCE_DEBUG_VERSION)
|
||||
// to pause the game and get screenshots easy, press H on pause menu!
|
||||
if (FlxG.keys.justPressed.H)
|
||||
{
|
||||
var visible = !metaDataGrp.visible;
|
||||
metadata = visible;
|
||||
menuEntryText = visible;
|
||||
var visible = !metadata.visible;
|
||||
|
||||
metadata.visible = visible;
|
||||
menuEntryText.visible = visible;
|
||||
this.bgColor = visible ? 0x99000000 : 0x00000000; // 60% or fully transparent black
|
||||
}
|
||||
#end
|
||||
|
@ -232,14 +313,14 @@ class PauseSubState extends MusicBeatSubState
|
|||
|
||||
currentEntry += change;
|
||||
|
||||
if (currentEntry < 0) currentEntry = menuEntries.length - 1;
|
||||
if (currentEntry >= menuEntries.length) currentEntry = 0;
|
||||
if (currentEntry < 0) currentEntry = currentMenuEntries.length - 1;
|
||||
if (currentEntry >= currentMenuEntries.length) currentEntry = 0;
|
||||
|
||||
for (entryIndex in 0...menuEntries.length)
|
||||
for (entryIndex in 0...currentMenuEntries.length)
|
||||
{
|
||||
var isCurrent:Bool = entryIndex == currentEntry;
|
||||
|
||||
var entry:PauseMenuEntry = menuEntries[entryIndex];
|
||||
var entry:PauseMenuEntry = currentMenuEntries[entryIndex];
|
||||
var text:AtlasText = entry.sprite;
|
||||
|
||||
// Set the transparency.
|
||||
|
@ -248,6 +329,7 @@ class PauseSubState extends MusicBeatSubState
|
|||
// Set the position.
|
||||
var targetX = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 20 + 90;
|
||||
var targetY = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 120 + (FlxG.height * 0.48);
|
||||
trace(targetY);
|
||||
FlxTween.tween(text, {x: targetX, y: targetY}, 0.16, {ease: FlxEase.linear});
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +373,35 @@ class PauseSubState extends MusicBeatSubState
|
|||
if (PlayState.instance == null) return;
|
||||
|
||||
PlayState.instance.isPracticeMode = true;
|
||||
regenerateMenu();
|
||||
state.regenerateMenu();
|
||||
}
|
||||
|
||||
static function restartVideoCutscene(state:PauseSubState):Void
|
||||
{
|
||||
VideoCutscene.restartVideo();
|
||||
state.close();
|
||||
}
|
||||
|
||||
static function skipVideoCutscene(state:PauseSubState):Void
|
||||
{
|
||||
VideoCutscene.finishVideo();
|
||||
state.close();
|
||||
}
|
||||
|
||||
static function restartConversation(state:PauseSubState):Void
|
||||
{
|
||||
if (PlayState.instance?.currentConversation == null) return;
|
||||
|
||||
PlayState.instance.currentConversation.resetConversation();
|
||||
state.close();
|
||||
}
|
||||
|
||||
static function skipConversation(state:PauseSubState):Void
|
||||
{
|
||||
if (PlayState.instance?.currentConversation == null) return;
|
||||
|
||||
PlayState.instance.currentConversation.skipConversation();
|
||||
state.close();
|
||||
}
|
||||
|
||||
static function quitToMenu(state:PauseSubState):Void
|
||||
|
@ -306,11 +416,11 @@ class PauseSubState extends MusicBeatSubState
|
|||
if (PlayStatePlaylist.isStoryMode)
|
||||
{
|
||||
PlayStatePlaylist.reset();
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.story.StoryMenuState(sticker)));
|
||||
state.openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.story.StoryMenuState(sticker)));
|
||||
}
|
||||
else
|
||||
{
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(null, sticker)));
|
||||
state.openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(null, sticker)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,7 +461,12 @@ enum PauseMode
|
|||
Difficulty;
|
||||
|
||||
/**
|
||||
* The menu displayed when the player pauses the game during a cutscene.
|
||||
* The menu displayed when the player pauses the game during a conversation.
|
||||
*/
|
||||
Conversation;
|
||||
|
||||
/**
|
||||
* The menu displayed when the player pauses the game during a video cutscene.
|
||||
*/
|
||||
Cutscene;
|
||||
}
|
||||
|
|
|
@ -314,6 +314,11 @@ class PlayState extends MusicBeatSubState
|
|||
**/
|
||||
var inputReleaseQueue:Array<PreciseInputEvent> = [];
|
||||
|
||||
/**
|
||||
* If we just unpaused the game, we shouldn't be able to pause again for one frame.
|
||||
*/
|
||||
var justUnpaused:Bool = false;
|
||||
|
||||
/**
|
||||
* PRIVATE INSTANCE VARIABLES
|
||||
* Private instance variables should be used for information that must be reset or dereferenced
|
||||
|
@ -442,11 +447,6 @@ class PlayState extends MusicBeatSubState
|
|||
*/
|
||||
var comboPopUps:PopUpStuff;
|
||||
|
||||
/**
|
||||
* The circular sprite that appears while the user is holding down the Skip Cutscene button.
|
||||
*/
|
||||
var skipTimer:FlxPieDial;
|
||||
|
||||
/**
|
||||
* PROPERTIES
|
||||
*/
|
||||
|
@ -474,7 +474,7 @@ class PlayState extends MusicBeatSubState
|
|||
if (!Std.isOfType(this.subState, PauseSubState)) return false;
|
||||
|
||||
var pauseSubState:PauseSubState = cast this.subState;
|
||||
return pauseSubState.exitingToMenu;
|
||||
return !pauseSubState.allowInput;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -629,14 +629,6 @@ class PlayState extends MusicBeatSubState
|
|||
comboPopUps.cameras = [camHUD];
|
||||
add(comboPopUps);
|
||||
|
||||
// The little dial that shows up when you hold the Skip Cutscene key.
|
||||
skipTimer = new FlxPieDial(16, 16, 32, FlxColor.WHITE, 36, CIRCLE, true, 24);
|
||||
skipTimer.amount = 0;
|
||||
skipTimer.zIndex = 1000;
|
||||
add(skipTimer);
|
||||
// Renders only in video cutscene mode.
|
||||
skipTimer.cameras = [camCutscene];
|
||||
|
||||
#if discord_rpc
|
||||
// Initialize Discord Rich Presence.
|
||||
initDiscord();
|
||||
|
@ -752,6 +744,8 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
// TOTAL: 9.42% CPU Time when profiled in VS 2019.
|
||||
|
||||
if (criticalFailure) return;
|
||||
|
||||
super.update(elapsed);
|
||||
|
@ -853,7 +847,7 @@ class PlayState extends MusicBeatSubState
|
|||
#end
|
||||
|
||||
// Attempt to pause the game.
|
||||
if ((controls.PAUSE || androidPause) && isInCountdown && mayPauseGame)
|
||||
if ((controls.PAUSE || androidPause) && isInCountdown && mayPauseGame && !justUnpaused)
|
||||
{
|
||||
var event = new PauseScriptEvent(FlxG.random.bool(1 / 1000));
|
||||
|
||||
|
@ -888,12 +882,12 @@ class PlayState extends MusicBeatSubState
|
|||
boyfriendPos = currentStage.getBoyfriend().getScreenPosition();
|
||||
}
|
||||
|
||||
var pauseSubState:FlxSubState = new PauseSubState(isChartingMode);
|
||||
var pauseSubState:FlxSubState = new PauseSubState({mode: isChartingMode ? Charting : Standard});
|
||||
|
||||
FlxTransitionableSubState.skipNextTransIn = true;
|
||||
FlxTransitionableSubState.skipNextTransOut = true;
|
||||
openSubState(pauseSubState);
|
||||
pauseSubState.camera = camHUD;
|
||||
openSubState(pauseSubState);
|
||||
// boyfriendPos.put(); // TODO: Why is this here?
|
||||
}
|
||||
|
||||
|
@ -1017,6 +1011,8 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
// Moving notes into position is now done by Strumline.update().
|
||||
processNotes(elapsed);
|
||||
|
||||
justUnpaused = false;
|
||||
}
|
||||
|
||||
public override function dispatchEvent(event:ScriptEvent):Void
|
||||
|
@ -1105,6 +1101,8 @@ class PlayState extends MusicBeatSubState
|
|||
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC);
|
||||
}
|
||||
#end
|
||||
|
||||
justUnpaused = true;
|
||||
}
|
||||
else if (Std.isOfType(subState, Transition))
|
||||
{
|
||||
|
@ -2444,58 +2442,39 @@ class PlayState extends MusicBeatSubState
|
|||
*/
|
||||
function handleCutsceneKeys(elapsed:Float):Void
|
||||
{
|
||||
if (isGamePaused) return;
|
||||
|
||||
if (currentConversation != null)
|
||||
{
|
||||
if (controls.CUTSCENE_ADVANCE) currentConversation?.advanceConversation();
|
||||
|
||||
if (controls.CUTSCENE_SKIP)
|
||||
// Pause/unpause may conflict with advancing the conversation!
|
||||
if (controls.CUTSCENE_ADVANCE && !justUnpaused)
|
||||
{
|
||||
currentConversation?.trySkipConversation(elapsed);
|
||||
currentConversation?.advanceConversation();
|
||||
}
|
||||
else
|
||||
else if (controls.PAUSE && !justUnpaused)
|
||||
{
|
||||
currentConversation?.trySkipConversation(-1);
|
||||
var pauseSubState:FlxSubState = new PauseSubState({mode: Conversation});
|
||||
|
||||
persistentUpdate = false;
|
||||
FlxTransitionableSubState.skipNextTransIn = true;
|
||||
FlxTransitionableSubState.skipNextTransOut = true;
|
||||
pauseSubState.camera = camCutscene;
|
||||
openSubState(pauseSubState);
|
||||
}
|
||||
}
|
||||
else if (VideoCutscene.isPlaying())
|
||||
{
|
||||
// This is a video cutscene.
|
||||
|
||||
if (controls.CUTSCENE_SKIP)
|
||||
if (controls.PAUSE && !justUnpaused)
|
||||
{
|
||||
trySkipVideoCutscene(elapsed);
|
||||
var pauseSubState:FlxSubState = new PauseSubState({mode: Cutscene});
|
||||
|
||||
persistentUpdate = false;
|
||||
FlxTransitionableSubState.skipNextTransIn = true;
|
||||
FlxTransitionableSubState.skipNextTransOut = true;
|
||||
pauseSubState.camera = camCutscene;
|
||||
openSubState(pauseSubState);
|
||||
}
|
||||
else
|
||||
{
|
||||
trySkipVideoCutscene(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle logic for the skip timer.
|
||||
* If the skip button is being held, pass the amount of time elapsed since last game update.
|
||||
* If the skip button has been released, pass a negative number.
|
||||
*/
|
||||
function trySkipVideoCutscene(elapsed:Float):Void
|
||||
{
|
||||
if (skipTimer == null || skipTimer.animation == null) return;
|
||||
|
||||
if (elapsed < 0)
|
||||
{
|
||||
skipHeldTimer = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skipHeldTimer += elapsed;
|
||||
}
|
||||
|
||||
skipTimer.visible = skipHeldTimer >= 0.05;
|
||||
skipTimer.amount = Math.min(skipHeldTimer / 1.5, 1.0);
|
||||
|
||||
if (skipHeldTimer >= 1.5)
|
||||
{
|
||||
VideoCutscene.finishVideo();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2694,7 +2673,7 @@ class PlayState extends MusicBeatSubState
|
|||
FlxG.sound.music.pause();
|
||||
if (vocals != null)
|
||||
{
|
||||
vocals.pause();
|
||||
vocals.destroy();
|
||||
remove(vocals);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,24 @@ class VideoCutscene
|
|||
}
|
||||
#end
|
||||
|
||||
public static function restartVideo():Void
|
||||
{
|
||||
#if html5
|
||||
if (vid != null)
|
||||
{
|
||||
vid.restartVideo();
|
||||
}
|
||||
#end
|
||||
|
||||
#if hxCodec
|
||||
if (vid != null)
|
||||
{
|
||||
// Seek to the start of the video.
|
||||
vid.bitmap.time = 0;
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public static function finishVideo(?transitionTime:Float = 0.5):Void
|
||||
{
|
||||
trace('ALERT: Finish video cutscene called!');
|
||||
|
|
|
@ -31,10 +31,6 @@ import funkin.data.dialogue.DialogueBoxRegistry;
|
|||
*/
|
||||
class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass implements IRegistryEntry<ConversationData>
|
||||
{
|
||||
static final CONVERSATION_SKIP_TIMER:Float = 1.5;
|
||||
|
||||
var skipHeldTimer:Float = 0.0;
|
||||
|
||||
/**
|
||||
* The ID of the conversation.
|
||||
*/
|
||||
|
@ -105,8 +101,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
|
||||
var currentDialogueBox:DialogueBox;
|
||||
|
||||
var skipTimer:FlxPieDial;
|
||||
|
||||
public function new(id:String)
|
||||
{
|
||||
super();
|
||||
|
@ -124,8 +118,8 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
{
|
||||
// Reset the progress in the dialogue.
|
||||
currentDialogueEntry = 0;
|
||||
currentDialogueLine = 0;
|
||||
this.state = ConversationState.Start;
|
||||
this.alpha = 1.0;
|
||||
|
||||
// Start the dialogue.
|
||||
dispatchEvent(new DialogueScriptEvent(DIALOGUE_START, this, false));
|
||||
|
@ -153,6 +147,12 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
|
||||
function setupBackdrop():Void
|
||||
{
|
||||
if (backdrop != null)
|
||||
{
|
||||
backdrop.destroy();
|
||||
backdrop = null;
|
||||
}
|
||||
|
||||
backdrop = new FunkinSprite(0, 0);
|
||||
|
||||
if (_data.backdrop == null) return;
|
||||
|
@ -181,12 +181,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
refresh();
|
||||
}
|
||||
|
||||
function setupSkipTimer():Void
|
||||
{
|
||||
add(skipTimer = new FlxPieDial(16, 16, 32, FlxColor.WHITE, 36, CIRCLE, true, 24));
|
||||
skipTimer.amount = 0;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
@ -201,8 +195,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
// Skip the next steps if the current speaker is already displayed.
|
||||
if (currentSpeaker != null && nextSpeakerId == currentSpeaker.id) return;
|
||||
|
||||
var nextSpeaker:Speaker = SpeakerRegistry.instance.fetchEntry(nextSpeakerId);
|
||||
|
||||
if (currentSpeaker != null)
|
||||
{
|
||||
remove(currentSpeaker);
|
||||
|
@ -210,6 +202,8 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
currentSpeaker = null;
|
||||
}
|
||||
|
||||
var nextSpeaker:Speaker = SpeakerRegistry.instance.fetchEntry(nextSpeakerId);
|
||||
|
||||
if (nextSpeaker == null)
|
||||
{
|
||||
if (nextSpeakerId == null)
|
||||
|
@ -222,6 +216,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (!nextSpeaker.alive) nextSpeaker.revive();
|
||||
|
||||
ScriptEventDispatcher.callEvent(nextSpeaker, new ScriptEvent(CREATE, true));
|
||||
|
||||
|
@ -266,6 +261,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
trace('Dialogue box could not be retrieved.');
|
||||
return;
|
||||
}
|
||||
if (!nextDialogueBox.alive) nextDialogueBox.revive();
|
||||
|
||||
ScriptEventDispatcher.callEvent(nextDialogueBox, new ScriptEvent(CREATE, true));
|
||||
|
||||
|
@ -347,29 +343,21 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
currentDialogueEntry = 0;
|
||||
this.state = ConversationState.Start;
|
||||
|
||||
advanceConversation();
|
||||
}
|
||||
if (outroTween != null) outroTween.cancel(); // Canc
|
||||
outroTween = null;
|
||||
|
||||
public function trySkipConversation(elapsed:Float):Void
|
||||
{
|
||||
if (skipTimer == null || skipTimer.animation == null) return;
|
||||
this.alpha = 0.0;
|
||||
if (this.music != null) this.music.stop();
|
||||
this.music = null;
|
||||
|
||||
if (elapsed < 0)
|
||||
{
|
||||
skipHeldTimer = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
skipHeldTimer += elapsed;
|
||||
}
|
||||
if (currentSpeaker != null) currentSpeaker.kill();
|
||||
currentSpeaker = null;
|
||||
if (currentDialogueBox != null) currentDialogueBox.kill();
|
||||
currentDialogueBox = null;
|
||||
if (backdrop != null) backdrop.kill();
|
||||
backdrop = null;
|
||||
|
||||
skipTimer.visible = skipHeldTimer >= 0.05;
|
||||
skipTimer.amount = Math.min(skipHeldTimer / CONVERSATION_SKIP_TIMER, 1.0);
|
||||
|
||||
if (skipHeldTimer >= CONVERSATION_SKIP_TIMER)
|
||||
{
|
||||
skipConversation();
|
||||
}
|
||||
startConversation();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,7 +413,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
// Fade in the music and backdrop.
|
||||
setupMusic();
|
||||
setupBackdrop();
|
||||
setupSkipTimer();
|
||||
|
||||
// Advance the conversation.
|
||||
state = ConversationState.Opening;
|
||||
|
@ -554,12 +541,16 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl
|
|||
if (this.music != null) this.music.stop();
|
||||
this.music = null;
|
||||
|
||||
this.skipTimer = null;
|
||||
if (currentSpeaker != null) currentSpeaker.kill();
|
||||
remove(currentSpeaker);
|
||||
currentSpeaker = null;
|
||||
|
||||
if (currentDialogueBox != null) currentDialogueBox.kill();
|
||||
remove(currentDialogueBox);
|
||||
currentDialogueBox = null;
|
||||
|
||||
if (backdrop != null) backdrop.kill();
|
||||
remove(backdrop);
|
||||
backdrop = null;
|
||||
|
||||
this.clear();
|
||||
|
|
|
@ -8,6 +8,7 @@ import flixel.text.FlxText;
|
|||
import flixel.addons.text.FlxTypeText;
|
||||
import funkin.util.assets.FlxAnimationUtil;
|
||||
import funkin.modding.events.ScriptEvent;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.modding.IScriptedClass.IDialogueScriptedClass;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.data.dialogue.DialogueBoxData;
|
||||
|
@ -111,9 +112,6 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple
|
|||
this.y = 0;
|
||||
this.alpha = 1;
|
||||
|
||||
this.boxSprite = new FlxSprite(0, 0);
|
||||
add(this.boxSprite);
|
||||
|
||||
loadSpritesheet();
|
||||
loadAnimations();
|
||||
|
||||
|
@ -122,6 +120,15 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple
|
|||
|
||||
function loadSpritesheet():Void
|
||||
{
|
||||
if (this.boxSprite != null)
|
||||
{
|
||||
remove(this.boxSprite);
|
||||
this.boxSprite = null;
|
||||
}
|
||||
|
||||
this.boxSprite = new FlxSprite(0, 0);
|
||||
add(this.boxSprite);
|
||||
|
||||
trace('[DIALOGUE BOX] Loading spritesheet ${_data.assetPath} for ${id}');
|
||||
|
||||
var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath);
|
||||
|
@ -190,6 +197,31 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple
|
|||
this.boxSprite.updateHitbox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `kill()` on the group's members and then on the group itself.
|
||||
* You can revive this group later via `revive()` after this.
|
||||
*/
|
||||
public override function kill():Void
|
||||
{
|
||||
super.kill();
|
||||
if (this.boxSprite != null)
|
||||
{
|
||||
this.boxSprite.kill();
|
||||
this.boxSprite = null;
|
||||
}
|
||||
if (this.textDisplay != null)
|
||||
{
|
||||
this.textDisplay.kill();
|
||||
this.textDisplay = null;
|
||||
}
|
||||
this.clear();
|
||||
}
|
||||
|
||||
public override function revive():Void
|
||||
{
|
||||
super.revive();
|
||||
}
|
||||
|
||||
function loadAnimations():Void
|
||||
{
|
||||
trace('[DIALOGUE BOX] Loading ${_data.animations.length} animations for ${id}');
|
||||
|
@ -246,7 +278,8 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple
|
|||
textDisplay.setFormat(_data.text.fontFamily, _data.text.size, FlxColor.fromString(_data.text.color), LEFT, SHADOW,
|
||||
FlxColor.fromString(_data.text.shadowColor ?? '#00000000'), false);
|
||||
textDisplay.borderSize = _data.text.shadowWidth ?? 2;
|
||||
textDisplay.sounds = [FlxG.sound.load(Paths.sound('pixelText'), 0.6)];
|
||||
// TODO: Add an option to configure this.
|
||||
textDisplay.sounds = [FunkinSound.load(Paths.sound('pixelText'), 0.6)];
|
||||
|
||||
textDisplay.completeCallback = onTypingComplete;
|
||||
|
||||
|
|
|
@ -106,6 +106,23 @@ class Speaker extends FlxSprite implements IDialogueScriptedClass implements IRe
|
|||
loadAnimations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `kill()` on the group's members and then on the group itself.
|
||||
* You can revive this group later via `revive()` after this.
|
||||
*/
|
||||
public override function kill():Void
|
||||
{
|
||||
super.kill();
|
||||
}
|
||||
|
||||
public override function revive():Void
|
||||
{
|
||||
super.revive();
|
||||
|
||||
loadSpritesheet();
|
||||
loadAnimations();
|
||||
}
|
||||
|
||||
function loadSpritesheet():Void
|
||||
{
|
||||
trace('[SPEAKER] Loading spritesheet ${_data.assetPath} for ${id}');
|
||||
|
|
|
@ -614,9 +614,9 @@ class SongDifficulty
|
|||
}
|
||||
|
||||
// Add player vocals.
|
||||
if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(Assets.getSound(voiceList[0])));
|
||||
if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(voiceList[0]));
|
||||
// Add opponent vocals.
|
||||
if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(Assets.getSound(voiceList[1])));
|
||||
if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(voiceList[1]));
|
||||
|
||||
// Add additional vocals.
|
||||
if (voiceList.length > 2)
|
||||
|
|
|
@ -893,12 +893,6 @@ typedef SaveControlsData =
|
|||
*/
|
||||
var ?CUTSCENE_ADVANCE:Array<Int>;
|
||||
|
||||
/**
|
||||
* Keybind for skipping a cutscene.
|
||||
* @default `Escape`
|
||||
*/
|
||||
var ?CUTSCENE_SKIP:Array<Int>;
|
||||
|
||||
/**
|
||||
* Keybind for increasing volume.
|
||||
* @default `Plus`
|
||||
|
|
|
@ -35,7 +35,6 @@ typedef SaveControlsData_v1_0_0 =
|
|||
var ?ACCEPT:Array<Int>;
|
||||
var ?BACK:Array<Int>;
|
||||
var ?CUTSCENE_ADVANCE:Array<Int>;
|
||||
var ?CUTSCENE_SKIP:Array<Int>;
|
||||
var ?NOTE_DOWN:Array<Int>;
|
||||
var ?NOTE_LEFT:Array<Int>;
|
||||
var ?NOTE_RIGHT:Array<Int>;
|
||||
|
|
|
@ -272,7 +272,6 @@ class SaveDataMigrator
|
|||
ACCEPT: controlsData?.keys?.ACCEPT ?? null,
|
||||
BACK: controlsData?.keys?.BACK ?? null,
|
||||
CUTSCENE_ADVANCE: controlsData?.keys?.CUTSCENE_ADVANCE ?? null,
|
||||
CUTSCENE_SKIP: controlsData?.keys?.CUTSCENE_SKIP ?? null,
|
||||
NOTE_DOWN: controlsData?.keys?.NOTE_DOWN ?? null,
|
||||
NOTE_LEFT: controlsData?.keys?.NOTE_LEFT ?? null,
|
||||
NOTE_RIGHT: controlsData?.keys?.NOTE_RIGHT ?? null,
|
||||
|
@ -293,7 +292,6 @@ class SaveDataMigrator
|
|||
ACCEPT: controlsData?.pad?.ACCEPT ?? null,
|
||||
BACK: controlsData?.pad?.BACK ?? null,
|
||||
CUTSCENE_ADVANCE: controlsData?.pad?.CUTSCENE_ADVANCE ?? null,
|
||||
CUTSCENE_SKIP: controlsData?.pad?.CUTSCENE_SKIP ?? null,
|
||||
NOTE_DOWN: controlsData?.pad?.NOTE_DOWN ?? null,
|
||||
NOTE_LEFT: controlsData?.pad?.NOTE_LEFT ?? null,
|
||||
NOTE_RIGHT: controlsData?.pad?.NOTE_RIGHT ?? null,
|
||||
|
|
|
@ -51,6 +51,7 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler
|
|||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
// 3.59% CPU Usage (100% is FlxTypedGroup#update() and most of that is updating each member.)
|
||||
super.update(elapsed);
|
||||
|
||||
// Emergency exit button.
|
||||
|
@ -61,8 +62,11 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler
|
|||
|
||||
// Display Conductor info in the watch window.
|
||||
FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0);
|
||||
|
||||
// 0.09% CPU Usage?
|
||||
Conductor.watchQuick();
|
||||
|
||||
// 4.31% CPU Usage
|
||||
dispatchEvent(new UpdateScriptEvent(elapsed));
|
||||
}
|
||||
|
||||
|
|
|
@ -62,15 +62,6 @@ class ConversationDebugState extends MusicBeatState
|
|||
if (conversation != null)
|
||||
{
|
||||
if (controls.CUTSCENE_ADVANCE) conversation.advanceConversation();
|
||||
|
||||
if (controls.CUTSCENE_SKIP)
|
||||
{
|
||||
conversation.trySkipConversation(elapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
conversation.trySkipConversation(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page
|
|||
static var controlGroups:Array<Array<Control>> = [
|
||||
[NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT],
|
||||
[UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK],
|
||||
[CUTSCENE_ADVANCE, CUTSCENE_SKIP],
|
||||
[CUTSCENE_ADVANCE],
|
||||
[VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE],
|
||||
[DEBUG_MENU, DEBUG_CHART]
|
||||
];
|
||||
|
|
37
source/funkin/util/plugins/MemoryGCPlugin.hx
Normal file
37
source/funkin/util/plugins/MemoryGCPlugin.hx
Normal file
|
@ -0,0 +1,37 @@
|
|||
package funkin.util.plugins;
|
||||
|
||||
import flixel.FlxBasic;
|
||||
|
||||
/**
|
||||
* A plugin which adds functionality to press `Ins` to immediately perform memory garbage collection.
|
||||
*/
|
||||
class MemoryGCPlugin extends FlxBasic
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public static function initialize():Void
|
||||
{
|
||||
FlxG.plugins.addPlugin(new MemoryGCPlugin());
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (FlxG.keys.justPressed.INSERT)
|
||||
{
|
||||
var perfStart:Float = Sys.time();
|
||||
funkin.util.MemoryUtil.collect(true);
|
||||
var perfEnd:Float = Sys.time();
|
||||
trace("Memory GC took " + (perfEnd - perfStart) + " seconds");
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy():Void
|
||||
{
|
||||
super.destroy();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package funkin.util.tools;
|
||||
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.FlxTween.FlxTweenManager;
|
||||
|
||||
class FlxTweenTools
|
||||
{
|
||||
/**
|
||||
* Tween the background color of a FlxState.
|
||||
* @param globalManager `flixel.tweens.FlxTween.globalManager`
|
||||
* @param targetState The FlxState to tween the background color of.
|
||||
* @param duration The duration of the tween.
|
||||
* @param fromColor The starting color.
|
||||
* @param toColor The ending color.
|
||||
* @param options The options for the tween.
|
||||
* @return The tween.
|
||||
*/
|
||||
public static function bgColor(globalManager:FlxTweenManager, targetState:FlxState, duration:Float = 1.0, fromColor:FlxColor, toColor:FlxColor,
|
||||
?options:TweenOptions):BackgroundColorTween
|
||||
{
|
||||
var tween = new BackgroundColorTween(options, this);
|
||||
tween.tween(duration, fromColor, toColor, targetState);
|
||||
globalManager.add(tween);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue