finalizing the dialogue system 11

more stuff and text formats!

Co-Authored-By: Ne_Eo <NeeEoo@users.noreply.github.com>
This commit is contained in:
⍚~Nex
2024-02-27 01:50:21 +01:00
co-authored by Ne_Eo
parent 0ef969db1f
commit 9ca7f01866
21 changed files with 261 additions and 111 deletions
+2 -2
View File
@@ -8,9 +8,9 @@
<!--
All positions for characters
-->
<charpos name="left" x="-500" y="184" />
<charpos name="left" x="-500" y="184" flipBubble="true" />
<charpos name="middle" x="0" y="184" />
<charpos name="right" x="500" y="184" flipBubble="true" />
<charpos name="right" x="500" y="184" />
<!--
All animations for the dialogue box
@@ -3,7 +3,7 @@
<!--
Node containing all text settings
-->
<text font="pixel.otf" x="239" y="218" width="768" color="#3f2021" size="32" antialiasing="false" borderSize="2" borderStyle="shadow" borderColor="#D89494" />
<text font="pixel.otf" x="239" y="218" width="768" color="#3f2021" size="32" antialiasing="false" borderSize="1" borderStyle="shadow" borderColor="#D89494" shadowOffsetX="2" shadowOffsetY="2"/>
<!--
All positions for characters
+1 -1
View File
@@ -1,5 +1,5 @@
<!DOCTYPE codename-engine-dialogue-character>
<character sprite="pixel/senpai" x="-392" y="-599" graphicSizex="1334" antialiasing="false" textSound="pixel/pixelText">
<anim name="normal-show" anim="Senpai Portrait Enter instance 10" fps="24" />
<anim name="normal-show" anim="Senpai Portrait Enter instance 10" fps="24" x="4.4" />
<anim name="angry-show" anim="Senpai Portrait Angry instance 10" x="-56" y="-9" fps="24" />
</character>
+7 -1
View File
@@ -8,7 +8,7 @@
<!-- Lines -->
<line char="dad">
yo its me your enemy! how are you
yo its me your <format color="#FF0000">enemy!</format> how are you
</line>
<line char="boyfriend">
shut up u stupid bitch
@@ -59,4 +59,10 @@
<line char="boyfriend">
ok now stfu and lets rap its getting annoying
</line>
<line char="girlfriend">
Wanna <format font="pixel.otf" size="10">have <format color="#33ff33">sex</format> later</format> cutie
</line>
<line char="boyfriend">
bro <format color="#FF0000">what</format>
</line>
</dialogue>
+1 -1
View File
@@ -47,7 +47,7 @@ function create() {
if(FlxG.camera._fxFadeAlpha > 0.3) swagTimer.reset();
else {
camHUD.visible = true;
self.startDialogue("songs/" + PlayState.instance.SONG.meta.name.toLowerCase() + "/creepyDialogue.xml", self.close);
self.startDialogue("assets/songs/" + PlayState.instance.SONG.meta.name.toLowerCase() + "/creepyDialogue.xml", self.close);
}
});
});
@@ -1,12 +0,0 @@
package funkin.backend.scripting.events;
import flixel.sound.FlxSound;
final class DialogueBoxSetTextEvent extends CancellableEvent
{
public var text:String;
public var speed:Float;
public var customTypeSFX:Array<FlxSound>;
}
@@ -0,0 +1,12 @@
package funkin.backend.scripting.events;
/**
* Event with random dynamic values useful for making your own custom events
*/
final class DynamicEvent extends CancellableEvent {
public var value1:Dynamic = null;
public var value2:Dynamic = null;
public var value3:Dynamic = null;
public var value4:Dynamic = null;
public var value5:Dynamic = null;
}
@@ -1,8 +1,10 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import funkin.game.cutscenes.dialogue.DialogueCharacter;
final class DialogueBoxCharPopupEvent extends CancellableEvent
{
public var char:DialogueCharacter;
public var force:Bool;
}
@@ -1,5 +1,6 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import funkin.backend.utils.XMLUtil.TextFormat;
import flixel.sound.FlxSound;
final class DialogueBoxPlayBubbleEvent extends CancellableEvent
@@ -10,6 +11,8 @@ final class DialogueBoxPlayBubbleEvent extends CancellableEvent
public var text:String;
public var format:Array<TextFormat>;
public var speed:Float;
public var customSFX:FlxSound;
@@ -0,0 +1,15 @@
package funkin.backend.scripting.events.dialogue;
import funkin.backend.utils.XMLUtil.TextFormat;
import flixel.sound.FlxSound;
final class DialogueBoxSetTextEvent extends CancellableEvent
{
public var text:String;
public var format:Array<TextFormat>;
public var speed:Null<Float>;
public var customTypeSFX:Array<FlxSound>;
}
@@ -1,4 +1,4 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import haxe.xml.Access;
@@ -1,4 +1,4 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import funkin.game.cutscenes.dialogue.DialogueCharacter.DialogueCharAnimContext;
@@ -1,4 +1,4 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import funkin.game.cutscenes.dialogue.DialogueCharacter.DialogueCharAnimContext;
@@ -1,4 +1,4 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import haxe.xml.Access;
@@ -1,4 +1,4 @@
package funkin.backend.scripting.events;
package funkin.backend.scripting.events.dialogue;
import haxe.xml.Access;
+44
View File
@@ -1,5 +1,8 @@
package funkin.backend.utils;
import flixel.text.FlxText;
import openfl.text.TextFormatAlign;
import funkin.backend.utils.XMLUtil.TextFormat;
import flixel.tweens.FlxTween;
import flixel.system.frontEnds.SoundFrontEnd;
import flixel.sound.FlxSound;
@@ -457,6 +460,47 @@ class CoolUtil
return xml.att.resolve(name);
}
/**
* Sets automatically all the compatible formats to a text.
*
* WARNING: These are dependant from the font, so if the font doesn't support for example the `bold` format it won't work!
* @param text Text to set the format for
* @param formats Array of the formats (to get the formats from a node, you can use `XMLUtil.getTextFormats(node)`)
*/
public static function autoSetFormat(text:FlxText, formats:Array<TextFormat>) {
var i = 0;
@:privateAccess
for(format in formats) {
var fmtt = format.format;
var start = i;
var end = i + format.text.length;
i = end;
if(Reflect.fields(fmtt).length == 0) continue;
var fmt = new FlxTextFormat();
fmt.format.color = Reflect.hasField(fmtt, "color") ? FlxColor.fromString(fmtt.color) : text.color;
fmt.format.font = Reflect.hasField(fmtt, "font") ? Paths.font(fmtt.font) : text.font;
fmt.format.size = Reflect.hasField(fmtt, "size") ? Std.parseInt(fmtt.size) : text.size;
fmt.format.italic = Reflect.hasField(fmtt, "italic") ? fmtt.italic == "true" : text.italic;
fmt.format.bold = Reflect.hasField(fmtt, "bold") ? fmtt.bold == "true" : text.bold;
fmt.borderColor = Reflect.hasField(fmtt, "borderColor") ? FlxColor.fromString(fmtt.borderColor) : text.borderColor;
fmt.format.align = Reflect.hasField(fmtt, "align") ? TextFormatAlign.fromString(fmtt.align) : FlxTextAlign.toOpenFL(text.alignment);
if(Reflect.hasField(fmtt, "leading")) fmt.format.leading = Std.parseInt(fmtt.leading);
if(Reflect.hasField(fmtt, "kerning")) fmt.format.kerning = fmtt.kerning == "true";
if(Reflect.hasField(fmtt, "blockIndent")) fmt.format.blockIndent = Std.parseInt(fmtt.blockIndent);
if(Reflect.hasField(fmtt, "bullet")) fmt.format.bullet = fmtt.bullet == "true";
if(Reflect.hasField(fmtt, "indent")) fmt.format.indent = Std.parseInt(fmtt.indent);
if(Reflect.hasField(fmtt, "leftMargin")) fmt.format.leftMargin = Std.parseInt(fmtt.leftMargin);
if(Reflect.hasField(fmtt, "letterSpacing")) fmt.format.letterSpacing = Std.parseFloat(fmtt.letterSpacing);
if(Reflect.hasField(fmtt, "rightMargin")) fmt.format.rightMargin = Std.parseInt(fmtt.rightMargin);
if(Reflect.hasField(fmtt, "tabStops")) fmt.format.tabStops = [for(x in cast(fmtt.tabStops, String).split(",")) Std.parseInt(x)];
if(Reflect.hasField(fmtt, "underline")) fmt.format.underline = fmtt.underline == "true";
text.addFormat(fmt, start, end);
}
return text;
}
/**
* Loads an animated graphic, and automatically animates it.
* @param spr Sprite to load the graphic for
+49
View File
@@ -5,9 +5,13 @@ import funkin.backend.system.ErrorCode;
import funkin.backend.FunkinSprite.XMLAnimType;
import flixel.util.FlxColor;
import haxe.xml.Access;
import flixel.util.typeLimit.OneOfTwo;
import funkin.backend.system.interfaces.IOffsetCompatible;
using StringTools;
typedef TextFormat = { text:String, format:Dynamic }
/**
* Class made to make XML parsing easier.
*/
@@ -279,6 +283,51 @@ class XMLUtil {
var v:String;
return [for(l in text.split("\n")) if ((v = l.trim()) != "") v].join("\n");
}
/**
* WARNING: will edit directly the node!
*/
public static function fixSpacingInNode(node:Access):Access {
var arr = [for(x in node.x) x];
for(i => n in arr) {
if(n.nodeType == PCData) {
if(i == 0) n.nodeValue = n.nodeValue.ltrim();
if(i == arr.length - 1) n.nodeValue = n.nodeValue.rtrim();
if(n.nodeValue.contains("\n")) {
var a = n.nodeValue.split("\n");
n.nodeValue = [for(i => x in a) i == 0 ? x.rtrim() : i == arr.length - 1 ? x.ltrim() : x.trim()].join("\n");
}
}
}
return node;
}
public static function getTextFormats(_node:OneOfTwo<Xml, Access>, currentFormat:Dynamic = null, parsedSegments:Array<TextFormat> = null):Array<TextFormat> {
var node:Xml = cast _node;
if (currentFormat == null)
currentFormat = {};
if (parsedSegments == null)
parsedSegments = [];
for (child in node) {
switch (child.nodeType) {
case Element:
if (child.nodeName == "format") {
var format:Dynamic = Reflect.copy(currentFormat);
@:privateAccess for (key => name in child.attributeMap) {
Reflect.setField(format, key, name);
}
getTextFormats(child, format, parsedSegments);
}
case PCData:
parsedSegments.push({ text: child.nodeValue, format: Reflect.copy(currentFormat) });
default:
// Ignore other node types
}
}
return parsedSegments;
}
}
typedef AnimData = {
+60 -58
View File
@@ -23,82 +23,84 @@ class SplashGroup extends FlxTypedGroup<FunkinSprite> {
* Creates a new Splash group
* @param path Path to the splash data (xml)
*/
public function new(path) {
public function new(path:String) {
super();
try {
xml = new Access(Xml.parse(Assets.getText(path)).firstElement());
if (!xml.has.sprite) throw "The <splash> element requires a sprite attribute.";
var splashSprite = new FunkinSprite();
splashSprite.antialiasing = true;
splashSprite.active = splashSprite.visible = false;
splashSprite.loadSprite(Paths.image(xml.att.sprite));
/**
* ANIMATIONS
*/
for(strum in xml.nodes.strum) {
var id:Null<Int> = Std.parseInt(strum.att.id);
if (id != null) {
animationNames[id] = [];
for(anim in strum.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
animationNames[id].push(anim.att.name);
}
}
}
if (animationNames.length <= 0)
animationNames.push([]);
for(anim in xml.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splashSprite, anim, false);
for(a in animationNames) {
if (a == null) continue;
a.push(anim.att.name);
}
}
/**
* END OF ANIMATIONS
*/
splashSprite.animation.finishCallback = function(name) {
splashSprite.active = splashSprite.visible = false;
};
if (xml.has.scale) splashSprite.scale.scale(Std.parseFloat(xml.att.scale).getDefault(1));
if (xml.has.alpha) splashSprite.alpha = Std.parseFloat(xml.att.alpha).getDefault(1);
if (xml.has.antialiasing) splashSprite.antialiasing = xml.att.antialiasing == "true";
add(splashSprite);
for (i in 0...7) {
// make 7 additional splashes
var spr = FunkinSprite.copyFrom(splashSprite);
spr.animation.finishCallback = function(name) {
spr.active = spr.visible = false;
};
add(spr);
}
var splash = createSplash(xml.att.sprite);
setupAnims(xml, splash);
pregenerateSplashes(splash);
add(splash);
// immediatly draw once and put image in GPU to prevent freezes
// TODO: change to graphics cache
splashSprite.drawComplex(FlxG.camera);
} catch(e) {
splash.drawComplex(FlxG.camera);
} catch(e:Dynamic) {
Logs.trace('Couldn\'t parse splash data for "${path}": ${e.toString()}', ERROR);
valid = false;
}
maxSize = 8;
}
function createSplash(imagePath:String) {
var splash = new FunkinSprite();
splash.antialiasing = true;
splash.active = splash.visible = false;
splash.loadSprite(Paths.image(imagePath));
if (xml.has.scale) splash.scale.scale(Std.parseFloat(xml.att.scale).getDefault(1));
if (xml.has.alpha) splash.alpha = Std.parseFloat(xml.att.alpha).getDefault(1);
if (xml.has.antialiasing) splash.antialiasing = xml.att.antialiasing == "true";
return splash;
}
function setupAnims(xml:Access, splash:FunkinSprite) {
for(strum in xml.nodes.strum) {
var id:Null<Int> = Std.parseInt(strum.att.id);
if (id != null) {
animationNames[id] = [];
for(anim in strum.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splash, anim, false);
animationNames[id].push(anim.att.name);
}
}
}
// if (animationNames.length <= 0)
// animationNames.push([]);
for(anim in xml.nodes.anim) {
if (!anim.has.name) continue;
XMLUtil.addXMLAnimation(splash, anim, false);
for(a in animationNames) {
if (a == null) continue;
a.push(anim.att.name);
}
}
splash.animation.finishCallback = function(name:String) {
splash.active = splash.visible = false;
};
}
function pregenerateSplashes(splash:FunkinSprite) {
// make 7 additional splashes
for(i in 0...7) {
var spr = FunkinSprite.copyFrom(splash);
spr.animation.finishCallback = function(name:String) {
spr.active = spr.visible = false;
};
add(spr);
}
}
public function getSplashAnim(id:Int):String {
if (animationNames.length <= 0) return null;
id %= animationNames.length;
if (animationNames[id] == null) return null;
if (animationNames[id].length <= 0) return null;
return animationNames[id][FlxG.random.int(0, animationNames[id].length-1)];
if (animationNames[id] == null || animationNames[id].length <= 0) return null;
return animationNames[id][FlxG.random.int(0, animationNames[id].length - 1)];
}
var __splash:FunkinSprite;
@@ -1,7 +1,9 @@
package funkin.game.cutscenes;
import funkin.backend.utils.FunkinParentDisabler;
import funkin.backend.scripting.events.*;
import funkin.backend.scripting.events.dialogue.*;
import funkin.backend.scripting.events.CancellableEvent;
import funkin.backend.scripting.events.DynamicEvent;
import funkin.backend.scripting.Script;
import flixel.sound.FlxSound;
import funkin.game.cutscenes.dialogue.*;
@@ -49,7 +51,7 @@ class DialogueCutscene extends Cutscene {
public override function create() {
super.create();
add(parentDisabler = new FunkinParentDisabler());
add(parentDisabler = new FunkinParentDisabler()); // MESS WITH THIS IN SCRIPTS TO RESUME PLAYSTATE'S TWEENS!! - Nex
try {
var event = EventManager.get(DialogueStructureEvent).recycle(dialogueData);
event.dialogueData = new Access(Xml.parse(Assets.getText(dialoguePath)).firstElement());
@@ -64,7 +66,7 @@ class DialogueCutscene extends Cutscene {
Logs.trace('2 dialogue characters share the same name (${char.att.name}, ${char.att.name}). The old character has been replaced.');
var leChar:DialogueCharacter = new DialogueCharacter(char.att.name, char.getAtt('position').getDefault('default'));
if(char.has.defaultAnim) leChar.defaultAnim = char.getAtt('defaultAnim');
if(char.has.defaultAnim) leChar.defaultAnim = char.att.defaultAnim;
add(charMap[char.att.name] = leChar);
}
@@ -74,26 +76,28 @@ class DialogueCutscene extends Cutscene {
// Add lines
for(node in dialogueData.nodes.line) {
var formats = XMLUtil.getTextFormats(XMLUtil.fixSpacingInNode(node));
var volume:Null<Float> = 0.8;
var line:DialogueLine = {
text: XMLUtil.fixXMLText(node.innerHTML),
text: [for(x in formats) x.text].join(""),
format: formats,
char: node.getAtt('char').getDefault('boyfriend'),
bubble: node.getAtt('bubble').getDefault('normal'),
callback: node.getAtt('callback'),
changeDefAnim: node.getAtt('changeDefAnim'),
speed: node.has.speed ? Std.parseFloat(node.att.speed).getDefault(0.05) : 0.05,
speed: Std.parseFloat(node.getAtt("speed")).getDefault(0.05),
musicVolume: node.has.musicVolume ? (volume = Std.parseFloat(node.att.speed).getDefault(0.8)) : null,
changeMusic: node.has.changeMusic ? FlxG.sound.load(Paths.music(node.getAtt('changeMusic')), volume, true) : null,
playSound: node.has.playSound ? FlxG.sound.load(Paths.sound(node.getAtt('playSound'))) : null,
nextSound: node.has.nextSound ? FlxG.sound.load(Paths.music(node.getAtt('nextSound'))) : null,
changeMusic: node.has.changeMusic ? FlxG.sound.load(Paths.music(node.att.changeMusic), volume, true) : null,
playSound: node.has.playSound ? FlxG.sound.load(Paths.sound(node.att.playSound)) : null,
nextSound: node.has.nextSound ? FlxG.sound.load(Paths.music(node.att.nextSound)) : null,
textSound: null
};
if(node.has.textSound) line.textSound = FlxG.sound.load(Paths.sound(node.getAtt('textSound')));
if(node.has.textSound) line.textSound = FlxG.sound.load(Paths.sound(node.att.textSound));
else if(!useDef) {
var char:DialogueCharacter = charMap[line.char];
if(char != null && char.charData != null && char.charData.has.textSound)
line.textSound = FlxG.sound.load(Paths.sound(char.charData.getAtt("textSound")));
line.textSound = FlxG.sound.load(Paths.sound(char.charData.att.textSound));
}
dialogueLines.push(line);
@@ -107,6 +111,7 @@ class DialogueCutscene extends Cutscene {
next(true);
} catch(e) {
Logs.trace('Error while loading dialogue at ${dialoguePath}: ${e.toString()}', ERROR);
trace(CoolUtil.getLastExceptionStack());
close();
}
dialogueScript.call("postCreate");
@@ -122,7 +127,6 @@ class DialogueCutscene extends Cutscene {
dialogueScript.call("update", [elapsed]);
if(controls.ACCEPT) {
@:privateAccess
if(dialogueBox.dialogueEnded) next();
else dialogueBox.text.skip();
}
@@ -134,8 +138,9 @@ class DialogueCutscene extends Cutscene {
public var canProceed:Bool = true;
public function next(playFirst:Bool = false) {
var event = EventManager.get(DynamicEvent).recycle(playFirst);
dialogueScript.call("next", [playFirst]);
if(!canProceed) return;
if(event.cancelled || !canProceed) return;
if ((curLine = dialogueLines.shift()) == null) {
if(lastLine != null && dialogueBox.hasAnimation(lastLine.bubble + "-close")) {
@@ -148,7 +153,10 @@ class DialogueCutscene extends Cutscene {
return;
}
for(k=>c in charMap)
if (curLine.callback != null)
dialogueScript.call(curLine.callback, [playFirst]);
for (k=>c in charMap)
if (k != curLine.char)
c.hide();
@@ -160,7 +168,7 @@ class DialogueCutscene extends Cutscene {
}
var finalSuffix:String = playFirst && dialogueBox.hasAnimation(curLine.bubble + "-firstOpen") ? "-firstOpen" : dialogueBox.hasAnimation(curLine.bubble + "-open") ? "-open" : "";
dialogueBox.playBubbleAnim(curLine.bubble, finalSuffix, curLine.text, curLine.speed, curLine.nextSound, curLine.textSound != null ? [curLine.textSound] : null, finalSuffix == "-firstOpen" || finalSuffix == "-open", !playFirst);
dialogueBox.playBubbleAnim(curLine.bubble, finalSuffix, curLine.text, curLine.format, curLine.speed, curLine.nextSound, curLine.textSound != null ? [curLine.textSound] : null, finalSuffix == "-firstOpen" || finalSuffix == "-open", !playFirst);
if(curLine.playSound != null) curLine.playSound.play();
if(curLine.changeMusic != null) {
@@ -196,6 +204,7 @@ class DialogueCutscene extends Cutscene {
typedef DialogueLine = {
var text:String;
var format:Array<XMLUtil.TextFormat>;
var char:String;
var bubble:String;
var callback:String;
@@ -1,13 +1,14 @@
package funkin.game.cutscenes.dialogue;
import funkin.backend.scripting.events.*;
import funkin.backend.scripting.events.dialogue.*;
import funkin.backend.scripting.events.PlayAnimEvent;
import funkin.backend.scripting.events.PlayAnimEvent.PlayAnimContext;
import funkin.backend.scripting.events.CancellableEvent;
import funkin.backend.scripting.Script;
import flixel.sound.FlxSound;
import flixel.addons.text.FlxTypeText;
import flixel.text.FlxText;
import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import haxe.xml.Access;
class DialogueBox extends FunkinSprite {
@@ -72,7 +73,7 @@ class DialogueBox extends FunkinSprite {
textNode.has.width ? Std.parseInt(textNode.att.width).getDefault(FlxG.width) : FlxG.width, "");
text.color = textNode.getAtt("color").getColorFromDynamic().getDefault(0xFF000000);
text.size = Std.parseInt(textNode.att.size).getDefault(20);
text.font = Paths.font('${textNode.getAtt("font").getDefault("vcr.ttf")}');
text.font = Paths.font(textNode.getAtt("font").getDefault("vcr.ttf"));
text.antialiasing = textNode.getAtt("antialiasing").getDefault("false") == "true";
if(textNode.has.borderStyle) {
text.borderStyle = switch(textNode.att.borderStyle.trim().toLowerCase()) {
@@ -81,6 +82,9 @@ class DialogueBox extends FunkinSprite {
case "outline_fast": OUTLINE_FAST;
default: OUTLINE;
}
text.borderQuality = Std.parseFloat(textNode.getAtt("borderQuality")).getDefault(1);
text.shadowOffset.x = Std.parseFloat(textNode.getAtt("shadowOffsetX")).getDefault(1);
text.shadowOffset.y = Std.parseFloat(textNode.getAtt("shadowOffsetY")).getDefault(1);
text.borderSize = Std.parseFloat(textNode.getAtt("borderSize")).getDefault(1);
text.borderColor = textNode.getAtt("borderColor").getColorFromDynamic().getDefault(0xFFFFFFFF);
}
@@ -112,29 +116,31 @@ class DialogueBox extends FunkinSprite {
}
public function popupChar(char:DialogueCharacter, force:Bool = false) {
var event = EventManager.get(DialogueBoxCharPopupEvent).recycle(char);
var event = EventManager.get(DialogueBoxCharPopupEvent).recycle(char, force);
dialogueBoxScript.call("popupChar", [event]);
if (event.cancelled || event.char == null || !active) return;
var pos = positions[event.char.positionName];
if (pos == null) return;
event.char.show((FlxG.width / 2) + pos.x, FlxG.height - pos.y, null, force);
event.char.show((FlxG.width / 2) + pos.x, FlxG.height - pos.y, null, event.force);
flipX = pos.flipBubble;
dialogueBoxScript.call("postPopupChar", [event]);
}
public function playBubbleAnim(bubble:String, suffix:String = '', text:String = '', speed:Float = 0.05, ?customSFX:FlxSound, ?customTypeSFX:Array<FlxSound>, setTextAfter:Bool = false, allowDefault:Bool = true) {
var event = EventManager.get(DialogueBoxPlayBubbleEvent).recycle(bubble, suffix, text, speed, customSFX, customTypeSFX, setTextAfter, allowDefault);
public function playBubbleAnim(bubble:String, suffix:String = '', text:String = '', ?format:Array<XMLUtil.TextFormat>, speed:Float = 0.05, ?customSFX:FlxSound, ?customTypeSFX:Array<FlxSound>, setTextAfter:Bool = false, allowDefault:Bool = true) {
var event = EventManager.get(DialogueBoxPlayBubbleEvent).recycle(bubble, suffix, text, format, speed, customSFX, customTypeSFX, setTextAfter, allowDefault);
dialogueBoxScript.call("playBubbleAnim", [event]);
if(event.cancelled) return;
if(event.customSFX != null) event.customSFX.play();
else if(event.allowDefault) FlxG.sound.play(nextSFX);
var idk:Void->Void = () -> {
if(text != null && text.trim().length > 0) setText(event.text, event.speed, event.customTypeSFX);
if(text != null && text.trim().length > 0) startText(event.text, event.format, event.speed, event.customTypeSFX);
else dialogueEnded = true;
}
dialogueEnded = false;
this.text.resetText('');
resetText();
var anim:String = event.bubble + event.suffix;
if(hasAnimation(anim)) playAnim(anim, true);
if(!event.setTextAfter) idk();
@@ -148,16 +154,30 @@ class DialogueBox extends FunkinSprite {
dialogueBoxScript.call("postPlayBubbleAnim", [event]);
}
public function setText(text:String, speed:Float = 0.05, ?customTypeSFX:Array<FlxSound>) {
var event = EventManager.get(DialogueBoxSetTextEvent).recycle(text, speed, customTypeSFX);
dialogueBoxScript.call("setText", [event]);
public function resetText(text:String = '', ?formats:Array<XMLUtil.TextFormat>, ?event:DialogueBoxSetTextEvent) {
if(event == null) event = EventManager.get(DialogueBoxSetTextEvent).recycle(text, formats, null, null);
dialogueBoxScript.call("resetText", [event]);
if(event.cancelled) return;
this.text.clearFormats();
if(formats != null)
this.text.autoSetFormat(formats);
this.text.resetText(event.text);
dialogueBoxScript.call("postResetText");
}
public function startText(text:String = '', ?format:Array<XMLUtil.TextFormat>, speed:Float = 0.05, ?customTypeSFX:Array<FlxSound>) {
var event = EventManager.get(DialogueBoxSetTextEvent).recycle(text, format, speed, customTypeSFX);
dialogueBoxScript.call("startText", [event]);
if(event.cancelled) return;
resetText(event.text, event.format, event);
this.text.sounds = event.customTypeSFX != null ? event.customTypeSFX : defaultTextTypeSFX;
this.text.delay = event.speed;
this.text.start(event.speed, true);
this.text.completeCallback = () -> dialogueEnded = true;
dialogueBoxScript.call("postStartText");
}
public override function destroy() {
@@ -1,7 +1,7 @@
package funkin.game.cutscenes.dialogue;
import funkin.backend.scripting.events.*;
import funkin.backend.scripting.events.PlayAnimEvent.PlayAnimContext;
import funkin.backend.scripting.events.PlayAnimEvent;
import funkin.backend.scripting.events.dialogue.*;
import funkin.backend.scripting.events.CancellableEvent;
import funkin.backend.scripting.Script;
import flixel.tweens.FlxTween;