From 6f1bbe4f2f465cff85a3313f87c0eda2bc86e704 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sat, 19 Sep 2026 10:45:06 -0500 Subject: [PATCH] First pass story flags --- assets/story/storyflag.jsonc | 5 +++ src/dusk/rpg/rpg.c | 2 + src/dusk/rpg/story/CMakeLists.txt | 12 +----- src/dusk/rpg/story/story.c | 27 ++++++++++++++ src/dusk/rpg/story/story.h | 17 +++++++++ src/dusk/rpg/story/storyflag.c | 12 +++--- src/dusk/rpg/story/storyflag.csv | 2 - src/dusk/rpg/story/storyflag.h | 17 +++++++-- src/dusk/rpg/story/storyflagdefs.h | 11 ------ tools/story.py | 60 ------------------------------ 10 files changed, 73 insertions(+), 92 deletions(-) create mode 100644 assets/story/storyflag.jsonc create mode 100644 src/dusk/rpg/story/story.c create mode 100644 src/dusk/rpg/story/story.h delete mode 100644 src/dusk/rpg/story/storyflag.csv delete mode 100644 src/dusk/rpg/story/storyflagdefs.h delete mode 100644 tools/story.py diff --git a/assets/story/storyflag.jsonc b/assets/story/storyflag.jsonc new file mode 100644 index 00000000..6a487f71 --- /dev/null +++ b/assets/story/storyflag.jsonc @@ -0,0 +1,5 @@ +{ + "flags": { + "test": { "description": "Test flag for debugging purposes", "initial": true } + } +} diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c index d2056e9b..66400a45 100644 --- a/src/dusk/rpg/rpg.c +++ b/src/dusk/rpg/rpg.c @@ -23,11 +23,13 @@ #include "scene/scene.h" #include "ui/rpg/uiemoji.h" #include "rpg/story/storyflag.h" +#include "rpg/story/story.h" errorret_t rpgInit(void) { memoryZero(ENTITIES, sizeof(ENTITIES)); memoryZero(MAP_AREAS, sizeof(MAP_AREAS)); + errorChain(storyInit()); errorChain(itemInit()); backpackInit(); partyInit(); diff --git a/src/dusk/rpg/story/CMakeLists.txt b/src/dusk/rpg/story/CMakeLists.txt index 6aace3e7..a3c89a28 100644 --- a/src/dusk/rpg/story/CMakeLists.txt +++ b/src/dusk/rpg/story/CMakeLists.txt @@ -1,19 +1,11 @@ # 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 + story.c storyflag.c ) - -# Story Flag Definitions -dusk_run_python( - dusk_story_defs - tools.story - --csv ${CMAKE_CURRENT_SOURCE_DIR}/storyflag.csv - --output ${DUSK_GENERATED_HEADERS_DIR}/rpg/story/storyflagvalue.h -) -add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_story_defs) \ No newline at end of file diff --git a/src/dusk/rpg/story/story.c b/src/dusk/rpg/story/story.c new file mode 100644 index 00000000..a3179e24 --- /dev/null +++ b/src/dusk/rpg/story/story.c @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "story.h" +#include "asset/asset.h" +#include "asset/loader/assetloader.h" + +errorret_t storyInit(void) { + assetentry_t *entry = assetLock( + "story/storyflag.jsonc", ASSET_LOADER_TYPE_JSON, NULL + ); + errorret_t ret = assetRequireLoaded(entry); + if(errorIsNotOk(ret)) { + assetUnlockEntry(entry); + errorChain(ret); + } + + // TODO: Parse entry->data.json into a storyflagid_t registry, the same + // way item.c's itemInit() builds ITEM.defs from items/items.jsonc. + + assetUnlockEntry(entry); + errorOk(); +} diff --git a/src/dusk/rpg/story/story.h b/src/dusk/rpg/story/story.h new file mode 100644 index 00000000..463ea7f2 --- /dev/null +++ b/src/dusk/rpg/story/story.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "error/error.h" + + +/** + * Initializes the story subsystem, loading assets/story/storyflag.jsonc. + * + * @return Any error that occurs. + */ +errorret_t storyInit(void); diff --git a/src/dusk/rpg/story/storyflag.c b/src/dusk/rpg/story/storyflag.c index 6b91a769..0e40f705 100644 --- a/src/dusk/rpg/story/storyflag.c +++ b/src/dusk/rpg/story/storyflag.c @@ -9,15 +9,15 @@ #include "assert/assert.h" #include "console/console.h" -storyflagvalue_t storyFlagGet(const storyflag_t flag) { - assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag"); +bool_t storyFlagGet(const storyflag_t flag) { + assertTrue(flag < STORY_FLAG_COUNT_MAX, "Bad Flag"); consolePrint("Story flag get without save implementation"); - return 0; + return false; } -void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value) { - assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag"); - +void storyFlagSet(const storyflag_t flag, const bool_t value) { + assertTrue(flag < STORY_FLAG_COUNT_MAX, "Bad Flag"); + // TODO: Dirty savefile consolePrint("Story flag set without save implementation"); } \ No newline at end of file diff --git a/src/dusk/rpg/story/storyflag.csv b/src/dusk/rpg/story/storyflag.csv deleted file mode 100644 index ac5197d1..00000000 --- a/src/dusk/rpg/story/storyflag.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,description,initial -test,"Test flag for debugging purposes",1 diff --git a/src/dusk/rpg/story/storyflag.h b/src/dusk/rpg/story/storyflag.h index f320d5ef..842a11a3 100644 --- a/src/dusk/rpg/story/storyflag.h +++ b/src/dusk/rpg/story/storyflag.h @@ -6,7 +6,18 @@ */ #pragma once -#include "rpg/story/storyflagvalue.h" +#include "dusk.h" + +#define STORY_FLAG_BASE_TYPE uint32_t +#define STORY_FLAG_BASE_BITS (sizeof(STORY_FLAG_BASE_TYPE) * 8) +#define STORY_FLAG_COUNT_MAX 1024 +#define STORY_FLAG_BASE_COUNT \ + ((STORY_FLAG_COUNT_MAX + STORY_FLAG_BASE_BITS - 1) / STORY_FLAG_BASE_BITS) + +typedef STORY_FLAG_BASE_TYPE storyflag_t; +typedef STORY_FLAG_BASE_TYPE storyflaglist_t[STORY_FLAG_BASE_COUNT]; +typedef uint16_t storyflagid_t; + /** * Gets the value of a story flag. Reads directly from the active save @@ -15,7 +26,7 @@ * @param flag The story flag to get. * @return The value of the story flag. */ -storyflagvalue_t storyFlagGet(const storyflag_t flag); +bool_t storyFlagGet(const storyflag_t flag); /** * Sets the value of a story flag. Will dirty the savefile. @@ -23,4 +34,4 @@ storyflagvalue_t storyFlagGet(const storyflag_t 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); +void storyFlagSet(const storyflag_t flag, const bool_t value); diff --git a/src/dusk/rpg/story/storyflagdefs.h b/src/dusk/rpg/story/storyflagdefs.h deleted file mode 100644 index 2dd81c3f..00000000 --- a/src/dusk/rpg/story/storyflagdefs.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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/story.py b/tools/story.py deleted file mode 100644 index fd7fac31..00000000 --- a/tools/story.py +++ /dev/null @@ -1,60 +0,0 @@ -import argparse -import csv -import os - -parser = argparse.ArgumentParser(description="Story CSV to .h defines") -parser.add_argument("--csv", required=True, help="Path to story CSV file") -parser.add_argument("--output", required=True, help="Path to output .h file") -args = parser.parse_args() - -def flag_enum(name): - return "STORY_FLAG_" + name.upper().replace(" ", "_") - -# Load flags -flags = [] -with open(args.csv, newline="", encoding="utf-8") as f: - reader = csv.DictReader(f) - if "id" not in reader.fieldnames: - raise ValueError("CSV must have an 'id' column") - for row in reader: - flags.append({ - "id": row["id"].strip(), - "initial": (row.get("initial") or "0").strip(), - }) - -# Build output -out = [ - "#pragma once", - '#include "rpg/story/storyflagdefs.h"', - "", - "typedef enum {", - " STORY_FLAG_NULL,", - "", -] -for flag in flags: - out.append(f" {flag_enum(flag['id'])},") -out += [ - "", - " STORY_FLAG_COUNT", - "} storyflag_t;", - "", - "// Stamped onto a save file's storyFlags the first time it's used (see", - "// storyFlagInitDefaults()) - not a live value array. Live flag state", - "// lives entirely in the save file (savefile_t.storyFlags), read/written", - "// via storyFlagGet()/storyFlagSet() - see storyflag.h.", - "static const storyflagvalue_t STORY_FLAG_DEFAULTS[STORY_FLAG_COUNT] = {", -] -for flag in flags: - out.append(f" [{flag_enum(flag['id'])}] = {flag['initial']},") -out += [ - "};", - "", - "static const char_t *STORY_FLAG_SCRIPT =", -] -for i, flag in enumerate(flags): - out.append(f" \"{flag_enum(flag['id'])} = {i + 1}\\n\"") -out += [";", ""] - -os.makedirs(os.path.dirname(args.output), exist_ok=True) -with open(args.output, "w", encoding="utf-8") as f: - f.write("\n".join(out))