diff --git a/.vscode/settings.json b/.vscode/settings.json
index e45b72390..2f795d56e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -9,5 +9,6 @@
}
},
- "haxe.enableExtendedIndentation": true
+ "haxe.enableExtendedIndentation": true,
+ "restructuredtext.confPath": "${workspaceFolder}\\docs"
}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 16a77646f..3daafd90a 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -4,10 +4,23 @@
{
"type": "lime",
"command": "test",
+ "targetConfiguration": "Windows",
"group": {
- "kind": "build",
+ "kind": "test",
"isDefault": true
}
+ },
+ {
+ "type": "lime",
+ "command": "test",
+ "targetConfiguration": "Windows",
+ "problemMatcher": [
+ "$haxe-absolute",
+ "$haxe",
+ "$haxe-error",
+ "$haxe-trace"
+ ],
+ "label": "lime: test windows"
}
]
}
diff --git a/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.json b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.json
new file mode 100644
index 000000000..3991cb19a
--- /dev/null
+++ b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.json
@@ -0,0 +1,15 @@
+{
+ "position": [515, 370],
+ "textPos": [200, 480],
+ "scale": 5.4,
+ "antialiasing": false,
+ "singleFrame": true,
+ "doFlip": false,
+ "bgColor": [255, 255, 255],
+ "states": {
+ "normal": {
+ "open": ["Text Box Appear instance 1"],
+ "default": ["Text Box Appear instance 1"]
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.png b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.png
new file mode 100644
index 000000000..c7d88ff5f
Binary files /dev/null and b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.png differ
diff --git a/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.xml b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.xml
new file mode 100644
index 000000000..e0a1070a5
--- /dev/null
+++ b/assets/images/dialogue/boxes/dialogueBox-pixel/dialogueBox-pixel.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.json b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.json
new file mode 100644
index 000000000..8f1094cb8
--- /dev/null
+++ b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.json
@@ -0,0 +1,13 @@
+{
+ "position": [20, 370],
+ "states": {
+ "normal": {
+ "open": ["Speech Bubble Normal Open"],
+ "default": ["speech bubble normal", [-30, 0]]
+ },
+ "yell": {
+ "open": ["speech bubble loud open", [80, 140]],
+ "default": ["AHH speech bubble", [0, 80]]
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.png b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.png
new file mode 100644
index 000000000..b10d26bce
Binary files /dev/null and b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.png differ
diff --git a/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.xml b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.xml
new file mode 100644
index 000000000..367e31a45
--- /dev/null
+++ b/assets/images/dialogue/boxes/speech_bubble_talking/speech_bubble_talking.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/dialogue/portraits/bf-pixel/bf-pixel.json b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.json
new file mode 100644
index 000000000..38d46412a
--- /dev/null
+++ b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.json
@@ -0,0 +1,14 @@
+{
+ "name": "bf-pixel",
+ "expressions": {
+ "normal": "Boyfriend portrait enter"
+ },
+ "position": [630, 370],
+ "scale": 5.4,
+ "antialiasing": false,
+ "loop": false,
+
+ "sounds": ["pixelText"],
+ "soundChance": 100,
+ "soundPath": "sounds/"
+}
\ No newline at end of file
diff --git a/assets/images/dialogue/portraits/bf-pixel/bf-pixel.png b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.png
new file mode 100644
index 000000000..303914d98
Binary files /dev/null and b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.png differ
diff --git a/assets/images/dialogue/portraits/bf-pixel/bf-pixel.xml b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.xml
new file mode 100644
index 000000000..4a56a9a2e
--- /dev/null
+++ b/assets/images/dialogue/portraits/bf-pixel/bf-pixel.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/assets/images/dialogue/portraits/bf/BF_1.ogg b/assets/images/dialogue/portraits/bf/BF_1.ogg
new file mode 100644
index 000000000..12660f145
Binary files /dev/null and b/assets/images/dialogue/portraits/bf/BF_1.ogg differ
diff --git a/assets/images/dialogue/portraits/bf/BF_2.ogg b/assets/images/dialogue/portraits/bf/BF_2.ogg
new file mode 100644
index 000000000..44fc87db7
Binary files /dev/null and b/assets/images/dialogue/portraits/bf/BF_2.ogg differ
diff --git a/assets/images/dialogue/portraits/bf/BF_3.ogg b/assets/images/dialogue/portraits/bf/BF_3.ogg
new file mode 100644
index 000000000..a6c8e3a8c
Binary files /dev/null and b/assets/images/dialogue/portraits/bf/BF_3.ogg differ
diff --git a/assets/images/dialogue/portraits/bf/bf.json b/assets/images/dialogue/portraits/bf/bf.json
new file mode 100644
index 000000000..473e728f7
--- /dev/null
+++ b/assets/images/dialogue/portraits/bf/bf.json
@@ -0,0 +1,11 @@
+{
+ "name": "bf",
+ "expressions": {
+ "normal": "Normal Talk",
+ "mad": "Angry Talk",
+ "smug": "Smug Talk"
+ },
+ "position": "right",
+
+ "sounds": ["BF_1", "BF_2", "BF_3"]
+}
\ No newline at end of file
diff --git a/assets/images/dialogue/portraits/bf/bf.png b/assets/images/dialogue/portraits/bf/bf.png
new file mode 100644
index 000000000..b162efcd6
Binary files /dev/null and b/assets/images/dialogue/portraits/bf/bf.png differ
diff --git a/assets/images/dialogue/portraits/bf/bf.xml b/assets/images/dialogue/portraits/bf/bf.xml
new file mode 100644
index 000000000..d1a946d92
--- /dev/null
+++ b/assets/images/dialogue/portraits/bf/bf.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/dialogue/portraits/senpai/senpai.json b/assets/images/dialogue/portraits/senpai/senpai.json
new file mode 100644
index 000000000..b458fec0d
--- /dev/null
+++ b/assets/images/dialogue/portraits/senpai/senpai.json
@@ -0,0 +1,16 @@
+{
+ "name": "senpai",
+ "expressions": {
+ "normal": "Senpai Portrait Enter",
+ "mad": "SENPAI ANGRY IMPACT SPEECH"
+ },
+ "position": [420, 370],
+ "scale": 5.4,
+ "flipX": true,
+ "antialiasing": false,
+ "loop": false,
+
+ "sounds": ["pixelText"],
+ "soundChance": 100,
+ "soundPath": "sounds/"
+}
\ No newline at end of file
diff --git a/assets/images/dialogue/portraits/senpai/senpai.png b/assets/images/dialogue/portraits/senpai/senpai.png
new file mode 100644
index 000000000..27deb9f1b
Binary files /dev/null and b/assets/images/dialogue/portraits/senpai/senpai.png differ
diff --git a/assets/images/dialogue/portraits/senpai/senpai.xml b/assets/images/dialogue/portraits/senpai/senpai.xml
new file mode 100644
index 000000000..bfd2468ed
--- /dev/null
+++ b/assets/images/dialogue/portraits/senpai/senpai.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/assets/songs/dadbattle/dialogue.json b/assets/songs/dadbattle/dialogue.json
new file mode 100644
index 000000000..60623d63b
--- /dev/null
+++ b/assets/songs/dadbattle/dialogue.json
@@ -0,0 +1,58 @@
+{
+ "box": "speech_bubble_talking",
+ "boxState": "normal",
+ "dialogue": [
+ {
+ "portrait": "kade",
+ "expression": "normal",
+ "text": "I have no idea what Psych engine is."
+ },
+ {
+ "portrait": "bf2",
+ "text": "vine boom"
+ },
+ {
+ "portrait": "kade",
+ "text": "I really wish I didn't make engines.\nBecause I made fucking the worse\ndecision of my life."
+ },
+ {
+ "text": "Because all these engines either\nfucking suck."
+ },
+ {
+ "portrait": "bf2",
+ "text": "vine boom"
+ },
+ {
+ "portrait": "kade",
+ "text": "They copy me."
+ },
+ {
+ "portrait": "bf2",
+ "text": "vine boom"
+ },
+ {
+ "portrait": "kade",
+ "text": "Or they copy somebody else."
+ },
+ {
+ "portrait": "bf2",
+ "text": "vine boom"
+ },
+ {
+ "portrait": "kade",
+ "text": "Nobodys original."
+ },
+ {
+ "portrait": "bf2",
+ "text": "vine boom"
+ },
+ {
+ "portrait": "kade",
+ "text": "Its fucking really stupid."
+ },
+ {
+ "portrait": "bf2",
+ "text": "kade\nwtf dude"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/songs/senpai/dialogue.json b/assets/songs/senpai/dialogue.json
new file mode 100644
index 000000000..1f370dddc
--- /dev/null
+++ b/assets/songs/senpai/dialogue.json
@@ -0,0 +1,18 @@
+{
+ "box": "dialogueBox-pixel",
+ "boxState": "normal",
+ "dialogue": [
+ {
+ "portrait": "senpai",
+ "expression": "normal",
+ "text": "Ah, a new fair maiden has come in search of true love!"
+ },
+ {
+ "text": "A serenade between gentlemen shall decide where her beautiful heart shall reside."
+ },
+ {
+ "portrait": "bf-pixel",
+ "text": "Beep bo bop"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/songs/test/dialogue.json b/assets/songs/test/dialogue.json
new file mode 100644
index 000000000..a4893f047
--- /dev/null
+++ b/assets/songs/test/dialogue.json
@@ -0,0 +1,68 @@
+{
+ "box": "speech_bubble_talking",
+ "boxState": "normal",
+ "dialogue": [
+ {
+ "portrait": "bf",
+ "expression": "normal",
+ "text": "hey"
+ },
+ {
+ "portrait": "bf",
+ "expression": "normal",
+ "text": "do you know sawcon"
+ },
+ {
+ "portrait": "bf",
+ "expression": "normal",
+ "text": "whats sawcon lmao"
+ },
+ {
+ "portrait": "bf",
+ "expression": "smug",
+ "text": "sawcon deez nuts"
+ },
+ {
+ "portrait": "bf",
+ "expression": "smug",
+ "text": "idiot"
+ },
+ {
+ "portrait": "bf",
+ "expression": "mad",
+ "text": "I fucking hate you."
+ },
+ {
+ "portrait": "bf-pixel",
+ "expression": "normal",
+ "text": "I am going to kick your ass.",
+ "boxState": "yell",
+ "scale": 1.4
+ },
+ {
+ "portrait": "bf",
+ "expression": "mad",
+ "text": "Bet.",
+ "boxState": "normal",
+ "scale": 0.8
+ },
+ {
+ "portrait": "bf",
+ "expression": "smug",
+ "text": "'lololololololol' .'`?!\nline break test.`?!\ncool",
+ "speed": 10
+ },
+ {
+ "portrait": "bf",
+ "expression": "mad",
+ "text": "Shut the fuck up...\nShut the fuck up...... !!'? .''?!",
+ "boxState": "yell",
+ "speed": 0.5
+ },
+ {
+ "portrait": "bf",
+ "expression": "mad",
+ "text": "Seriously!\nI cant believe I hate you!"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index 48a3e1047..9d639ec98 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -16,6 +16,7 @@ We hope you learn something new!
:caption: Tutorials
tutorials/1-getting-started
+ tutorials/dialogue
.. Indices and tables
diff --git a/docs/tutorials/dialogue.rst b/docs/tutorials/dialogue.rst
new file mode 100644
index 000000000..16d804076
--- /dev/null
+++ b/docs/tutorials/dialogue.rst
@@ -0,0 +1,83 @@
+Dialogue
+============
+
+==================
+Creating Dialogue
+==================
+
+To add dialogue to a song, create a dialogue.json file in the songs directory.
+(``songs/tutorial/dialogue.json``)
+
+The example dialogue.json file has the following structure.
+
+.. code-block:: json
+
+ {
+ "box": "speech_bubble_talking",
+ "boxState": "normal",
+ "dialogue": [
+ {
+ "events": [],
+ "portrait": "",
+ "expression": "",
+ "text": ""
+ },
+ {
+ etc...
+ }
+ }
+
+==================
+dialogue.json
+==================
+
+A list of each value that can be used to create dialogue.
+
+:box:
+ The box to be used for the entire dialogue. *CANNOT BE CHANGED MID DIALOGUE* ``"text": ""``
+
+:boxState:
+ The *default* animation state to use for the current box. ``"boxState": ""``
+
+
+The ``dialogue`` object is where each page of the dialogue is stored.
+
+All values that can be assigned are the following:
+
+:text:
+ The text to be used for the current page of dialogue. ``"text": ""``
+
+:portrait:
+ The name of the portrait to use for the current dialogue. ``"portrait": ""``
+
+:expression:
+ The expression to use for the current portrait. ``"expression": ""``
+
+:events:
+ Events have different values depending on what event it is. ``"events": [["type", arguments], etc...]``
+
+ List of current event types:
+
+ image:
+ :file:
+ The location of the image file used.
+ *If you would like the image to be animated, this needs to be an array.
+ Formatted as follows.* ``[images/..., animation, loops]``
+
+ :x:
+ The images X position.
+
+ :y:
+ The images Y position.
+
+ :x scale:
+ The images X scale factor.
+
+ :y scale:
+ The images Y scale factor.
+
+ sound:
+ :file:
+ The location of the sound file.
+:boxState:
+ The animation state to use for the current box. ``"boxState": ""``
\ No newline at end of file
diff --git a/source/Init.hx b/source/Init.hx
index e49e83efe..c7bcc43e1 100644
--- a/source/Init.hx
+++ b/source/Init.hx
@@ -113,6 +113,7 @@ class Init extends FlxState
"Enables the custom Forever Engine titlescreen! (only effective with a restart)",
FORCED
],
+ 'Skip Cutscenes' => [false, 0, 'Skip the cutscenes in story mode. (Includes Dialogue)'],
'SM-like Judgements' => [
false,
0,
@@ -123,6 +124,7 @@ class Init extends FlxState
0,
"When enabled, displays the amount of combo breaks you have in a song."
],
+
];
public static var trueSettings:Map = [];
diff --git a/source/Paths.hx b/source/Paths.hx
index 079fb0d84..9eaa77c02 100644
--- a/source/Paths.hx
+++ b/source/Paths.hx
@@ -113,7 +113,7 @@ class Paths
inline static public function json(key:String, ?library:String)
{
- return getPath('data/$key.json', TEXT, library);
+ return getPath('songs/$key.json', TEXT, library);
}
inline static public function songJson(song:String, secondSong:String, ?library:String)
diff --git a/source/gameFolder/gameObjects/userInterface/DialogueBox.hx b/source/gameFolder/gameObjects/userInterface/DialogueBox.hx
index bd3f36815..009c0d3fa 100644
--- a/source/gameFolder/gameObjects/userInterface/DialogueBox.hx
+++ b/source/gameFolder/gameObjects/userInterface/DialogueBox.hx
@@ -1,6 +1,65 @@
package gameFolder.gameObjects.userInterface;
+import flixel.FlxBasic;
+import flixel.FlxG;
+import flixel.FlxSprite;
import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxPoint;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import gameFolder.meta.data.dependency.FNFSprite;
+import gameFolder.meta.data.font.Alphabet;
+
+typedef PortraitDataDef =
+{
+ var name:String;
+ var expressions:Array;
+ var position:Null;
+ var offset:Null>;
+ var scale:Null;
+ var antialiasing:Null;
+ var flipX:Null;
+ var loop:Null;
+
+ var sounds:Null>;
+ var soundChance:Null;
+ var soundPath:Null;
+}
+
+typedef DialogueDataDef =
+{
+ var events:Array>;
+ var portrait:String;
+ var expression:String;
+ var text:Null;
+ var boxState:Null;
+
+ var speed:Null;
+ var scale:Null;
+}
+
+typedef BoxDataDef =
+{
+ var position:Null>;
+ var textPos:Null>;
+ var scale:Null;
+ var antialiasing:Null;
+ var singleFrame:Null;
+ var doFlip:Null;
+ var bgColor:Null>;
+
+ var states:Null;
+}
+
+typedef DialogueFileDataDef =
+{
+ var box:String;
+ var boxState:Null;
+ var dialogue:Array;
+}
class DialogueBox extends FlxSpriteGroup
{
@@ -10,15 +69,477 @@ class DialogueBox extends FlxSpriteGroup
nothing yet :P
*/
- public static function createDialogue(thisDialogue:Array):DialogueBox
+ var box:FNFSprite;
+ var bgFade:FlxSprite;
+ var portrait:FNFSprite;
+ var text:FlxText;
+ var alphabetText:Alphabet;
+
+ var dialogueData:DialogueFileDataDef;
+ var portraitData:PortraitDataDef;
+ var boxData:BoxDataDef;
+
+ var curPage:Int = 0;
+ var curCharacter:String;
+ var curExpression:String;
+ var curBoxState:String;
+
+ var eventImage:Null;
+
+ public var whenDaFinish:Void->Void;
+
+ var textStarted:Bool = false;
+
+ public static function createDialogue(thisDialogue:String):DialogueBox
{
//
var newDialogue = new DialogueBox(false, thisDialogue);
return newDialogue;
}
- public function new(?talkingRight:Bool = false, ?dialogueList:Array)
+ function dialoguePath(file:String):String
+ {
+ var dialoguePath = Paths.file('assets/images/dialogue/portraits/$curCharacter/$file');
+ var truePath = Paths.file(file);
+
+ // load the json file
+ if (sys.FileSystem.exists(dialoguePath))
+ return dialoguePath;
+ else
+ return truePath;
+ }
+
+ public function new(?talkingRight:Bool = false, ?daDialogue:String)
{
super();
+
+ trace("start");
+
+ // get dialog data from dialogue.json
+ dialogueData = haxe.Json.parse(daDialogue);
+
+ dialogDataCheck();
+
+ // background fade
+ bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), FlxColor.BLACK);
+ bgFade.scrollFactor.set();
+ bgFade.alpha = 0;
+ add(bgFade);
+
+ // add the dialog box
+ box = new FNFSprite(0, 370);
+
+ // cur portrait
+ portrait = new FNFSprite(800, 160);
+
+ // thank u sammu for fixing alphabet.hx
+ // i dont wanna touch it ever
+ alphabetText = new Alphabet(100, 425, "cool", false, true, 0.7);
+
+ // text
+ text = new FlxText(100, 480, 1000, "", 35);
+ text.color = FlxColor.BLACK;
+ text.visible = false;
+
+ updateDialog(true);
+
+ // add stuff
+ add(portrait);
+ add(box);
+ add(text);
+
+ add(alphabetText);
+
+ // skip text
+ var skipText = new FlxText(100, 670, 1000, "PRESS SHIFT TO SKIP", 20);
+ skipText.alignment = FlxTextAlign.CENTER;
+
+ skipText.borderStyle = FlxTextBorderStyle.OUTLINE;
+ skipText.borderColor = FlxColor.BLACK;
+ skipText.borderSize = 3;
+
+ skipText.screenCenter(X);
+ add(skipText);
+ }
+
+ function updateDialog(force:Bool = false)
+ {
+ // set current portrait
+ updateTextBox(force);
+ updatePortrait(force);
+ updateEvents(force);
+
+ var pageData = dialogueData.dialogue[curPage];
+
+ var startText:Void->Void = function()
+ {
+ // Text update
+ var textToDisplay = "lol u need text for dialog";
+
+ if (pageData.text != null)
+ textToDisplay = pageData.text;
+
+ alphabetText.startText(textToDisplay, true);
+ }
+
+ // change speed
+ if (pageData.speed != null)
+ alphabetText.textSpeed = 0.06 / pageData.speed;
+ else
+ alphabetText.textSpeed = 0.06;
+
+ // change size
+ if (pageData.scale != null)
+ alphabetText.textSize = 0.7 * pageData.scale;
+ else
+ alphabetText.textSize = 0.7;
+
+ // If no text has shown up yet, we need to wait a moment
+ if (textStarted == false)
+ {
+ // Set the text to nothing for now
+ alphabetText.startText('', true);
+ // To prevent awkward text not against a dialogue background, a quick fix is to delay the initial text
+ new FlxTimer().start(0.375, function(tmr:FlxTimer)
+ {
+ textStarted = true;
+ startText();
+ });
+ }
+ // If the text has started, build the text
+ else
+ startText();
+ }
+
+ function updateTextBox(force:Bool = false)
+ {
+ var curBox = dialogueData.box;
+ var newState = dialogueData.dialogue[curPage].boxState;
+
+ if (force && newState == null)
+ newState = dialogueData.boxState;
+
+ if (newState == null)
+ return;
+
+ if (curBoxState != newState || force)
+ {
+ curBoxState = newState;
+
+ // get the path to the json
+ var boxJson = Paths.file('images/dialogue/boxes/$curBox/$curBox.json');
+
+ // load the json and sprite
+ boxData = haxe.Json.parse(sys.io.File.getContent(boxJson));
+ box.frames = Paths.getSparrowAtlas('dialogue/boxes/$curBox/$curBox');
+
+ // get the states sectioon
+ var curStateData = Reflect.field(boxData.states, curBoxState);
+
+ if (curStateData == null)
+ return;
+
+ // default and open animations
+ var defaultAnim:Array = Reflect.field(curStateData, "default");
+ var openAnim:Array = Reflect.field(curStateData, "open");
+
+ // make sure theres atleast a offset if things are null
+ if (defaultAnim[1] == null)
+ defaultAnim[1] = [0, 0];
+
+ if (openAnim[1] == null)
+ openAnim[1] = [0, 0];
+
+ // check if single frame
+ if (boxData.singleFrame == null)
+ boxData.singleFrame = false;
+
+ // do flip
+ if (boxData.doFlip == null)
+ boxData.doFlip = true;
+
+ if (boxData.bgColor != null)
+ {
+ var colorArray = boxData.bgColor;
+ var newColor = FlxColor.fromRGB(colorArray[0], colorArray[1], colorArray[2]);
+
+ bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), newColor);
+ bgFade.scrollFactor.set();
+ bgFade.alpha = 0;
+ add(bgFade);
+ }
+
+ // add the animations
+ box.animation.addByPrefix('normal', defaultAnim[0], 24, true);
+ box.addOffset('normal', defaultAnim[1][0], defaultAnim[1][1]);
+
+ box.animation.addByPrefix('normalOpen', openAnim[0], 24, false);
+ box.addOffset('normalOpen', openAnim[1][0], openAnim[1][1]);
+
+ // if the box doesnt have a position set it to 0 0
+ if (boxData.position == null)
+ boxData.position = [0, 0];
+
+ box.x = boxData.position[0];
+ box.y = boxData.position[1];
+
+ // other stuff
+ if (boxData.scale == null)
+ boxData.scale = 1;
+
+ if (boxData.antialiasing == null)
+ boxData.antialiasing = true;
+
+ box.scale = new FlxPoint(boxData.scale, boxData.scale);
+ box.antialiasing = boxData.antialiasing;
+
+ if (boxData.textPos != null)
+ {
+ text.x = boxData.textPos[0];
+ text.y = boxData.textPos[1];
+ }
+
+ box.playAnim('normalOpen');
+ }
+ }
+
+ function updatePortrait(force:Bool = false)
+ {
+ var newChar = dialogueData.dialogue[curPage].portrait;
+
+ if (curCharacter != newChar || force)
+ {
+ if (newChar != null)
+ {
+ // made the curCharacter the new character
+ curCharacter = newChar;
+ var portraitJson = Paths.file('images/dialogue/portraits/$curCharacter/$curCharacter.json');
+
+ // load the json file
+ if (sys.FileSystem.exists(portraitJson))
+ {
+ portraitData = haxe.Json.parse(sys.io.File.getContent(portraitJson));
+ portrait.frames = Paths.getSparrowAtlas('dialogue/portraits/$curCharacter/$curCharacter');
+ }
+
+ // check if the animation loops for the talking anim lol
+ var loop = true;
+ if (portraitData.loop != null)
+ loop = portraitData.loop;
+
+ // loop through the expressions and add the to the list of expressions
+ for (n in Reflect.fields(portraitData.expressions))
+ {
+ var curAnim = Reflect.field(portraitData.expressions, n);
+ var animName = n;
+
+ portrait.animation.addByPrefix(animName, curAnim, 24, loop);
+ }
+
+ // check for null values
+ if (portraitData.scale == null)
+ portraitData.scale = 1;
+
+ if (portraitData.antialiasing == null)
+ portraitData.antialiasing = true;
+
+ // change some smaller values
+ portrait.scale.set(portraitData.scale, portraitData.scale);
+ portrait.antialiasing = portraitData.antialiasing;
+
+ // position and flip stuff
+ // honestly
+ var newX = 850;
+ var newY = 160;
+ var enterX = -20;
+ var newFlip = false;
+
+ if (Std.is(portraitData.position, String))
+ {
+ switch (portraitData.position)
+ {
+ case "left":
+ newX = 10;
+ enterX = -enterX;
+ newFlip = true;
+ case "middle":
+ newX = 400;
+ }
+ }
+ else if (Std.is(portraitData.position, Array))
+ {
+ if (portraitData.flipX)
+ enterX = -enterX;
+
+ newX = portraitData.position[0];
+ newY = portraitData.position[1];
+ }
+
+ if (portraitData.offset == null)
+ portraitData.offset = [0, 0];
+
+ newX -= portraitData.offset[0];
+ newY -= portraitData.offset[1];
+
+ portrait.x = newX - enterX;
+ portrait.y = newY;
+
+ // flip
+ if (portraitData.flipX != null)
+ newFlip = portraitData.flipX;
+
+ portrait.flipX = newFlip;
+
+ // update bloops
+ if (portraitData.sounds != null)
+ {
+ if (portraitData.soundPath != null)
+ alphabetText.beginPath = "assets/" + portraitData.soundPath;
+ else
+ alphabetText.beginPath = 'assets/images/dialogue/portraits/$curCharacter/';
+
+ alphabetText.soundChoices = portraitData.sounds;
+
+ if (portraitData.soundChance != null)
+ alphabetText.soundChance = portraitData.soundChance;
+ else
+ alphabetText.soundChance = 40;
+ }
+ else
+ alphabetText.soundChance = 0;
+
+ // flip check
+ if (boxData.doFlip == true)
+ box.flipX = newFlip;
+
+ // this causes problems, and i know exactly what the problem is... i just cant fix it
+ // basically i need to get rid of the last tween before doing a new one, or else the portraits slide around all over the place
+ // ngl its kinda funny
+ FlxTween.tween(portrait, {x: newX + enterX}, 0.2, {ease: FlxEase.quadInOut});
+ }
+ }
+
+ // change expressions
+ var newExpression = dialogueData.dialogue[curPage].expression;
+ if (newExpression != null)
+ curExpression = newExpression;
+
+ portrait.animation.play(curExpression);
+ }
+
+ function runEvent(eventArray:Array)
+ {
+ var event = eventArray[0];
+
+ switch (event)
+ {
+ case "image":
+ var _sprite:Dynamic = eventArray[1];
+ var _x = eventArray[2];
+ var _y = eventArray[3];
+ var _scaleX = eventArray[4];
+ var _scaleY = eventArray[5];
+
+ trace(Paths.file(_sprite));
+
+ eventImage = new FlxSprite(_x, _y);
+
+ if (Std.is(_sprite, Array))
+ {
+ eventImage.frames = Paths.getSparrowAtlas(_sprite[0]);
+
+ eventImage.animation.addByPrefix("anim", _sprite[1], 24, _sprite[2]);
+ eventImage.animation.play("anim");
+ }
+ else
+ {
+ eventImage.loadGraphic(Paths.file(_sprite + ".png"));
+ }
+
+ eventImage.scale.set(_scaleX, _scaleY);
+ add(eventImage);
+
+ case "sound":
+ var _sound = eventArray[1] + "." + Paths.SOUND_EXT;
+
+ trace(Paths.file(_sound));
+
+ FlxG.sound.play(Paths.file(_sound));
+ }
+ }
+
+ function updateEvents(force:Bool = false)
+ {
+ var curEvents = dialogueData.dialogue[curPage].events;
+
+ if (eventImage != null)
+ eventImage.destroy();
+
+ // do da current vent
+ if (curEvents == null)
+ return;
+
+ for (event in curEvents)
+ {
+ trace(event);
+ runEvent(event);
+ }
+ }
+
+ // mario
+ function closeDialog()
+ {
+ whenDaFinish();
+ alphabetText.playSounds = false;
+ kill();
+ }
+
+ function dialogDataCheck()
+ {
+ var tisOkay = true;
+
+ if (dialogueData.box == null)
+ tisOkay = false;
+ if (dialogueData.dialogue == null)
+ tisOkay = false;
+
+ if (!tisOkay)
+ closeDialog();
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (box.animation.finished)
+ {
+ if (boxData.singleFrame != true)
+ box.playAnim('normal');
+
+ text.visible = true;
+ }
+
+ portrait.animation.paused = alphabetText.finishedLine;
+ if (portrait.animation.paused)
+ portrait.animation.finish();
+
+ bgFade.alpha += 0.02;
+ if (bgFade.alpha > 0.6)
+ bgFade.alpha = 0.6;
+
+ if (FlxG.keys.justPressed.SHIFT)
+ closeDialog();
+
+ if (FlxG.keys.justPressed.ANY && textStarted)
+ {
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+
+ curPage += 1;
+
+ if (curPage == dialogueData.dialogue.length)
+ closeDialog()
+ else
+ updateDialog();
+ }
+
+ super.update(elapsed);
}
}
diff --git a/source/gameFolder/meta/data/font/Alphabet.hx b/source/gameFolder/meta/data/font/Alphabet.hx
index 7de15494a..d81d5964a 100644
--- a/source/gameFolder/meta/data/font/Alphabet.hx
+++ b/source/gameFolder/meta/data/font/Alphabet.hx
@@ -17,7 +17,11 @@ using StringTools;
*/
class Alphabet extends FlxSpriteGroup
{
- public var delay:Float = 0.05;
+ public var textSpeed:Float = 0.06;
+ public var randomSpeed:Bool = false; // When enabled, it'll change the speed of the text speed randomly between 80% and 180%
+
+ public var textSize:Float;
+
public var paused:Bool = false;
// for menu shit
@@ -39,6 +43,8 @@ class Alphabet extends FlxSpriteGroup
public var widthOfWords:Float = FlxG.width;
+ public var finishedLine:Bool = false;
+
var yMulti:Float = 1;
// custom shit
@@ -51,22 +57,32 @@ class Alphabet extends FlxSpriteGroup
var isBold:Bool = false;
- public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false)
+ public var soundChoices:Array = ["GF_1", "GF_2", "GF_3", "GF_4",];
+ public var beginPath:String = "assets/sounds/";
+ public var soundChance:Int = 40;
+ public var playSounds:Bool = true;
+ public var lastPlayed:Int = 0;
+
+ public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false, ?textSize:Float = 1)
{
super(x, y);
this.text = text;
isBold = bold;
+ this.textSize = textSize;
- restartText(text, typed);
+ startText(text, typed);
}
- public function restartText(text, typed)
+ public function startText(newText, typed)
{
+ yMulti = 1;
+ finishedLine = false;
xPosResetted = true;
- _finalText = text;
- textInit = text;
+ _finalText = newText;
+ textInit = newText;
+ this.text = newText;
if (text != "")
{
@@ -79,6 +95,22 @@ class Alphabet extends FlxSpriteGroup
addText();
}
}
+ else
+ {
+ if (swagTypingTimer != null)
+ {
+ destroyText();
+ swagTypingTimer.cancel();
+ swagTypingTimer.destroy();
+ }
+ }
+ }
+
+ function destroyText():Void
+ {
+ for (_sprite in _sprites.copy())
+ _sprite.destroy();
+ clear();
}
public var arrayLetters:Array;
@@ -91,10 +123,6 @@ class Alphabet extends FlxSpriteGroup
var xPos:Float = 0;
for (character in splitWords)
{
- // if (character.fastCodeAt() == " ")
- // {
- // }
-
if (character == " " || character == "-")
lastWasSpace = true;
@@ -102,7 +130,6 @@ class Alphabet extends FlxSpriteGroup
var isSymbol:Bool = AlphaCharacter.symbols.contains(character);
if ((AlphaCharacter.alphabet.indexOf(character.toLowerCase()) != -1) || (AlphaCharacter.numbers.contains(character)))
- // if (AlphaCharacter.alphabet.contains(character.toLowerCase()))
{
if (xPosResetted)
{
@@ -121,8 +148,7 @@ class Alphabet extends FlxSpriteGroup
lastWasSpace = false;
}
- // var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
- var letter:AlphaCharacter = new AlphaCharacter(xPos, 0);
+ var letter:AlphaCharacter = new AlphaCharacter(xPos, 0, textSize);
if (isBold)
letter.createBold(character);
@@ -141,35 +167,36 @@ class Alphabet extends FlxSpriteGroup
lastSprite = letter;
}
-
- // loopNum += 1;
}
-
- // add(displayedLetters);
}
function doSplitWords():Void
- {
splitWords = _finalText.split("");
- }
public var personTalking:String = 'gf';
+ public var swagTypingTimer:FlxTimer;
+
public function startTypedText():Void
{
_finalText = text;
doSplitWords();
- // trace(arrayShit);
+ // Remove all the old garbage
+ destroyText();
var loopNum:Int = 0;
var xPos:Float = 0;
var curRow:Int = 0;
- new FlxTimer().start(0.05, function(tmr:FlxTimer)
+ // Forget any potential old timers
+ if (swagTypingTimer != null)
+ swagTypingTimer.destroy();
+
+ // Create a new timer
+ swagTypingTimer = new FlxTimer().start(textSpeed, function(tmr:FlxTimer)
{
- // trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
if (_finalText.fastCodeAt(loopNum) == "\n".code)
{
yMulti += 1;
@@ -191,15 +218,11 @@ class Alphabet extends FlxSpriteGroup
#end
if (AlphaCharacter.alphabet.indexOf(splitWords[loopNum].toLowerCase()) != -1 || isNumber || isSymbol)
- // if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
-
{
if (lastSprite != null && !xPosResetted)
{
lastSprite.updateHitbox();
xPos += lastSprite.width + 3;
- // if (isBold)
- // xPos -= 80;
}
else
{
@@ -212,10 +235,7 @@ class Alphabet extends FlxSpriteGroup
xPos += 20;
lastWasSpace = false;
}
- // trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
-
- // var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
- var letter:AlphaCharacter = new AlphaCharacter(xPos, 55 * yMulti);
+ var letter:AlphaCharacter = new AlphaCharacter(xPos, 55 * yMulti, textSize);
letter.row = curRow;
if (isBold)
{
@@ -233,11 +253,20 @@ class Alphabet extends FlxSpriteGroup
letter.x += 90;
}
- if (FlxG.random.bool(40))
+ if (FlxG.random.bool(soundChance) || lastPlayed > 2)
{
- var daSound:String = "GF_";
- FlxG.sound.play(Paths.soundRandom(daSound, 1, 4));
+ if (playSounds)
+ {
+ lastPlayed = 0;
+
+ var cur = FlxG.random.int(0, soundChoices.length - 1);
+ var daSound:String = beginPath + soundChoices[cur] + "." + Paths.SOUND_EXT;
+
+ FlxG.sound.play(daSound);
+ }
}
+ else
+ lastPlayed += 1;
add(letter);
@@ -246,8 +275,18 @@ class Alphabet extends FlxSpriteGroup
loopNum += 1;
- tmr.time = FlxG.random.float(0.04, 0.09);
- }, splitWords.length);
+ if (randomSpeed)
+ tmr.time = FlxG.random.float(0.8 * textSpeed, 1.8 * textSpeed);
+
+ // I'm sorry for this implementation being a bit janky but the FlxTimer loops were not reliable for this
+ // Hope you forgive me <3 <3 xoxo Sammu
+ // i forgive u sammu :D
+ if (loopNum >= splitWords.length)
+ {
+ finishedLine = true;
+ tmr.destroy();
+ }
+ }, 0);
}
override function update(elapsed:Float)
@@ -271,7 +310,7 @@ class Alphabet extends FlxSpriteGroup
arrayLetters[i].destroy();
//
lastSprite = null;
- restartText(text, false);
+ startText(text, false);
}
super.update(elapsed);
@@ -288,9 +327,12 @@ class AlphaCharacter extends FlxSprite
public var row:Int = 0;
- public function new(x:Float, y:Float)
+ private var textSize:Float = 1;
+
+ public function new(x:Float, y:Float, ?textSize:Float = 1)
{
super(x, y);
+ this.textSize = textSize;
var tex = Paths.getSparrowAtlas('UI/default/base/alphabet');
frames = tex;
@@ -304,6 +346,7 @@ class AlphaCharacter extends FlxSprite
// or just load regular text
animation.addByPrefix(letter, letter.toUpperCase() + " bold", 24);
animation.play(letter);
+ scale.set(textSize, textSize);
updateHitbox();
}
}
@@ -318,12 +361,13 @@ class AlphaCharacter extends FlxSprite
animation.addByPrefix(letter, letter + " " + letterCase, 24);
animation.play(letter);
+ scale.set(textSize, textSize);
updateHitbox();
FlxG.log.add('the row' + row);
y = (110 - height);
- y += row * 60;
+ y += row * 50;
}
public function createNumber(letter:String):Void
@@ -341,17 +385,23 @@ class AlphaCharacter extends FlxSprite
case '.':
animation.addByPrefix(letter, 'period', 24);
animation.play(letter);
- y += 50;
+ setGraphicSize(8, 8);
+ y += 48;
case "'":
animation.addByPrefix(letter, 'apostraphie', 24);
animation.play(letter);
- y -= 0;
+ setGraphicSize(10, 10);
+ y += 20;
case "?":
animation.addByPrefix(letter, 'question mark', 24);
animation.play(letter);
+ setGraphicSize(20, 40);
+ y += 16;
case "!":
animation.addByPrefix(letter, 'exclamation point', 24);
animation.play(letter);
+ setGraphicSize(10, 40);
+ y += 16;
default:
animation.addByPrefix(letter, letter, 24);
animation.play(letter);
diff --git a/source/gameFolder/meta/data/font/Dialogue.hx b/source/gameFolder/meta/data/font/Dialogue.hx
new file mode 100644
index 000000000..061b3d721
--- /dev/null
+++ b/source/gameFolder/meta/data/font/Dialogue.hx
@@ -0,0 +1,73 @@
+package gameFolder.meta.data.font;
+
+import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxPoint;
+import flixel.util.FlxTimer;
+import gameFolder.meta.data.font.Alphabet.AlphaCharacter;
+
+using StringTools;
+
+class Dialogue extends FlxSpriteGroup
+{
+ public var textSpeed:Float = 0.05;
+ public var textSize:Float = 1;
+ public var textPosition:Int = 0;
+
+ private var _buildText:String;
+ private var _finalText:String;
+
+ private var splitWords:Array = [];
+
+ private var dialogueMaxSize:FlxPoint;
+
+ public function new(x:Float, y:Float, text:String = "", width:Int, height:Int)
+ {
+ super(x, y);
+ _finalText = text;
+ dialogueMaxSize = new FlxPoint(width, height);
+ }
+
+ public function buildText():Void
+ {
+ // Reset values on the hypothetical that the text was started over
+ textPosition = 0;
+
+ var curRow = 0;
+ var loopNum = 0;
+ var lastWasSpace = false;
+
+ // Clear out all the old sprites if there are any
+ if (_sprites.length > 0)
+ {
+ for (_sprite in _sprites)
+ {
+ _sprite.destroy();
+ }
+ clear();
+ }
+
+ // Split all of the text into an array
+ splitWords = _finalText.split("");
+
+ new FlxTimer().start(textSpeed, function(timer:FlxTimer)
+ {
+ if (_finalText.fastCodeAt(loopNum) == "\n".code)
+ {
+ curRow++;
+ }
+
+ if (splitWords[curRow] == " ")
+ {
+ lastWasSpace = true;
+ }
+
+ #if (haxe >= "4.0.0")
+ var isNumber:Bool = AlphaCharacter.numbers.contains(splitWords[curRow]);
+ var isSymbol:Bool = AlphaCharacter.symbols.contains(splitWords[curRow]);
+ #else
+ var isNumber:Bool = AlphaCharacter.numbers.indexOf(splitWords[curRow]) != -1;
+ var isSymbol:Bool = AlphaCharacter.symbols.indexOf(splitWords[curRow]) != -1;
+ #end
+ });
+ }
+}
diff --git a/source/gameFolder/meta/state/PlayState.hx b/source/gameFolder/meta/state/PlayState.hx
index 886cdd805..45bd00057 100644
--- a/source/gameFolder/meta/state/PlayState.hx
+++ b/source/gameFolder/meta/state/PlayState.hx
@@ -326,7 +326,8 @@ class PlayState extends MusicBeatState
//
// call the funny intro cutscene depending on the song
- if (isStoryMode)
+ var freeplayOverride = true;
+ if (isStoryMode || freeplayOverride)
songIntroCutscene();
else
startCountdown();
@@ -581,7 +582,8 @@ class PlayState extends MusicBeatState
}
}
- if (generatedMusic)
+ // if the song is generated
+ if (generatedMusic && startedCountdown)
{
for (strumline in strumLines)
{
@@ -1479,12 +1481,18 @@ class PlayState extends MusicBeatState
FlxG.sound.play(Paths.sound('ANGRY'));
// schoolIntro(doof);
default:
- if (sys.FileSystem.exists(Paths.txt(SONG.song.toLowerCase() + '/' + SONG.song.toLowerCase() + 'Dialogue')))
+ var dialogPath = Paths.json(SONG.song.toLowerCase() + '/dialogue');
+
+ if (!Init.trueSettings.get('Skip Cutscenes') && sys.FileSystem.exists(dialogPath))
{
+ startedCountdown = false;
+
var dialogueBox:DialogueBox;
- dialogueBox = DialogueBox.createDialogue(CoolUtil.coolTextFile(Paths.txt(SONG.song.toLowerCase() + '/' + SONG.song.toLowerCase()
- + 'Dialogue')));
+ dialogueBox = DialogueBox.createDialogue(sys.io.File.getContent(dialogPath));
dialogueBox.cameras = [camHUD];
+ dialogueBox.whenDaFinish = startCountdown;
+
+ add(dialogueBox);
}
else
startCountdown();
@@ -1501,6 +1509,8 @@ class PlayState extends MusicBeatState
startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer)
{
+ startedCountdown = true;
+
charactersDance(curBeat);
var introAssets:Map> = new Map>();
diff --git a/source/gameFolder/meta/state/menus/OptionsMenuState.hx b/source/gameFolder/meta/state/menus/OptionsMenuState.hx
index cd8257252..5067913bd 100644
--- a/source/gameFolder/meta/state/menus/OptionsMenuState.hx
+++ b/source/gameFolder/meta/state/menus/OptionsMenuState.hx
@@ -66,6 +66,7 @@ class OptionsMenuState extends MusicBeatState
['Centered Notefield', getFromOption],
['Ghost Tapping', getFromOption],
['Display Accuracy', getFromOption],
+ ['Skip Cutscenes', getFromOption],
['Display Miss Count', getFromOption],
//
['', null],