# Story, Items & Save --- ## Story flags (`src/dusk/rpg/story/`) Story flags are the primary mechanism for tracking game-world state (quest progress, one-time events, unlocks). Each flag is a `uint8_t` value (`storyflagvalue_t`), so they can hold booleans or small counts. ### Defining flags Flags are defined in `src/dusk/rpg/story/storyflag.csv`: ``` id,description,initial test,"Test flag for debugging purposes",1 ``` The build tool generates: - A `storyflag_t` enum (e.g. `STORY_FLAG_TEST`) in the generated header. - `STORY_FLAG_VALUES[]` — the runtime array, pre-populated with the `initial` column values. To add a flag: add a row to the CSV. The build re-runs the Python tool automatically on the next CMake build. ### Access ```c storyflagvalue_t v = storyFlagGet(STORY_FLAG_TEST); // macro: array read storyFlagSet(STORY_FLAG_TEST, 1); // function: also marks save dirty ``` `storyFlagGet` is a macro that directly indexes `STORY_FLAG_VALUES[]` — no function call overhead. --- ## Items (`src/dusk/rpg/item/`) ### Item definitions Items are defined in `src/dusk/rpg/item/item.csv`. The build tool generates `itemid_t` enum values and item metadata. `itemid_t` is a generated `uint8_t` typedef. ### Inventory (`inventory.h`) `inventory_t` is a generic container backed by a caller-supplied `inventorystack_t` array: ```c typedef struct { itemid_t item; uint8_t quantity; // max ITEM_STACK_QUANTITY_MAX (255) } inventorystack_t; typedef struct { inventorystack_t *storage; uint8_t storageSize; } inventory_t; ``` Key operations: ```c inventoryInit(&inv, storageArray, size); inventoryAdd(&inv, ITEM_POTION, 3); inventoryRemove(&inv, ITEM_POTION); inventorySet(&inv, ITEM_POTION, 10); inventoryGetCount(&inv, ITEM_POTION); // returns 0 if not present inventoryItemExists(&inv, ITEM_POTION); inventoryIsFull(&inv); inventorySort(&inv, INVENTORY_SORT_BY_ID, false); ``` `inventory_t` itself holds no data — the backing array is always external. This avoids fixed-size struct limits and lets different inventories (backpack, shop, chest) share the same logic. ### Backpack (`backpack.h`) The player's inventory is the global `BACKPACK` instance: ```c extern inventorystack_t BACKPACK_STORAGE[BACKPACK_STORAGE_SIZE_MAX]; // 20 slots extern inventory_t BACKPACK; backpackInit(); // wires BACKPACK_STORAGE into BACKPACK ``` --- ## Save system (`src/dusk/save/`) The save system is stubbed out — it exists and compiles but is commented out of engine init (`engine.c`). What follows describes the design as implemented. ### Slots `save_t SAVE` holds `SAVE_FILE_COUNT_MAX` slots: ```c typedef struct { savefile_t files[SAVE_FILE_COUNT_MAX]; saveplatform_t platform; // platform-specific state (paths, card handles) } save_t; ``` ### Streams `savestream_t` (`save/savestream.h`) is a raw byte cursor used to serialize/deserialize `savefile_t`. Platform backends in `src/dusk{platform}/save/` implement the actual I/O: - Linux: filesystem files in a save directory. - GameCube/Wii: memory card via libogc. ### API ```c saveInit(); saveLoad(slot); // reads platform storage → savefile_t saveWrite(slot); // writes savefile_t → platform storage saveDelete(slot); saveExists(slot); // bool saveGet(slot); // returns savefile_t * saveDispose(); ``` --- ## Locale / i18n (`src/dusk/locale/`) Translations are loaded from `.po` files in `assets/locale/` (e.g. `en_US.po`). `localemanager.c` manages the active locale and exposes a key→string lookup. `assetlocaleloader.c` parses the PO format via the asset system. All player-visible strings must go through the locale system rather than being hardcoded. The locale is loaded asynchronously via the asset system so it is available before the first scene renders.