diff --git a/source/funkin/data/ClientPrefs.hx b/source/funkin/data/ClientPrefs.hx index 09c5e00c..3200bae4 100644 --- a/source/funkin/data/ClientPrefs.hx +++ b/source/funkin/data/ClientPrefs.hx @@ -104,6 +104,8 @@ class ClientPrefs @saveVar public static var quants:Bool = false; + @:saveVar public static var hudStyle:String = 'NightmareVision'; + // @saveVar public static var noteSkin:String = 'Vanilla'; @saveVar public static var comboOffset:Array = [0, 0, 0, 0]; diff --git a/source/funkin/game/huds/ClassicHUD.hx b/source/funkin/game/huds/ClassicHUD.hx new file mode 100644 index 00000000..57e15f9b --- /dev/null +++ b/source/funkin/game/huds/ClassicHUD.hx @@ -0,0 +1,293 @@ +package funkin.game.huds; + +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.FlxObject; +import flixel.util.FlxStringUtil; + +import funkin.objects.Bar; +import funkin.objects.HealthIcon; + + +@:access(funkin.states.PlayState) +class ClassicHUD extends BaseHUD +{ + var ratingGraphic:FlxSprite; + var ratingNumGroup:FlxTypedGroup; + + var healthBar:Bar; + var iconP1:HealthIcon; + var iconP2:HealthIcon; + var scoreTxt:FlxText; + + var pixelZoom:Float = 6; // idgaf + + var ratingPrefix:String = ""; + var ratingSuffix:String = ''; + var comboPrefix:String = ""; + + var comboTween:Bool = true; + var _psychStyle = false; + + var textDivider = '•'; + var showRating:Bool = ClientPrefs.showRatings; + var showRatingNum:Bool = ClientPrefs.showRatings; + var showCombo:Bool = ClientPrefs.showRatings; + var updateIconPos:Bool = true; + var updateIconScale:Bool = true; + var comboOffsets:Null> = null; // So u can overwrite the users combo offset if needed without messing with clientprefs + + // TODO: Make combo shit change for week 6, the ground work is already there so incase someone else wants to come on in and mess w it. + override function init() + { + name = 'CLASSIC'; + + ratingPrefix = Paths.RATINGS_PREFIX; + comboPrefix = Paths.COMBO_PREFIX; + + final healthGraphic = FunkinAssets.exists(Paths.mods('images/${Paths.UI_PREFIX}healthBar')) ? '${Paths.UI_PREFIX}healthBar' : 'UI/healthBar'; + + healthBar = new Bar(0, FlxG.height * (!ClientPrefs.downScroll ? 0.89 : 0.11), healthGraphic, function() return parent.health, parent.healthBounds.min, parent.healthBounds.max); + healthBar.screenCenter(X); + healthBar.leftToRight = false; + healthBar.scrollFactor.set(); + healthBar.visible = !ClientPrefs.hideHud; + healthBar.alphaMultipler = ClientPrefs.healthBarAlpha; + + reloadHealthBarColors(); + add(healthBar); + + iconP1 = new HealthIcon(parent.boyfriend.healthIcon, true); + iconP1.y = healthBar.y - 75; + iconP1.visible = !ClientPrefs.hideHud; + iconP1.alphaMultipler = ClientPrefs.healthBarAlpha; + add(iconP1); + + iconP2 = new HealthIcon(parent.dad.healthIcon, false); + iconP2.y = healthBar.y - 75; + iconP2.visible = !ClientPrefs.hideHud; + iconP2.alphaMultipler = ClientPrefs.healthBarAlpha; + add(iconP2); + + scoreTxt = new FlxText(healthBar.x + healthBar.width - 190, healthBar.y + 30, 0, "", 20); + scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + add(scoreTxt); + + ratingGraphic = new FlxSprite(); + ratingGraphic.alpha = 0; + add(ratingGraphic); + + ratingNumGroup = new FlxTypedGroup(); + add(ratingNumGroup); + + onUpdateScore(0, 0, 0); + + parent.scripts.set('healthBar', healthBar); + parent.scripts.set('iconP1', iconP1); + parent.scripts.set('iconP2', iconP2); + parent.scripts.set('scoreTxt', scoreTxt); + parent.scripts.set('ratingPrefix', ratingPrefix); + parent.scripts.set('ratingSuffix', ratingSuffix); + parent.scripts.set('comboPrefix', comboPrefix); + parent.scripts.set('comboOffsets', comboOffsets); + + if (comboOffsets == null) + { + comboOffsets = ClientPrefs.comboOffset; + } + } + + override function onUpdateScore(score:Int = 0, accuracy:Float = 0, misses:Int = 0, missed:Bool = false) + { + final tempScore:String = 'Score: ${FlxStringUtil.formatMoney(score, false)}'; + scoreTxt.text = '${tempScore}\n'; + } + + public function updateIconsPosition() + { + if (!updateIconPos) return; + + final iconOffset:Int = 26; + if (!healthBar.leftToRight) + { + iconP1.x = healthBar.barCenter + (150 * iconP1.scale.x - 150) / 2 - iconOffset; + iconP2.x = healthBar.barCenter - (150 * iconP2.scale.x) / 2 - iconOffset * 2; + } + else + { + iconP1.x = healthBar.barCenter - (150 * iconP2.scale.x) / 2 - iconOffset * 2; + iconP2.x = healthBar.barCenter + (150 * iconP1.scale.x - 150) / 2 - iconOffset; + } + } + + public function updateIconsScale(elapsed:Float) + { + if (!updateIconScale) return; + + final mult:Float = MathUtil.decayLerp(iconP1.scale.x, 1, 18, elapsed); + iconP1.scale.set(mult, mult); + iconP1.updateHitbox(); + + final mult:Float = MathUtil.decayLerp(iconP2.scale.x, 1, 18, elapsed); + iconP2.scale.set(mult, mult); + iconP2.updateHitbox(); + + iconP1.origin.y = iconP2.origin.y = 0; + } + + public function updateIconsAnimation() + { + iconP1.updateIconAnim(healthBar.percent * 0.01); + iconP2.updateIconAnim((100 - healthBar.percent) * 0.01); + } + + public function reloadHealthBarColors() + { + var dad = parent.dad; + var boyfriend = parent.boyfriend; + if (!healthBar.leftToRight) + { + healthBar.setColors(0xFFFF0000, 0xFF66FF33); + } + else + { + healthBar.setColors(0xFF66FF33, 0xFFFF0000); + } + } + + public function flipBar() + { + healthBar.leftToRight = !healthBar.leftToRight; + iconP1.flipX = !iconP1.flipX; + iconP2.flipX = !iconP2.flipX; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + updateIconsPosition(); + updateIconsScale(elapsed); + updateIconsAnimation(); + } + + override function beatHit() + { + if (!updateIconScale) return; + + iconP1.scale.set(1.2, 1.2); + iconP2.scale.set(1.2, 1.2); + + iconP1.updateHitbox(); + iconP2.updateHitbox(); + } + + override function onCharacterChange() + { + reloadHealthBarColors(); + iconP1.changeIcon(parent.boyfriend.healthIcon); + iconP2.changeIcon(parent.dad.healthIcon); + } + + override function onHealthChange(health:Float) + { + final newPercent:Null = FlxMath.remapToRange(FlxMath.bound(healthBar.valueFunction(), healthBar.bounds.min, healthBar.bounds.max), healthBar.bounds.min, healthBar.bounds.max, 0, 100); + healthBar.percent = (newPercent != null ? newPercent : 0); + } + + override function popUpScore(daRating:funkin.game.Rating, combo:Int, note:funkin.objects.note.Note) + { + final ratingImage = daRating.image; + + final posX = FlxG.width * 0.35; + + if (ClientPrefs.hideHud) return; + + parent.scripts.call('onPopUpScore', [note, daRating, ratingGraphic, ratingNumGroup]); + + if (showRating) + { + FlxTween.cancelTweensOf(ratingGraphic, ['scale.x', 'scale.y', 'alpha']); + ratingGraphic.alpha = 1; + ratingGraphic.loadGraphic(Paths.image(ratingPrefix + ratingImage + ratingSuffix)); + ratingGraphic.screenCenter(); + ratingGraphic.x = posX - 40; + ratingGraphic.y -= 60; + ratingGraphic.x += comboOffsets[0]; + ratingGraphic.y -= comboOffsets[1]; + + if (comboTween) + { + ratingGraphic.scale.set(0.785, 0.785); + FlxTween.tween(ratingGraphic.scale, {x: 0.7, y: 0.7}, 0.5, {ease: FlxEase.expoOut}); + } + ratingGraphic.updateHitbox(); + FlxTween.tween(ratingGraphic, {alpha: 0}, 0.5, {startDelay: Conductor.stepCrotchet * 0.01, ease: FlxEase.expoOut}); + } + + if (showRatingNum) + { + for (i in ratingNumGroup) + { + if (i.alive) + { + i.kill(); + } + } + + var seperatedScore:Array = []; + + if (combo >= 1000) + { + seperatedScore.push(Math.floor(combo / 1000) % 10); + } + seperatedScore.push(Math.floor(combo / 100) % 10); + seperatedScore.push(Math.floor(combo / 10) % 10); + seperatedScore.push(combo % 10); + + var daLoop:Int = 0; + for (i in seperatedScore) + { + var numScore:FlxSprite = ratingNumGroup.recycle(FlxSprite); + FlxTween.cancelTweensOf(numScore); + + numScore.loadGraphic(Paths.image(comboPrefix + 'num' + Std.int(i) + ratingSuffix)); + numScore.alpha = 1; + numScore.screenCenter(); + numScore.x = posX + (43 * daLoop) - 90; + numScore.y += 80; + numScore.x += comboOffsets[2]; + numScore.y -= comboOffsets[3]; + + if (comboTween) + { + numScore.scale.set(0.6, 0.6); + FlxTween.cancelTweensOf(numScore, ['scale.x', 'scale.y']); + FlxTween.tween(numScore.scale, {x: 0.5, y: 0.5}, 0.5, {ease: FlxEase.expoOut}); + } + numScore.updateHitbox(); + ratingNumGroup.add(numScore); + FlxTween.tween(numScore, {alpha: 0}, 0.5, {startDelay: Conductor.stepCrotchet * 0.01, ease: FlxEase.expoOut}); + + daLoop++; + } + } + + parent.scripts.call('onPopUpScorePost', [note, daRating, ratingGraphic, ratingNumGroup]); + } + + override function cachePopUpScore() + { + var ratings = ["sick", "good", "bad", "shit"]; + if (ClientPrefs.useEpicRankings) ratings.push('epic'); + + for (rating in ratings) + { + ratingGraphic.loadGraphic(Paths.image('$ratingPrefix$rating$ratingSuffix')); + } + + for (i in 0...10) + { + Paths.image('${comboPrefix}num$i$ratingSuffix'); + } + } +} diff --git a/source/funkin/game/huds/PsychHUD.hx b/source/funkin/game/huds/PsychHUD.hx index e418e018..2dd2631a 100644 --- a/source/funkin/game/huds/PsychHUD.hx +++ b/source/funkin/game/huds/PsychHUD.hx @@ -28,6 +28,7 @@ class PsychHUD extends BaseHUD var comboPrefix:String = ""; var comboTween:Bool = true; + var _psychStyle = false; var textDivider = '•'; var showRating:Bool = ClientPrefs.showRatings; @@ -37,6 +38,12 @@ class PsychHUD extends BaseHUD var updateIconScale:Bool = true; var comboOffsets:Null> = null; // So u can overwrite the users combo offset if needed without messing with clientprefs + public function new(parent, ?psychStyle:Bool = false) + { + super(parent); + _psychStyle = psychStyle; + } + // TODO: Make combo shit change for week 6, the ground work is already there so incase someone else wants to come on in and mess w it. override function init() { diff --git a/source/funkin/states/PlayState.hx b/source/funkin/states/PlayState.hx index d3a78b1d..f65a0d04 100644 --- a/source/funkin/states/PlayState.hx +++ b/source/funkin/states/PlayState.hx @@ -756,7 +756,7 @@ class PlayState extends MusicBeatState notes = new FlxTypedGroup(); add(notes); - playHUD = new funkin.game.huds.PsychHUD(this); + playHUD = getHUD(); insert(members.indexOf(playFields), playHUD); // Data told me to do this playHUD.cameras = [camHUD]; @@ -920,6 +920,18 @@ class PlayState extends MusicBeatState var splashLayering:Array = []; + public function getHUD():BaseHUD + { + final style = ClientPrefs.hudStyle; + switch (style) + { + default: + return new funkin.game.huds.PsychHUD(this, style == 'Psych'); + case 'Classic': + return new funkin.game.huds.ClassicHUD(this); + } + } + public function generatePlayfields() { if (generatedFields) return; diff --git a/source/funkin/states/options/VisualsUISubState.hx b/source/funkin/states/options/VisualsUISubState.hx index 479eee79..f0a26243 100644 --- a/source/funkin/states/options/VisualsUISubState.hx +++ b/source/funkin/states/options/VisualsUISubState.hx @@ -14,6 +14,9 @@ class VisualsUISubState extends BaseOptionsMenu var option:Option = new Option('Hide HUD', 'If checked, hides most HUD elements.', 'hideHud', 'bool', false); addOption(option); + var option:Option = new Option('HUD Style:', "What style should the HUD use?", 'hudStyle', 'string', 'NightmareVision', ['NightmareVision', 'Classic']); + addOption(option); + var option:Option = new Option('Show Ratings', 'If checked, rating graphics will appear on your HUD.', 'showRatings', 'bool', true); addOption(option);