diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b588950023c..62621aec9f2 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -52,6 +52,7 @@ import funkin.play.notes.Strumline; import funkin.play.notes.SustainTrail; import funkin.play.notes.NoteVibrationsHandler; import funkin.play.scoring.Scoring; +import funkin.play.scoring.ScoringPBOT1; import funkin.play.song.Song; import funkin.play.stage.Stage; import funkin.save.Save; @@ -447,6 +448,11 @@ class PlayState extends MusicBeatSubState */ public var currentConversation:Null; + /** + * The current scoring system used for judging and calculating scores. + */ + public var scoring = new ScoringPBOT1(); + /** * Key press inputs which have been received but not yet processed. * These are encoded with an OS timestamp, so we can account for input latency. @@ -3117,8 +3123,8 @@ class PlayState extends MusicBeatSubState // Round inward (trim remainder) for consistency. var noteDiff:Int = Std.int(Conductor.instance.songPosition - note.noteData.time - inputLatencyMs); - var score = Scoring.scoreNote(noteDiff, PBOT1); - var daRating = Scoring.judgeNote(noteDiff, PBOT1); + var score = scoring.scoreNote(noteDiff); + var daRating = scoring.judgeNote(noteDiff); var healthChange = 0.0; var isComboBreak = false; @@ -3184,7 +3190,7 @@ class PlayState extends MusicBeatSubState } } - applyScore(Scoring.getMissScore(), 'miss', healthChange, true); + applyScore(scoring.getMissScore(), 'miss', healthChange, true); if (playSound) { diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 36d98a76e70..ce9b492652d 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -5,376 +5,57 @@ import funkin.save.Save.SaveScoreData; import funkin.save.Save.SaveScoreTallyData; /** - * Which system to use when scoring and judging notes. - */ -enum abstract ScoringSystem(String) -{ - /** - * The scoring system used in versions of the game Week 6 and older. - * Scores the player based on judgement, represented by a step function. - */ - public var LEGACY; - - /** - * The scoring system used in Week 7. It has tighter scoring windows than Legacy. - * Scores the player based on judgement, represented by a step function. - */ - public var WEEK7; - - /** - * Points Based On Timing scoring system, version 1 - * Scores the player based on the offset based on timing, represented by a sigmoid function. - */ - public var PBOT1; -} - -/** - * A static class which holds any functions related to scoring. + * A base class which holds functions related to scoring. + * Scripts can override this class for if they want to make their own scoring system to be used. */ class Scoring { /** - * Determine the score a note receives under a given scoring system. - * @param msTiming The difference between the note's time and when it was hit. - * @param scoringSystem The scoring system to use. - * @return The score the note receives. + * The id for this system being used for scoring (incase of debugging). */ - public static function scoreNote(msTiming:Float, scoringSystem:ScoringSystem = PBOT1):Int + public var id:String; + + public function new(id:String) { - return switch (scoringSystem) - { - case LEGACY: - scoreNoteLEGACY(msTiming); - case WEEK7: - scoreNoteWEEK7(msTiming); - case PBOT1: - scoreNotePBOT1(msTiming); - default: - FlxG.log.error('Unknown scoring system: ${scoringSystem}'); - 0; - } + this.id = id; } /** * Determine the judgement a note receives under a given scoring system. * @param msTiming The difference between the note's time and when it was hit. - * @param scoringSystem The scoring system to use. * @return The judgement the note receives. */ - public static function judgeNote(msTiming:Float, scoringSystem:ScoringSystem = PBOT1):String - { - return switch (scoringSystem) - { - case LEGACY: - judgeNoteLEGACY(msTiming); - case WEEK7: - judgeNoteWEEK7(msTiming); - case PBOT1: - judgeNotePBOT1(msTiming); - default: - FlxG.log.error('Unknown scoring system: ${scoringSystem}'); - 'miss'; - } - } - - public static function getMissScore(scoringSystem:ScoringSystem = PBOT1):Int + public function judgeNote(msTiming:Float):String { - return switch (scoringSystem) - { - case LEGACY: - LEGACY_MISS_SCORE; - case WEEK7: - WEEK7_MISS_SCORE; - case PBOT1: - PBOT1_MISS_SCORE; - default: - FlxG.log.error('Unknown scoring system: ${scoringSystem}'); - 0; - } + return 'miss'; } /** - * The maximum score a note can receive. - */ - public static final PBOT1_MAX_SCORE:Int = 500; - - /** - * The offset of the sigmoid curve for the scoring function. - */ - public static final PBOT1_SCORING_OFFSET:Float = 54.99; - - /** - * The slope of the sigmoid curve for the scoring function. - */ - public static final PBOT1_SCORING_SLOPE:Float = 0.080; - - /** - * The minimum score a note can receive while still being considered a hit. - */ - public static final PBOT1_MIN_SCORE:Float = 9.0; - - /** - * The score a note receives when it is missed. - */ - public static final PBOT1_MISS_SCORE:Int = -100; - - /** - * The threshold at which a note hit is considered perfect and always given the max score. - */ - public static final PBOT1_PERFECT_THRESHOLD:Float = 5.0; // 5ms - - /** - * The threshold at which a note hit is considered missed. - * `160ms` - */ - public static final PBOT1_MISS_THRESHOLD:Float = 160.0; - - /** - * The time within which a note is considered to have been hit with the Killer judgement. - * `~7.5% of the hit window, or 12.5ms` - */ - public static final PBOT1_KILLER_THRESHOLD:Float = 12.5; - - /** - * The time within which a note is considered to have been hit with the Sick judgement. - * `~25% of the hit window, or 45ms` - */ - public static final PBOT1_SICK_THRESHOLD:Float = 45.0; - - /** - * The time within which a note is considered to have been hit with the Good judgement. - * `~55% of the hit window, or 90ms` - */ - public static final PBOT1_GOOD_THRESHOLD:Float = 90.0; - - /** - * The time within which a note is considered to have been hit with the Bad judgement. - * `~85% of the hit window, or 135ms` - */ - public static final PBOT1_BAD_THRESHOLD:Float = 135.0; - - /** - * The time within which a note is considered to have been hit with the Shit judgement. - * `100% of the hit window, or 160ms` + * Determine the score a note receives under a given scoring system. + * @param msTiming The difference between the note's time and when it was hit. + * @return The score the note receives. */ - public static final PBOT1_SHIT_THRESHOLD:Float = 160.0; - - static function scoreNotePBOT1(msTiming:Float):Int + public function scoreNote(msTiming:Float):Int { - // Absolute value because otherwise late hits are always given the max score. - var absTiming:Float = Math.abs(msTiming); - - return switch (absTiming) - { - case(_ > PBOT1_MISS_THRESHOLD) => true: - PBOT1_MISS_SCORE; - case(_ < PBOT1_PERFECT_THRESHOLD) => true: - PBOT1_MAX_SCORE; - default: - // Fancy equation. - var factor:Float = 1.0 - (1.0 / (1.0 + Math.exp(-PBOT1_SCORING_SLOPE * (absTiming - PBOT1_SCORING_OFFSET)))); - - var score:Int = Std.int(PBOT1_MAX_SCORE * factor + PBOT1_MIN_SCORE); - - score; - } + return 0; } - static function judgeNotePBOT1(msTiming:Float):String - { - var absTiming:Float = Math.abs(msTiming); - - return switch (absTiming) - { - // case(_ <= PBOT1_KILLER_THRESHOLD) => true: - // 'killer'; - case(_ <= PBOT1_SICK_THRESHOLD) => true: - 'sick'; - case(_ <= PBOT1_GOOD_THRESHOLD) => true: - 'good'; - case(_ <= PBOT1_BAD_THRESHOLD) => true: - 'bad'; - case(_ <= PBOT1_SHIT_THRESHOLD) => true: - 'shit'; - default: - FlxG.log.warn('Missed note: Bad timing ($absTiming < $PBOT1_SHIT_THRESHOLD)'); - 'miss'; - } - } - - /** - * The window of time in which a note is considered to be hit, on the Funkin Legacy scoring system. - * Currently equal to 10 frames at 60fps, or ~166ms. - */ - public static final LEGACY_HIT_WINDOW:Float = (10 / 60) * 1000; // 166.67 ms hit window (10 frames at 60fps) - - /** - * The threshold at which a note is considered a "Sick" hit rather than another judgement. - * Represented as a percentage of the total hit window. - */ - public static final LEGACY_SICK_THRESHOLD:Float = 0.2; - - /** - * The threshold at which a note is considered a "Good" hit rather than another judgement. - * Represented as a percentage of the total hit window. - */ - public static final LEGACY_GOOD_THRESHOLD:Float = 0.75; - - /** - * The threshold at which a note is considered a "Bad" hit rather than another judgement. - * Represented as a percentage of the total hit window. - */ - public static final LEGACY_BAD_THRESHOLD:Float = 0.9; - - /** - * The score a note receives when hit within the Shit threshold, rather than a miss. - * Represented as a percentage of the total hit window. - */ - public static final LEGACY_SHIT_THRESHOLD:Float = 1.0; - /** - * The score a note receives when hit within the Sick threshold. + * The amount of scoring to receive when missing a note. + * @return The score the miss receives. */ - public static final LEGACY_SICK_SCORE:Int = 350; - - /** - * The score a note receives when hit within the Good threshold. - */ - public static final LEGACY_GOOD_SCORE:Int = 200; - - /** - * The score a note receives when hit within the Bad threshold. - */ - public static final LEGACY_BAD_SCORE:Int = 100; - - /** - * The score a note receives when hit within the Shit threshold. - */ - public static final LEGACY_SHIT_SCORE:Int = 50; - - /** - * The score a note receives when missed. - */ - public static final LEGACY_MISS_SCORE:Int = -10; - - static function scoreNoteLEGACY(msTiming:Float):Int - { - var absTiming:Float = Math.abs(msTiming); - - return switch (absTiming) - { - case(_ < LEGACY_HIT_WINDOW * LEGACY_SICK_THRESHOLD) => true: - LEGACY_SICK_SCORE; - case(_ < LEGACY_HIT_WINDOW * LEGACY_GOOD_THRESHOLD) => true: - LEGACY_GOOD_SCORE; - case(_ < LEGACY_HIT_WINDOW * LEGACY_BAD_THRESHOLD) => true: - LEGACY_BAD_SCORE; - case(_ < LEGACY_HIT_WINDOW * LEGACY_SHIT_THRESHOLD) => true: - LEGACY_SHIT_SCORE; - default: - 0; - } - } - - static function judgeNoteLEGACY(msTiming:Float):String + public function getMissScore():Int { - var absTiming:Float = Math.abs(msTiming); - - return switch (absTiming) - { - case(_ <= LEGACY_HIT_WINDOW * LEGACY_SICK_THRESHOLD) => true: - 'sick'; - case(_ <= LEGACY_HIT_WINDOW * LEGACY_GOOD_THRESHOLD) => true: - 'good'; - case(_ <= LEGACY_HIT_WINDOW * LEGACY_BAD_THRESHOLD) => true: - 'bad'; - case(_ <= LEGACY_HIT_WINDOW * LEGACY_SHIT_THRESHOLD) => true: - 'shit'; - default: - FlxG.log.warn('Missed note: Bad timing ($absTiming < $LEGACY_SHIT_THRESHOLD)'); - 'miss'; - } + return 0; } /** - * The window of time in which a note is considered to be hit, on the Funkin Classic scoring system. - * Same as L 10 frames at 60fps, or ~166ms. + * String representation of this scoring object. + * @return String */ - public static final WEEK7_HIT_WINDOW:Float = LEGACY_HIT_WINDOW; - - public static final WEEK7_BAD_THRESHOLD:Float = 0.8; // 80% of the hit window, or ~125ms - public static final WEEK7_GOOD_THRESHOLD:Float = 0.55; // 55% of the hit window, or ~91ms - public static final WEEK7_SICK_THRESHOLD:Float = 0.2; // 20% of the hit window, or ~33ms - public static final WEEK7_MISS_SCORE:Int = -10; - public static final WEEK7_SHIT_SCORE:Int = 50; - public static final WEEK7_BAD_SCORE:Int = 100; - public static final WEEK7_GOOD_SCORE:Int = 200; - public static final WEEK7_SICK_SCORE:Int = 350; - - static function scoreNoteWEEK7(msTiming:Float):Int - { - var absTiming:Float = Math.abs(msTiming); - - return switch (absTiming) - { - case(_ < WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) => true: - LEGACY_SICK_SCORE; - case(_ < WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) => true: - LEGACY_GOOD_SCORE; - case(_ < WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) => true: - LEGACY_BAD_SCORE; - case(_ < WEEK7_HIT_WINDOW) => true: - LEGACY_SHIT_SCORE; - default: - 0; - } - - if (absTiming < WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) - { - return WEEK7_SICK_SCORE; - } - else if (absTiming < WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) - { - return WEEK7_GOOD_SCORE; - } - else if (absTiming < WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) - { - return WEEK7_BAD_SCORE; - } - else if (absTiming < WEEK7_HIT_WINDOW) - { - return WEEK7_SHIT_SCORE; - } - else - { - return 0; - } - } - - static function judgeNoteWEEK7(msTiming:Float):String + public function toString():String { - var absTiming = Math.abs(msTiming); - if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) - { - return 'sick'; - } - else if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) - { - return 'good'; - } - else if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) - { - return 'bad'; - } - else if (absTiming <= WEEK7_HIT_WINDOW) - { - return 'shit'; - } - else - { - FlxG.log.warn('Missed note: Bad timing ($absTiming < $WEEK7_HIT_WINDOW)'); - return 'miss'; - } + return 'Scoring($id)'; } public static function calculateRank(scoreData:Null):Null @@ -430,8 +111,11 @@ class Scoring public static function tallyCompletion(?tallies:SaveScoreTallyData):Float { if (tallies == null) return 0.0; - return ((tallies.sick + tallies.good - tallies.missed) / tallies.totalNotes).clamp(0, - 1); // Needs to be clamped to make sure Perfect ranks are saved properly + return (( + tallies.sick + + tallies.good + - tallies.missed + ) / tallies.totalNotes).clamp(0, 1); // Needs to be clamped to make sure Perfect ranks are saved properly } } diff --git a/source/funkin/play/scoring/ScoringLegacy.hx b/source/funkin/play/scoring/ScoringLegacy.hx new file mode 100644 index 00000000000..a841d6861f9 --- /dev/null +++ b/source/funkin/play/scoring/ScoringLegacy.hx @@ -0,0 +1,112 @@ +package funkin.play.scoring; + +/** + * The scoring system used in versions of the game Week 6 and older. + * Scores the player based on judgement, represented by a step function. + */ +class ScoringLegacy extends Scoring +{ + /** + * The window of time in which a note is considered to be hit, on the Funkin Legacy scoring system. + * Currently equal to 10 frames at 60fps, or ~166ms. + */ + public static final LEGACY_HIT_WINDOW:Float = (10 / 60) * 1000; // 166.67 ms hit window (10 frames at 60fps) + + /** + * The threshold at which a note is considered a "Sick" hit rather than another judgement. + * Represented as a percentage of the total hit window. + */ + public static final LEGACY_SICK_THRESHOLD:Float = 0.2; + + /** + * The threshold at which a note is considered a "Good" hit rather than another judgement. + * Represented as a percentage of the total hit window. + */ + public static final LEGACY_GOOD_THRESHOLD:Float = 0.75; + + /** + * The threshold at which a note is considered a "Bad" hit rather than another judgement. + * Represented as a percentage of the total hit window. + */ + public static final LEGACY_BAD_THRESHOLD:Float = 0.9; + + /** + * The score a note receives when hit within the Shit threshold, rather than a miss. + * Represented as a percentage of the total hit window. + */ + public static final LEGACY_SHIT_THRESHOLD:Float = 1.0; + + /** + * The score a note receives when hit within the Sick threshold. + */ + public static final LEGACY_SICK_SCORE:Int = 350; + + /** + * The score a note receives when hit within the Good threshold. + */ + public static final LEGACY_GOOD_SCORE:Int = 200; + + /** + * The score a note receives when hit within the Bad threshold. + */ + public static final LEGACY_BAD_SCORE:Int = 100; + + /** + * The score a note receives when hit within the Shit threshold. + */ + public static final LEGACY_SHIT_SCORE:Int = 50; + + /** + * The score a note receives when missed. + */ + public static final LEGACY_MISS_SCORE:Int = -10; + + public function new() + { + super('legacy'); + } + + public override function scoreNote(msTiming:Float):Int + { + var absTiming:Float = Math.abs(msTiming); + + return switch (absTiming) + { + case(_ < LEGACY_HIT_WINDOW * LEGACY_SICK_THRESHOLD) => true: + LEGACY_SICK_SCORE; + case(_ < LEGACY_HIT_WINDOW * LEGACY_GOOD_THRESHOLD) => true: + LEGACY_GOOD_SCORE; + case(_ < LEGACY_HIT_WINDOW * LEGACY_BAD_THRESHOLD) => true: + LEGACY_BAD_SCORE; + case(_ < LEGACY_HIT_WINDOW * LEGACY_SHIT_THRESHOLD) => true: + LEGACY_SHIT_SCORE; + default: + 0; + } + } + + public override function judgeNote(msTiming:Float):String + { + var absTiming:Float = Math.abs(msTiming); + + return switch (absTiming) + { + case(_ <= LEGACY_HIT_WINDOW * LEGACY_SICK_THRESHOLD) => true: + 'sick'; + case(_ <= LEGACY_HIT_WINDOW * LEGACY_GOOD_THRESHOLD) => true: + 'good'; + case(_ <= LEGACY_HIT_WINDOW * LEGACY_BAD_THRESHOLD) => true: + 'bad'; + case(_ <= LEGACY_HIT_WINDOW * LEGACY_SHIT_THRESHOLD) => true: + 'shit'; + default: + FlxG.log.warn('Missed note: Bad timing ($absTiming < $LEGACY_SHIT_THRESHOLD)'); + 'miss'; + } + } + + public override function getMissScore():Int + { + return LEGACY_MISS_SCORE; + } +} diff --git a/source/funkin/play/scoring/ScoringPBOT1.hx b/source/funkin/play/scoring/ScoringPBOT1.hx new file mode 100644 index 00000000000..a068adf9335 --- /dev/null +++ b/source/funkin/play/scoring/ScoringPBOT1.hx @@ -0,0 +1,127 @@ +package funkin.play.scoring; + +/** + * Points Based On Timing scoring system, version 1 + * Scores the player based on the offset based on timing, represented by a sigmoid function. + */ +class ScoringPBOT1 extends Scoring +{ + /** + * The maximum score a note can receive. + */ + public static final PBOT1_MAX_SCORE:Int = 500; + + /** + * The offset of the sigmoid curve for the scoring function. + */ + public static final PBOT1_SCORING_OFFSET:Float = 54.99; + + /** + * The slope of the sigmoid curve for the scoring function. + */ + public static final PBOT1_SCORING_SLOPE:Float = 0.080; + + /** + * The minimum score a note can receive while still being considered a hit. + */ + public static final PBOT1_MIN_SCORE:Float = 9.0; + + /** + * The score a note receives when it is missed. + */ + public static final PBOT1_MISS_SCORE:Int = -100; + + /** + * The threshold at which a note hit is considered perfect and always given the max score. + */ + public static final PBOT1_PERFECT_THRESHOLD:Float = 5.0; // 5ms + + /** + * The threshold at which a note hit is considered missed. + * `160ms` + */ + public static final PBOT1_MISS_THRESHOLD:Float = 160.0; + + /** + * The time within which a note is considered to have been hit with the Killer judgement. + * `~7.5% of the hit window, or 12.5ms` + */ + public static final PBOT1_KILLER_THRESHOLD:Float = 12.5; + + /** + * The time within which a note is considered to have been hit with the Sick judgement. + * `~25% of the hit window, or 45ms` + */ + public static final PBOT1_SICK_THRESHOLD:Float = 45.0; + + /** + * The time within which a note is considered to have been hit with the Good judgement. + * `~55% of the hit window, or 90ms` + */ + public static final PBOT1_GOOD_THRESHOLD:Float = 90.0; + + /** + * The time within which a note is considered to have been hit with the Bad judgement. + * `~85% of the hit window, or 135ms` + */ + public static final PBOT1_BAD_THRESHOLD:Float = 135.0; + + /** + * The time within which a note is considered to have been hit with the Shit judgement. + * `100% of the hit window, or 160ms` + */ + public static final PBOT1_SHIT_THRESHOLD:Float = 160.0; + + public function new() + { + super('pbot1'); + } + + public override function scoreNote(msTiming:Float):Int + { + // Absolute value because otherwise late hits are always given the max score. + var absTiming:Float = Math.abs(msTiming); + + return switch (absTiming) + { + case(_ > PBOT1_MISS_THRESHOLD) => true: + PBOT1_MISS_SCORE; + case(_ < PBOT1_PERFECT_THRESHOLD) => true: + PBOT1_MAX_SCORE; + default: + // Fancy equation. + var factor:Float = 1.0 - (1.0 / (1.0 + Math.exp(-PBOT1_SCORING_SLOPE * (absTiming - PBOT1_SCORING_OFFSET)))); + + var score:Int = Std.int(PBOT1_MAX_SCORE * factor + PBOT1_MIN_SCORE); + + score; + } + } + + public override function judgeNote(msTiming:Float):String + { + var absTiming:Float = Math.abs(msTiming); + + return switch (absTiming) + { + // case(_ <= PBOT1_KILLER_THRESHOLD) => true: + // 'killer'; + case(_ <= PBOT1_SICK_THRESHOLD) => true: + 'sick'; + case(_ <= PBOT1_GOOD_THRESHOLD) => true: + 'good'; + case(_ <= PBOT1_BAD_THRESHOLD) => true: + 'bad'; + case(_ <= PBOT1_SHIT_THRESHOLD) => true: + 'shit'; + default: + FlxG.log.warn('Missed note: Bad timing ($absTiming < $PBOT1_SHIT_THRESHOLD)'); + 'miss'; + } + } + + public override function getMissScore():Int + { + return PBOT1_MISS_SCORE; + } +} diff --git a/source/funkin/play/scoring/ScoringWeek7.hx b/source/funkin/play/scoring/ScoringWeek7.hx new file mode 100644 index 00000000000..20f613579b2 --- /dev/null +++ b/source/funkin/play/scoring/ScoringWeek7.hx @@ -0,0 +1,100 @@ +package funkin.play.scoring; + +/** + * The scoring system used in Week 7. It has tighter scoring windows than Legacy. + * Scores the player based on judgement, represented by a step function. + */ +class ScoringWeek7 extends Scoring +{ + /** + * The window of time in which a note is considered to be hit, on the Funkin Classic scoring system. + * Same as L 10 frames at 60fps, or ~166ms. + */ + public static final WEEK7_HIT_WINDOW:Float = (10 / 60) * 1000; // 166.67 ms hit window (10 frames at 60fps) + + public static final WEEK7_BAD_THRESHOLD:Float = 0.8; // 80% of the hit window, or ~125ms + public static final WEEK7_GOOD_THRESHOLD:Float = 0.55; // 55% of the hit window, or ~91ms + public static final WEEK7_SICK_THRESHOLD:Float = 0.2; // 20% of the hit window, or ~33ms + public static final WEEK7_MISS_SCORE:Int = -10; + public static final WEEK7_SHIT_SCORE:Int = 50; + public static final WEEK7_BAD_SCORE:Int = 100; + public static final WEEK7_GOOD_SCORE:Int = 200; + public static final WEEK7_SICK_SCORE:Int = 350; + + public function new() + { + super('week7'); + } + + override function scoreNote(msTiming:Float):Int + { + var absTiming:Float = Math.abs(msTiming); + + return switch (absTiming) + { + case(_ < WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) => true: + WEEK7_SICK_SCORE; + case(_ < WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) => true: + WEEK7_GOOD_SCORE; + case(_ < WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) => true: + WEEK7_BAD_SCORE; + case(_ < WEEK7_HIT_WINDOW) => true: + WEEK7_SHIT_SCORE; + default: + 0; + } + + if (absTiming < WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) + { + return WEEK7_SICK_SCORE; + } + else if (absTiming < WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) + { + return WEEK7_GOOD_SCORE; + } + else if (absTiming < WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) + { + return WEEK7_BAD_SCORE; + } + else if (absTiming < WEEK7_HIT_WINDOW) + { + return WEEK7_SHIT_SCORE; + } + else + { + return 0; + } + } + + override function judgeNote(msTiming:Float):String + { + var absTiming = Math.abs(msTiming); + + if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_SICK_THRESHOLD) + { + return 'sick'; + } + else if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_GOOD_THRESHOLD) + { + return 'good'; + } + else if (absTiming <= WEEK7_HIT_WINDOW * WEEK7_BAD_THRESHOLD) + { + return 'bad'; + } + else if (absTiming <= WEEK7_HIT_WINDOW) + { + return 'shit'; + } + else + { + FlxG.log.warn('Missed note: Bad timing ($absTiming < $WEEK7_HIT_WINDOW)'); + return 'miss'; + } + } + + public override function getMissScore():Int + { + return WEEK7_MISS_SCORE; + } +} diff --git a/source/funkin/play/scoring/ScriptedScoring.hx b/source/funkin/play/scoring/ScriptedScoring.hx new file mode 100644 index 00000000000..0f6c13d1bc1 --- /dev/null +++ b/source/funkin/play/scoring/ScriptedScoring.hx @@ -0,0 +1,10 @@ +package funkin.play.scoring; + +/** + * A script that can be tied to a Scoring object. + * Create a scripted class that extends Scoring to use this. + */ +@:hscriptClass +class ScriptedScoring extends funkin.play.scoring.Scoring implements polymod.hscript.HScriptedClass +{ +}