2023-09-24 00:53:53 -04:00
|
|
|
package funkin.ui.charSelect;
|
|
|
|
|
|
|
|
import flixel.FlxSprite;
|
|
|
|
import flixel.FlxState;
|
|
|
|
import flixel.group.FlxSpriteGroup;
|
|
|
|
import flixel.text.FlxText;
|
|
|
|
import flixel.tweens.FlxEase;
|
|
|
|
import flixel.tweens.FlxTween;
|
|
|
|
import flixel.util.FlxColor;
|
|
|
|
import funkin.play.character.CharacterData;
|
|
|
|
import funkin.play.character.CharacterData.CharacterDataParser;
|
|
|
|
import funkin.play.components.HealthIcon;
|
|
|
|
import funkin.ui.freeplay.charselect.PlayableCharacter;
|
|
|
|
import funkin.data.freeplay.player.PlayerData;
|
|
|
|
import funkin.data.freeplay.player.PlayerRegistry;
|
|
|
|
import funkin.ui.mainmenu.MainMenuState;
|
|
|
|
|
|
|
|
using flixel.util.FlxSpriteUtil;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When you want the player to unlock a character, call `CharacterUnlockState.unlock(characterName)`.
|
|
|
|
* It handles both the act of unlocking the character and displaying the dialog.
|
|
|
|
*/
|
|
|
|
class CharacterUnlockState extends MusicBeatState
|
|
|
|
{
|
|
|
|
public var targetCharacterId:String = "";
|
|
|
|
public var targetCharacterData:Null<PlayableCharacter>;
|
|
|
|
|
|
|
|
var nextState:FlxState;
|
|
|
|
|
|
|
|
static final DIALOG_BG_COLOR:FlxColor = 0xFF000000; // Iconic
|
|
|
|
static final DIALOG_COLOR:FlxColor = 0xFF4344F6; // Iconic
|
|
|
|
static final DIALOG_FONT_COLOR:FlxColor = 0xFFFFFFFF; // Iconic
|
|
|
|
|
|
|
|
var busy:Bool = false;
|
|
|
|
|
|
|
|
public function new(targetPlayableCharacter:String, ?nextState:FlxState)
|
|
|
|
{
|
|
|
|
super();
|
|
|
|
|
|
|
|
this.targetCharacterId = targetPlayableCharacter;
|
|
|
|
this.targetCharacterData = PlayerRegistry.instance.fetchEntry(targetCharacterId);
|
|
|
|
this.nextState = nextState == null ? new MainMenuState() : nextState;
|
|
|
|
}
|
|
|
|
|
|
|
|
override function create():Void
|
|
|
|
{
|
|
|
|
super.create();
|
|
|
|
|
|
|
|
handleMusic();
|
|
|
|
|
|
|
|
bgColor = DIALOG_BG_COLOR;
|
|
|
|
|
|
|
|
var dialogContainer:FlxSpriteGroup = new FlxSpriteGroup();
|
|
|
|
add(dialogContainer);
|
|
|
|
|
|
|
|
// Build the graphic for the text...
|
|
|
|
var charName:String = targetCharacterData != null ? targetCharacterData.getName() : targetCharacterId.toTitleCase();
|
|
|
|
// var dialogText:FlxText = new FlxText(0, 0, 0, 'You can now play as $charName.\n\nCheck it out in Freeplay!');
|
|
|
|
var dialogText:FlxText = new FlxText(0, 0, 0, 'You can now play as $charName.');
|
|
|
|
dialogText.setFormat("VCR OSD Mono", 32, DIALOG_FONT_COLOR, LEFT);
|
|
|
|
|
|
|
|
// THEN we can size the dialog to match...
|
|
|
|
var dialogBG:FlxSprite = new FlxSprite(0, 0);
|
|
|
|
dialogBG.makeGraphic(Std.int(dialogText.width + 32), Std.int(dialogText.height + 32), FlxColor.TRANSPARENT);
|
|
|
|
dialogBG.drawRoundRect(0, 0, dialogBG.width, dialogBG.height, 16, 16, DIALOG_COLOR);
|
|
|
|
dialogContainer.add(dialogBG);
|
|
|
|
|
|
|
|
dialogBG.screenCenter(XY);
|
|
|
|
|
|
|
|
// THEN we can position the text inside that.
|
|
|
|
dialogText.x = dialogBG.x + 16;
|
|
|
|
dialogText.y = dialogBG.y + 16;
|
|
|
|
dialogContainer.add(dialogText);
|
|
|
|
|
|
|
|
// HealthIcon handles getting the right frames for us,
|
|
|
|
// but it has a bunch of overhead in it that makes it gross to work with outside the health bar.
|
|
|
|
var healthIconCharacterId = targetCharacterData.getOwnedCharacterIds()[0];
|
|
|
|
var baseCharacter = CharacterDataParser.fetchCharacter(healthIconCharacterId);
|
|
|
|
var healthIcon:HealthIcon = new HealthIcon(healthIconCharacterId);
|
|
|
|
@:privateAccess
|
|
|
|
healthIcon.configure(baseCharacter._data.healthIcon);
|
|
|
|
healthIcon.autoUpdate = false;
|
|
|
|
healthIcon.bopEvery = 0; // You can increase this number later once the animation is done.
|
|
|
|
healthIcon.size.set(0.5, 0.5);
|
|
|
|
healthIcon.x = dialogBG.x + 390;
|
|
|
|
healthIcon.y = dialogBG.y + 6;
|
|
|
|
healthIcon.flipX = true;
|
|
|
|
healthIcon.snapToTargetSize();
|
|
|
|
dialogContainer.add(healthIcon);
|
|
|
|
|
|
|
|
dialogContainer.scale.set(0, 0);
|
|
|
|
FlxTween.num(0.0, 1.0, 0.75,
|
|
|
|
{
|
|
|
|
ease: FlxEase.elasticOut,
|
|
|
|
}, function(curScale) {
|
|
|
|
dialogContainer.scale.set(curScale, curScale);
|
|
|
|
healthIcon.size.set(0.5 * curScale, 0.5 * curScale);
|
|
|
|
});
|
|
|
|
|
|
|
|
// performUnlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleMusic():Void
|
|
|
|
{
|
2024-09-06 19:44:33 -04:00
|
|
|
FlxG.sound.music?.stop();
|
2023-09-24 00:53:53 -04:00
|
|
|
FlxG.sound.play(Paths.sound('confirmMenu'));
|
|
|
|
}
|
|
|
|
|
|
|
|
override function update(elapsed:Float):Void
|
|
|
|
{
|
|
|
|
super.update(elapsed);
|
|
|
|
|
|
|
|
if (controls.ACCEPT || controls.BACK && !busy)
|
|
|
|
{
|
|
|
|
busy = true;
|
|
|
|
startClose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function startClose():Void
|
|
|
|
{
|
|
|
|
// Fade to black, then switch state.
|
|
|
|
FlxG.camera.fade(FlxColor.BLACK, 0.75, false, () -> {
|
|
|
|
FlxG.switchState(nextState);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|