First pass story flags

This commit is contained in:
2026-09-19 10:45:06 -05:00
parent f64364f37d
commit 6f1bbe4f2f
10 changed files with 73 additions and 92 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"flags": {
"test": { "description": "Test flag for debugging purposes", "initial": true }
}
}
+2
View File
@@ -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();
+2 -10
View File
@@ -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)
+27
View File
@@ -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();
}
+17
View File
@@ -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);
+6 -6
View File
@@ -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");
}
-2
View File
@@ -1,2 +0,0 @@
id,description,initial
test,"Test flag for debugging purposes",1
1 id description initial
2 test Test flag for debugging purposes 1
+14 -3
View File
@@ -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);
-11
View File
@@ -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;
-60
View File
@@ -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))