Move global item collected-state, deadzone, and story flags into save file

Adds three new pieces of save-file state, all following the same shape:
the save file is the single source of truth, not a separate live runtime
copy that gets synced in/out.

- globalitemstore.h/.c: per-global-entity-ID "collected" flags
  (savefile_t.globalItemCollected), so a global item entity's init
  callback can check whether it was already picked up in a prior session
  without needing to keep the entity itself alive to remember that.

- Gamepad deadzone: removed input_t.deadzone entirely. The setting UI and
  every platform's actual deadzone-applying code (inputGetDeadzoneDolphin/
  SDL2, previously hardcoded per-platform literals that the settings menu
  didn't actually affect) now read savefile_t.deadzone directly via
  saveGet(SAVE_ACTIVE_SLOT). Default lives in savefile.h
  (SAVE_DEADZONE_DEFAULT), stamped onto every slot in saveInit().

- Story flags: STORY_FLAG_VALUES (a live, codegen-initialized array) is
  replaced by savefile_t.storyFlags, read/written via the existing
  storyFlagGet()/storyFlagSet() call sites (now macros/functions over the
  active save file instead of a separate array). tools/story.py now
  generates STORY_FLAG_DEFAULTS (const) instead; storyFlagInitDefaults()
  stamps those onto a save the first time it's used (file->exists false),
  called from rpgInit().

Added SAVE_ACTIVE_SLOT (0) to savefile.h as the one shared "which slot is
actually being played" constant, replacing three different local/implicit
0s (uigamemenu.c, rpg.c, and now the settings/input call sites).

Verified round-trip on Linux (all three together in one save/load cycle);
both Linux and PSP build clean.
This commit is contained in:
2026-08-04 11:10:44 -05:00
parent 2cbd80a004
commit 4d95415232
18 changed files with 203 additions and 35 deletions
-1
View File
@@ -17,7 +17,6 @@ input_t INPUT;
errorret_t inputInit(void) { errorret_t inputInit(void) {
memoryZero(&INPUT, sizeof(input_t)); memoryZero(&INPUT, sizeof(input_t));
INPUT.deadzone = INPUT_DEADZONE_DEFAULT;
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) { for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
INPUT.actions[i].action = (inputaction_t)i; INPUT.actions[i].action = (inputaction_t)i;
-4
View File
@@ -12,15 +12,11 @@
#define INPUT_LISTENER_PRESSED_MAX 16 #define INPUT_LISTENER_PRESSED_MAX 16
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX #define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
#define INPUT_DEADZONE_DEFAULT 0.1f
typedef struct { typedef struct {
inputactiondata_t actions[INPUT_ACTION_COUNT]; inputactiondata_t actions[INPUT_ACTION_COUNT];
inputplatform_t platform; inputplatform_t platform;
/** User-configured gamepad axis deadzone (0.0f to 1.0f). */
float_t deadzone;
} input_t; } input_t;
extern input_t INPUT; extern input_t INPUT;
@@ -6,4 +6,5 @@
# Sources # Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME} target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
globalitemstore.c
) )
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "globalitemstore.h"
#include "assert/assert.h"
bool_t globalItemStoreIsCollected(
const savefile_t *file, const entityglobalid_t id
) {
assertNotNull(file, "Save file cannot be NULL");
assertTrue(id < SAVE_GLOBAL_ITEM_COUNT_MAX, "Global item ID out of range");
return file->globalItemCollected[id];
}
void globalItemStoreSetCollected(
savefile_t *file, const entityglobalid_t id, const bool_t collected
) {
assertNotNull(file, "Save file cannot be NULL");
assertTrue(id < SAVE_GLOBAL_ITEM_COUNT_MAX, "Global item ID out of range");
file->globalItemCollected[id] = collected;
}
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include "save/savefile.h"
#include "rpg/entity/entity.h"
/**
* Checks whether the global entity with the given ID has already been
* marked collected in the given save file's data - e.g. so a global item
* entity's init callback (see rpg/entity/global/entitygloballist.h) can
* skip spawning itself if the player already picked it up in a prior
* session, without needing to keep the entity itself alive to remember
* that (which would need render/collision special-casing - this doesn't).
*
* @param file The save file to check.
* @param id The global entity ID to check.
* @return True if already marked collected.
*/
bool_t globalItemStoreIsCollected(
const savefile_t *file, const entityglobalid_t id
);
/**
* Marks the global entity with the given ID as collected (or not) in the
* given save file's data. Does not itself write the save to disk - call
* saveWrite() separately once ready to persist it.
*
* @param file The save file to write into.
* @param id The global entity ID to mark.
* @param collected The new collected state.
*/
void globalItemStoreSetCollected(
savefile_t *file, const entityglobalid_t id, const bool_t collected
);
+8 -2
View File
@@ -22,6 +22,7 @@
#include "error/error.h" #include "error/error.h"
#include "ui/rpg/uiemoji.h" #include "ui/rpg/uiemoji.h"
#include "rpg/story/storyflag.h"
static void rpgTestSaveComplete(errorret_t result, void *user) { static void rpgTestSaveComplete(errorret_t result, void *user) {
if(errorIsNotOk(result)) errorCatch(errorPrint(result)); if(errorIsNotOk(result)) errorCatch(errorPrint(result));
@@ -31,6 +32,11 @@ errorret_t rpgInit(void) {
memoryZero(ENTITIES, sizeof(ENTITIES)); memoryZero(ENTITIES, sizeof(ENTITIES));
memoryZero(MAP_AREAS, sizeof(MAP_AREAS)); memoryZero(MAP_AREAS, sizeof(MAP_AREAS));
// Must run before any code reads a story flag - stamps CSV-defined
// defaults onto the active save slot if it's never actually been
// loaded from disk yet.
storyFlagInitDefaults(saveGet(SAVE_ACTIVE_SLOT));
backpackInit(); backpackInit();
partyInit(); partyInit();
cutsceneSystemInit(); cutsceneSystemInit();
@@ -61,9 +67,9 @@ errorret_t rpgInit(void) {
// header/version. Remove once there's an actual name-entry flow. On PSP // header/version. Remove once there's an actual name-entry flow. On PSP
// this shows the real native save dialog every boot - expected while // this shows the real native save dialog every boot - expected while
// testing that path, not something to ship as-is. // testing that path, not something to ship as-is.
savefile_t *saveFile = saveGet(0); savefile_t *saveFile = saveGet(SAVE_ACTIVE_SLOT);
stringCopy(saveFile->playerName, "Dusk", SAVE_PLAYER_NAME_MAX); stringCopy(saveFile->playerName, "Dusk", SAVE_PLAYER_NAME_MAX);
saveWrite(0, rpgTestSaveComplete, NULL); saveWrite(SAVE_ACTIVE_SLOT, rpgTestSaveComplete, NULL);
// All Good! // All Good!
errorOk(); errorOk();
+15 -3
View File
@@ -1,6 +1,6 @@
/** /**
* Copyright (c) 2026 Dominic Masters * Copyright (c) 2026 Dominic Masters
* *
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
@@ -10,5 +10,17 @@
void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value) { void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value) {
assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag"); assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag");
STORY_FLAG_VALUES[flag] = value; saveGet(SAVE_ACTIVE_SLOT)->storyFlags[flag] = value;
} }
void storyFlagInitDefaults(savefile_t *file) {
assertNotNull(file, "Save file cannot be NULL");
if(file->exists) return;
assertTrue(
STORY_FLAG_COUNT <= SAVE_STORY_FLAG_COUNT_MAX,
"Too many story flags for the save format - bump SAVE_STORY_FLAG_COUNT_MAX"
);
for(storyflag_t i = 0; i < STORY_FLAG_COUNT; i++) {
file->storyFlags[i] = STORY_FLAG_DEFAULTS[i];
}
}
+22 -7
View File
@@ -1,25 +1,40 @@
/** /**
* Copyright (c) 2026 Dominic Masters * Copyright (c) 2026 Dominic Masters
* *
* This software is released under the MIT License. * This software is released under the MIT License.
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#pragma once #pragma once
#include "rpg/story/storyflagvalue.h" #include "rpg/story/storyflagvalue.h"
#include "save/save.h"
/** /**
* Gets the value of a story flag. * Gets the value of a story flag. Reads directly from the active save
* * file (see SAVE_ACTIVE_SLOT) - flag values have no separate live copy.
*
* @param flag The story flag to get. * @param flag The story flag to get.
* @return The value of the story flag. * @return The value of the story flag.
*/ */
#define storyFlagGet(flag) (STORY_FLAG_VALUES[(flag)]) #define storyFlagGet(flag) (saveGet(SAVE_ACTIVE_SLOT)->storyFlags[(flag)])
/** /**
* Sets the value of a story flag. * Sets the value of a story flag, directly in the active save file (see
* * SAVE_ACTIVE_SLOT). Does not itself write the save to disk - call
* saveWrite() separately once ready to persist it.
*
* @param flag The story flag to set. * @param flag The story flag to set.
* @param value The value to set the story flag to. * @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 storyflagvalue_t value);
/**
* Stamps each story flag's CSV-defined default (STORY_FLAG_DEFAULTS) onto
* the given save file, but only if it hasn't actually been loaded from
* disk yet (file->exists is false) - otherwise leaves already-played
* progress alone. Call once, e.g. during rpgInit(), before any gameplay
* code reads a story flag.
*
* @param file The save file to stamp defaults onto.
*/
void storyFlagInitDefaults(savefile_t *file);
+7
View File
@@ -16,6 +16,13 @@ save_t SAVE;
errorret_t saveInit(void) { errorret_t saveInit(void) {
memoryZero(&SAVE, sizeof(save_t)); memoryZero(&SAVE, sizeof(save_t));
// Establishes the default for a slot that hasn't actually been loaded
// from disk yet - saveLoad() overwrites this the moment a real file is
// found, so this only matters for a brand new save.
for(uint8_t i = 0; i < SAVE_FILE_COUNT_MAX; i++) {
SAVE.files[i].deadzone = SAVE_DEADZONE_DEFAULT;
}
#ifdef saveInitPlatform #ifdef saveInitPlatform
// A missing/unreachable save medium is expected, recoverable state, // A missing/unreachable save medium is expected, recoverable state,
// not a reason to fail booting the whole game - log it and carry on // not a reason to fail booting the whole game - log it and carry on
+49
View File
@@ -20,9 +20,44 @@
/** Maximum number of independent save slots supported. */ /** Maximum number of independent save slots supported. */
#define SAVE_FILE_COUNT_MAX 3 #define SAVE_FILE_COUNT_MAX 3
/**
* The save slot actually used for gameplay right now - there's no slot
* select/multi-save UX yet (SAVE_FILE_COUNT_MAX > 1 exists for later), so
* every part of the game that needs "the" save file (settings, the game
* menu's Save button, etc.) reads/writes this one slot.
*/
#define SAVE_ACTIVE_SLOT 0
/** Maximum length of a saved player name, including the null terminator. */ /** Maximum length of a saved player name, including the null terminator. */
#define SAVE_PLAYER_NAME_MAX 32 #define SAVE_PLAYER_NAME_MAX 32
/**
* Maximum number of global entities whose "collected" state can be
* tracked - see rpg/entity/global/globalitemstore.h. Bounded/fixed here
* rather than tied to ENTITY_GLOBAL_LIST_COUNT, since savefile.h is a
* leaf header with no dependency on the entity system (and no reason to
* take one just for a size constant).
*/
#define SAVE_GLOBAL_ITEM_COUNT_MAX 64
/**
* Default gamepad deadzone for a save slot that's never actually been
* loaded from disk yet (see saveInit(), which stamps this onto every
* slot up front) - defined here, rather than by the input system, since
* the save file is now the single source of truth for this value (see
* savefile_t.deadzone) - nothing else stores or defaults it.
*/
#define SAVE_DEADZONE_DEFAULT 0.1f
/**
* Maximum number of story flags the save format can hold - see
* rpg/story/storyflag.h. Bounded/fixed here (with real headroom over the
* current flag count) rather than tied to STORY_FLAG_COUNT, since
* savefile.h is a leaf header with no dependency on generated story
* content, matching SAVE_GLOBAL_ITEM_COUNT_MAX's reasoning.
*/
#define SAVE_STORY_FLAG_COUNT_MAX 128
typedef struct { typedef struct {
/** Magic header bytes read from the file; must equal SAVE_FILE_HEADER. */ /** Magic header bytes read from the file; must equal SAVE_FILE_HEADER. */
char_t header[SAVE_FILE_HEADER_SIZE]; char_t header[SAVE_FILE_HEADER_SIZE];
@@ -32,6 +67,20 @@ typedef struct {
bool_t exists; bool_t exists;
/** The player's saved name. */ /** The player's saved name. */
char_t playerName[SAVE_PLAYER_NAME_MAX]; char_t playerName[SAVE_PLAYER_NAME_MAX];
/** Per-global-ID "already collected" flags - see globalitemstore.h. */
bool_t globalItemCollected[SAVE_GLOBAL_ITEM_COUNT_MAX];
/**
* User-configured gamepad deadzone (0.0f-1.0f) - the save file is the
* only place this lives; read it directly via saveGet(SAVE_ACTIVE_SLOT)
* ->deadzone rather than caching it anywhere else.
*/
float_t deadzone;
/**
* Story flag values, indexed by storyflag_t - the save file is the only
* place these live; read/write via storyFlagGet()/storyFlagSet() (see
* rpg/story/storyflag.h), not directly.
*/
uint8_t storyFlags[SAVE_STORY_FLAG_COUNT_MAX];
} savefile_t; } savefile_t;
/** /**
+14
View File
@@ -331,6 +331,13 @@ errorret_t saveFileLoad(savestream_t *stream, savefile_t *file) {
saveFileReadHeader(stream, file->header); saveFileReadHeader(stream, file->header);
saveFileReadVersion(stream, &file->version); saveFileReadVersion(stream, &file->version);
saveFileReadString(stream, file->playerName, SAVE_PLAYER_NAME_MAX); saveFileReadString(stream, file->playerName, SAVE_PLAYER_NAME_MAX);
for(size_t i = 0; i < SAVE_GLOBAL_ITEM_COUNT_MAX; i++) {
saveFileReadBool(stream, &file->globalItemCollected[i]);
}
saveFileReadFloat(stream, &file->deadzone);
for(size_t i = 0; i < SAVE_STORY_FLAG_COUNT_MAX; i++) {
saveFileReadUInt8(stream, &file->storyFlags[i]);
}
errorOk(); errorOk();
} }
@@ -338,5 +345,12 @@ errorret_t saveFileWrite(savestream_t *stream, savefile_t *file) {
saveFileWriteHeader(stream, file->header); saveFileWriteHeader(stream, file->header);
saveFileWriteVersion(stream, &file->version); saveFileWriteVersion(stream, &file->version);
saveFileWriteString(stream, file->playerName, SAVE_PLAYER_NAME_MAX); saveFileWriteString(stream, file->playerName, SAVE_PLAYER_NAME_MAX);
for(size_t i = 0; i < SAVE_GLOBAL_ITEM_COUNT_MAX; i++) {
saveFileWriteBool(stream, &file->globalItemCollected[i]);
}
saveFileWriteFloat(stream, &file->deadzone);
for(size_t i = 0; i < SAVE_STORY_FLAG_COUNT_MAX; i++) {
saveFileWriteUInt8(stream, &file->storyFlags[i]);
}
errorOk(); errorOk();
} }
+4 -8
View File
@@ -26,10 +26,6 @@
#define UI_GAME_MENU_INDEX_SETTINGS 2 #define UI_GAME_MENU_INDEX_SETTINGS 2
#define UI_GAME_MENU_INDEX_SAVE 3 #define UI_GAME_MENU_INDEX_SAVE 3
// Only one save slot is exposed through this menu for now - there is no
// slot-select UI yet, and SAVE_FILE_COUNT_MAX > 1 exists for later.
#define UI_GAME_MENU_SAVE_SLOT 0
static void uiGameMenuSaveWriteComplete(errorret_t result, void *user) { static void uiGameMenuSaveWriteComplete(errorret_t result, void *user) {
if(errorIsNotOk(result)) { if(errorIsNotOk(result)) {
// Generously sized - stringFormat asserts (crashes) rather than // Generously sized - stringFormat asserts (crashes) rather than
@@ -53,7 +49,7 @@ static void uiGameMenuSaveCreateConfirmed(const bool_t confirmed, void *user) {
return; return;
} }
saveWrite(UI_GAME_MENU_SAVE_SLOT, uiGameMenuSaveWriteComplete, NULL); saveWrite(SAVE_ACTIVE_SLOT, uiGameMenuSaveWriteComplete, NULL);
} }
// Determines whether there's actually save data to overwrite (not just // Determines whether there's actually save data to overwrite (not just
@@ -72,8 +68,8 @@ static void uiGameMenuSaveCheckComplete(errorret_t result, void *user) {
return; return;
} }
if(saveExists(UI_GAME_MENU_SAVE_SLOT)) { if(saveExists(SAVE_ACTIVE_SLOT)) {
saveWrite(UI_GAME_MENU_SAVE_SLOT, uiGameMenuSaveWriteComplete, NULL); saveWrite(SAVE_ACTIVE_SLOT, uiGameMenuSaveWriteComplete, NULL);
return; return;
} }
@@ -91,7 +87,7 @@ static void uiGameMenuSave(void) {
} }
if(saveIsBusy()) return;// A save/load dialog (e.g. on PSP) is already up. if(saveIsBusy()) return;// A save/load dialog (e.g. on PSP) is already up.
saveLoad(UI_GAME_MENU_SAVE_SLOT, uiGameMenuSaveCheckComplete, NULL); saveLoad(SAVE_ACTIVE_SLOT, uiGameMenuSaveCheckComplete, NULL);
} }
uigamemenu_t UI_GAME_MENU; uigamemenu_t UI_GAME_MENU;
+5 -5
View File
@@ -11,7 +11,7 @@
#include "util/memory.h" #include "util/memory.h"
#include "locale/localemanager.h" #include "locale/localemanager.h"
#include "asset/loader/locale/assetlocaleloader.h" #include "asset/loader/locale/assetlocaleloader.h"
#include "input/input.h" #include "save/save.h"
void uiSettingsInputSelected( void uiSettingsInputSelected(
const uimenu_t *menu, const uimenu_t *menu,
@@ -39,7 +39,7 @@ errorret_t uiSettingsInputInit(uisettingsdata_t *data) {
UI_SETTINGS_INPUT_LABEL_MAX UI_SETTINGS_INPUT_LABEL_MAX
)); ));
MENU_SLIDER_FLOAT( MENU_SLIDER_FLOAT(
input->deadzoneLabel, INPUT_DEADZONE_DEFAULT, 0.0f, 1.0f, 0.05f input->deadzoneLabel, SAVE_DEADZONE_DEFAULT, 0.0f, 1.0f, 0.05f
); );
#else #else
MENU_LABEL("No input settings yet"); MENU_LABEL("No input settings yet");
@@ -55,14 +55,14 @@ void uiSettingsInputLoad(void) {
#ifdef DUSK_INPUT_GAMEPAD #ifdef DUSK_INPUT_GAMEPAD
uiSliderSetFloat( uiSliderSetFloat(
&UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider, &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider,
INPUT.deadzone saveGet(SAVE_ACTIVE_SLOT)->deadzone
); );
#endif #endif
} }
void uiSettingsInputApply(void) { void uiSettingsInputApply(void) {
#ifdef DUSK_INPUT_GAMEPAD #ifdef DUSK_INPUT_GAMEPAD
INPUT.deadzone = uiSliderGetFloat( saveGet(SAVE_ACTIVE_SLOT)->deadzone = uiSliderGetFloat(
&UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider
); );
#endif #endif
@@ -73,7 +73,7 @@ bool_t uiSettingsInputHasChanges(void) {
#ifdef DUSK_INPUT_GAMEPAD #ifdef DUSK_INPUT_GAMEPAD
if(uiSliderGetFloat( if(uiSliderGetFloat(
&UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider
) != INPUT.deadzone) return true; ) != saveGet(SAVE_ACTIVE_SLOT)->deadzone) return true;
#endif #endif
return false; return false;
+2 -1
View File
@@ -9,6 +9,7 @@
#include "assert/assert.h" #include "assert/assert.h"
#include "log/log.h" #include "log/log.h"
#include "util/string.h" #include "util/string.h"
#include "save/save.h"
inputbuttondata_t INPUT_BUTTON_DATA[] = { inputbuttondata_t INPUT_BUTTON_DATA[] = {
#ifdef DUSK_INPUT_GAMEPAD #ifdef DUSK_INPUT_GAMEPAD
@@ -187,5 +188,5 @@ float_t inputButtonGetValueDolphin(const inputbutton_t button) {
} }
float_t inputGetDeadzoneDolphin(const inputbutton_t button) { float_t inputGetDeadzoneDolphin(const inputbutton_t button) {
return 0.2f; return saveGet(SAVE_ACTIVE_SLOT)->deadzone;
} }
+2 -1
View File
@@ -6,6 +6,7 @@
*/ */
#include "input/input.h" #include "input/input.h"
#include "save/save.h"
inputbuttondata_t INPUT_BUTTON_DATA[] = { inputbuttondata_t INPUT_BUTTON_DATA[] = {
#ifdef DUSK_INPUT_GAMEPAD #ifdef DUSK_INPUT_GAMEPAD
@@ -547,5 +548,5 @@ errorret_t inputInitLinux(void) {
} }
float_t inputGetDeadzoneSDL2(const inputbutton_t button) { float_t inputGetDeadzoneSDL2(const inputbutton_t button) {
return 0.17f; return saveGet(SAVE_ACTIVE_SLOT)->deadzone;
} }
+2 -1
View File
@@ -6,6 +6,7 @@
*/ */
#include "input/input.h" #include "input/input.h"
#include "save/save.h"
// #define INPUT_PSP_GAMEPAD_BUTTON_ACCEPT INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM // #define INPUT_PSP_GAMEPAD_BUTTON_ACCEPT INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM
// #define INPUT_PSP_GAMEPAD_BUTTON_CANCEL INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM // #define INPUT_PSP_GAMEPAD_BUTTON_CANCEL INPUT_SDL2_GAMEPAD_BUTTON_CUSTOM
@@ -94,5 +95,5 @@ errorret_t inputInitPSP(void) {
} }
float_t inputGetDeadzoneSDL2(const inputbutton_t button) { float_t inputGetDeadzoneSDL2(const inputbutton_t button) {
return 0.2f; return saveGet(SAVE_ACTIVE_SLOT)->deadzone;
} }
+2 -1
View File
@@ -6,6 +6,7 @@
*/ */
#include "input/input.h" #include "input/input.h"
#include "save/save.h"
inputbuttondata_t INPUT_BUTTON_DATA[] = { inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "triangle", { { .name = "triangle", {
@@ -83,5 +84,5 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
}; };
float_t inputGetDeadzoneSDL2(const inputbutton_t button) { float_t inputGetDeadzoneSDL2(const inputbutton_t button) {
return 0.17f; return saveGet(SAVE_ACTIVE_SLOT)->deadzone;
} }
+5 -1
View File
@@ -38,7 +38,11 @@ out += [
" STORY_FLAG_COUNT", " STORY_FLAG_COUNT",
"} storyflag_t;", "} storyflag_t;",
"", "",
"static storyflagvalue_t STORY_FLAG_VALUES[STORY_FLAG_COUNT] = {", "// 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: for flag in flags:
out.append(f" [{flag_enum(flag['id'])}] = {flag['initial']},") out.append(f" [{flag_enum(flag['id'])}] = {flag['initial']},")