138 lines
5.0 KiB
Haxe
138 lines
5.0 KiB
Haxe
package funkin.game.cutscenes.dialogue;
|
|
|
|
import flixel.tweens.FlxTween;
|
|
import funkin.backend.scripting.Script;
|
|
import funkin.backend.scripting.events.PlayAnimContext;
|
|
import funkin.backend.scripting.events.PlayAnimEvent;
|
|
import funkin.backend.scripting.events.dialogue.*;
|
|
import haxe.xml.Access;
|
|
|
|
class DialogueCharacter extends FunkinSprite {
|
|
public var charData:Access;
|
|
public var curTween:FlxTween;
|
|
public var curAnimContext:DialogueCharAnimContext = NONE;
|
|
public var positionName:String;
|
|
|
|
public var finishAnimCallback:String->Void = null;
|
|
public var defaultAnim:String = 'normal';
|
|
|
|
public var defPath:String = 'dialogue/characters/';
|
|
public var dialogueCharScript:Script;
|
|
public var cutscene:DialogueCutscene = DialogueCutscene.cutscene;
|
|
|
|
public function new(name:String, position:String) {
|
|
super();
|
|
|
|
dialogueCharScript = Script.create(Paths.script('data/' + defPath + name));
|
|
dialogueCharScript.setParent(this);
|
|
dialogueCharScript.load();
|
|
|
|
var event = EventManager.get(DialogueCharStructureEvent).recycle(name, position, null);
|
|
dialogueCharScript.call('create', [event]); // Its not really create() since its inside new() but, nah, it makes no difference at least here - Nex
|
|
if(event.cancelled) return;
|
|
|
|
try {
|
|
event.charData = new Access(Xml.parse(Assets.getText(Paths.xml(defPath + event.name))).firstElement());
|
|
dialogueCharScript.call('structureLoaded', [event]);
|
|
if(event.cancelled) return;
|
|
name = event.name;
|
|
positionName = event.position;
|
|
charData = event.charData;
|
|
|
|
if(!charData.has.sprite) charData.x.set("sprite", name);
|
|
if(!charData.has.updateHitbox) charData.x.set("updateHitbox", "true");
|
|
XMLUtil.loadSpriteFromXML(this, charData, defPath, LOOP);
|
|
|
|
animation.finishCallback = (name:String) -> {
|
|
if(finishAnimCallback != null) finishAnimCallback(name);
|
|
|
|
if(name.endsWith("-show") || name == 'show') hasAnimation(defaultAnim) ? playAnim(defaultAnim, true) : animation.stop();
|
|
else if(name.endsWith("-hide") || name == 'hide') alpha = 0;
|
|
}
|
|
|
|
offset.set(x, y + height);
|
|
x = 0; y = 0;
|
|
} catch(e) {
|
|
var message:String = e.toString();
|
|
Logs.trace('Failed to load dialogue character $name: ${message}', ERROR);
|
|
dialogueCharScript.call("loadingError", [message]);
|
|
}
|
|
visible = false;
|
|
dialogueCharScript.call("postCreate");
|
|
}
|
|
|
|
public override function playAnim(AnimName:String, ?Force:Bool, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
|
|
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
|
|
dialogueCharScript.call("playAnim", [event]);
|
|
if(event.cancelled) return;
|
|
|
|
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
|
|
}
|
|
|
|
public override function beatHit(curBeat:Int) {
|
|
super.beatHit(curBeat);
|
|
dialogueCharScript.call("beatHit", [curBeat]);
|
|
}
|
|
|
|
public override function update(elapsed:Float) {
|
|
super.update(elapsed);
|
|
dialogueCharScript.call("update", [elapsed]);
|
|
}
|
|
|
|
public function show(x:Float, y:Float, ?animation:String, force:Bool = false) {
|
|
if(animation == null) animation = defaultAnim;
|
|
var lastAnimContext:DialogueCharAnimContext = force ? POPOUT : curAnimContext;
|
|
curAnimContext = POPIN;
|
|
|
|
var event = EventManager.get(DialogueCharShowEvent).recycle(x, y, animation, lastAnimContext);
|
|
dialogueCharScript.call("show", [event]);
|
|
if (event.cancelled || event.lastAnimContext == curAnimContext) return;
|
|
|
|
visible = true;
|
|
var anim:String;
|
|
if (hasAnimation(anim = '${event.animation}-show') || hasAnimation(anim = 'show')) {
|
|
playAnim(anim, true);
|
|
setPosition(event.x, event.y);
|
|
alpha = 1;
|
|
} else {
|
|
setPosition(event.x, event.y + 100);
|
|
if(curTween != null) curTween.cancel();
|
|
playAnim(event.animation, true);
|
|
alpha = 0;
|
|
curTween = FlxTween.tween(this, {alpha: 1, y: event.y}, 0.2, {ease: FlxEase.quintOut, onComplete: function(twn:FlxTween) dialogueCharScript.call("showTweenCompleted", [twn])});
|
|
}
|
|
dialogueCharScript.call("postShow", [event]);
|
|
}
|
|
|
|
public function hide(?animation:String, force:Bool = false) {
|
|
if(animation == null) animation = defaultAnim;
|
|
var lastAnimContext:DialogueCharAnimContext = force ? POPIN : curAnimContext;
|
|
curAnimContext = POPOUT;
|
|
|
|
var event = EventManager.get(DialogueCharHideEvent).recycle(animation, lastAnimContext);
|
|
dialogueCharScript.call("hide", [event]);
|
|
if (event.cancelled || event.lastAnimContext == curAnimContext) return;
|
|
|
|
var anim:String;
|
|
if(hasAnimation(anim = '${event.animation}-hide') || hasAnimation(anim = 'hide')) playAnim(anim, true);
|
|
else {
|
|
if(curTween != null) curTween.cancel();
|
|
curTween = FlxTween.tween(this, {alpha: 0, y: y + 100}, 0.2, {ease: FlxEase.quintIn, onComplete: function(twn:FlxTween) dialogueCharScript.call("hideTweenCompleted", [twn])});
|
|
}
|
|
dialogueCharScript.call("postHide", [event]);
|
|
}
|
|
|
|
override function destroy()
|
|
{
|
|
dialogueCharScript.call("destroy");
|
|
dialogueCharScript.destroy();
|
|
|
|
super.destroy();
|
|
}
|
|
}
|
|
|
|
enum abstract DialogueCharAnimContext(Int) {
|
|
var NONE = -1;
|
|
var POPIN = 0;
|
|
var POPOUT = 1;
|
|
} |