diff --git a/assets/games/pokergame/locale/en.csv b/assets/games/pokergame/locale/en.csv
deleted file mode 100644
index f791a745..00000000
--- a/assets/games/pokergame/locale/en.csv
+++ /dev/null
@@ -1,86 +0,0 @@
-undefined,UNDEFINED
-hello.world,Hello World!
-character.death.name,"Santa Muerte"
-character.penny.name,Penny
-
-scene.1.1,"...Huh? Where am I?"
-scene.1.2,"Relax child, come forward, it is time."
-scene.1.3,"Who said that? Where is that voice coming from?"
-scene.1.4,"Hello, and welcome to the other side wanderer."
-scene.1.5,"Other side? Wait that robe! You don't mean?"
-scene.1.6,"Yeah let's speed things up here a bit. Normally I go on script but short on time right now unfortunately."
-scene.1.7,"You died, dead, passed on, kaput. This is the space between spaces. You may be going up, you may be going down, that's not my choice, I'm just here to guide you."
-scene.1.8,"...Are you?"
-scene.1.9,"Yes, some call me the Grim Reaper, some Muerte, and a long time ago it was Torva messor."
-scene.1.10,"Nowadays most people others just call me Death, but I prefer Nami, short for Izanami."
-scene.1.11,"Truth be told I am not the reason you are here, I am just here to guide you, don't know why I keep getting lumped with this bad reputation of killing people."
-scene.1.12,"Wait, so I am dead? For real? This has to be some kind of misunderstanding-wait I must be dreaming, that's it."
-scene.1.121,"Oh no this can't be happening, this can't be real..."
-scene.1.13,"If I had a penny for every time...
-No, don't get it wrong, you are meant to be here."
-scene.1.131,"I can't be.. you gotta send me back! How did I die?"
-scene.1.132,"I don't know. Regardless, I can't send you back to your world. We are getting off topic anyway."
-scene.1.133,"What?"
-scene.1.134,"*ahem* I have a request of you child."
-scene.1.14,"Me? Help you? Unless you're taking me back to my home I don't think you can convince me to help the likes of you."
-scene.1.141,"Yes... See, normally I'd just take you to Charon. It is his role to take the newcomers where they need to go."
-scene.1.142,"You know how it goes, I introduce you to Charon, you pay a coin, jump on a boat, and then you're not my problem any more."
-scene.1.15,"You mean send me down the river styx? You're not helping your case."
-scene.1.16,"Yes, well I would normally do that, but at the moment I have a bit of a problem with capacity."
-scene.1.17,"Capacity? What kind of capacity issue?"
-scene.1.18,"I manage a few worlds, not just the one that you come from."
-scene.1.19,"In your world, people rely on technology and their own ability to progress civilization."
-scene.1.20,"In another world, I manage people who raise and tame small pocket sized creatures with different abilities to progress their civilization."
-scene.1.21,"But one world I manage has been having some real troubles lately."
-scene.1.22,"This world contains humans alongside other intelligent creatures and species. They would be analagous to the medieval times in your world."
-scene.1.23,"So far they have managed to keep a good balance by having some creatures weild weapons, and some use magical powers."
-scene.1.24,"But lately there has been more cases of stronger creatures killing off the human population."
-scene.1.25,"It's causing me to work overtime just to make sure I can get everyone where they need to go."
-scene.1.26,"You have to work overtime?"
-scene.1.27,"The benefits here are really good, my union gives us time and a half for overtime we do."
-scene.1.28,"Death has unionized? That sounds horrible."
-scene.1.29,"Yes I did, and please just call me Nami. My union is starting to threaten a strike and I need to try and prevent that."
-scene.1.30,"I haven't been on strike since the 1940's when we had our last capacity issue."
-scene.1.31,"The union negotiated a great dental plan after that. But we need to try and avoid striking this time."
-scene.1.32,"Okay but I don't know how you think I can help."
-scene.1.33,"It's easy. Now understand that I cannot send you back to your world, that is out of my control."
-scene.1.34,"But there are no rules about you being sent to another world."
-scene.1.35,"So, I send you to the medieval world, you get another crack at life and perhaps you can assist me in finding out how to stop all the deaths."
-scene.1.36,"So, Nami, you want me to go to a world I don't know, that has monsters and a problem with lots of death, stuck in the medieval times, just to help out literal death?"
-scene.1.37,"Not to mention I won't know anyone, I won't understand their language and don't know their culture."
-scene.1.38,"I'll put it bluntly Nami, it sounds like I would be signing up for a short, miserable, lonely life, just for a chance to help you out."
-scene.1.39,"That's great, thanks for offering to help out!"
-scene.1.40,"I don't have a choice do I?"
-scene.1.41,"No, besides we have already started. Now, stand still and take a deep breath I am going to send you over to the other world now."
-scene.1.42,"I feel really tired all of a sudden... Wait does the Grim Reaper even have any kind of powers?"
-scene.1.43,"Of course I do, now open your eyes..."
-
-scene.2.1,"This scene has you waking in the new world"
-scene.3.1,"This is the scene to prep you for the first game"
-scene.4.1,"First Poker Game with friendlies"
-scene.5.1,"After first game, wind up maybe shop instructions or something"
-scene.6.1,"Talk with death probably, check in on you, etc."
-scene.7.1,"Pre-Orc Battle"
-scene.8.1,"Orc Battle"
-scene.9.1,"Immediately Post Orc Battle"
-scene.10.1,"Morning after orc battle and some foreshadowing"
-scene.11.1,"Pre battle with theif"
-scene.12.1,"Battle with theif"
-unknown1,"There needs to be the big bad here."
-scene.13.1,"After battle with theif, things cool off a bit."
-scene.14.1,"Harem times maybe"
-scene.15.1,"Harem times interrupted by some chaos"
-scene.16.1,"I'm putting chaos here but this scene is probably redundant."
-scene.17.1,"Chaos battle"
-scene.18.1,"Post Chaos Battle, things are still gloomy"
-unknown2,"Another big bad here probably."
-scene.19.1,"Pre King Arrival, rumours"
-scene.20.1,"King Arrival, Everyone's annoyed"
-scene.21.1,"King in the bar, running his mouth"
-scene.22.1,"King Fight"
-scene.23.1,"Post King Fight, angry he leaves, town rallies around you"
-scene.24.1," Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on."
-unknown3,"Something here has to bring the big bad to town."
-unknown4,"It's revealed that death knows the big bad",
-test.1,"Test"
-test.2,"Test*"
\ No newline at end of file
diff --git a/assets/games/pokergame/locale/jp.csv b/assets/games/pokergame/locale/jp.csv
deleted file mode 100644
index 911a9f52..00000000
--- a/assets/games/pokergame/locale/jp.csv
+++ /dev/null
@@ -1,21 +0,0 @@
-undefined,UNDEFINED
-hello.world,Hello World!
-character.penny.name,Penny
-scene.1.1,"日本語パスコん"
-scene.2.1,"This scene has you waking in the new world"
-scene.3.1,"This is the scene to prep you for the first game"
-scene.4.1,"First Poker Game with friendlies"
-scene.5.1,"After first game, wind up maybe shop instructions or something"
-scene.6.1,"Talk with death probably, check in on you, etc."
-scene.7.1,"Pre-Orc Battle"
-scene.8.1,"Orc Battle"
-scene.9.1,"Immediately Post Orc Battle"
-scene.10.1,"Morning after orc battle and some foreshadowing"
-scene.11.1,"Pre battle with theif"
-scene.12.1,"Battle with theif"
-scene.13.1,"After battle with theif, things cool off a bit."
-scene.14.1,"Harem times maybe"
-scene.15.1,"Harem times interrupted by some chaos"
-scene.16.1,"I'm putting chaos here but this scene is probably redundant."
-scene.17.1,"Chaos battle"
-scene.18.1,"Post Chaos Battle, things are still gloomy"
\ No newline at end of file
diff --git a/assets/games/pokergame/locale/locale.xml b/assets/games/pokergame/locale/locale.xml
new file mode 100644
index 00000000..8498383e
--- /dev/null
+++ b/assets/games/pokergame/locale/locale.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+ ...Huh? Where am I?
+
+
+
+ This scene has you waking in the new world
+
+
+ This is the scene to prep you for the first game
+
+
+ First Poker Game with friendlies
+
+
+ After first game, wind up maybe shop instructions or something
+
+
+ Talk with death probably, check in on you, etc.
+
+
+ Pre-Orc Battle
+
+
+ Orc Battle
+
+
+ Immediately Post Orc Battle
+
+
+ Morning after orc battle and some foreshadowing
+
+
+ Pre battle with theif
+
+
+ Battle with theif
+
+
+ There needs to be the big bad here.
+
+
+ After battle with theif, things cool off a bit.
+
+
+ Harem times maybe
+
+
+ Harem times interrupted by some chaos
+
+
+ I'm putting chaos here but this scene is probably redundant.
+
+
+ Chaos battle
+
+
+ Post Chaos Battle, things are still gloomy
+
+
+ Another big bad here probably.
+
+
+ Pre King Arrival, rumours
+
+
+ King Arrival, Everyone's annoyed
+
+
+ King in the bar, running his mouth
+
+
+ King Fight
+
+
+ Post King Fight, angry he leaves, town rallies around you
+
+
+ Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on.
+
+
+ Something here has to bring the big bad to town.
+
+
+ It's revealed that death knows the big bad
+
+
+
\ No newline at end of file
diff --git a/assets/games/pokergame/ui/uitest.xml b/assets/games/pokergame/ui/uitest.xml
deleted file mode 100644
index 88d82609..00000000
--- a/assets/games/pokergame/ui/uitest.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/games/pokergame/vn/testvn.txt b/assets/games/pokergame/vn/testvn.txt
new file mode 100644
index 00000000..b513ecb3
--- /dev/null
+++ b/assets/games/pokergame/vn/testvn.txt
@@ -0,0 +1,36 @@
+# This is a sample VN Scene that I am creating to create a scene generator.
+# The scene generator will simply create a series of events, nothing more.
+# Infact, the scene generator really is just a scene event with trailed events
+# Generator.
+
+# Scene name is probably going to be inherited from either the target or the
+# filename
+
+# By default the mode we are in is in TEXT mode, unless you explicitly change
+# the mode. The text mode takes the person, emotion and text string and tries
+# to convert it to this C++ equivallent code;
+# new VisualNovelTextboxEvent(vnManager, this->[person]->vnCharacter, this->[person]->[emotion], [text])
+
+# Here is our first example. We take death, give her an emotion, and write some
+# text.
+death:happy: scene.1.1
+
+# Here, we inherit the existing emotion. I've also omitted the space because it
+# is just there for show.
+death:scene.1.1
+
+# Now let's fade our character in. Fade char in events start like this
+fade death in quad over 1.0
+# Could also be written like any of these
+# fade death out
+# fade death in
+# fade death out over 1.0 seconds
+# fade death in over 1.0 seconds
+# fade death in linear
+# fade death out linear over 10 seconds
+# fade death out over 10
+# Basically the format just needs to be
+# fade [character] [in/out] (easing function) (time)
+# Each time a fade occurs the parameters will be remembered, and used for any
+# other fade after that, so you just need to define the easing curve once per
+# scene.
\ No newline at end of file
diff --git a/lint.js b/lint.js
new file mode 100644
index 00000000..b00b5479
--- /dev/null
+++ b/lint.js
@@ -0,0 +1,94 @@
+const fs = require('fs');
+const path = require('path');
+
+const DIR_SOURCES = path.resolve('src');
+
+const fileGetContents = filePath => fs.readFileSync(filePath, 'utf-8');
+
+const ensureCopyright = (file, contents) => {
+ if(
+ contents.includes('Copyright (c)') &&
+ contents.includes('MIT')
+ ) return;
+ throw new Error(`${file} is missing its copyright!`);
+}
+
+const ensurePragma = (file, contents) => {
+ if(contents.includes('#pragma once')) return;
+ throw new Error(`${file} is missing a #pragma once`);
+}
+
+
+const fileHandleCpp = filePath => {
+ // Load contents
+ const contents = fileGetContents(filePath);
+ ensureCopyright(filePath, contents);
+}
+
+const fileHandleC = filePath => {
+ // Load contents
+ const contents = fileGetContents(filePath);
+ ensureCopyright(filePath, contents);
+}
+
+const fileHandleHpp = filePath => {
+ // Load contents
+ const contents = fileGetContents(filePath);
+
+ ensureCopyright(filePath, contents);
+ ensurePragma(filePath, contents);
+}
+
+const fileHandleH = filePath => {
+ // Load contents
+ const contents = fileGetContents(filePath);
+
+ ensureCopyright(filePath, contents);
+ ensurePragma(filePath, contents);
+}
+
+const fileHandleCmake = filePath => {
+ // Load contents
+ const contents = fileGetContents(filePath);
+
+ // Check for the copyright
+ ensureCopyright(filePath, contents);
+}
+
+
+
+const fileScan = filePath => {
+ const ext = path.extname(filePath).replace(/\./g, '');
+ const base = path.basename(filePath);
+
+ if(ext === 'cpp') {
+ fileHandleCpp(filePath);
+ } else if(ext === 'hpp') {
+ fileHandleHpp(filePath);
+ } else if(ext === 'c') {
+ fileHandleC(filePath);
+ } else if(ext === 'h') {
+ fileHandleH(filePath);
+ }else if(base === 'CMakeLists.txt') {
+ fileHandleCmake(filePath);
+ } else {
+ throw new Error(`Unknown file type ${filePath}`);
+ }
+};
+
+const dirScan = directory => {
+ const contents = fs.readdirSync(directory);
+ contents.forEach(filePath => {
+ const abs = path.join(directory, filePath);
+ const stat = fs.statSync(abs);
+ if(stat.isDirectory()) {
+ dirScan(abs);
+ } else {
+ fileScan(abs);
+ }
+ });
+}
+
+(() => {
+ dirScan(DIR_SOURCES);
+})();
\ No newline at end of file
diff --git a/src/dawnpokergame/CMakeLists.txt b/src/dawnpokergame/CMakeLists.txt
index dedd4ee0..2fd520ef 100644
--- a/src/dawnpokergame/CMakeLists.txt
+++ b/src/dawnpokergame/CMakeLists.txt
@@ -30,7 +30,7 @@ add_subdirectory(scenes)
set(DIR_GAME_ASSETS games/pokergame)
tool_texture(texture_test texture_test.png)
-tool_language(language_en ${DIR_GAME_ASSETS}/locale/en.csv)
+tool_language(locale_poker ${DIR_GAME_ASSETS}/locale/locale.xml)
tool_tileset(tileset_death texture_death ${DIR_GAME_ASSETS}/characters/death/sheet.png 1 3)
tool_tileset(tileset_penny texture_penny ${DIR_GAME_ASSETS}/characters/penny/sheet.png 1 3)
@@ -39,10 +39,8 @@ tool_truetype(truetype_alice ${DIR_GAME_ASSETS}/font/Alice-Regular.ttf truetype_
tool_audio(audio_test borrowed/sample_short.wav)
-tool_ui(ui_test ${DIR_GAME_ASSETS}/ui/uitest.xml)
-
add_dependencies(${DAWN_TARGET_NAME}
- language_en
+ locale_poker
tileset_death
tileset_penny
@@ -52,6 +50,4 @@ add_dependencies(${DAWN_TARGET_NAME}
texture_test
audio_test
-
- ui_test
)
\ No newline at end of file
diff --git a/src/dawntools/CMakeLists.txt b/src/dawntools/CMakeLists.txt
index d73b2021..30206d91 100644
--- a/src/dawntools/CMakeLists.txt
+++ b/src/dawntools/CMakeLists.txt
@@ -1,9 +1,13 @@
-# Copyright (c) 2021 Dominic Msters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-add_subdirectory(audio)
-add_subdirectory(display)
-add_subdirectory(file)
-add_subdirectory(locale)
\ No newline at end of file
+# Copyright (c) 2021 Dominic Msters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+add_subdirectory(audio)
+add_subdirectory(display)
+add_subdirectory(file)
+add_subdirectory(locale)
+
+if(DAWN_VISUAL_NOVEL)
+ add_subdirectory(visualnovel)
+endif()
\ No newline at end of file
diff --git a/src/dawntools/display/uigen/CMakeLists.txt b/src/dawntools/display/uigen/CMakeLists.txt
index 9fb7a2c9..70ed4992 100644
--- a/src/dawntools/display/uigen/CMakeLists.txt
+++ b/src/dawntools/display/uigen/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Dominic Msters
+# Copyright (c) 2023 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
diff --git a/src/dawntools/locale/CMakeLists.txt b/src/dawntools/locale/CMakeLists.txt
index 65ad32d6..79506401 100644
--- a/src/dawntools/locale/CMakeLists.txt
+++ b/src/dawntools/locale/CMakeLists.txt
@@ -1,15 +1,15 @@
-# Copyright (c) 2021 Dominic Msters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-add_subdirectory(languagegen)
-
-# Language Tool
-function(tool_language target in)
- add_custom_target(${target}
- COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${target}"
- COMMENT "Generating texture ${target} from ${in}"
- DEPENDS languagegen
- )
-endfunction()
\ No newline at end of file
+# Copyright (c) 2021 Dominic Msters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+add_subdirectory(languagegen)
+
+# Language Tool
+function(tool_language target in)
+ add_custom_target(${target}
+ COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}"
+ COMMENT "Generating language set ${target} from ${in}"
+ DEPENDS languagegen
+ )
+endfunction()
diff --git a/src/dawntools/locale/languagegen/CMakeLists.txt b/src/dawntools/locale/languagegen/CMakeLists.txt
index e628bc38..423852ae 100644
--- a/src/dawntools/locale/languagegen/CMakeLists.txt
+++ b/src/dawntools/locale/languagegen/CMakeLists.txt
@@ -1,25 +1,24 @@
-# Copyright (c) 2021 Dominic Msters
-#
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-# Texture Build Tool
-project(languagegen VERSION 1.0)
-add_executable(languagegen)
-target_sources(languagegen
- PRIVATE
- main.c
- ../../utils/file.c
- ../../utils/image.c
- ../../utils/csv.c
-)
-target_include_directories(languagegen
- PUBLIC
- ${CMAKE_CURRENT_LIST_DIR}/../../
- ${CMAKE_CURRENT_LIST_DIR}
-)
-target_link_libraries(languagegen
- PUBLIC
- ${DAWN_BUILD_HOST_LIBS}
- stb
+# Copyright (c) 2021 Dominic Msters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Texture Build Tool
+project(languagegen VERSION 2.0)
+add_executable(languagegen)
+target_sources(languagegen
+ PRIVATE
+ main.cpp
+ ../../utils/file.c
+ ../../utils/csv.c
+ ../../utils/xml.c
+)
+target_include_directories(languagegen
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/../../
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+target_link_libraries(languagegen
+ PUBLIC
+ ${DAWN_BUILD_HOST_LIBS}
)
\ No newline at end of file
diff --git a/src/dawntools/locale/languagegen/main.c b/src/dawntools/locale/languagegen/main.c
deleted file mode 100644
index a37aedd9..00000000
--- a/src/dawntools/locale/languagegen/main.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Copyright (c) 2021 Dominic Masters
- *
- * This software is released under the MIT License.
- * https://opensource.org/licenses/MIT
- */
-
-#include "../../utils/common.h"
-#include "../../utils/file.h"
-#include "../../utils/csv.h"
-
-int main(int argc, char *argv[]) {
- FILE *file;
- char path[FILENAME_MAX + 1];
- csv_t csv;
- char *in;
- char *out;
- char *buffer;
- char sep = '|';
-
- if(argc != 3) {
- printf("Invalid number of arguments\n");
- return 1;
- }
-
- // Set up strings
- in = argv[1];
- out = argv[2];
-
- // Normalize slashes
- fileNormalizeSlashes(in);
- fileNormalizeSlashes(out);
-
- // Check the output doesn't already exist
- sprintf(path, "%s.language", out);
- // file = fopen(path, "rb");
- // if(file != NULL) {
- // fclose(file);
- // return 0;
- // }
-
- // Read in original CSV string
- file = fopen(in, "rb");
- if(file == NULL) {
- printf("Failed to open file!\n");
- return 1;
- }
-
- // Seek to end, get length, seek back to start.
- fseek(file, 0, SEEK_END);
- size_t fileSize = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- // Read in all data
- buffer = malloc(sizeof(char) * (fileSize + 1));
- size_t readSize = fread(buffer, 1, fileSize, file);
- fclose(file);
- if(readSize < fileSize) {
- printf("Failed to read all data from CSV\n");
- free(buffer);
- return 1;
- }
- buffer[fileSize] = '\0';
-
- csvParse(buffer, &csv);
- free(buffer);
-
- // Prepare output file for writing.
- sprintf(path, "%s.language", out);
- fileMkdirp(path);
- file = fopen(path, "wb");
- if(file == NULL) {
- printf("Failed to create output language file\n");
- csvDispose(&csv);
- return 1;
- }
-
- // Iterate over the CSV
- for(int32_t y = 0; y < csv.rowCount; y++) {
- // Ensure valid line
- if(csv.cellCounts[y] != 2) {
- printf("Failed to parse language. Line %i has %i cells instead of 2\n", y, csv.cellCounts);
- fclose(file);
- csvDispose(&csv);
- return 1;
- }
-
- char *key = csvGetCell(&csv, y, 0);
- char *value = csvGetCell(&csv, y, 1);
-
- // 23/01/14 - Replace \r in CSV.
- stringRemoveAll(key, '\r');
- stringRemoveAll(value, '\r');
- if(strlen(key) <= 0 || strlen(value) <= 0) {
- printf("Failed to parse language. Line %i has an invalid string\n", y);
- fclose(file);
- csvDispose(&csv);
- return 1;
- }
-
- fwrite(key, sizeof(char), strlen(key), file);
- fwrite(&sep, sizeof(char), 1, file);
- fwrite(value, sizeof(char), strlen(value), file);
- fwrite(&sep, sizeof(char), 1, file);
- }
-
- // Finished writing
- fclose(file);
- csvDispose(&csv);
-
- return 0;
-}
\ No newline at end of file
diff --git a/src/dawntools/locale/languagegen/main.cpp b/src/dawntools/locale/languagegen/main.cpp
new file mode 100644
index 00000000..a2b57854
--- /dev/null
+++ b/src/dawntools/locale/languagegen/main.cpp
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) 2021 Dominic Masters
+ *
+ * This software is released under the MIT License.
+ * https://opensource.org/licenses/MIT
+ */
+
+extern "C" {
+ #include "../../utils/common.h"
+ #include "../../utils/file.h"
+ #include "../../utils/csv.h"
+ #include "../../utils/xml.h"
+ #include
+}
+
+#include
+#include