diff --git a/README.md b/README.md index 0f623784..09823177 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/TODO.md b/TODO.md index d2bc473e..66ba0373 100644 --- a/TODO.md +++ b/TODO.md @@ -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`) diff --git a/assets/data/dialogue/boxes/hating-simulator.hx b/assets/data/dialogue/boxes/hating-simulator.hx new file mode 100644 index 00000000..24aa06fd --- /dev/null +++ b/assets/data/dialogue/boxes/hating-simulator.hx @@ -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); +} \ No newline at end of file diff --git a/assets/data/dialogue/boxes/hating-simulator.xml b/assets/data/dialogue/boxes/hating-simulator.xml index 5e9e6595..34828b61 100644 --- a/assets/data/dialogue/boxes/hating-simulator.xml +++ b/assets/data/dialogue/boxes/hating-simulator.xml @@ -1,21 +1,21 @@ - + - + - + - + \ No newline at end of file diff --git a/assets/data/dialogue/characters/senpai.xml b/assets/data/dialogue/characters/senpai.xml index 6c33e08e..a87de32a 100644 --- a/assets/data/dialogue/characters/senpai.xml +++ b/assets/data/dialogue/characters/senpai.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/assets/images/stages/school/ui/dialogueBox-evil.png b/assets/images/stages/school/ui/dialogueBox-evil.png deleted file mode 100644 index 1b99a05b..00000000 Binary files a/assets/images/stages/school/ui/dialogueBox-evil.png and /dev/null differ diff --git a/assets/images/stages/school/ui/dialogueBox-evil.xml b/assets/images/stages/school/ui/dialogueBox-evil.xml deleted file mode 100644 index 94a1fb45..00000000 --- a/assets/images/stages/school/ui/dialogueBox-evil.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/assets/images/stages/school/ui/dialogueBox-pixel.png b/assets/images/stages/school/ui/dialogueBox-pixel.png deleted file mode 100644 index fb93a114..00000000 Binary files a/assets/images/stages/school/ui/dialogueBox-pixel.png and /dev/null differ diff --git a/assets/images/stages/school/ui/dialogueBox-pixel.xml b/assets/images/stages/school/ui/dialogueBox-pixel.xml deleted file mode 100644 index e0a1070a..00000000 --- a/assets/images/stages/school/ui/dialogueBox-pixel.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/images/stages/school/ui/dialogueBox-senpaiMad.png b/assets/images/stages/school/ui/dialogueBox-senpaiMad.png deleted file mode 100644 index 4df2c855..00000000 Binary files a/assets/images/stages/school/ui/dialogueBox-senpaiMad.png and /dev/null differ diff --git a/assets/images/stages/school/ui/dialogueBox-senpaiMad.xml b/assets/images/stages/school/ui/dialogueBox-senpaiMad.xml deleted file mode 100644 index 4f247aa6..00000000 --- a/assets/images/stages/school/ui/dialogueBox-senpaiMad.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/source/funkin/backend/scripting/events/DialogueBoxCreationEvent.hx b/source/funkin/backend/scripting/events/DialogueBoxCreationEvent.hx deleted file mode 100644 index 781c5399..00000000 --- a/source/funkin/backend/scripting/events/DialogueBoxCreationEvent.hx +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/source/funkin/backend/scripting/events/DialogueBoxPlayBubbleEvent.hx b/source/funkin/backend/scripting/events/DialogueBoxPlayBubbleEvent.hx index 0613603e..0baf7a65 100644 --- a/source/funkin/backend/scripting/events/DialogueBoxPlayBubbleEvent.hx +++ b/source/funkin/backend/scripting/events/DialogueBoxPlayBubbleEvent.hx @@ -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; - public var playNext:Null; + public var setTextAfter:Bool; + + public var allowDefault:Bool; } \ No newline at end of file diff --git a/source/funkin/backend/scripting/events/DialogueCharCreationEvent.hx b/source/funkin/backend/scripting/events/DialogueCharCreationEvent.hx deleted file mode 100644 index d3694d0d..00000000 --- a/source/funkin/backend/scripting/events/DialogueCharCreationEvent.hx +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/source/funkin/game/cutscenes/DialogueCutscene.hx b/source/funkin/game/cutscenes/DialogueCutscene.hx index 18ce6e39..7daa78e6 100644 --- a/source/funkin/game/cutscenes/DialogueCutscene.hx +++ b/source/funkin/game/cutscenes/DialogueCutscene.hx @@ -16,7 +16,8 @@ class DialogueCutscene extends Cutscene { public var charMap:Map = []; public var dialogueLines:Array = []; - 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); diff --git a/source/funkin/game/cutscenes/dialogue/DialogueBox.hx b/source/funkin/game/cutscenes/dialogue/DialogueBox.hx index cb8aac13..d5614b36 100644 --- a/source/funkin/game/cutscenes/dialogue/DialogueBox.hx +++ b/source/funkin/game/cutscenes/dialogue/DialogueBox.hx @@ -13,8 +13,6 @@ import haxe.xml.Access; class DialogueBox extends FunkinSprite { public var dialogueBoxData:Access; public var positions:Map = []; - public var everPlayedAny:Bool = false; - public var finishAnimCallback:String->Void = null; public var nextSFX:String = Paths.sound('dialogue/next'); public var defaultTextTypeSFX:Array; @@ -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; - public function playBubbleAnim(bubble:String, text:String, speed:Float = 0.05, ?customSFX:FlxSound, ?customTypeSFX:Array, ?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, 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) { 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; diff --git a/source/funkin/game/cutscenes/dialogue/DialogueCharacter.hx b/source/funkin/game/cutscenes/dialogue/DialogueCharacter.hx index a7ee70ed..223d2111 100644 --- a/source/funkin/game/cutscenes/dialogue/DialogueCharacter.hx +++ b/source/funkin/game/cutscenes/dialogue/DialogueCharacter.hx @@ -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); }