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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user