From 22398ddcefb5a0bf843a829e4514498b0318050c Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 3 Feb 2026 15:16:21 -0600 Subject: [PATCH] Added story flags --- assets/init.lua | 5 +- assets/scene/initial.lua | 1 - src/CMakeLists.txt | 1 + src/script/module/CMakeLists.txt | 1 + src/script/module/story/CMakeLists.txt | 10 ++ src/script/module/story/modulestoryflag.c | 109 ++++++++++++++++++++++ src/script/module/story/modulestoryflag.h | 48 ++++++++++ src/script/scriptmodule.c | 2 + src/story/CMakeLists.txt | 18 ++++ src/story/storyflag.c | 14 +++ src/story/storyflag.csv | 2 + src/story/storyflag.h | 25 +++++ src/story/storyflagdefs.h | 11 +++ tools/item/csv/__main__.py | 4 - tools/story/csv/__main__.py | 49 ++++++++++ 15 files changed, 292 insertions(+), 8 deletions(-) create mode 100644 src/script/module/story/CMakeLists.txt create mode 100644 src/script/module/story/modulestoryflag.c create mode 100644 src/script/module/story/modulestoryflag.h create mode 100644 src/story/CMakeLists.txt create mode 100644 src/story/storyflag.c create mode 100644 src/story/storyflag.csv create mode 100644 src/story/storyflag.h create mode 100644 src/story/storyflagdefs.h create mode 100644 tools/story/csv/__main__.py diff --git a/assets/init.lua b/assets/init.lua index 2799fd6..7fc695b 100644 --- a/assets/init.lua +++ b/assets/init.lua @@ -31,10 +31,9 @@ else inputBind("enter", INPUT_ACTION_ACCEPT) inputBind("e", INPUT_ACTION_ACCEPT) - inputBind("escape", INPUT_ACTION_CANCEL) inputBind("q", INPUT_ACTION_CANCEL) - - inputBind("z", INPUT_ACTION_RAGEQUIT) + + inputBind("escape", INPUT_ACTION_RAGEQUIT) end end diff --git a/assets/scene/initial.lua b/assets/scene/initial.lua index 3ea5f5b..8a03296 100644 --- a/assets/scene/initial.lua +++ b/assets/scene/initial.lua @@ -16,7 +16,6 @@ end function sceneUpdate() end - function sceneRender() cameraPushMatrix(camera) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 409cef9..d9b0f42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,7 @@ add_subdirectory(locale) # add_subdirectory(rpg) add_subdirectory(scene) add_subdirectory(script) +add_subdirectory(story) add_subdirectory(thread) add_subdirectory(time) add_subdirectory(ui) diff --git a/src/script/module/CMakeLists.txt b/src/script/module/CMakeLists.txt index 260f1a0..46bec9c 100644 --- a/src/script/module/CMakeLists.txt +++ b/src/script/module/CMakeLists.txt @@ -11,5 +11,6 @@ add_subdirectory(item) add_subdirectory(locale) add_subdirectory(system) add_subdirectory(scene) +add_subdirectory(story) add_subdirectory(time) add_subdirectory(ui) \ No newline at end of file diff --git a/src/script/module/story/CMakeLists.txt b/src/script/module/story/CMakeLists.txt new file mode 100644 index 0000000..6496420 --- /dev/null +++ b/src/script/module/story/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + modulestoryflag.c +) \ No newline at end of file diff --git a/src/script/module/story/modulestoryflag.c b/src/script/module/story/modulestoryflag.c new file mode 100644 index 0000000..7f2efbc --- /dev/null +++ b/src/script/module/story/modulestoryflag.c @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "modulestoryflag.h" +#include "assert/assert.h" +#include "story/storyflag.h" + +void moduleStoryFlag(scriptcontext_t *context) { + assertNotNull(context, "Script context cannot be NULL"); + + lua_register(context->luaState, "storyFlagGet", moduleStoryFlagGet); + lua_register(context->luaState, "storyFlagSet", moduleStoryFlagSet); + lua_register( + context->luaState, "storyFlagIncrement", moduleStoryFlagIncrement + ); + lua_register( + context->luaState, "storyFlagDecrement", moduleStoryFlagDecrement + ); +} + +int moduleStoryFlagGet(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + // Require story flag ID argument + if(!lua_isnumber(L, 1)) { + luaL_error(L, "Expected flag ID."); + return 0; + } + + storyflag_t flag = (storyflag_t)lua_tointeger(L, 1); + if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { + luaL_error(L, "Invalid flag ID %d", flag); + return 0; + } + + storyflagvalue_t value = storyFlagGet(flag); + lua_pushinteger(L, value); + return 1; +} + +int moduleStoryFlagSet(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + // Require story flag ID argument + if(!lua_isnumber(L, 1)) { + luaL_error(L, "Expected flag ID."); + return 0; + } + + // Require story flag value argument + if(!lua_isnumber(L, 2)) { + luaL_error(L, "Expected flag value."); + return 0; + } + + storyflag_t flag = (storyflag_t)lua_tointeger(L, 1); + if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { + luaL_error(L, "Invalid flag ID %d", flag); + return 0; + } + + storyflagvalue_t value = (storyflagvalue_t)lua_tointeger(L, 2); + storyFlagSet(flag, value); + return 0; +} + +int moduleStoryFlagIncrement(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + // Require story flag ID argument + if(!lua_isnumber(L, 1)) { + luaL_error(L, "Expected flag ID."); + return 0; + } + + storyflag_t flag = (storyflag_t)lua_tointeger(L, 1); + if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { + luaL_error(L, "Invalid flag ID %d", flag); + return 0; + } + + storyflagvalue_t value = storyFlagGet(flag); + storyFlagSet(flag, value + 1); + return 0; +} + +int moduleStoryFlagDecrement(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + // Require story flag ID argument + if(!lua_isnumber(L, 1)) { + luaL_error(L, "Expected flag ID."); + return 0; + } + + storyflag_t flag = (storyflag_t)lua_tointeger(L, 1); + if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { + luaL_error(L, "Invalid flag ID %d", flag); + return 0; + } + + storyflagvalue_t value = storyFlagGet(flag); + storyFlagSet(flag, value - 1); + return 0; +} \ No newline at end of file diff --git a/src/script/module/story/modulestoryflag.h b/src/script/module/story/modulestoryflag.h new file mode 100644 index 0000000..c398c3e --- /dev/null +++ b/src/script/module/story/modulestoryflag.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" + +/** + * Register story flag module functions to the given script context. + * + * @param context The script context to register story flag module functions to. + */ +void moduleStoryFlag(scriptcontext_t *context); + +/** + * Script binding for getting the value of a story flag. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleStoryFlagGet(lua_State *L); + +/** + * Script binding for setting the value of a story flag. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleStoryFlagSet(lua_State *L); + +/** + * Script binding for incrementing a story flag. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleStoryFlagIncrement(lua_State *L); + +/** + * Script binding for decrementing a story flag. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleStoryFlagDecrement(lua_State *L); \ No newline at end of file diff --git a/src/script/scriptmodule.c b/src/script/scriptmodule.c index 5606555..1e27301 100644 --- a/src/script/scriptmodule.c +++ b/src/script/scriptmodule.c @@ -21,6 +21,7 @@ #include "script/module/ui/moduleui.h" #include "script/module/display/moduletext.h" #include "script/module/display/modulescreen.h" +#include "script/module/story/modulestoryflag.h" #include "util/string.h" const scriptmodule_t SCRIPT_MODULE_LIST[] = { @@ -39,6 +40,7 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = { { .name = "ui", .callback = moduleUi }, { .name = "text", .callback = moduleText }, { .name = "screen", .callback = moduleScreen }, + { .name = "storyflag", .callback = moduleStoryFlag }, }; #define SCRIPT_MODULE_COUNT ( \ diff --git a/src/story/CMakeLists.txt b/src/story/CMakeLists.txt new file mode 100644 index 0000000..b9553a2 --- /dev/null +++ b/src/story/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + storyflag.c +) + +dusk_run_python( + dusk_story_defs + tools.story.csv + --csv ${CMAKE_CURRENT_SOURCE_DIR}/storyflag.csv + --header-file ${DUSK_GENERATED_HEADERS_DIR}/story/storyflagvalue.h +) +add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_story_defs) \ No newline at end of file diff --git a/src/story/storyflag.c b/src/story/storyflag.c new file mode 100644 index 0000000..e83ba3a --- /dev/null +++ b/src/story/storyflag.c @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "storyflag.h" +#include "assert/assert.h" + +void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value) { + assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag"); + STORY_FLAG_VALUES[flag] = value; +} \ No newline at end of file diff --git a/src/story/storyflag.csv b/src/story/storyflag.csv new file mode 100644 index 0000000..ac5197d --- /dev/null +++ b/src/story/storyflag.csv @@ -0,0 +1,2 @@ +id,description,initial +test,"Test flag for debugging purposes",1 diff --git a/src/story/storyflag.h b/src/story/storyflag.h new file mode 100644 index 0000000..baeec38 --- /dev/null +++ b/src/story/storyflag.h @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "story/storyflagvalue.h" + +/** + * Gets the value of a story flag. + * + * @param flag The story flag to get. + * @return The value of the story flag. + */ +#define storyFlagGet(flag) (STORY_FLAG_VALUES[(flag)]) + +/** + * Sets the value of a story flag. + * + * @param flag The story flag to set. + * @param value The value to set the story flag to. + */ +void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value); \ No newline at end of file diff --git a/src/story/storyflagdefs.h b/src/story/storyflagdefs.h new file mode 100644 index 0000000..2dd81c3 --- /dev/null +++ b/src/story/storyflagdefs.h @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef uint8_t storyflagvalue_t; \ No newline at end of file diff --git a/tools/item/csv/__main__.py b/tools/item/csv/__main__.py index 0ab2ca2..bf2dffe 100644 --- a/tools/item/csv/__main__.py +++ b/tools/item/csv/__main__.py @@ -11,10 +11,6 @@ args = parser.parse_args() def csvIdToEnumName(itemId): return "ITEM_ID_" + itemId.upper() -# Load up CSV file. -outHeader = "#pragma once\n" -outHeader += '#include "dusk.h"\n\n' - itemIds = [] itemTypes = [] itemRowById = {} diff --git a/tools/story/csv/__main__.py b/tools/story/csv/__main__.py new file mode 100644 index 0000000..a230ccd --- /dev/null +++ b/tools/story/csv/__main__.py @@ -0,0 +1,49 @@ +import argparse +import os +import csv +from tools.util.type import detectType, stringToCType, typeToCType + +parser = argparse.ArgumentParser(description="Story CSV to .h defines") +parser.add_argument("--csv", required=True, help="Path to story CSV file") +parser.add_argument("--header-file", required=True, help="Path to output .h file") +args = parser.parse_args() + +def idToEnum(id): + return "STORY_FLAG_" + id.upper().replace(" ", "_") + +# Load up CSV file. +outHeader = "#pragma once\n" +outHeader += '#include "story/storyflagdefs.h"\n\n' + +with open(args.csv, newline="", encoding="utf-8") as csvfile: + reader = csv.DictReader(csvfile) + + # CSV must have id column + if "id" not in reader.fieldnames: + raise Exception("CSV file must have 'id' column") + + # Generate enum + outHeader += "typedef enum {\n" + outHeader += " STORY_FLAG_NULL,\n\n" + for row in reader: + id = idToEnum(row["id"].strip()) + outHeader += f" {id},\n" + outHeader += "\n STORY_FLAG_COUNT\n" + outHeader += "} storyflag_t;\n\n" + + # Generate flag values + csvfile.seek(0) + reader = csv.DictReader(csvfile) + + outHeader += "static storyflagvalue_t STORY_FLAG_VALUES[STORY_FLAG_COUNT] = {\n" + for row in reader: + id = idToEnum(row["id"].strip()) + initial = row.get("initial", "0").strip() or "0" + outHeader += f" [{id}] = {initial},\n" + outHeader += "};\n" + +os.makedirs(os.path.dirname(args.header_file), exist_ok=True) + +# Write header +with open(args.header_file, "w", encoding="utf-8") as headerFile: + headerFile.write(outHeader) \ No newline at end of file