mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-11-15 11:22:55 +00:00
Make Freeplay use correct ranks, play the slam animation after Results, new Results music
This commit is contained in:
parent
d4cf18df00
commit
b7a828e7d8
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 8fea0bf1fe07b6dd0efb8ecf46dc8091b0177007
|
||||
Subproject commit 2719d3fc1d8f5d0cbafae8d27141d6c471148482
|
|
@ -220,6 +220,8 @@ class InitState extends FlxState
|
|||
{
|
||||
storyMode: false,
|
||||
title: "CUM SONG",
|
||||
songId: "cum",
|
||||
difficultyId: "hard",
|
||||
isNewHighscore: true,
|
||||
scoreData:
|
||||
{
|
||||
|
@ -227,7 +229,7 @@ class InitState extends FlxState
|
|||
tallies:
|
||||
{
|
||||
sick: 130,
|
||||
good: 25,
|
||||
good: 70,
|
||||
bad: 69,
|
||||
shit: 69,
|
||||
missed: 69,
|
||||
|
|
|
@ -3123,9 +3123,10 @@ class PlayState extends MusicBeatSubState
|
|||
var res:ResultState = new ResultState(
|
||||
{
|
||||
storyMode: PlayStatePlaylist.isStoryMode,
|
||||
songId: currentChart.song.id,
|
||||
difficultyId: currentDifficulty,
|
||||
title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'),
|
||||
prevScoreData: prevScoreData,
|
||||
difficultyId: currentDifficulty,
|
||||
scoreData:
|
||||
{
|
||||
score: PlayStatePlaylist.isStoryMode ? PlayStatePlaylist.campaignScore : songScore,
|
||||
|
|
|
@ -21,6 +21,7 @@ import funkin.audio.FunkinSound;
|
|||
import flixel.util.FlxGradient;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.save.Save;
|
||||
import funkin.play.scoring.Scoring;
|
||||
import funkin.save.Save.SaveScoreData;
|
||||
import funkin.graphics.shaders.LeftMaskShader;
|
||||
import funkin.play.components.TallyCounter;
|
||||
|
@ -34,7 +35,7 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
final params:ResultsStateParams;
|
||||
|
||||
final rank:ResultRank;
|
||||
final rank:ScoringRank;
|
||||
final songName:FlxBitmapText;
|
||||
final difficulty:FlxSprite;
|
||||
final clearPercentSmall:ClearPercentCounter;
|
||||
|
@ -64,8 +65,7 @@ class ResultState extends MusicBeatSubState
|
|||
|
||||
this.params = params;
|
||||
|
||||
rank = calculateRank(params);
|
||||
// rank = SHIT;
|
||||
rank = Scoring.calculateRank(params.scoreData) ?? SHIT;
|
||||
|
||||
// We build a lot of this stuff in the constructor, then place it in create().
|
||||
// This prevents having to do `null` checks everywhere.
|
||||
|
@ -99,6 +99,8 @@ class ResultState extends MusicBeatSubState
|
|||
|
||||
override function create():Void
|
||||
{
|
||||
if (FlxG.sound.music != null) FlxG.sound.music.stop();
|
||||
|
||||
// Reset the camera zoom on the results screen.
|
||||
FlxG.camera.zoom = 1.0;
|
||||
|
||||
|
@ -327,6 +329,33 @@ class ResultState extends MusicBeatSubState
|
|||
}
|
||||
};
|
||||
|
||||
new FlxTimer().start(rank.getMusicDelay(), _ -> {
|
||||
if (rank.hasMusicIntro())
|
||||
{
|
||||
// Play the intro music.
|
||||
var introMusic:String = Paths.music(rank.getMusicPath() + '/' + rank.getMusicPath() + '-intro');
|
||||
FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
|
||||
FunkinSound.playMusic(rank.getMusicPath(),
|
||||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FunkinSound.playMusic(rank.getMusicPath(),
|
||||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
super.create();
|
||||
|
@ -376,7 +405,8 @@ class ResultState extends MusicBeatSubState
|
|||
|
||||
displayRankText();
|
||||
|
||||
new FlxTimer().start(2.0, _ -> {
|
||||
// previously 2.0 seconds
|
||||
new FlxTimer().start(0.25, _ -> {
|
||||
FlxTween.tween(clearPercentCounter, {alpha: 0}, 0.5,
|
||||
{
|
||||
startDelay: 0.5,
|
||||
|
@ -444,28 +474,6 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
showSmallClearPercent();
|
||||
|
||||
FunkinSound.playMusic(rank.getMusicPath(),
|
||||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: rank.shouldMusicLoop()
|
||||
});
|
||||
|
||||
FlxG.sound.music.onComplete = () -> {
|
||||
if (rank == SHIT)
|
||||
{
|
||||
FunkinSound.playMusic('bluu',
|
||||
{
|
||||
startingVolume: 0.0,
|
||||
overrideExisting: true,
|
||||
restartTrack: true,
|
||||
loop: true
|
||||
});
|
||||
FlxG.sound.music.fadeIn(10.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
switch (rank)
|
||||
{
|
||||
case PERFECT | PERFECT_GOLD:
|
||||
|
@ -478,7 +486,6 @@ class ResultState extends MusicBeatSubState
|
|||
bfPerfect.visible = true;
|
||||
bfPerfect.playAnimation('');
|
||||
}
|
||||
|
||||
case EXCELLENT:
|
||||
if (bfExcellent == null)
|
||||
{
|
||||
|
@ -489,7 +496,6 @@ class ResultState extends MusicBeatSubState
|
|||
bfExcellent.visible = true;
|
||||
bfExcellent.playAnimation('Intro');
|
||||
}
|
||||
|
||||
case GREAT:
|
||||
if (bfGreat == null)
|
||||
{
|
||||
|
@ -500,7 +506,6 @@ class ResultState extends MusicBeatSubState
|
|||
bfGreat.visible = true;
|
||||
bfGreat.playAnimation('Intro');
|
||||
}
|
||||
|
||||
case SHIT:
|
||||
if (bfShit == null)
|
||||
{
|
||||
|
@ -511,7 +516,6 @@ class ResultState extends MusicBeatSubState
|
|||
bfShit.visible = true;
|
||||
bfShit.playAnimation('Intro');
|
||||
}
|
||||
|
||||
case GOOD:
|
||||
if (bfGood == null)
|
||||
{
|
||||
|
@ -521,7 +525,6 @@ class ResultState extends MusicBeatSubState
|
|||
{
|
||||
bfGood.animation.play('fall');
|
||||
bfGood.visible = true;
|
||||
|
||||
new FlxTimer().start((1 / 24) * 22, _ -> {
|
||||
// plays about 22 frames (at 24fps timing) after bf spawns in
|
||||
if (gfGood != null)
|
||||
|
@ -635,154 +638,39 @@ class ResultState extends MusicBeatSubState
|
|||
|
||||
if (controls.PAUSE)
|
||||
{
|
||||
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8);
|
||||
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
|
||||
{
|
||||
onComplete: _ -> {
|
||||
FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4);
|
||||
}
|
||||
});
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8);
|
||||
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
|
||||
{
|
||||
onComplete: _ -> {
|
||||
FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (params.storyMode)
|
||||
{
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)));
|
||||
}
|
||||
else
|
||||
{
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build(null, sticker)));
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build(
|
||||
{
|
||||
{
|
||||
fromResults:
|
||||
{
|
||||
oldRank: Scoring.calculateRank(params?.prevScoreData),
|
||||
newRank: rank,
|
||||
songId: params.songId,
|
||||
difficultyId: params.difficultyId
|
||||
}
|
||||
}
|
||||
}, sticker)));
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public static function calculateRank(params:ResultsStateParams):ResultRank
|
||||
{
|
||||
// Perfect (Platinum) is a Sick Full Clear
|
||||
var isPerfectGold = params.scoreData.tallies.sick == params.scoreData.tallies.totalNotes;
|
||||
if (isPerfectGold) return ResultRank.PERFECT_GOLD;
|
||||
|
||||
// Else, use the standard grades
|
||||
|
||||
// Grade % (only good and sick), 1.00 is a full combo
|
||||
var grade = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes;
|
||||
// Clear % (including bad and shit). 1.00 is a full clear but not a full combo
|
||||
var clear = (params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes;
|
||||
|
||||
if (grade == Constants.RANK_PERFECT_THRESHOLD)
|
||||
{
|
||||
return ResultRank.PERFECT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_EXCELLENT_THRESHOLD)
|
||||
{
|
||||
return ResultRank.EXCELLENT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_GREAT_THRESHOLD)
|
||||
{
|
||||
return ResultRank.GREAT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_GOOD_THRESHOLD)
|
||||
{
|
||||
return ResultRank.GOOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResultRank.SHIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum abstract ResultRank(String)
|
||||
{
|
||||
var PERFECT_GOLD;
|
||||
var PERFECT;
|
||||
var EXCELLENT;
|
||||
var GREAT;
|
||||
var GOOD;
|
||||
var SHIT;
|
||||
|
||||
public function getMusicPath():String
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultsPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultsPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultsNORMAL';
|
||||
case GREAT:
|
||||
return 'resultsNORMAL';
|
||||
case GOOD:
|
||||
return 'resultsNORMAL';
|
||||
case SHIT:
|
||||
return 'resultsSHIT';
|
||||
default:
|
||||
return 'resultsNORMAL';
|
||||
}
|
||||
}
|
||||
|
||||
public function shouldMusicLoop():Bool
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return true;
|
||||
case PERFECT:
|
||||
return true;
|
||||
case EXCELLENT:
|
||||
return true;
|
||||
case GREAT:
|
||||
return true;
|
||||
case GOOD:
|
||||
return true;
|
||||
case SHIT:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getHorTextAsset()
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultScreen/rankText/rankScrollPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultScreen/rankText/rankScrollPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultScreen/rankText/rankScrollEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultScreen/rankText/rankScrollGREAT';
|
||||
case GOOD:
|
||||
return 'resultScreen/rankText/rankScrollGOOD';
|
||||
case SHIT:
|
||||
return 'resultScreen/rankText/rankScrollLOSS';
|
||||
default:
|
||||
return 'resultScreen/rankText/rankScrollGOOD';
|
||||
}
|
||||
}
|
||||
|
||||
public function getVerTextAsset()
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultScreen/rankText/rankTextPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultScreen/rankText/rankTextPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultScreen/rankText/rankTextEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultScreen/rankText/rankTextGREAT';
|
||||
case GOOD:
|
||||
return 'resultScreen/rankText/rankTextGOOD';
|
||||
case SHIT:
|
||||
return 'resultScreen/rankText/rankTextLOSS';
|
||||
default:
|
||||
return 'resultScreen/rankText/rankTextGOOD';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef ResultsStateParams =
|
||||
|
@ -797,6 +685,8 @@ typedef ResultsStateParams =
|
|||
*/
|
||||
var title:String;
|
||||
|
||||
var songId:String;
|
||||
|
||||
/**
|
||||
* Whether the displayed score is a new highscore
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package funkin.play.scoring;
|
||||
|
||||
import funkin.save.Save.SaveScoreData;
|
||||
|
||||
/**
|
||||
* Which system to use when scoring and judging notes.
|
||||
*/
|
||||
|
@ -344,4 +346,178 @@ class Scoring
|
|||
return 'miss';
|
||||
}
|
||||
}
|
||||
|
||||
public static function calculateRank(scoreData:Null<SaveScoreData>):Null<ScoringRank>
|
||||
{
|
||||
if (scoreData == null) return null;
|
||||
|
||||
// Perfect (Platinum) is a Sick Full Clear
|
||||
var isPerfectGold = scoreData.tallies.sick == scoreData.tallies.totalNotes;
|
||||
if (isPerfectGold) return ScoringRank.PERFECT_GOLD;
|
||||
|
||||
// Else, use the standard grades
|
||||
|
||||
// Grade % (only good and sick), 1.00 is a full combo
|
||||
var grade = (scoreData.tallies.sick + scoreData.tallies.good) / scoreData.tallies.totalNotes;
|
||||
// Clear % (including bad and shit). 1.00 is a full clear but not a full combo
|
||||
var clear = (scoreData.tallies.totalNotesHit) / scoreData.tallies.totalNotes;
|
||||
|
||||
if (grade == Constants.RANK_PERFECT_THRESHOLD)
|
||||
{
|
||||
return ScoringRank.PERFECT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_EXCELLENT_THRESHOLD)
|
||||
{
|
||||
return ScoringRank.EXCELLENT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_GREAT_THRESHOLD)
|
||||
{
|
||||
return ScoringRank.GREAT;
|
||||
}
|
||||
else if (grade >= Constants.RANK_GOOD_THRESHOLD)
|
||||
{
|
||||
return ScoringRank.GOOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ScoringRank.SHIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum abstract ScoringRank(String)
|
||||
{
|
||||
var PERFECT_GOLD;
|
||||
var PERFECT;
|
||||
var EXCELLENT;
|
||||
var GREAT;
|
||||
var GOOD;
|
||||
var SHIT;
|
||||
|
||||
/**
|
||||
* Delay in seconds
|
||||
*/
|
||||
public function getMusicDelay():Float
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD | PERFECT:
|
||||
// return 2.5;
|
||||
return 5.0;
|
||||
case EXCELLENT:
|
||||
return 1.75;
|
||||
default:
|
||||
return 3.5;
|
||||
}
|
||||
}
|
||||
|
||||
public function getMusicPath():String
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultsPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultsPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultsEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultsNORMAL';
|
||||
case GOOD:
|
||||
return 'resultsNORMAL';
|
||||
case SHIT:
|
||||
return 'resultsSHIT';
|
||||
default:
|
||||
return 'resultsNORMAL';
|
||||
}
|
||||
}
|
||||
|
||||
public function hasMusicIntro():Bool
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case EXCELLENT:
|
||||
return true;
|
||||
case SHIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFreeplayRankIconAsset():Null<String>
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'PERFECTSICK';
|
||||
case PERFECT:
|
||||
return 'PERFECT';
|
||||
case EXCELLENT:
|
||||
return 'EXCELLENT';
|
||||
case GREAT:
|
||||
return 'GREAT';
|
||||
case GOOD:
|
||||
return 'GOOD';
|
||||
case SHIT:
|
||||
return 'LOSS';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultScreen/rankText/rankScrollPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultScreen/rankText/rankScrollPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultScreen/rankText/rankScrollEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultScreen/rankText/rankScrollGREAT';
|
||||
case GOOD:
|
||||
return 'resultScreen/rankText/rankScrollGOOD';
|
||||
case SHIT:
|
||||
return 'resultScreen/rankText/rankScrollLOSS';
|
||||
default:
|
||||
return 'resultScreen/rankText/rankScrollGOOD';
|
||||
}
|
||||
}
|
||||
|
||||
public function getVerTextAsset()
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultScreen/rankText/rankTextPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultScreen/rankText/rankTextPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultScreen/rankText/rankTextEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultScreen/rankText/rankTextGREAT';
|
||||
case GOOD:
|
||||
return 'resultScreen/rankText/rankTextGOOD';
|
||||
case SHIT:
|
||||
return 'resultScreen/rankText/rankTextLOSS';
|
||||
default:
|
||||
return 'resultScreen/rankText/rankTextGOOD';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package funkin.save;
|
||||
|
||||
import flixel.util.FlxSave;
|
||||
import funkin.save.migrator.SaveDataMigrator;
|
||||
import thx.semver.Version;
|
||||
import funkin.input.Controls.Device;
|
||||
import funkin.play.scoring.Scoring;
|
||||
import funkin.play.scoring.Scoring.ScoringRank;
|
||||
import funkin.save.migrator.RawSaveData_v1_0_0;
|
||||
import funkin.save.migrator.SaveDataMigrator;
|
||||
import funkin.save.migrator.SaveDataMigrator;
|
||||
import funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle;
|
||||
import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme;
|
||||
import thx.semver.Version;
|
||||
import funkin.util.SerializerUtil;
|
||||
import thx.semver.Version;
|
||||
import thx.semver.Version;
|
||||
|
||||
@:nullSafety
|
||||
class Save
|
||||
|
@ -492,6 +494,11 @@ class Save
|
|||
return song.get(difficultyId);
|
||||
}
|
||||
|
||||
public function getSongRank(songId:String, difficultyId:String = 'normal'):Null<ScoringRank>
|
||||
{
|
||||
return Scoring.calculateRank(getSongScore(songId, difficultyId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the score the user achieved for a given song on a given difficulty.
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,8 @@ import funkin.play.song.Song;
|
|||
import funkin.save.Save;
|
||||
import funkin.save.Save.SaveScoreData;
|
||||
import funkin.ui.AtlasText;
|
||||
import funkin.play.scoring.Scoring;
|
||||
import funkin.play.scoring.Scoring.ScoringRank;
|
||||
import funkin.ui.mainmenu.MainMenuState;
|
||||
import funkin.ui.MusicBeatSubState;
|
||||
import funkin.ui.transition.LoadingState;
|
||||
|
@ -49,6 +51,34 @@ import funkin.effects.IntervalShake;
|
|||
typedef FreeplayStateParams =
|
||||
{
|
||||
?character:String,
|
||||
|
||||
?fromResults:FromResultsParams,
|
||||
};
|
||||
|
||||
/**
|
||||
* A set of parameters for transitioning to the FreeplayState from the ResultsState.
|
||||
*/
|
||||
typedef FromResultsParams =
|
||||
{
|
||||
/**
|
||||
* The previous rank the song hand, if any. Null if it had no score before.
|
||||
*/
|
||||
var ?oldRank:ScoringRank;
|
||||
|
||||
/**
|
||||
* The new rank the song has.
|
||||
*/
|
||||
var newRank:ScoringRank;
|
||||
|
||||
/**
|
||||
* The song ID to play the animation on.
|
||||
*/
|
||||
var songId:String;
|
||||
|
||||
/**
|
||||
* The difficulty ID to play the animation on.
|
||||
*/
|
||||
var difficultyId:String;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -160,10 +190,14 @@ class FreeplayState extends MusicBeatSubState
|
|||
var bgDad:FlxSprite;
|
||||
var cardGlow:FlxSprite;
|
||||
|
||||
var fromResultsParams:Null<FromResultsParams> = null;
|
||||
|
||||
public function new(?params:FreeplayStateParams, ?stickers:StickerSubState)
|
||||
{
|
||||
currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER;
|
||||
|
||||
fromResultsParams = params?.fromResults;
|
||||
|
||||
if (stickers != null)
|
||||
{
|
||||
stickerSubState = stickers;
|
||||
|
@ -587,6 +621,11 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
cardGlow.visible = true;
|
||||
FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut});
|
||||
|
||||
if (fromResultsParams != null)
|
||||
{
|
||||
rankAnimStart(fromResultsParams);
|
||||
}
|
||||
});
|
||||
|
||||
generateSongList(null, false);
|
||||
|
@ -657,6 +696,12 @@ class FreeplayState extends MusicBeatSubState
|
|||
// If curSelected is 0, the result will be null and fall back to the rememberedSongId.
|
||||
rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId ?? rememberedSongId;
|
||||
|
||||
if (fromResultsParams != null)
|
||||
{
|
||||
rememberedSongId = fromResultsParams.songId;
|
||||
rememberedDifficulty = fromResultsParams.difficultyId;
|
||||
}
|
||||
|
||||
for (cap in grpCapsules.members)
|
||||
{
|
||||
cap.songText.resetText();
|
||||
|
@ -763,8 +808,10 @@ class FreeplayState extends MusicBeatSubState
|
|||
return songsToFilter;
|
||||
}
|
||||
|
||||
function rankAnimStart()
|
||||
function rankAnimStart(fromResults:Null<FromResultsParams>):Void
|
||||
{
|
||||
busy = true;
|
||||
|
||||
dj.fistPump();
|
||||
// rankCamera.fade(FlxColor.BLACK, 0.5, true);
|
||||
rankCamera.fade(0xFF000000, 0.5, true, null, true);
|
||||
|
@ -789,21 +836,21 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
new FlxTimer().start(0.5, _ -> {
|
||||
grpCapsules.members[curSelected].doLerp = false;
|
||||
rankDisplayNew();
|
||||
rankDisplayNew(fromResults);
|
||||
});
|
||||
}
|
||||
|
||||
function rankDisplayNew()
|
||||
function rankDisplayNew(fromResults:Null<FromResultsParams>):Void
|
||||
{
|
||||
grpCapsules.members[curSelected].ranking.alpha = 1;
|
||||
grpCapsules.members[curSelected].blurredRanking.alpha = 1;
|
||||
|
||||
grpCapsules.members[curSelected].ranking.scale.set(20, 20);
|
||||
grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20);
|
||||
// var tempr:Int = FlxG.random.int(0, 4);
|
||||
|
||||
// grpCapsules.members[curSelected].ranking.rank = tempr;
|
||||
grpCapsules.members[curSelected].ranking.animation.play(grpCapsules.members[curSelected].ranking.animation.curAnim.name, true);
|
||||
grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true);
|
||||
// grpCapsules.members[curSelected].ranking.animation.curAnim.name, true);
|
||||
|
||||
FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1);
|
||||
|
||||
grpCapsules.members[curSelected].blurredRanking.animation.play(grpCapsules.members[curSelected].blurredRanking.animation.curAnim.name, true);
|
||||
|
@ -811,13 +858,13 @@ class FreeplayState extends MusicBeatSubState
|
|||
|
||||
new FlxTimer().start(0.1, _ -> {
|
||||
trace(grpCapsules.members[curSelected].ranking.rank);
|
||||
switch (grpCapsules.members[curSelected].tempr)
|
||||
switch (fromResultsParams?.newRank)
|
||||
{
|
||||
case 0:
|
||||
case SHIT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/rankinbad'));
|
||||
case 4:
|
||||
case PERFECT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/rankinperfect'));
|
||||
case 5:
|
||||
case PERFECT_GOLD:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/rankinperfect'));
|
||||
default:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/rankinnormal'));
|
||||
|
@ -846,31 +893,31 @@ class FreeplayState extends MusicBeatSubState
|
|||
});
|
||||
|
||||
new FlxTimer().start(0.6, _ -> {
|
||||
rankAnimSlam();
|
||||
rankAnimSlam(fromResults);
|
||||
// IntervalShake.shake(grpCapsules.members[curSelected].capsule, 0.3, 1 / 30, 0, 0.3, FlxEase.quartIn);
|
||||
});
|
||||
}
|
||||
|
||||
function rankAnimSlam()
|
||||
function rankAnimSlam(fromResultsParams:Null<FromResultsParams>)
|
||||
{
|
||||
// FlxTween.tween(rankCamera, {"zoom": 1.9}, 0.5, {ease: FlxEase.backOut});
|
||||
FlxTween.tween(rankBg, {alpha: 0}, 0.5, {ease: FlxEase.expoIn});
|
||||
|
||||
// FlxTween.tween(grpCapsules.members[curSelected], {angle: 5}, 0.5, {ease: FlxEase.backIn});
|
||||
|
||||
switch (grpCapsules.members[curSelected].tempr)
|
||||
switch (fromResultsParams?.newRank)
|
||||
{
|
||||
case 0:
|
||||
case SHIT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/loss'));
|
||||
case 1:
|
||||
case GOOD:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/good'));
|
||||
case 2:
|
||||
case GREAT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/great'));
|
||||
case 3:
|
||||
case EXCELLENT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/excellent'));
|
||||
case 4:
|
||||
case PERFECT:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/perfect'));
|
||||
case 5:
|
||||
case PERFECT_GOLD:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/perfect'));
|
||||
default:
|
||||
FunkinSound.playOnce(Paths.sound('ranks/loss'));
|
||||
|
@ -880,7 +927,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
new FlxTimer().start(0.5, _ -> {
|
||||
funnyCam.shake(0.0045, 0.35);
|
||||
|
||||
if (grpCapsules.members[curSelected].tempr == 0)
|
||||
if (fromResultsParams?.newRank == SHIT)
|
||||
{
|
||||
dj.pumpFistBad();
|
||||
}
|
||||
|
@ -915,6 +962,9 @@ class FreeplayState extends MusicBeatSubState
|
|||
IntervalShake.shake(capsule, 0.6, 1 / 24, 0.12, 0, FlxEase.quadOut, function(_) {
|
||||
capsule.doLerp = true;
|
||||
capsule.cameras = [funnyCam];
|
||||
|
||||
// NOW we can interact with the menu
|
||||
busy = false;
|
||||
}, null);
|
||||
|
||||
// FlxTween.tween(capsule, {"targetPos.x": capsule.targetPos.x - 50}, 0.6,
|
||||
|
@ -981,7 +1031,10 @@ class FreeplayState extends MusicBeatSubState
|
|||
var spamTimer:Float = 0;
|
||||
var spamming:Bool = false;
|
||||
|
||||
var busy:Bool = false; // Set to true once the user has pressed enter to select a song.
|
||||
/**
|
||||
* If true, disable interaction with the interface.
|
||||
*/
|
||||
var busy:Bool = false;
|
||||
|
||||
var originalPos:FlxPoint = new FlxPoint();
|
||||
|
||||
|
@ -989,19 +1042,20 @@ class FreeplayState extends MusicBeatSubState
|
|||
{
|
||||
super.update(elapsed);
|
||||
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.T)
|
||||
{
|
||||
rankAnimStart();
|
||||
rankAnimStart(fromResultsParams);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.H)
|
||||
{
|
||||
rankDisplayNew();
|
||||
rankDisplayNew(fromResultsParams);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.G)
|
||||
{
|
||||
rankAnimSlam();
|
||||
rankAnimSlam(fromResultsParams);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.I)
|
||||
|
@ -1024,6 +1078,7 @@ class FreeplayState extends MusicBeatSubState
|
|||
confirmTextGlow.y += 1;
|
||||
trace(confirmTextGlow.x, confirmTextGlow.y);
|
||||
}
|
||||
#end
|
||||
|
||||
if (FlxG.keys.justPressed.F)
|
||||
{
|
||||
|
@ -1765,6 +1820,8 @@ class FreeplaySongData
|
|||
|
||||
public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
|
||||
|
||||
public var scoringRank:Null<ScoringRank> = null;
|
||||
|
||||
var displayedVariations:Array<String> = [Constants.DEFAULT_VARIATION];
|
||||
|
||||
function set_currentDifficulty(value:String):String
|
||||
|
@ -1827,6 +1884,8 @@ class FreeplaySongData
|
|||
{
|
||||
this.albumId = songDifficulty.album;
|
||||
}
|
||||
|
||||
this.scoringRank = Save.instance.getSongRank(songId, currentDifficulty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import funkin.graphics.FunkinSprite;
|
|||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.addons.effects.FlxTrail;
|
||||
import funkin.play.scoring.Scoring.ScoringRank;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class SongMenuItem extends FlxSpriteGroup
|
||||
|
@ -70,8 +71,6 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
|
||||
var impactThing:FunkinSprite;
|
||||
|
||||
public var tempr:Int;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
@ -132,13 +131,10 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
// doesn't get added, simply is here to help with visibility of things for the pop in!
|
||||
grpHide = new FlxGroup();
|
||||
|
||||
var rank:String = FlxG.random.getObject(ranks);
|
||||
|
||||
tempr = FlxG.random.int(0, 5);
|
||||
ranking = new FreeplayRank(420, 41, tempr);
|
||||
ranking = new FreeplayRank(420, 41);
|
||||
add(ranking);
|
||||
|
||||
blurredRanking = new FreeplayRank(ranking.x, ranking.y, tempr);
|
||||
blurredRanking = new FreeplayRank(ranking.x, ranking.y);
|
||||
blurredRanking.shader = new GaussianBlurShader(1);
|
||||
add(blurredRanking);
|
||||
// ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank));
|
||||
|
@ -344,19 +340,19 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
});
|
||||
add(evilTrail);
|
||||
|
||||
switch (tempr)
|
||||
switch (ranking.rank)
|
||||
{
|
||||
case 0:
|
||||
case SHIT:
|
||||
evilTrail.color = 0xFF6044FF;
|
||||
case 1:
|
||||
case GOOD:
|
||||
evilTrail.color = 0xFFEF8764;
|
||||
case 2:
|
||||
case GREAT:
|
||||
evilTrail.color = 0xFFEAF6FF;
|
||||
case 3:
|
||||
case EXCELLENT:
|
||||
evilTrail.color = 0xFFFDCB42;
|
||||
case 4:
|
||||
case PERFECT:
|
||||
evilTrail.color = 0xFFFF58B4;
|
||||
case 5:
|
||||
case PERFECT_GOLD:
|
||||
evilTrail.color = 0xFFFFB619;
|
||||
}
|
||||
}
|
||||
|
@ -393,6 +389,12 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
// diffRatingSprite.visible = false;
|
||||
}
|
||||
|
||||
function updateScoringRank(newRank:Null<ScoringRank>):Void
|
||||
{
|
||||
this.ranking.rank = newRank;
|
||||
this.blurredRanking.rank = newRank;
|
||||
}
|
||||
|
||||
function set_hsvShader(value:HSVShader):HSVShader
|
||||
{
|
||||
this.hsvShader = value;
|
||||
|
@ -441,6 +443,7 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
if (songData?.songCharacter != null) setCharacter(songData.songCharacter);
|
||||
updateBPM(Std.int(songData?.songStartingBpm) ?? 0);
|
||||
updateDifficultyRating(songData?.difficultyRating ?? 0);
|
||||
updateScoringRank(songData?.scoringRank);
|
||||
// Update opacity, offsets, etc.
|
||||
updateSelected();
|
||||
|
||||
|
@ -668,41 +671,53 @@ class SongMenuItem extends FlxSpriteGroup
|
|||
|
||||
class FreeplayRank extends FlxSprite
|
||||
{
|
||||
public var rank(default, set):Int = 0;
|
||||
public var rank(default, set):Null<ScoringRank> = null;
|
||||
|
||||
var numToRank:Array<String> = ["LOSS", "GOOD", "GREAT", "EXCELLENT", "PERFECT", "PERFECTSICK"];
|
||||
|
||||
function set_rank(val):Int
|
||||
function set_rank(val:Null<ScoringRank>):Null<ScoringRank>
|
||||
{
|
||||
animation.play(numToRank[val], true, false);
|
||||
rank = val;
|
||||
|
||||
centerOffsets(false);
|
||||
|
||||
switch (val)
|
||||
if (rank == null)
|
||||
{
|
||||
case 0:
|
||||
// offset.x -= 1;
|
||||
case 1:
|
||||
// offset.x -= 1;
|
||||
offset.y -= 8;
|
||||
case 2:
|
||||
// offset.x -= 1;
|
||||
offset.y -= 8;
|
||||
case 3:
|
||||
// offset.y += 5;
|
||||
case 4:
|
||||
// offset.y += 5;
|
||||
default:
|
||||
centerOffsets(false);
|
||||
this.visible = false;
|
||||
}
|
||||
updateHitbox();
|
||||
return val;
|
||||
else
|
||||
{
|
||||
this.visible = true;
|
||||
|
||||
animation.play(val.getFreeplayRankIconAsset(), true, false);
|
||||
|
||||
centerOffsets(false);
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case SHIT:
|
||||
// offset.x -= 1;
|
||||
case GOOD:
|
||||
// offset.x -= 1;
|
||||
offset.y -= 8;
|
||||
case GREAT:
|
||||
// offset.x -= 1;
|
||||
offset.y -= 8;
|
||||
case EXCELLENT:
|
||||
// offset.y += 5;
|
||||
case PERFECT:
|
||||
// offset.y += 5;
|
||||
case PERFECT_GOLD:
|
||||
// offset.y += 5;
|
||||
default:
|
||||
centerOffsets(false);
|
||||
}
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
return rank = val;
|
||||
}
|
||||
|
||||
public var baseY:Float = 0;
|
||||
public var baseX:Float = 0;
|
||||
public var baseY:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float, ?initRank:Int = 0)
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
|
@ -717,9 +732,7 @@ class FreeplayRank extends FlxSprite
|
|||
|
||||
blend = BlendMode.ADD;
|
||||
|
||||
this.rank = initRank;
|
||||
|
||||
animation.play(numToRank[initRank], true);
|
||||
this.rank = null;
|
||||
|
||||
// setGraphicSize(Std.int(width * 0.9));
|
||||
scale.set(0.9, 0.9);
|
||||
|
|
Loading…
Reference in a new issue