1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-01-01 09:48:14 +00:00

Messing around with logic for hold note misses/health gain

This commit is contained in:
EliteMasterEric 2023-06-27 13:43:42 -04:00
parent 47d8d9e4db
commit a672db7b0e
4 changed files with 166 additions and 93 deletions

View file

@ -136,10 +136,8 @@ class PlayState extends MusicBeatState
/**
* The player's current health.
* The default maximum health is 2.0, and the default starting health is 1.0.
* TODO: Refactor this to [0.0, 1.0]
*/
public var health:Float = 1;
public var health:Float = Constants.HEALTH_STARTING;
/**
* The player's current score.
@ -255,7 +253,7 @@ class PlayState extends MusicBeatState
* The displayed value of the player's health.
* Used to provide smooth animations based on linear interpolation of the player's health.
*/
var healthLerp:Float = 1;
var healthLerp:Float = Constants.HEALTH_STARTING;
/**
* How long the user has held the "Skip Video Cutscene" button for.
@ -643,7 +641,7 @@ class PlayState extends MusicBeatState
hudCameraZoomIntensity = Constants.DEFAULT_ZOOM_INTENSITY * 2.0;
cameraZoomRate = Constants.DEFAULT_ZOOM_RATE;
health = 1;
health = Constants.HEALTH_STARTING;
songScore = 0;
Highscore.tallies.combo = 0;
Countdown.performCountdown(currentStageId.startsWith('school'));
@ -735,8 +733,8 @@ class PlayState extends MusicBeatState
}
// Cap health.
if (health > 2.0) health = 2.0;
if (health < 0.0) health = 0.0;
if (health > Constants.HEALTH_MAX) health = Constants.HEALTH_MAX;
if (health < Constants.HEALTH_MIN) health = Constants.HEALTH_MIN;
// Lerp the camera zoom towards the target level.
if (subState == null)
@ -761,19 +759,19 @@ class PlayState extends MusicBeatState
// RESET = Quick Game Over Screen
if (controls.RESET)
{
health = 0;
health = Constants.HEALTH_MIN;
trace('RESET = True');
}
#if CAN_CHEAT // brandon's a pussy
if (controls.CHEAT)
{
health += 1;
health += 0.25 * Constants.HEALTH_MAX; // +25% health.
trace('User is cheating!');
}
#end
if (health <= 0 && !isPracticeMode)
if (health <= Constants.HEALTH_MIN && !isPracticeMode)
{
vocals.pause();
FlxG.sound.music.pause();
@ -934,7 +932,7 @@ class PlayState extends MusicBeatState
*/
public override function onFocus():Void
{
if (health > 0 && !paused && FlxG.autoPause)
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause)
{
if (Conductor.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
+ ' ('
@ -954,7 +952,8 @@ class PlayState extends MusicBeatState
*/
public override function onFocusLost():Void
{
if (health > 0 && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText,
currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
super.onFocusLost();
}
@ -1645,7 +1644,8 @@ class PlayState extends MusicBeatState
{
note.tooEarly = false;
note.mayHit = false;
note.tooLate = true;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
}
else if (Conductor.songPosition > hitWindowCenter)
{
@ -1660,20 +1660,20 @@ class PlayState extends MusicBeatState
// Command the opponent to hit the note on time.
// NOTE: This is what handles the strumline and cleaning up the note itself!
opponentStrumline.hitNote(note);
// scoreNote();
}
else if (Conductor.songPosition > hitWindowStart)
{
note.tooEarly = false;
note.mayHit = true;
note.tooLate = false;
note.hasMissed = false;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false;
}
else
{
note.tooEarly = true;
note.mayHit = false;
note.tooLate = false;
note.hasMissed = false;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false;
}
}
@ -1682,8 +1682,35 @@ class PlayState extends MusicBeatState
{
if (note == null || note.hasBeenHit) continue;
// If this is true, the note is already properly off the screen.
if (note.hasMissed)
var hitWindowStart = note.strumTime - Conductor.HIT_WINDOW_MS;
var hitWindowCenter = note.strumTime;
var hitWindowEnd = note.strumTime + Conductor.HIT_WINDOW_MS;
if (Conductor.songPosition > hitWindowEnd)
{
note.tooEarly = false;
note.mayHit = false;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
}
else if (Conductor.songPosition > hitWindowStart)
{
note.tooEarly = false;
note.mayHit = true;
note.hasMissed = false;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false;
}
else
{
note.tooEarly = true;
note.mayHit = false;
note.hasMissed = false;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false;
}
// This becomes true when the note leaves the hit window.
// It might still be on screen.
if (note.hasMissed && !note.handledMiss)
{
// Call an event to allow canceling the note miss.
// NOTE: This is what handles the character animations!
@ -1696,6 +1723,8 @@ class PlayState extends MusicBeatState
// Judge the miss.
// NOTE: This is what handles the scoring.
onNoteMiss(note);
note.handledMiss = true;
}
}
@ -1725,11 +1754,9 @@ class PlayState extends MusicBeatState
}
// Generate a list of notes within range.
var notesInRange:Array<NoteSprite> = playerStrumline.getNotesInRange(Conductor.songPosition, Conductor.HIT_WINDOW_MS);
var notesInRange:Array<NoteSprite> = playerStrumline.getNotesMayHit();
// If there are notes in range, pressing a key will cause a ghost miss.
// var canMiss:Bool = notesInRange.length > 0;
var canMiss:Bool = true; // Forced to true for consistency with other input systems.
var notesByDirection:Array<Array<NoteSprite>> = [[], [], [], []];
@ -1744,10 +1771,19 @@ class PlayState extends MusicBeatState
var notesInDirection:Array<NoteSprite> = notesByDirection[input.noteDirection];
if (canMiss && notesInDirection.length == 0)
if (!Constants.GHOST_TAPPING && notesInDirection.length == 0)
{
// Pressed a wrong key with notes in range.
// Perform a ghost miss.
// Pressed a wrong key with no notes nearby.
// Perform a ghost miss (anti-spam).
ghostNoteMiss(input.noteDirection, notesInRange.length > 0);
// Play the strumline animation.
playerStrumline.playPress(input.noteDirection);
}
else if (Constants.GHOST_TAPPING && notesInRange.length > 0 && notesInDirection.length == 0)
{
// Pressed a wrong key with no notes nearby AND with notes in a different direction available.
// Perform a ghost miss (anti-spam).
ghostNoteMiss(input.noteDirection, notesInRange.length > 0);
// Play the strumline animation.
@ -1837,37 +1873,6 @@ class PlayState extends MusicBeatState
var directionList:Array<Int> = []; // directions that can be hit
var dumbNotes:Array<NoteSprite> = []; // notes to kill later
/*
activeNotes.forEachAlive(function(daNote:Note) {
if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.hasBeenHit)
{
if (directionList.contains(daNote.data.noteData))
{
for (coolNote in possibleNotes)
{
if (coolNote.data.noteData == daNote.data.noteData && Math.abs(daNote.data.strumTime - coolNote.data.strumTime) < 10)
{ // if it's the same note twice at < 10ms distance, just delete it
// EXCEPT u cant delete it in this loop cuz it fucks with the collection lol
dumbNotes.push(daNote);
break;
}
else if (coolNote.data.noteData == daNote.data.noteData && daNote.data.strumTime < coolNote.data.strumTime)
{ // if daNote is earlier than existing note (coolNote), replace
possibleNotes.remove(coolNote);
possibleNotes.push(daNote);
break;
}
}
}
else
{
possibleNotes.push(daNote);
directionList.push(daNote.data.noteData);
}
}
});
*/
for (note in dumbNotes)
{
FlxG.log.add('killing dumb ass note at ' + note.noteData.time);
@ -1955,7 +1960,7 @@ class PlayState extends MusicBeatState
// Calling event.cancelEvent() skips all the other logic! Neat!
if (event.eventCanceled) return;
health -= 0.0775;
health -= Constants.HEALTH_MISS_PENALTY;
if (!isPracticeMode)
{
@ -2008,9 +2013,6 @@ class PlayState extends MusicBeatState
vocals.playerVolume = 0;
FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2));
}
note.active = false;
note.visible = false;
}
/**
@ -2025,7 +2027,7 @@ class PlayState extends MusicBeatState
{
var event:GhostMissNoteScriptEvent = new GhostMissNoteScriptEvent(direction, // Direction missed in.
hasPossibleNotes, // Whether there was a note you could have hit.
- 0.035 * 2, // How much health to add (negative).
- 1 * Constants.HEALTH_MISS_PENALTY, // How much health to add (negative).
- 10 // Amount of score to add (negative).
);
dispatchEvent(event);
@ -2098,10 +2100,10 @@ class PlayState extends MusicBeatState
if (FlxG.keys.justPressed.ONE) endSong();
// 2: Gain 10% health.
if (FlxG.keys.justPressed.TWO) health += 0.1 * 2.0;
if (FlxG.keys.justPressed.TWO) health += 0.1 * Constants.HEALTH_MAX;
// 3: Lose 5% health.
if (FlxG.keys.justPressed.THREE) health -= 0.05 * 2.0;
if (FlxG.keys.justPressed.THREE) health -= 0.05 * Constants.HEALTH_MAX;
#end
// 7: Move to the charter.
@ -2146,36 +2148,33 @@ class PlayState extends MusicBeatState
var score = Scoring.scoreNote(noteDiff, PBOT1);
var daRating = Scoring.judgeNote(noteDiff, PBOT1);
var isSick:Bool = false;
var healthMulti:Float = 0;
switch (daRating)
{
case 'killer':
Highscore.tallies.killer += 1;
healthMulti = 0.033;
health += Constants.HEALTH_KILLER_BONUS;
case 'sick':
Highscore.tallies.sick += 1;
healthMulti = 0.033;
health += Constants.HEALTH_SICK_BONUS;
case 'good':
Highscore.tallies.good += 1;
healthMulti = 0.033 * 0.78;
health += Constants.HEALTH_GOOD_BONUS;
case 'bad':
Highscore.tallies.bad += 1;
healthMulti = 0.033 * 0.2;
health += Constants.HEALTH_BAD_BONUS;
case 'shit':
Highscore.tallies.shit += 1;
healthMulti = 0;
health += Constants.HEALTH_SHIT_BONUS;
case 'miss':
Highscore.tallies.missed += 1;
healthMulti = 0;
health -= Constants.HEALTH_MISS_PENALTY;
}
health += healthMulti;
if (daRating == "sick" || daRating == "killer")
{
playerStrumline.playNoteSplash(daNote.noteData.getDirection());
}
// Only add the score if you're not on practice mode
if (!isPracticeMode)
{

View file

@ -87,8 +87,10 @@ class NoteSprite extends FlxSprite
public var lowPriority:Bool = false;
/**
* This is true if the note has been fully missed by the player.
* It will be destroyed immediately.
* This is true if the note is later than 10 frames within the strumline,
* and thus can't be hit by the player.
* It will be destroyed after it moves offscreen.
* Managed by PlayState.
*/
public var hasMissed:Bool;
@ -107,11 +109,10 @@ class NoteSprite extends FlxSprite
public var mayHit:Bool;
/**
* This is true if the note is earlier than 10 frames after the strumline,
* and thus can't be hit by the player.
* Managed by PlayState.
* This is true if the PlayState has performed the logic for missing this note.
* Subtracting score, subtracting health, etc.
*/
public var tooLate:Bool;
public var handledMiss:Bool;
public function new(strumTime:Float = 0, direction:Int = 0)
{
@ -171,7 +172,6 @@ class NoteSprite extends FlxSprite
this.tooEarly = false;
this.hasBeenHit = false;
this.mayHit = false;
this.tooLate = false;
this.hasMissed = false;
}

View file

@ -123,6 +123,13 @@ class Strumline extends FlxSpriteGroup
});
}
public function getNotesMayHit():Array<NoteSprite>
{
return notes.members.filter(function(note:NoteSprite) {
return note != null && note.alive && !note.hasBeenHit && note.mayHit;
});
}
public function getHoldNotesInRange(strumTime:Float, hitWindow:Float):Array<SustainTrail>
{
var hitWindowStart:Float = strumTime - hitWindow;
@ -207,24 +214,17 @@ class Strumline extends FlxSpriteGroup
// Update rendering of notes.
for (note in notes.members)
{
if (note == null || note.hasBeenHit) continue;
if (note == null || !note.alive || note.hasBeenHit) continue;
var vwoosh:Bool = note.holdNoteSprite == null;
// Set the note's position.
note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh);
// Check if the note is outside the hit window, and if so, mark it as missed.
// TODO: Check to make sure this doesn't happen when the note is on screen because it'll probably get deleted.
if (Conductor.songPosition > (note.noteData.time + Conductor.HIT_WINDOW_MS))
// If the note is miss
var isOffscreen = PreferencesMenu.getPref('downscroll') ? note.y > FlxG.height : note.y < -note.height;
if (note.handledMiss && isOffscreen)
{
note.visible = false;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
}
else
{
note.visible = true;
note.hasMissed = false;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false;
killNote(note);
}
}

View file

@ -122,6 +122,80 @@ class Constants
*/
public static final DEFAULT_VARIATION:String = 'default';
/**
* HEALTH VALUES
*/
// ==============================
/**
* The player's maximum health.
* If the player is at this value, they can't gain any more health.
*/
public static final HEALTH_MAX:Float = 2.0;
/**
* The player's starting health.
*/
public static final HEALTH_STARTING = HEALTH_MAX / 2.0;
/**
* The player's minimum health.
* If the player is at or below this value, they lose.
*/
public static final HEALTH_MIN:Float = 0.0;
/**
* The amount of health the player gains when hitting a note with the KILLER rating.
*/
public static final HEALTH_KILLER_BONUS:Float = 2.0 / 100.0 / HEALTH_MAX; // +2.0%
/**
* The amount of health the player gains when hitting a note with the SICK rating.
*/
public static final HEALTH_SICK_BONUS:Float = 1.5 / 100.0 / HEALTH_MAX; // +1.0%
/**
* The amount of health the player gains when hitting a note with the GOOD rating.
*/
public static final HEALTH_GOOD_BONUS:Float = 0.75 / 100.0 / HEALTH_MAX; // +0.75%
/**
* The amount of health the player gains when hitting a note with the BAD rating.
*/
public static final HEALTH_BAD_BONUS:Float = 0.0 / 100.0 / HEALTH_MAX; // +0.0%
/**
* The amount of health the player gains when hitting a note with the SHIT rating.
* If negative, the player will actually lose health.
*/
public static final HEALTH_SHIT_BONUS:Float = -1.0 / 100.0 / HEALTH_MAX; // -1.0%
/**
* The amount of health the player loses upon missing a note.
*/
public static final HEALTH_MISS_PENALTY:Float = 4.0 / 100.0 / HEALTH_MAX; // 4.0%
/**
* The amount of health the player loses upon pressing a key when no note is there.
*/
public static final HEALTH_GHOST_MISS_PENALTY:Float = 2.0 / 100.0 / HEALTH_MAX; // 2.0%
/**
* The amount of health the player loses upon letting go of a hold note while it is still going.
*/
public static final HEALTH_HOLD_DROP_PENALTY:Float = 0.0; // 0.0%
/**
* The amount of health the player loses upon hitting a mine.
*/
public static final HEALTH_MINE_PENALTY:Float = 15.0 / 100.0 / HEALTH_MAX; // 15.0%
/**
* If true, the player will not receive the ghost miss penalty if there are no notes within the hit window.
* This is the thing people have been begging for forever lolol.
*/
public static final GHOST_TAPPING:Bool = true;
/**
* OTHER
*/