mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-11-15 11:22:55 +00:00
Merge branch 'feature/charter-in-pause-menu' into develop-0.4.0
This commit is contained in:
commit
30fd86befb
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 35803c5cf9946f66f572b4fb8044e7df84cd9cdd
|
||||
Subproject commit 57a862595af16a5808b384ec1a22d5b35afc4cd6
|
|
@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.2.3]
|
||||
### Added
|
||||
- Added `charter` field to denote authorship of a chart.
|
||||
|
||||
## [2.2.2]
|
||||
### Added
|
||||
- Added `playData.previewStart` and `playData.previewEnd` fields to specify when in the song should the song's audio should be played as a preview in Freeplay.
|
||||
|
|
|
@ -30,6 +30,9 @@ class SongMetadata implements ICloneable<SongMetadata>
|
|||
@:default("Unknown")
|
||||
public var artist:String;
|
||||
|
||||
@:optional
|
||||
public var charter:Null<String> = null;
|
||||
|
||||
@:optional
|
||||
@:default(96)
|
||||
public var divisions:Null<Int>; // Optional field
|
||||
|
|
|
@ -20,7 +20,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
|
|||
* Handle breaking changes by incrementing this value
|
||||
* and adding migration to the `migrateStageData()` function.
|
||||
*/
|
||||
public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.2";
|
||||
public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.3";
|
||||
|
||||
public static final SONG_METADATA_VERSION_RULE:thx.semver.VersionRule = "2.2.x";
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class FNFLegacyImporter
|
|||
{
|
||||
trace('Migrating song metadata from FNF Legacy.');
|
||||
|
||||
var songMetadata:SongMetadata = new SongMetadata('Import', 'Kawai Sprite', 'default');
|
||||
var songMetadata:SongMetadata = new SongMetadata('Import', Constants.DEFAULT_ARTIST, 'default');
|
||||
|
||||
var hadError:Bool = false;
|
||||
|
||||
|
|
|
@ -101,6 +101,10 @@ class PauseSubState extends MusicBeatSubState
|
|||
*/
|
||||
static final MUSIC_FINAL_VOLUME:Float = 0.75;
|
||||
|
||||
static final CHARTER_FADE_DELAY:Float = 15.0;
|
||||
|
||||
static final CHARTER_FADE_DURATION:Float = 0.75;
|
||||
|
||||
/**
|
||||
* Defines which pause music to use.
|
||||
*/
|
||||
|
@ -163,6 +167,12 @@ class PauseSubState extends MusicBeatSubState
|
|||
*/
|
||||
var metadataDeaths:FlxText;
|
||||
|
||||
/**
|
||||
* A text object which displays the current song's artist.
|
||||
* Fades to the charter after a period before fading back.
|
||||
*/
|
||||
var metadataArtist:FlxText;
|
||||
|
||||
/**
|
||||
* The actual text objects for the menu entries.
|
||||
*/
|
||||
|
@ -203,6 +213,8 @@ class PauseSubState extends MusicBeatSubState
|
|||
regenerateMenu();
|
||||
|
||||
transitionIn();
|
||||
|
||||
startCharterTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,6 +234,8 @@ class PauseSubState extends MusicBeatSubState
|
|||
public override function destroy():Void
|
||||
{
|
||||
super.destroy();
|
||||
charterFadeTween.destroy();
|
||||
charterFadeTween = null;
|
||||
pauseMusic.stop();
|
||||
}
|
||||
|
||||
|
@ -270,16 +284,25 @@ class PauseSubState extends MusicBeatSubState
|
|||
metadata.scrollFactor.set(0, 0);
|
||||
add(metadata);
|
||||
|
||||
var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name - Artist');
|
||||
var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name');
|
||||
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}';
|
||||
}
|
||||
metadataSong.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataSong);
|
||||
|
||||
var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, FlxG.width - 40, 'Difficulty: ');
|
||||
metadataArtist = new FlxText(20, metadataSong.y + 32, FlxG.width - 40, 'Artist: ${Constants.DEFAULT_ARTIST}');
|
||||
metadataArtist.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
if (PlayState.instance?.currentChart != null)
|
||||
{
|
||||
metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}';
|
||||
}
|
||||
metadataArtist.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataArtist);
|
||||
|
||||
var metadataDifficulty:FlxText = new FlxText(20, metadataArtist.y + 32, FlxG.width - 40, 'Difficulty: ');
|
||||
metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
if (PlayState.instance?.currentDifficulty != null)
|
||||
{
|
||||
|
@ -288,12 +311,12 @@ class PauseSubState extends MusicBeatSubState
|
|||
metadataDifficulty.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataDifficulty);
|
||||
|
||||
metadataDeaths = new FlxText(20, 15 + 64, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls');
|
||||
metadataDeaths = new FlxText(20, metadataDifficulty.y + 32, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls');
|
||||
metadataDeaths.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
|
||||
metadataDeaths.scrollFactor.set(0, 0);
|
||||
metadata.add(metadataDeaths);
|
||||
|
||||
metadataPractice = new FlxText(20, 15 + 96, FlxG.width - 40, 'PRACTICE MODE');
|
||||
metadataPractice = new FlxText(20, metadataDeaths.y + 32, 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);
|
||||
|
@ -302,6 +325,62 @@ class PauseSubState extends MusicBeatSubState
|
|||
updateMetadataText();
|
||||
}
|
||||
|
||||
var charterFadeTween:Null<FlxTween> = null;
|
||||
|
||||
function startCharterTimer():Void
|
||||
{
|
||||
charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION,
|
||||
{
|
||||
startDelay: CHARTER_FADE_DELAY,
|
||||
ease: FlxEase.quartOut,
|
||||
onComplete: (_) -> {
|
||||
if (PlayState.instance?.currentChart != null)
|
||||
{
|
||||
metadataArtist.text = 'Charter: ${PlayState.instance.currentChart.charter ?? 'Unknown'}';
|
||||
}
|
||||
else
|
||||
{
|
||||
metadataArtist.text = 'Charter: ${Constants.DEFAULT_CHARTER}';
|
||||
}
|
||||
|
||||
FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION,
|
||||
{
|
||||
ease: FlxEase.quartOut,
|
||||
onComplete: (_) -> {
|
||||
startArtistTimer();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startArtistTimer():Void
|
||||
{
|
||||
charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION,
|
||||
{
|
||||
startDelay: CHARTER_FADE_DELAY,
|
||||
ease: FlxEase.quartOut,
|
||||
onComplete: (_) -> {
|
||||
if (PlayState.instance?.currentChart != null)
|
||||
{
|
||||
metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}';
|
||||
}
|
||||
else
|
||||
{
|
||||
metadataArtist.text = 'Artist: ${Constants.DEFAULT_ARTIST}';
|
||||
}
|
||||
|
||||
FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION,
|
||||
{
|
||||
ease: FlxEase.quartOut,
|
||||
onComplete: (_) -> {
|
||||
startCharterTimer();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform additional animations to transition the pause menu in when it is first displayed.
|
||||
*/
|
||||
|
|
|
@ -2322,8 +2322,6 @@ class PlayState extends MusicBeatSubState
|
|||
var notesInRange:Array<NoteSprite> = playerStrumline.getNotesMayHit();
|
||||
var holdNotesInRange:Array<SustainTrail> = playerStrumline.getHoldNotesHitOrMissed();
|
||||
|
||||
// If there are notes in range, pressing a key will cause a ghost miss.
|
||||
|
||||
var notesByDirection:Array<Array<NoteSprite>> = [[], [], [], []];
|
||||
|
||||
for (note in notesInRange)
|
||||
|
@ -2345,17 +2343,27 @@ class PlayState extends MusicBeatSubState
|
|||
|
||||
// Play the strumline animation.
|
||||
playerStrumline.playPress(input.noteDirection);
|
||||
trace('PENALTY Score: ${songScore}');
|
||||
}
|
||||
else if (Constants.GHOST_TAPPING && (holdNotesInRange.length + notesInRange.length > 0) && notesInDirection.length == 0)
|
||||
else if (Constants.GHOST_TAPPING && (!playerStrumline.mayGhostTap()) && notesInDirection.length == 0)
|
||||
{
|
||||
// Pressed a wrong key with no notes nearby AND with notes in a different direction available.
|
||||
// Pressed a wrong key with notes visible on-screen.
|
||||
// Perform a ghost miss (anti-spam).
|
||||
ghostNoteMiss(input.noteDirection, notesInRange.length > 0);
|
||||
|
||||
// Play the strumline animation.
|
||||
playerStrumline.playPress(input.noteDirection);
|
||||
trace('PENALTY Score: ${songScore}');
|
||||
}
|
||||
else if (notesInDirection.length > 0)
|
||||
else if (notesInDirection.length == 0)
|
||||
{
|
||||
// Press a key with no penalty.
|
||||
|
||||
// Play the strumline animation.
|
||||
playerStrumline.playPress(input.noteDirection);
|
||||
trace('NO PENALTY Score: ${songScore}');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Choose the first note, deprioritizing low priority notes.
|
||||
var targetNote:Null<NoteSprite> = notesInDirection.find((note) -> !note.lowPriority);
|
||||
|
@ -2365,17 +2373,13 @@ class PlayState extends MusicBeatSubState
|
|||
// Judge and hit the note.
|
||||
trace('Hit note! ${targetNote.noteData}');
|
||||
goodNoteHit(targetNote, input);
|
||||
trace('Score: ${songScore}');
|
||||
|
||||
notesInDirection.remove(targetNote);
|
||||
|
||||
// Play the strumline animation.
|
||||
playerStrumline.playConfirm(input.noteDirection);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play the strumline animation.
|
||||
playerStrumline.playPress(input.noteDirection);
|
||||
}
|
||||
}
|
||||
|
||||
while (inputReleaseQueue.length > 0)
|
||||
|
|
|
@ -171,6 +171,20 @@ class Strumline extends FlxSpriteGroup
|
|||
updateNotes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if no notes are in range of the strumline and the player can spam without penalty.
|
||||
*/
|
||||
public function mayGhostTap():Bool
|
||||
{
|
||||
// TODO: Refine this. Only querying "can be hit" is too tight but "is being rendered" is too loose.
|
||||
// Also, if you just hit a note, there should be a (short) period where this is off so you can't spam.
|
||||
|
||||
// If there are any notes on screen, we can't ghost tap.
|
||||
return notes.members.filter(function(note:NoteSprite) {
|
||||
return note != null && note.alive && !note.hasBeenHit;
|
||||
}).length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return notes that are within `Constants.HIT_WINDOW` ms of the strumline.
|
||||
* @return An array of `NoteSprite` objects.
|
||||
|
|
|
@ -120,6 +120,18 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
return DEFAULT_ARTIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* The artist of the song.
|
||||
*/
|
||||
public var charter(get, never):String;
|
||||
|
||||
function get_charter():String
|
||||
{
|
||||
if (_data != null) return _data?.charter ?? 'Unknown';
|
||||
if (_metadata.size() > 0) return _metadata.get(Constants.DEFAULT_VARIATION)?.charter ?? 'Unknown';
|
||||
return Constants.DEFAULT_CHARTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id The ID of the song to load.
|
||||
* @param ignoreErrors If false, an exception will be thrown if the song data could not be loaded.
|
||||
|
@ -270,6 +282,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
|
||||
difficulty.songName = metadata.songName;
|
||||
difficulty.songArtist = metadata.artist;
|
||||
difficulty.charter = metadata.charter ?? Constants.DEFAULT_CHARTER;
|
||||
difficulty.timeFormat = metadata.timeFormat;
|
||||
difficulty.divisions = metadata.divisions;
|
||||
difficulty.timeChanges = metadata.timeChanges;
|
||||
|
@ -334,6 +347,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
{
|
||||
difficulty.songName = metadata.songName;
|
||||
difficulty.songArtist = metadata.artist;
|
||||
difficulty.charter = metadata.charter ?? Constants.DEFAULT_CHARTER;
|
||||
difficulty.timeFormat = metadata.timeFormat;
|
||||
difficulty.divisions = metadata.divisions;
|
||||
difficulty.timeChanges = metadata.timeChanges;
|
||||
|
@ -586,6 +600,7 @@ class SongDifficulty
|
|||
|
||||
public var songName:String = Constants.DEFAULT_SONGNAME;
|
||||
public var songArtist:String = Constants.DEFAULT_ARTIST;
|
||||
public var charter:String = Constants.DEFAULT_CHARTER;
|
||||
public var timeFormat:SongTimeFormat = Constants.DEFAULT_TIMEFORMAT;
|
||||
public var divisions:Null<Int> = null;
|
||||
public var looped:Bool = false;
|
||||
|
|
|
@ -1270,7 +1270,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
var result:Null<SongMetadata> = songMetadata.get(selectedVariation);
|
||||
if (result == null)
|
||||
{
|
||||
result = new SongMetadata('DadBattle', 'Kawai Sprite', selectedVariation);
|
||||
result = new SongMetadata('Default Song Name', Constants.DEFAULT_ARTIST, selectedVariation);
|
||||
songMetadata.set(selectedVariation, result);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -29,6 +29,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
{
|
||||
var inputSongName:TextField;
|
||||
var inputSongArtist:TextField;
|
||||
var inputSongCharter:TextField;
|
||||
var inputStage:DropDown;
|
||||
var inputNoteStyle:DropDown;
|
||||
var buttonCharacterPlayer:Button;
|
||||
|
@ -89,6 +90,20 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
}
|
||||
};
|
||||
|
||||
inputSongCharter.onChange = function(event:UIEvent) {
|
||||
var valid:Bool = event.target.text != null && event.target.text != '';
|
||||
|
||||
if (valid)
|
||||
{
|
||||
inputSongCharter.removeClass('invalid-value');
|
||||
chartEditorState.currentSongMetadata.charter = event.target.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
chartEditorState.currentSongMetadata.charter = null;
|
||||
}
|
||||
};
|
||||
|
||||
inputStage.onChange = function(event:UIEvent) {
|
||||
var valid:Bool = event.data != null && event.data.id != null;
|
||||
|
||||
|
@ -176,6 +191,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
inputSongName.value = chartEditorState.currentSongMetadata.songName;
|
||||
inputSongArtist.value = chartEditorState.currentSongMetadata.artist;
|
||||
inputSongCharter.value = chartEditorState.currentSongMetadata.charter;
|
||||
inputStage.value = chartEditorState.currentSongMetadata.playData.stage;
|
||||
inputNoteStyle.value = chartEditorState.currentSongMetadata.playData.noteStyle;
|
||||
inputBPM.value = chartEditorState.currentSongMetadata.timeChanges[0].bpm;
|
||||
|
|
|
@ -248,6 +248,11 @@ class Constants
|
|||
*/
|
||||
public static final DEFAULT_ARTIST:String = 'Unknown';
|
||||
|
||||
/**
|
||||
* The default charter for songs.
|
||||
*/
|
||||
public static final DEFAULT_CHARTER:String = 'Unknown';
|
||||
|
||||
/**
|
||||
* The default note style for songs.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue