Merge branch 'rewrite/master' into bugfix/chart-editor-vocal-crash

This commit is contained in:
Eric 2024-03-04 23:00:38 -05:00 committed by GitHub
commit 3aa4c23340
10 changed files with 162 additions and 94 deletions

View file

@ -23,10 +23,10 @@
}, },
{ {
"props": { "props": {
"allowSingleArgParens": false, "allowSingleArgParens": true,
"allowReturn": false, "allowReturn": true,
"allowFunction": false, "allowFunction": true,
"allowCurlyBody": false "allowCurlyBody": true
}, },
"type": "ArrowFunction" "type": "ArrowFunction"
}, },
@ -80,7 +80,7 @@
"props": { "props": {
"ignoreExtern": true, "ignoreExtern": true,
"format": "^[A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$", "format": "^[A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$",
"tokens": [] "tokens": ["INLINE", "NOTINLINE"]
}, },
"type": "ConstantName" "type": "ConstantName"
}, },
@ -178,13 +178,7 @@
"fieldType": "BOTH", "fieldType": "BOTH",
"requireReturn": true, "requireReturn": true,
"ignoreOverride": true, "ignoreOverride": true,
"tokens": [ "tokens": ["ABSTRACT_DEF", "CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF"],
"ABSTRACT_DEF",
"CLASS_DEF",
"ENUM_DEF",
"INTERFACE_DEF",
"TYPEDEF_DEF"
],
"modifier": "PUBLIC", "modifier": "PUBLIC",
"excludeNames": ["new", "toString"] "excludeNames": ["new", "toString"]
}, },
@ -198,10 +192,6 @@
}, },
"type": "FileLength" "type": "FileLength"
}, },
{
"props": {},
"type": "Final"
},
{ {
"props": { "props": {
"option": "upperCase" "option": "upperCase"
@ -375,7 +365,7 @@
}, },
{ {
"props": { "props": {
"max": 1 "max": 4
}, },
"type": "NestedIfDepth" "type": "NestedIfDepth"
}, },
@ -387,7 +377,7 @@
}, },
{ {
"props": { "props": {
"option": "nullDefault" "option": "questionMark"
}, },
"type": "NullableParameter" "type": "NullableParameter"
}, },
@ -396,7 +386,6 @@
"oldFunctionTypePolicy": "none", "oldFunctionTypePolicy": "none",
"unaryOpPolicy": "none", "unaryOpPolicy": "none",
"intervalOpPolicy": "none", "intervalOpPolicy": "none",
"newFunctionTypePolicy": "around", "newFunctionTypePolicy": "around",
"ternaryOpPolicy": "around", "ternaryOpPolicy": "around",
"boolOpPolicy": "around", "boolOpPolicy": "around",
@ -589,19 +578,7 @@
}, },
{ {
"props": { "props": {
"ignoreEnumAbstractValues": true "tokens": ["CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF", "TYPEDEF_DEF"]
},
"type": "Type"
},
{
"props": {
"tokens": [
"ABSTRACT_DEF",
"CLASS_DEF",
"ENUM_DEF",
"INTERFACE_DEF",
"TYPEDEF_DEF"
]
}, },
"type": "TypeDocComment" "type": "TypeDocComment"
}, },
@ -630,12 +607,6 @@
}, },
"type": "UnusedLocalVar" "type": "UnusedLocalVar"
}, },
{
"props": {
"severity": "IGNORE"
},
"type": "VariableInitialisation"
},
{ {
"props": { "props": {
"typeHintPolicy": "enforce_all", "typeHintPolicy": "enforce_all",

View file

@ -6,7 +6,6 @@
"tabWidth": 2, "tabWidth": 2,
"indentCaseLabels": true "indentCaseLabels": true
}, },
"lineEnds": { "lineEnds": {
"anonFunctionCurly": { "anonFunctionCurly": {
"emptyCurly": "break", "emptyCurly": "break",

View file

@ -5,7 +5,42 @@ package funkin;
*/ */
class Highscore class Highscore
{ {
/**
* Keeps track of notes hit for the current song
* and how accurate you were with each note (bad, missed, shit, etc.)
*/
public static var tallies:Tallies = new Tallies(); public static var tallies:Tallies = new Tallies();
/**
* Keeps track of notes hit for the current WEEK / level
* for use with storymode, or likely any other "playlist" esque option
*/
public static var talliesLevel:Tallies = new Tallies();
/**
* Produces a new Tallies object which represents the sum of two existing Tallies
* @param newTally The first tally
* @param baseTally The second tally
* @return The combined tally
*/
public static function combineTallies(newTally:Tallies, baseTally:Tallies):Tallies
{
var combinedTally:Tallies = new Tallies();
combinedTally.missed = newTally.missed + baseTally.missed;
combinedTally.shit = newTally.shit + baseTally.shit;
combinedTally.bad = newTally.bad + baseTally.bad;
combinedTally.good = newTally.good + baseTally.good;
combinedTally.sick = newTally.sick + baseTally.sick;
combinedTally.totalNotes = newTally.totalNotes + baseTally.totalNotes;
combinedTally.totalNotesHit = newTally.totalNotesHit + baseTally.totalNotesHit;
// Current combo = use most recent.
combinedTally.combo = newTally.combo;
// Max combo = use maximum value.
combinedTally.maxCombo = Std.int(Math.max(newTally.maxCombo, baseTally.maxCombo));
return combinedTally;
}
} }
@:forward @:forward
@ -29,6 +64,9 @@ abstract Tallies(RawTallies)
} }
} }
/**
* A structure object containing the data for highscore tallies.
*/
typedef RawTallies = typedef RawTallies =
{ {
var combo:Int; var combo:Int;
@ -51,7 +89,7 @@ typedef RawTallies =
var totalNotesHit:Int; var totalNotesHit:Int;
/** /**
* How many notes PASSED BY AND/OR HIT!!! * How many notes in the current chart
*/ */
var totalNotes:Int; var totalNotes:Int;
} }

View file

@ -32,6 +32,7 @@ import funkin.util.CLIUtil;
import funkin.util.CLIUtil.CLIParams; import funkin.util.CLIUtil.CLIParams;
import funkin.util.tools.TimerTools; import funkin.util.tools.TimerTools;
import funkin.ui.transition.LoadingState; import funkin.ui.transition.LoadingState;
import funkin.util.TrackerUtil;
#if discord_rpc #if discord_rpc
import Discord.DiscordClient; import Discord.DiscordClient;
#end #end
@ -67,7 +68,7 @@ class InitState extends FlxState
/** /**
* Setup a bunch of important Flixel stuff. * Setup a bunch of important Flixel stuff.
*/ */
function setupShit() function setupShit():Void
{ {
// //
// GAME SETUP // GAME SETUP
@ -95,7 +96,7 @@ class InitState extends FlxState
#if (debug || FORCE_DEBUG_VERSION) #if (debug || FORCE_DEBUG_VERSION)
// Disable using ~ to open the console (we use that for the Editor menu) // Disable using ~ to open the console (we use that for the Editor menu)
FlxG.debugger.toggleKeys = [F2]; FlxG.debugger.toggleKeys = [F2];
TrackerUtil.initTrackers();
// Adds an additional Close Debugger button. // Adds an additional Close Debugger button.
// This big obnoxious white button is for MOBILE, so that you can press it // This big obnoxious white button is for MOBILE, so that you can press it
// easily with your finger when debug bullshit pops up during testing lol! // easily with your finger when debug bullshit pops up during testing lol!

View file

@ -90,6 +90,11 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
*/ */
var _label:String = "unknown"; var _label:String = "unknown";
/**
* Whether we received a focus lost event.
*/
var _lostFocus:Bool = false;
public function new() public function new()
{ {
super(); super();
@ -166,9 +171,19 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
} }
public override function pause():FunkinSound public override function pause():FunkinSound
{
if (_shouldPlay)
{
// This sound will eventually play, but is still at a negative timestamp.
// Manually set the paused flag to ensure proper focus/unfocus behavior.
_shouldPlay = false;
_paused = true;
active = false;
}
else
{ {
super.pause(); super.pause();
this._shouldPlay = false; }
return this; return this;
} }
@ -177,7 +192,10 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
*/ */
override function onFocus():Void override function onFocus():Void
{ {
if (!_alreadyPaused) // Flixel can sometimes toss spurious `onFocus` events, e.g. if the Flixel debugger is toggled
// on and off. We only want to resume the sound if we actually lost focus, and if we weren't
// already paused before we lost focus.
if (_lostFocus && !_alreadyPaused)
{ {
resume(); resume();
} }
@ -185,6 +203,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
{ {
trace('Not resuming audio on focus!'); trace('Not resuming audio on focus!');
} }
_lostFocus = false;
} }
/** /**
@ -193,6 +212,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
override function onFocusLost():Void override function onFocusLost():Void
{ {
trace('Focus lost, pausing audio!'); trace('Focus lost, pausing audio!');
_lostFocus = true;
_alreadyPaused = _paused; _alreadyPaused = _paused;
pause(); pause();
} }
@ -201,7 +221,10 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
{ {
if (this._time < 0) if (this._time < 0)
{ {
this._shouldPlay = true; // Sound with negative timestamp, restart the timer.
_shouldPlay = true;
_paused = false;
active = true;
} }
else else
{ {

View file

@ -106,6 +106,8 @@ class SongMetadata implements ICloneable<SongMetadata>
/** /**
* Serialize this SongMetadata into a JSON string. * Serialize this SongMetadata into a JSON string.
* @param pretty Whether the JSON should be big ol string (false),
* or formatted with tabs (true)
* @return The JSON string. * @return The JSON string.
*/ */
public function serialize(pretty:Bool = true):String public function serialize(pretty:Bool = true):String

View file

@ -1732,7 +1732,6 @@ class PlayState extends MusicBeatSubState
if (strumTime < startTime) continue; // Skip notes that are before the start time. if (strumTime < startTime) continue; // Skip notes that are before the start time.
var noteData:Int = songNote.getDirection(); var noteData:Int = songNote.getDirection();
var playerNote:Bool = true; var playerNote:Bool = true;
if (noteData > 3) playerNote = false; if (noteData > 3) playerNote = false;
@ -1741,6 +1740,8 @@ class PlayState extends MusicBeatSubState
{ {
case 0: case 0:
playerNoteData.push(songNote); playerNoteData.push(songNote);
// increment totalNotes for total possible notes able to be hit by the player
Highscore.tallies.totalNotes++;
case 1: case 1:
opponentNoteData.push(songNote); opponentNoteData.push(songNote);
} }
@ -2622,6 +2623,9 @@ class PlayState extends MusicBeatSubState
accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes, accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes,
}; };
// adds current song data into the tallies for the level (story levels)
Highscore.talliesLevel = Highscore.combineTallies(Highscore.tallies, Highscore.talliesLevel);
if (Save.instance.isSongHighScore(currentSong.id, currentDifficulty, data)) if (Save.instance.isSongHighScore(currentSong.id, currentDifficulty, data))
{ {
Save.instance.setSongScore(currentSong.id, currentDifficulty, data); Save.instance.setSongScore(currentSong.id, currentDifficulty, data);
@ -2895,11 +2899,14 @@ class PlayState extends MusicBeatSubState
persistentUpdate = false; persistentUpdate = false;
vocals.stop(); vocals.stop();
camHUD.alpha = 1; camHUD.alpha = 1;
var talliesToUse:Tallies = PlayStatePlaylist.isStoryMode ? Highscore.talliesLevel : Highscore.tallies;
var res:ResultState = new ResultState( var res:ResultState = new ResultState(
{ {
storyMode: PlayStatePlaylist.isStoryMode, storyMode: PlayStatePlaylist.isStoryMode,
title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'), title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'),
tallies: Highscore.tallies, tallies: talliesToUse,
}); });
res.camera = camHUD; res.camera = camHUD;
openSubState(res); openSubState(res);

View file

@ -2,27 +2,25 @@ package funkin.play;
import funkin.ui.story.StoryMenuState; import funkin.ui.story.StoryMenuState;
import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.adobeanimate.FlxAtlasSprite;
import flixel.FlxBasic;
import flixel.FlxSprite; import flixel.FlxSprite;
import funkin.graphics.FunkinSprite; import funkin.graphics.FunkinSprite;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.graphics.frames.FlxBitmapFont; import flixel.graphics.frames.FlxBitmapFont;
import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxPoint; import flixel.math.FlxPoint;
import funkin.ui.MusicBeatSubState; import funkin.ui.MusicBeatSubState;
import flixel.math.FlxRect; import flixel.math.FlxRect;
import flixel.text.FlxBitmapText; import flixel.text.FlxBitmapText;
import flixel.text.FlxText;
import flixel.tweens.FlxEase; import flixel.tweens.FlxEase;
import funkin.ui.freeplay.FreeplayState; import funkin.ui.freeplay.FreeplayState;
import flixel.tweens.FlxTween; import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import flixel.util.FlxGradient; import flixel.util.FlxGradient;
import flixel.util.FlxTimer; import flixel.util.FlxTimer;
import funkin.graphics.shaders.LeftMaskShader; import funkin.graphics.shaders.LeftMaskShader;
import funkin.play.components.TallyCounter; import funkin.play.components.TallyCounter;
import flxanimate.FlxAnimate.Settings;
/**
* The state for the results screen after a song or week is finished.
*/
class ResultState extends MusicBeatSubState class ResultState extends MusicBeatSubState
{ {
final params:ResultsStateParams; final params:ResultsStateParams;
@ -31,8 +29,8 @@ class ResultState extends MusicBeatSubState
var songName:FlxBitmapText; var songName:FlxBitmapText;
var difficulty:FlxSprite; var difficulty:FlxSprite;
var maskShaderSongName = new LeftMaskShader(); var maskShaderSongName:LeftMaskShader = new LeftMaskShader();
var maskShaderDifficulty = new LeftMaskShader(); var maskShaderDifficulty:LeftMaskShader = new LeftMaskShader();
public function new(params:ResultsStateParams) public function new(params:ResultsStateParams)
{ {
@ -50,22 +48,22 @@ class ResultState extends MusicBeatSubState
else else
resultsVariation = NORMAL; resultsVariation = NORMAL;
var loops = resultsVariation != SHIT; var loops:Bool = resultsVariation != SHIT;
FlxG.sound.playMusic(Paths.music("results" + resultsVariation), 1, loops); FlxG.sound.playMusic(Paths.music("results" + resultsVariation), 1, loops);
// TEMP-ish, just used to sorta "cache" the 3000x3000 image! // TEMP-ish, just used to sorta "cache" the 3000x3000 image!
var cacheBullShit = new FlxSprite().loadGraphic(Paths.image("resultScreen/soundSystem")); var cacheBullShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/soundSystem"));
add(cacheBullShit); add(cacheBullShit);
var dumb = new FlxSprite().loadGraphic(Paths.image("resultScreen/scorePopin")); var dumb:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/scorePopin"));
add(dumb); add(dumb);
var bg:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFECC5C, 0xFFFDC05C], 90); var bg:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFECC5C, 0xFFFDC05C], 90);
bg.scrollFactor.set(); bg.scrollFactor.set();
add(bg); add(bg);
var bgFlash:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFffeb69, 0xFFffe66a], 90); var bgFlash:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90);
bgFlash.scrollFactor.set(); bgFlash.scrollFactor.set();
bgFlash.visible = false; bgFlash.visible = false;
add(bgFlash); add(bgFlash);
@ -188,6 +186,10 @@ class ResultState extends MusicBeatSubState
var ratingGrp:FlxTypedGroup<TallyCounter> = new FlxTypedGroup<TallyCounter>(); var ratingGrp:FlxTypedGroup<TallyCounter> = new FlxTypedGroup<TallyCounter>();
add(ratingGrp); add(ratingGrp);
/**
* NOTE: We display how many notes were HIT, not how many notes there were in total.
*
*/
var totalHit:TallyCounter = new TallyCounter(375, hStuf * 3, params.tallies.totalNotesHit); var totalHit:TallyCounter = new TallyCounter(375, hStuf * 3, params.tallies.totalNotesHit);
ratingGrp.add(totalHit); ratingGrp.add(totalHit);
@ -202,7 +204,7 @@ class ResultState extends MusicBeatSubState
var tallyGood:TallyCounter = new TallyCounter(210, (hStuf * 6) + extraYOffset, params.tallies.good, 0xFF89C9E5); var tallyGood:TallyCounter = new TallyCounter(210, (hStuf * 6) + extraYOffset, params.tallies.good, 0xFF89C9E5);
ratingGrp.add(tallyGood); ratingGrp.add(tallyGood);
var tallyBad:TallyCounter = new TallyCounter(190, (hStuf * 7) + extraYOffset, params.tallies.bad, 0xffE6CF8A); var tallyBad:TallyCounter = new TallyCounter(190, (hStuf * 7) + extraYOffset, params.tallies.bad, 0xFFE6CF8A);
ratingGrp.add(tallyBad); ratingGrp.add(tallyBad);
var tallyShit:TallyCounter = new TallyCounter(220, (hStuf * 8) + extraYOffset, params.tallies.shit, 0xFFE68C8A); var tallyShit:TallyCounter = new TallyCounter(220, (hStuf * 8) + extraYOffset, params.tallies.shit, 0xFFE68C8A);
@ -274,13 +276,13 @@ class ResultState extends MusicBeatSubState
super.create(); super.create();
} }
function timerThenSongName() function timerThenSongName():Void
{ {
movingSongStuff = false; movingSongStuff = false;
difficulty.x = 555; difficulty.x = 555;
var diffYTween = 122; var diffYTween:Float = 122;
difficulty.y = -difficulty.height; difficulty.y = -difficulty.height;
FlxTween.tween(difficulty, {y: diffYTween}, 0.5, {ease: FlxEase.quartOut, startDelay: 0.8}); FlxTween.tween(difficulty, {y: diffYTween}, 0.5, {ease: FlxEase.quartOut, startDelay: 0.8});
@ -310,7 +312,7 @@ class ResultState extends MusicBeatSubState
// maskShaderSongName.frameUV = songName.frame.uv; // maskShaderSongName.frameUV = songName.frame.uv;
} }
override function update(elapsed:Float) override function update(elapsed:Float):Void
{ {
// maskShaderSongName.swagSprX = songName.x; // maskShaderSongName.swagSprX = songName.x;
maskShaderDifficulty.swagSprX = difficulty.x; maskShaderDifficulty.swagSprX = difficulty.x;

View file

@ -519,7 +519,7 @@ class StoryMenuState extends MusicBeatState
} }
} }
function selectLevel() function selectLevel():Void
{ {
if (!currentLevel.isUnlocked()) if (!currentLevel.isUnlocked())
{ {
@ -554,6 +554,8 @@ class StoryMenuState extends MusicBeatState
PlayStatePlaylist.campaignTitle = currentLevel.getTitle(); PlayStatePlaylist.campaignTitle = currentLevel.getTitle();
PlayStatePlaylist.campaignDifficulty = currentDifficultyId; PlayStatePlaylist.campaignDifficulty = currentDifficultyId;
Highscore.talliesLevel = new funkin.Highscore.Tallies();
new FlxTimer().start(1, function(tmr:FlxTimer) { new FlxTimer().start(1, function(tmr:FlxTimer) {
FlxTransitionableState.skipNextTransIn = false; FlxTransitionableState.skipNextTransIn = false;
FlxTransitionableState.skipNextTransOut = false; FlxTransitionableState.skipNextTransOut = false;

View file

@ -0,0 +1,23 @@
package funkin.util;
// This may or may not already be imported via imports.hx...
import flixel.system.debug.watch.Tracker;
import flixel.FlxG;
/**
* Utility class that helps manage adding profiles to the flixel debugger tracker
*/
class TrackerUtil
{
/**
* Adds profiles to the debugger to help track certain game objects.
* NOTE: This isn't the full list of profiles made, as sometimes they're made
* on in various places in code for random debugging purposes!
* Might be good to put them all here though!
*/
public static function initTrackers():Void
{
Tracker.addProfile(new TrackerProfile(Highscore, ["tallies"]));
FlxG.console.registerClass(Highscore);
}
}