dialogues stuff & porting WIP 7

This commit is contained in:
⍚~Nex
2024-02-24 01:56:04 +01:00
parent 06aeee975d
commit 7cc4148742
17 changed files with 132 additions and 132 deletions
-1
View File
@@ -4,7 +4,6 @@
### Mods created with beta versions of Codename may not be compatible with the release version
Known issues in the beta:
- Some options are missing
- Week 6 still have no dialogue
Build instructions are below. Press TAB on the main menu to switch mods.
+1 -1
View File
@@ -41,7 +41,7 @@
- [ ] New Switch Mod menu
- [x] Port shader camera stuff over to new flixel fork
- [ ] Add note offset
- [ ] Dialogue
- [x] Dialogue
- [ ] Finish Base Game port
- [x] Add credits
- [ ] Verbose mode (`--verbose`)
@@ -0,0 +1,61 @@
var bgFade:FlxSprite;
var hand:FlxSprite;
function postCreate() {
bgFade = new FlxSprite().makeSolid(FlxG.width + 100, FlxG.height + 100, 0xFFB3DFd8);
bgFade.screenCenter();
bgFade.scrollFactor.set();
bgFade.alpha = 0;
cutscene.insert(0, bgFade);
new FlxTimer().start(0.83, function(tmr:FlxTimer)
{
bgFade.alpha += (1 / 5) * 0.7;
if (bgFade.alpha > 0.7)
bgFade.alpha = 0.7;
}, 5);
hand = new FlxSprite(0, 600).loadGraphic(Paths.image('stages/school/ui/hand_textbox'));
hand.scale.set(4, 4);
hand.updateHitbox();
}
var finished:Bool = false;
function close(event) {
if(finished) return;
else event.cancelled = true;
cutscene.canProceed = false;
if(cutscene.curMusic != null) {
cutscene.curMusic.persist = true;
cutscene.curMusic.fadeOut(2.2, 0);
cutscene.curMusic.fadeTween.onComplete = (_) -> cutscene.curMusic.destroy();
}
for(c in cutscene.charMap) c.visible = false;
new FlxTimer().start(0.2, function(tmr:FlxTimer)
{
if (tmr.elapsedLoops <= 5) {
cutscene.dialogueBox.alpha -= 1 / 5;
cutscene.dialogueBox.text.alpha -= 1 / 5;
bgFade.alpha -= (1 / 5) * 0.7;
hand.alpha -= 1 / 5;
} else {
finished = true;
cutscene.close();
}
}, 6);
}
var time:Float = 0;
function update(elapsed:Float) {
hand.x = 1060 + Math.sin((time += elapsed) * Math.PI * 2) * 12;
hand.x -= hand.x % hand.scale.x;
hand.y -= hand.y % hand.scale.y;
}
function postPlayBubbleAnim() {
cutscene.remove(hand);
if(active && visible)
cutscene.add(hand);
}
@@ -1,21 +1,21 @@
<!DOCTYPE codename-engine-dialogue-box>
<dialoguebox sprite="pixel/dialogueBox" antialiasing="false" graphicSizex="1227" x="-43" y="-325" textSound="pixel/pixelText" nextSound="pixel/clickText" updateHitbox="true">
<dialoguebox sprite="pixel/dialogueBox" antialiasing="false" graphicSizex="1227" x="-67" y="-325" textSound="pixel/pixelText" nextSound="pixel/clickText" updateHitbox="true">
<!--
Node containing all text settings
-->
<text font="pixel.otf" x="265" 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="2" borderStyle="shadow" borderColor="#D89494" />
<!--
All positions for characters
-->
<charpos name="left" x="-500" y="184" />
<charpos name="middle" x="0" y="184" />
<charpos name="right" x="500" y="184" />
<charpos name="right" x="490" y="184" />
<!--
All animations for the dialogue box
For example, if you wanna add an "angry" animation, add an animation named "angry" (box idle), and "angry-open" (not needed, for box apparition)
-->
<anim name="normal-firstOpen" anim="Text Box Appear instance 10" fps="24" />
<anim name="angry-firstOpen" anim="Text Box Bump Appear instance 10" x="-16" y="-60" fps="24" />
<anim name="angry-firstOpen" anim="Text Box Bump Appear instance 10" x="-16" y="-59" fps="24" />
</dialoguebox>
+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="angry-show" anim="Senpai Portrait Angry instance 10" x="-56" y="-10" fps="24" />
<anim name="angry-show" anim="Senpai Portrait Angry instance 10" x="-56" y="-9" fps="24" />
</character>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="dialogueBox-evil.png">
<!-- Created with Adobe Animate version 20.0.0.17400 -->
<!-- http://www.adobe.com/products/animate.html -->
<SubTexture name="Spirit Textbox spawn instance 10000" x="0" y="0" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10001" x="0" y="0" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10002" x="259" y="0" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10003" x="259" y="0" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10004" x="0" y="155" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10005" x="0" y="155" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10006" x="259" y="155" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10007" x="259" y="155" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10008" x="0" y="310" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10009" x="0" y="310" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10010" x="259" y="310" width="249" height="145"/>
<SubTexture name="Spirit Textbox spawn instance 10011" x="259" y="310" width="249" height="145"/>
</TextureAtlas>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="dialogueBox-pixel.png">
<!-- Created with Adobe Animate version 20.0.0.17400 -->
<!-- http://www.adobe.com/products/animate.html -->
<SubTexture name="Text Box Appear instance 10000" x="0" y="0" width="249" height="144"/>
<SubTexture name="Text Box Appear instance 10001" x="259" y="0" width="249" height="144"/>
<SubTexture name="Text Box Appear instance 10002" x="0" y="154" width="249" height="144"/>
<SubTexture name="Text Box Appear instance 10003" x="259" y="154" width="249" height="144"/>
<SubTexture name="Text Box Appear instance 10004" x="259" y="154" width="249" height="144"/>
</TextureAtlas>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="dialogueBox-senpaiMad.png">
<!-- Created with Adobe Animate version 20.0.0.17400 -->
<!-- http://www.adobe.com/products/animate.html -->
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10000" x="0" y="0" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10001" x="259" y="0" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10002" x="0" y="154" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10003" x="259" y="154" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10004" x="0" y="308" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10005" x="0" y="308" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10006" x="259" y="308" width="249" height="144"/>
<SubTexture name="SENPAI ANGRY IMPACT SPEECH instance 10007" x="259" y="308" width="249" height="144"/>
</TextureAtlas>
@@ -1,11 +0,0 @@
package funkin.backend.scripting.events;
/**
* CANCEL this event to customize from 0 the creation part!
*/
final class DialogueBoxCreationEvent extends CancellableEvent
{
public var name:String;
public var textTypeSFX:String;
}
@@ -6,6 +6,8 @@ final class DialogueBoxPlayBubbleEvent extends CancellableEvent
{
public var bubble:String;
public var suffix:String;
public var text:String;
public var speed:Float;
@@ -14,5 +16,7 @@ final class DialogueBoxPlayBubbleEvent extends CancellableEvent
public var customTypeSFX:Array<FlxSound>;
public var playNext:Null<Bool>;
public var setTextAfter:Bool;
public var allowDefault:Bool;
}
@@ -1,11 +0,0 @@
package funkin.backend.scripting.events;
/**
* CANCEL this event to customize from 0 the creation part!
*/
final class DialogueCharCreationEvent extends CancellableEvent
{
public var name:String;
public var position:String;
}
@@ -16,7 +16,8 @@ class DialogueCutscene extends Cutscene {
public var charMap:Map<String, DialogueCharacter> = [];
public var dialogueLines:Array<DialogueLine> = [];
public var curLine:DialogueLine = null;
public var curLine(default, set):DialogueLine = null;
public var lastLine:DialogueLine = null;
public var dialogueBox:DialogueBox;
public var dialogueCamera:FlxCamera;
@@ -25,6 +26,11 @@ class DialogueCutscene extends Cutscene {
public static var cutscene:DialogueCutscene;
//public var dialogueScript:Script;
public function set_curLine(val:DialogueLine) {
lastLine = curLine;
return curLine = val;
}
public function new(dialoguePath:String, callback:Void->Void) {
super(callback);
this.dialoguePath = dialoguePath;
@@ -85,22 +91,30 @@ class DialogueCutscene extends Cutscene {
add(dialogueBox);
add(dialogueBox.text);
next();
next(true);
} catch(e) {
Logs.trace('Error while loading dialogue at ${dialoguePath}', ERROR);
Logs.trace('Error while loading dialogue at ${dialoguePath}: ${e.toString()}', ERROR);
close();
}
}
public override function update(elapsed:Float) {
super.update(elapsed);
if (controls.ACCEPT)
next();
if(controls.ACCEPT) next();
}
public function next() {
public var canProceed:Bool = true;
public function next(playFirst:Bool = false) {
if(!canProceed) return;
if ((curLine = dialogueLines.shift()) == null) {
close();
if(lastLine != null && dialogueBox.hasAnimation(lastLine.bubble + "-close")) {
dialogueBox.playBubbleAnim(lastLine.bubble, "-close");
dialogueBox.animation.finishCallback = (_) -> close();
} else {
FlxG.sound.play(dialogueBox.nextSFX);
close();
}
return;
}
@@ -115,7 +129,8 @@ class DialogueCutscene extends Cutscene {
dialogueBox.popupChar(char, force);
}
dialogueBox.playBubbleAnim(curLine.bubble, curLine.text, curLine.speed, curLine.nextSound, curLine.textSound != null ? [curLine.textSound] : null);
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);
if(curLine.playSound != null) curLine.playSound.play();
if(curLine.changeMusic != null) {
@@ -126,8 +141,18 @@ class DialogueCutscene extends Cutscene {
}
}
public override function close() {
var event = new CancellableEvent();
for(c in charMap) c.dialogueCharScript.call("close", [event]);
dialogueBox.dialogueBoxScript.call("close", [event]);
if(event.cancelled)
return;
super.close();
}
public override function destroy() {
if(curMusic != null) curMusic.destroy();
if(curMusic != null && !curMusic.persist) curMusic.destroy();
super.destroy();
cutscene = null;
FlxG.cameras.remove(dialogueCamera);
@@ -13,8 +13,6 @@ import haxe.xml.Access;
class DialogueBox extends FunkinSprite {
public var dialogueBoxData:Access;
public var positions:Map<String, CharPosDef> = [];
public var everPlayedAny:Bool = false;
public var finishAnimCallback:String->Void = null;
public var nextSFX:String = Paths.sound('dialogue/next');
public var defaultTextTypeSFX:Array<FlxSound>;
@@ -32,19 +30,14 @@ class DialogueBox extends FunkinSprite {
dialogueBoxScript.setParent(this);
dialogueBoxScript.load();
var event = EventManager.get(DialogueBoxCreationEvent).recycle(name, textTypeSFX);
var event = EventManager.get(DialogueBoxStructureEvent).recycle(name, textTypeSFX, null);
dialogueBoxScript.call('create', [event]);
if(event.cancelled)
return;
name = event.name;
textTypeSFX = event.textTypeSFX;
if(event.cancelled) return; // No idea the pyscho that would do this but hey, it can happen - Nex
try {
dialogueBoxData = new Access(Xml.parse(Assets.getText(Paths.xml(defPath + name))).firstElement());
var event = EventManager.get(DialogueBoxStructureEvent).recycle(name, textTypeSFX, dialogueBoxData);
event.dialogueBoxData = dialogueBoxData = new Access(Xml.parse(Assets.getText(Paths.xml(defPath + event.name))).firstElement());
dialogueBoxScript.call('structureLoaded', [event]);
if(event.cancelled)
return;
if(event.cancelled) return;
name = event.name;
textTypeSFX = event.textTypeSFX;
dialogueBoxData = event.dialogueBoxData;
@@ -60,16 +53,6 @@ class DialogueBox extends FunkinSprite {
if(dialogueBoxData.has.textSound) textTypeSFX = Paths.sound(dialogueBoxData.att.textSound);
if(dialogueBoxData.has.nextSound) nextSFX = Paths.sound(dialogueBoxData.att.nextSound);
animation.finishCallback = (name:String) -> {
if(finishAnimCallback != null) finishAnimCallback(name);
var finalPt:String;
if(name.endsWith(finalPt = "-open") || name.endsWith(finalPt = "-firstOpen")) {
playAnim(name.substr(0, name.length - finalPt.length));
setText(__nextText, __speed, __customTypeSFX);
}
}
for(pos in dialogueBoxData.nodes.charpos) {
if (!pos.has.name) continue;
positions[pos.att.name] = {
@@ -112,8 +95,7 @@ class DialogueBox extends FunkinSprite {
public override function playAnim(AnimName:String, Force:Bool = false, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
dialogueBoxScript.call("onPlayAnim", [event]);
if (event.cancelled)
return;
if(event.cancelled) return;
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
}
@@ -138,36 +120,33 @@ class DialogueBox extends FunkinSprite {
event.char.show((FlxG.width / 2) + pos.x, FlxG.height - pos.y, null, force);
}
private var __nextText:String;
private var __speed:Float;
private var __customTypeSFX:Array<FlxSound>;
public function playBubbleAnim(bubble:String, text:String, speed:Float = 0.05, ?customSFX:FlxSound, ?customTypeSFX:Array<FlxSound>, ?playNext:Bool) {
var event = EventManager.get(DialogueBoxPlayBubbleEvent).recycle(bubble, text, speed, customSFX, customTypeSFX, playNext);
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);
dialogueBoxScript.call("playBubbleAnim", [event]);
if (event.cancelled)
return;
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);
this.__nextText = event.text;
this.__speed = event.speed;
this.__customTypeSFX = event.customTypeSFX;
this.text.resetText('');
if(event.playNext || (event.playNext == null && everPlayedAny)) event.customSFX != null ? event.customSFX.play() : FlxG.sound.play(nextSFX);
if(hasAnimation('${event.bubble}-open')) playAnim('${event.bubble}-open', true);
else if(hasAnimation('${event.bubble}-firstOpen') && !everPlayedAny) playAnim('${event.bubble}-firstOpen', true);
else {
var anim:String = event.bubble + event.suffix;
if(hasAnimation(anim)) playAnim(anim, true);
if(!event.setTextAfter) idk();
else animation.finishCallback = (name:String) -> {
if(name != anim) return;
playAnim(event.bubble);
setText(__nextText, __speed, __customTypeSFX);
idk(); animation.finishCallback = null;
}
visible = true;
everPlayedAny = true;
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]);
if (event.cancelled)
return;
if(event.cancelled) return;
this.text.resetText(event.text);
this.text.sounds = event.customTypeSFX != null ? event.customTypeSFX : defaultTextTypeSFX;
@@ -27,21 +27,16 @@ class DialogueCharacter extends FunkinSprite {
dialogueCharScript.setParent(this);
dialogueCharScript.load();
var event = EventManager.get(DialogueCharCreationEvent).recycle(name, position);
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; // No idea the pyscho that would do this but hey, it can happen - Nex
name = event.name;
position = event.position;
if(event.cancelled) return;
try {
charData = new Access(Xml.parse(Assets.getText(Paths.xml(defPath + name))).firstElement());
var event = EventManager.get(DialogueCharStructureEvent).recycle(name, position, charData);
event.charData = charData = new Access(Xml.parse(Assets.getText(Paths.xml(defPath + event.name))).firstElement());
dialogueCharScript.call('structureLoaded', [event]);
if(event.cancelled)
return;
if(event.cancelled) return;
name = event.name;
this.positionName = event.position;
positionName = event.position;
charData = event.charData;
if(!charData.has.sprite) charData.x.set("sprite", name);
@@ -69,8 +64,7 @@ class DialogueCharacter extends FunkinSprite {
public override function playAnim(AnimName:String, Force:Bool = false, 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;
if(event.cancelled) return;
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
}