Game code start
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_subdirectory(dusk)
|
add_subdirectory(dusk)
|
||||||
|
add_subdirectory(duskrpg)
|
||||||
|
|
||||||
if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "knulli")
|
if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "knulli")
|
||||||
add_subdirectory(dusklinux)
|
add_subdirectory(dusklinux)
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ add_subdirectory(entity)
|
|||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(engine)
|
add_subdirectory(engine)
|
||||||
add_subdirectory(error)
|
add_subdirectory(error)
|
||||||
|
add_subdirectory(game)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(locale)
|
add_subdirectory(locale)
|
||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ void consoleUpdate(void) {
|
|||||||
if(TIME.dynamicUpdate) return;
|
if(TIME.dynamicUpdate) return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(inputPressed(INPUT_ACTION_CONSOLE)) {
|
if(inputPressed(INPUT_BIND_CONSOLE)) {
|
||||||
CONSOLE.visible = !CONSOLE.visible;
|
CONSOLE.visible = !CONSOLE.visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
|
#include "game/game.h"
|
||||||
#include "system/system.h"
|
#include "system/system.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
#include "save/save.h"
|
#include "save/save.h"
|
||||||
@@ -45,6 +46,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
errorChain(uiInit());
|
errorChain(uiInit());
|
||||||
errorChain(networkInit());
|
errorChain(networkInit());
|
||||||
errorChain(sceneInit());
|
errorChain(sceneInit());
|
||||||
|
errorChain(gameInit());
|
||||||
|
|
||||||
consolePrint("Engine initialized");
|
consolePrint("Engine initialized");
|
||||||
|
|
||||||
@@ -69,6 +71,7 @@ errorret_t engineUpdate(void) {
|
|||||||
inputUpdate();
|
inputUpdate();
|
||||||
consoleUpdate();
|
consoleUpdate();
|
||||||
|
|
||||||
|
errorChain(gameUpdate());
|
||||||
errorChain(sceneUpdate());
|
errorChain(sceneUpdate());
|
||||||
errorChain(assetUpdate());
|
errorChain(assetUpdate());
|
||||||
errorChain(uiUpdate());
|
errorChain(uiUpdate());
|
||||||
@@ -78,7 +81,7 @@ errorret_t engineUpdate(void) {
|
|||||||
errorChain(displayUpdate());
|
errorChain(displayUpdate());
|
||||||
if(
|
if(
|
||||||
dialogType == SYSTEM_DIALOG_TYPE_NONE &&
|
dialogType == SYSTEM_DIALOG_TYPE_NONE &&
|
||||||
inputPressed(INPUT_ACTION_RAGEQUIT)
|
inputPressed(INPUT_BIND_RAGEQUIT)
|
||||||
) {
|
) {
|
||||||
ENGINE.running = false;
|
ENGINE.running = false;
|
||||||
}
|
}
|
||||||
@@ -90,6 +93,7 @@ void engineExit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t engineDispose(void) {
|
errorret_t engineDispose(void) {
|
||||||
|
errorChain(gameDispose());
|
||||||
errorChain(sceneDispose());
|
errorChain(sceneDispose());
|
||||||
errorChain(networkDispose());
|
errorChain(networkDispose());
|
||||||
localeManagerDispose();
|
localeManagerDispose();
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Header-only: game.h's implementation lives in src/duskrpg/game/game.c
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 game. Called once, after the engine and all of its
|
||||||
|
* subsystems have finished initializing.
|
||||||
|
*
|
||||||
|
* @return An error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t gameInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the game. Called once per frame.
|
||||||
|
*
|
||||||
|
* @return An error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t gameUpdate(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the game. Called once, before the engine disposes of its
|
||||||
|
* own subsystems.
|
||||||
|
*
|
||||||
|
* @return An error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t gameDispose(void);
|
||||||
@@ -9,13 +9,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
input.c
|
input.c
|
||||||
inputbutton.c
|
inputbutton.c
|
||||||
inputaction.c
|
inputaction.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Input Action Definitions
|
|
||||||
dusk_run_python(
|
|
||||||
dusk_input_csv_defs
|
|
||||||
tools.input
|
|
||||||
--csv ${CMAKE_CURRENT_SOURCE_DIR}/input.csv
|
|
||||||
--output ${DUSK_GENERATED_HEADERS_DIR}/input/inputactiondefs.h
|
|
||||||
)
|
|
||||||
add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_input_csv_defs)
|
|
||||||
+35
-35
@@ -18,8 +18,8 @@ errorret_t inputInit(void) {
|
|||||||
memoryZero(&INPUT, sizeof(input_t));
|
memoryZero(&INPUT, sizeof(input_t));
|
||||||
INPUT.deadzone = INPUT_DEADZONE_DEFAULT;
|
INPUT.deadzone = INPUT_DEADZONE_DEFAULT;
|
||||||
|
|
||||||
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
|
for(uint8_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||||
INPUT.actions[i].action = (inputaction_t)i;
|
INPUT.actions[i].action = (inputbind_t)i;
|
||||||
INPUT.actions[i].lastValue = 0.0f;
|
INPUT.actions[i].lastValue = 0.0f;
|
||||||
INPUT.actions[i].currentValue = 0.0f;
|
INPUT.actions[i].currentValue = 0.0f;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ void inputUpdate(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
action++;
|
action++;
|
||||||
} while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
|
} while(action < &INPUT.actions[INPUT_BIND_COUNT]);
|
||||||
|
|
||||||
// For each button...
|
// For each button...
|
||||||
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
|
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
|
||||||
@@ -85,62 +85,62 @@ void inputUpdate(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputGetCurrentValue(const inputaction_t action) {
|
float_t inputGetCurrentValue(const inputbind_t action) {
|
||||||
#ifdef DUSK_TIME_DYNAMIC
|
#ifdef DUSK_TIME_DYNAMIC
|
||||||
if(TIME.dynamicUpdate) return inputGetCurrentValueDynamic(action);
|
if(TIME.dynamicUpdate) return inputGetCurrentValueDynamic(action);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].currentValue;
|
return INPUT.actions[action].currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputGetLastValue(const inputaction_t action) {
|
float_t inputGetLastValue(const inputbind_t action) {
|
||||||
#ifdef DUSK_TIME_DYNAMIC
|
#ifdef DUSK_TIME_DYNAMIC
|
||||||
if(TIME.dynamicUpdate) return inputGetLastValueDynamic(action);
|
if(TIME.dynamicUpdate) return inputGetLastValueDynamic(action);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].lastValue;
|
return INPUT.actions[action].lastValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUSK_TIME_DYNAMIC
|
#ifdef DUSK_TIME_DYNAMIC
|
||||||
float_t inputGetCurrentValueDynamic(const inputaction_t action) {
|
float_t inputGetCurrentValueDynamic(const inputbind_t action) {
|
||||||
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].currentDynamicValue;
|
return INPUT.actions[action].currentDynamicValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputGetLastValueDynamic(const inputaction_t action) {
|
float_t inputGetLastValueDynamic(const inputbind_t action) {
|
||||||
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].lastDynamicValue;
|
return INPUT.actions[action].lastDynamicValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputIsDownDynamic(const inputaction_t action) {
|
bool_t inputIsDownDynamic(const inputbind_t action) {
|
||||||
return inputGetCurrentValueDynamic(action) > 0.0f;
|
return inputGetCurrentValueDynamic(action) > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputWasDownDynamic(const inputaction_t action) {
|
bool_t inputWasDownDynamic(const inputbind_t action) {
|
||||||
return inputGetLastValueDynamic(action) > 0.0f;
|
return inputGetLastValueDynamic(action) > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputPressedDynamic(const inputaction_t action) {
|
bool_t inputPressedDynamic(const inputbind_t action) {
|
||||||
return inputIsDownDynamic(action) && !inputWasDownDynamic(action);
|
return inputIsDownDynamic(action) && !inputWasDownDynamic(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputReleasedDynamic(const inputaction_t action) {
|
bool_t inputReleasedDynamic(const inputbind_t action) {
|
||||||
return !inputIsDownDynamic(action) && inputWasDownDynamic(action);
|
return !inputIsDownDynamic(action) && inputWasDownDynamic(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputAxisDynamic(
|
float_t inputAxisDynamic(
|
||||||
const inputaction_t neg,
|
const inputbind_t neg,
|
||||||
const inputaction_t pos
|
const inputbind_t pos
|
||||||
) {
|
) {
|
||||||
return inputGetCurrentValueDynamic(pos) -
|
return inputGetCurrentValueDynamic(pos) -
|
||||||
inputGetCurrentValueDynamic(neg);
|
inputGetCurrentValueDynamic(neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void inputAxis2DDynamic(
|
void inputAxis2DDynamic(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
) {
|
) {
|
||||||
assertNotNull(result, "Result vector cannot be null");
|
assertNotNull(result, "Result vector cannot be null");
|
||||||
@@ -149,8 +149,8 @@ float_t inputGetLastValue(const inputaction_t action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void inputAngle2DDynamic(
|
void inputAngle2DDynamic(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
) {
|
) {
|
||||||
assertNotNull(result, "Result vector cannot be null");
|
assertNotNull(result, "Result vector cannot be null");
|
||||||
@@ -171,32 +171,32 @@ float_t inputGetLastValue(const inputaction_t action) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool_t inputIsDown(const inputaction_t action) {
|
bool_t inputIsDown(const inputbind_t action) {
|
||||||
return inputGetCurrentValue(action) > 0.0f;
|
return inputGetCurrentValue(action) > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputWasDown(const inputaction_t action) {
|
bool_t inputWasDown(const inputbind_t action) {
|
||||||
return inputGetLastValue(action) > 0.0f;
|
return inputGetLastValue(action) > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputPressed(const inputaction_t action) {
|
bool_t inputPressed(const inputbind_t action) {
|
||||||
return inputIsDown(action) && !inputWasDown(action);
|
return inputIsDown(action) && !inputWasDown(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputReleased(const inputaction_t action) {
|
bool_t inputReleased(const inputbind_t action) {
|
||||||
return !inputIsDown(action) && inputWasDown(action);
|
return !inputIsDown(action) && inputWasDown(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputAxis(const inputaction_t neg, const inputaction_t pos) {
|
float_t inputAxis(const inputbind_t neg, const inputbind_t pos) {
|
||||||
assertTrue(neg < INPUT_ACTION_COUNT, "Negative input action out of bounds");
|
assertTrue(neg < INPUT_BIND_COUNT, "Negative input action out of bounds");
|
||||||
assertTrue(pos < INPUT_ACTION_COUNT, "Positive input action out of bounds");
|
assertTrue(pos < INPUT_BIND_COUNT, "Positive input action out of bounds");
|
||||||
|
|
||||||
return inputGetCurrentValue(pos) - inputGetCurrentValue(neg);
|
return inputGetCurrentValue(pos) - inputGetCurrentValue(neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void inputAxis2D(
|
void inputAxis2D(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
) {
|
) {
|
||||||
assertNotNull(result, "Result vector cannot be null");
|
assertNotNull(result, "Result vector cannot be null");
|
||||||
@@ -205,8 +205,8 @@ void inputAxis2D(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void inputAngle2D(
|
void inputAngle2D(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
) {
|
) {
|
||||||
assertNotNull(result, "Result vector cannot be null");
|
assertNotNull(result, "Result vector cannot be null");
|
||||||
@@ -226,12 +226,12 @@ void inputAngle2D(
|
|||||||
result[1] = y;
|
result[1] = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void inputBind(const inputbutton_t button, const inputaction_t act) {
|
void inputBind(const inputbutton_t button, const inputbind_t act) {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
act < INPUT_ACTION_COUNT,
|
act < INPUT_BIND_COUNT,
|
||||||
"Invalid input action"
|
"Invalid input action"
|
||||||
);
|
);
|
||||||
assertTrue(act != INPUT_ACTION_NULL, "Cannot bind to NULL action");
|
assertTrue(act != INPUT_BIND_NULL, "Cannot bind to NULL action");
|
||||||
|
|
||||||
// Get the button data for this button.
|
// Get the button data for this button.
|
||||||
inputbuttondata_t *data = inputButtonGetData(button);
|
inputbuttondata_t *data = inputButtonGetData(button);
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
id,
|
|
||||||
UP,
|
|
||||||
DOWN,
|
|
||||||
LEFT,
|
|
||||||
RIGHT,
|
|
||||||
ACCEPT,
|
|
||||||
CANCEL,
|
|
||||||
PAUSE,
|
|
||||||
RAGEQUIT,
|
|
||||||
CONSOLE,
|
|
||||||
POINTERX,
|
|
||||||
POINTERY,
|
|
||||||
|
+25
-25
@@ -15,7 +15,7 @@
|
|||||||
#define INPUT_DEADZONE_DEFAULT 0.1f
|
#define INPUT_DEADZONE_DEFAULT 0.1f
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
inputactiondata_t actions[INPUT_ACTION_COUNT];
|
inputactiondata_t actions[INPUT_BIND_COUNT];
|
||||||
|
|
||||||
inputplatform_t platform;
|
inputplatform_t platform;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ void inputUpdate(void);
|
|||||||
* @param action The input action to get the value for.
|
* @param action The input action to get the value for.
|
||||||
* @return The current value of the action (0.0f to 1.0f).
|
* @return The current value of the action (0.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputGetCurrentValue(const inputaction_t action);
|
float_t inputGetCurrentValue(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the last value of a specific input action.
|
* Gets the last value of a specific input action.
|
||||||
@@ -51,7 +51,7 @@ float_t inputGetCurrentValue(const inputaction_t action);
|
|||||||
* @param action The input action to get the value for.
|
* @param action The input action to get the value for.
|
||||||
* @return The last value of the action (0.0f to 1.0f).
|
* @return The last value of the action (0.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputGetLastValue(const inputaction_t action);
|
float_t inputGetLastValue(const inputbind_t action);
|
||||||
|
|
||||||
#ifdef DUSK_TIME_DYNAMIC
|
#ifdef DUSK_TIME_DYNAMIC
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +60,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to get the value for.
|
* @param action The input action to get the value for.
|
||||||
* @return The current value of the action (0.0f to 1.0f).
|
* @return The current value of the action (0.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputGetCurrentValueDynamic(const inputaction_t action);
|
float_t inputGetCurrentValueDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the last value of a specific input action (dynamic timestep).
|
* Gets the last value of a specific input action (dynamic timestep).
|
||||||
@@ -68,7 +68,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to get the value for.
|
* @param action The input action to get the value for.
|
||||||
* @return The last value of the action (0.0f to 1.0f).
|
* @return The last value of the action (0.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputGetLastValueDynamic(const inputaction_t action);
|
float_t inputGetLastValueDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an action is currently down on the dynamic timestep.
|
* Checks if an action is currently down on the dynamic timestep.
|
||||||
@@ -76,7 +76,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action is currently down.
|
* @return true if the action is currently down.
|
||||||
*/
|
*/
|
||||||
bool_t inputIsDownDynamic(const inputaction_t action);
|
bool_t inputIsDownDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an action was down on the previous dynamic frame.
|
* Checks if an action was down on the previous dynamic frame.
|
||||||
@@ -84,7 +84,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action was down last dynamic frame.
|
* @return true if the action was down last dynamic frame.
|
||||||
*/
|
*/
|
||||||
bool_t inputWasDownDynamic(const inputaction_t action);
|
bool_t inputWasDownDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an action was pressed this dynamic frame (down now, not before).
|
* Checks if an action was pressed this dynamic frame (down now, not before).
|
||||||
@@ -92,7 +92,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action was just pressed this dynamic frame.
|
* @return true if the action was just pressed this dynamic frame.
|
||||||
*/
|
*/
|
||||||
bool_t inputPressedDynamic(const inputaction_t action);
|
bool_t inputPressedDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an action was released this dynamic frame (up now, down before).
|
* Checks if an action was released this dynamic frame (up now, down before).
|
||||||
@@ -100,7 +100,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action was just released this dynamic frame.
|
* @return true if the action was just released this dynamic frame.
|
||||||
*/
|
*/
|
||||||
bool_t inputReleasedDynamic(const inputaction_t action);
|
bool_t inputReleasedDynamic(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of an input axis on the dynamic timestep.
|
* Gets the value of an input axis on the dynamic timestep.
|
||||||
@@ -110,8 +110,8 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @return The current axis value (-1.0f to 1.0f).
|
* @return The current axis value (-1.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputAxisDynamic(
|
float_t inputAxisDynamic(
|
||||||
const inputaction_t neg,
|
const inputbind_t neg,
|
||||||
const inputaction_t pos
|
const inputbind_t pos
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,8 +124,8 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param result vec2 to store the result (-1.0f to 1.0f per axis).
|
* @param result vec2 to store the result (-1.0f to 1.0f per axis).
|
||||||
*/
|
*/
|
||||||
void inputAxis2DDynamic(
|
void inputAxis2DDynamic(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -139,8 +139,8 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param result vec2 to store the result.
|
* @param result vec2 to store the result.
|
||||||
*/
|
*/
|
||||||
void inputAngle2DDynamic(
|
void inputAngle2DDynamic(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
@@ -151,7 +151,7 @@ float_t inputGetLastValue(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action is currently pressed, false otherwise.
|
* @return true if the action is currently pressed, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t inputIsDown(const inputaction_t action);
|
bool_t inputIsDown(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a specific input action was pressed in the last update.
|
* Checks if a specific input action was pressed in the last update.
|
||||||
@@ -159,7 +159,7 @@ bool_t inputIsDown(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action was pressed in the last update, false otherwise.
|
* @return true if the action was pressed in the last update, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t inputWasDown(const inputaction_t action);
|
bool_t inputWasDown(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a specific input action was down this frame but not in the the
|
* Checks if a specific input action was down this frame but not in the the
|
||||||
@@ -168,7 +168,7 @@ bool_t inputWasDown(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action is currently pressed, false otherwise.
|
* @return true if the action is currently pressed, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t inputPressed(const inputaction_t action);
|
bool_t inputPressed(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a specific input action was released this frame.
|
* Checks if a specific input action was released this frame.
|
||||||
@@ -176,7 +176,7 @@ bool_t inputPressed(const inputaction_t action);
|
|||||||
* @param action The input action to check.
|
* @param action The input action to check.
|
||||||
* @return true if the action was released this frame, false otherwise.
|
* @return true if the action was released this frame, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t inputReleased(const inputaction_t action);
|
bool_t inputReleased(const inputbind_t action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of an input axis, defined by two actions (negative and
|
* Gets the value of an input axis, defined by two actions (negative and
|
||||||
@@ -186,7 +186,7 @@ bool_t inputReleased(const inputaction_t action);
|
|||||||
* @param pos The action representing the positive direction of the axis.
|
* @param pos The action representing the positive direction of the axis.
|
||||||
* @return The current value of the axis (-1.0f to 1.0f).
|
* @return The current value of the axis (-1.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
float_t inputAxis(const inputaction_t neg, const inputaction_t pos);
|
float_t inputAxis(const inputbind_t neg, const inputbind_t pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the values of a 2D input axis, defined by two pairs of actions (negative
|
* Gets the values of a 2D input axis, defined by two pairs of actions (negative
|
||||||
@@ -199,8 +199,8 @@ float_t inputAxis(const inputaction_t neg, const inputaction_t pos);
|
|||||||
* @param result A vec2 to store the resulting axis values (-1.0f to 1.0f).
|
* @param result A vec2 to store the resulting axis values (-1.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
void inputAxis2D(
|
void inputAxis2D(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -215,8 +215,8 @@ void inputAxis2D(
|
|||||||
* @param result A vec2 to store the resulting axis values (-1.0f to 1.0f).
|
* @param result A vec2 to store the resulting axis values (-1.0f to 1.0f).
|
||||||
*/
|
*/
|
||||||
void inputAngle2D(
|
void inputAngle2D(
|
||||||
const inputaction_t negX, const inputaction_t posX,
|
const inputbind_t negX, const inputbind_t posX,
|
||||||
const inputaction_t negY, const inputaction_t posY,
|
const inputbind_t negY, const inputbind_t posY,
|
||||||
vec2 result
|
vec2 result
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ void inputAngle2D(
|
|||||||
* @param button The input button to bind.
|
* @param button The input button to bind.
|
||||||
* @param action The input action to bind the button to.
|
* @param action The input action to bind the button to.
|
||||||
*/
|
*/
|
||||||
void inputBind(const inputbutton_t button, const inputaction_t act);
|
void inputBind(const inputbutton_t button, const inputbind_t act);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies deadzone formula to a raw input value. This will;
|
* Applies deadzone formula to a raw input value. This will;
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
inputaction_t inputActionGetByName(const char_t *name) {
|
inputbind_t inputActionGetByName(const char_t *name) {
|
||||||
assertNotNull(name, "name must not be NULL");
|
assertNotNull(name, "name must not be NULL");
|
||||||
|
|
||||||
for(inputaction_t i = 0; i < INPUT_ACTION_COUNT; i++) {
|
for(inputbind_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||||
if(INPUT_ACTION_IDS[i] == NULL) continue;
|
if(INPUT_BIND_IDS[i] == NULL) continue;
|
||||||
if(stringCompareInsensitive(INPUT_ACTION_IDS[i], name) != 0) continue;
|
if(stringCompareInsensitive(INPUT_BIND_IDS[i], name) != 0) continue;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return INPUT_ACTION_COUNT;
|
return INPUT_BIND_COUNT;
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
#include "input/inputactiondefs.h"
|
#include "input/inputbind.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
inputaction_t action;
|
inputbind_t action;
|
||||||
float_t lastValue;
|
float_t lastValue;
|
||||||
float_t currentValue;
|
float_t currentValue;
|
||||||
|
|
||||||
@@ -24,6 +24,6 @@ typedef struct {
|
|||||||
* Gets an input action by its name.
|
* Gets an input action by its name.
|
||||||
*
|
*
|
||||||
* @param name The name of the input action.
|
* @param name The name of the input action.
|
||||||
* @return The input action, or INPUT_ACTION_COUNT if not found.
|
* @return The input action, or INPUT_BIND_COUNT if not found.
|
||||||
*/
|
*/
|
||||||
inputaction_t inputActionGetByName(const char_t *name);
|
inputbind_t inputActionGetByName(const char_t *name);
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "inputaction.h"
|
#include "input/inputaction.h"
|
||||||
#include "input/inputplatform.h"
|
#include "input/inputplatform.h"
|
||||||
|
|
||||||
#ifndef inputButtonGetValuePlatform
|
#ifndef inputButtonGetValuePlatform
|
||||||
@@ -77,7 +77,7 @@ typedef struct {
|
|||||||
inputbutton_t button;
|
inputbutton_t button;
|
||||||
float_t curVal;
|
float_t curVal;
|
||||||
float_t lastVal;
|
float_t lastVal;
|
||||||
inputaction_t action;
|
inputbind_t action;
|
||||||
} inputbuttondata_t;
|
} inputbuttondata_t;
|
||||||
|
|
||||||
extern inputbuttondata_t INPUT_BUTTON_DATA[];
|
extern inputbuttondata_t INPUT_BUTTON_DATA[];
|
||||||
|
|||||||
+10
-10
@@ -12,11 +12,11 @@
|
|||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
|
||||||
const uifocusdirmap_t UI_FOCUS_DIR_MAP[] = {
|
const uifocusdirmap_t UI_FOCUS_DIR_MAP[] = {
|
||||||
{ INPUT_ACTION_UP, UI_FOCUS_DIRECTION_UP, 0, -1 },
|
{ INPUT_BIND_UP, UI_FOCUS_DIRECTION_UP, 0, -1 },
|
||||||
{ INPUT_ACTION_DOWN, UI_FOCUS_DIRECTION_DOWN, 0, 1 },
|
{ INPUT_BIND_DOWN, UI_FOCUS_DIRECTION_DOWN, 0, 1 },
|
||||||
{ INPUT_ACTION_LEFT, UI_FOCUS_DIRECTION_LEFT, -1, 0 },
|
{ INPUT_BIND_LEFT, UI_FOCUS_DIRECTION_LEFT, -1, 0 },
|
||||||
{ INPUT_ACTION_RIGHT, UI_FOCUS_DIRECTION_RIGHT, 1, 0 },
|
{ INPUT_BIND_RIGHT, UI_FOCUS_DIRECTION_RIGHT, 1, 0 },
|
||||||
{ INPUT_ACTION_NULL, UI_FOCUS_DIRECTION_NONE, 0, 0 },
|
{ INPUT_BIND_NULL, UI_FOCUS_DIRECTION_NONE, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
uifocus_t UI_FOCUS;
|
uifocus_t UI_FOCUS;
|
||||||
@@ -108,7 +108,7 @@ void uiFocusMoveDirection(
|
|||||||
) {
|
) {
|
||||||
for(
|
for(
|
||||||
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
||||||
m->action != INPUT_ACTION_NULL;
|
m->action != INPUT_BIND_NULL;
|
||||||
m++
|
m++
|
||||||
) {
|
) {
|
||||||
if(m->direction != dir) continue;
|
if(m->direction != dir) continue;
|
||||||
@@ -142,19 +142,19 @@ void uiFocusUpdate(void) {
|
|||||||
|
|
||||||
uifocusitem_t *item = &UI_FOCUS.items[UI_FOCUS.count - 1];
|
uifocusitem_t *item = &UI_FOCUS.items[UI_FOCUS.count - 1];
|
||||||
|
|
||||||
if(inputPressed(INPUT_ACTION_ACCEPT)) {
|
if(inputPressed(INPUT_BIND_ACCEPT)) {
|
||||||
if(item->selected != NULL) item->selected(item);
|
if(item->selected != NULL) item->selected(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inputPressed(INPUT_ACTION_CANCEL)) {
|
if(inputPressed(INPUT_BIND_CANCEL)) {
|
||||||
uiFocusPop();
|
uiFocusPop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(
|
for(
|
||||||
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
||||||
m->action != INPUT_ACTION_NULL;
|
m->action != INPUT_BIND_NULL;
|
||||||
m++
|
m++
|
||||||
) {
|
) {
|
||||||
if(!inputPressed(m->action)) continue;
|
if(!inputPressed(m->action)) continue;
|
||||||
@@ -167,7 +167,7 @@ void uiFocusUpdate(void) {
|
|||||||
bool_t held = false;
|
bool_t held = false;
|
||||||
for(
|
for(
|
||||||
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
const uifocusdirmap_t *m = UI_FOCUS_DIR_MAP;
|
||||||
m->action != INPUT_ACTION_NULL;
|
m->action != INPUT_BIND_NULL;
|
||||||
m++
|
m++
|
||||||
) {
|
) {
|
||||||
if(m->direction != UI_FOCUS.direction) continue;
|
if(m->direction != UI_FOCUS.direction) continue;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#define UI_FOCUS_HOLD_REPEAT 0.1f
|
#define UI_FOCUS_HOLD_REPEAT 0.1f
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
inputaction_t action;
|
inputbind_t action;
|
||||||
uifocusdirection_t direction;
|
uifocusdirection_t direction;
|
||||||
int8_t dx;
|
int8_t dx;
|
||||||
int8_t dy;
|
int8_t dy;
|
||||||
@@ -31,7 +31,7 @@ typedef struct {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping of input actions to focus directions, terminated by an
|
* Mapping of input actions to focus directions, terminated by an
|
||||||
* entry with action == INPUT_ACTION_NULL.
|
* entry with action == INPUT_BIND_NULL.
|
||||||
*/
|
*/
|
||||||
extern const uifocusdirmap_t UI_FOCUS_DIR_MAP[];
|
extern const uifocusdirmap_t UI_FOCUS_DIR_MAP[];
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
#include "input/inputbindmap.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "log/log.h"
|
#include "log/log.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
@@ -98,48 +99,17 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
errorret_t inputInitDolphin(void) {
|
errorret_t inputInitDolphin(void) {
|
||||||
PAD_Init();
|
PAD_Init();
|
||||||
|
|
||||||
#define X(buttonName, buttonAction) \
|
#if !defined(DUSK_GAMECUBE) && !defined(DUSK_WII)
|
||||||
inputBind(inputButtonGetByName(buttonName), buttonAction);
|
|
||||||
|
|
||||||
#if defined(DUSK_GAMECUBE)
|
|
||||||
X("up", INPUT_ACTION_UP);
|
|
||||||
X("down", INPUT_ACTION_DOWN);
|
|
||||||
X("left", INPUT_ACTION_LEFT);
|
|
||||||
X("right", INPUT_ACTION_RIGHT);
|
|
||||||
X("lstick_up", INPUT_ACTION_UP);
|
|
||||||
X("lstick_down", INPUT_ACTION_DOWN);
|
|
||||||
X("lstick_left", INPUT_ACTION_LEFT);
|
|
||||||
X("lstick_right", INPUT_ACTION_RIGHT);
|
|
||||||
|
|
||||||
X("a", INPUT_ACTION_ACCEPT);
|
|
||||||
X("b", INPUT_ACTION_CANCEL);
|
|
||||||
X("z", INPUT_ACTION_CONSOLE);
|
|
||||||
X("start", INPUT_ACTION_RAGEQUIT);
|
|
||||||
X("start", INPUT_ACTION_PAUSE);
|
|
||||||
|
|
||||||
#elif defined(DUSK_WII)
|
|
||||||
X("up", INPUT_ACTION_UP);
|
|
||||||
X("down", INPUT_ACTION_DOWN);
|
|
||||||
X("left", INPUT_ACTION_LEFT);
|
|
||||||
X("right", INPUT_ACTION_RIGHT);
|
|
||||||
X("lstick_up", INPUT_ACTION_UP);
|
|
||||||
X("lstick_down", INPUT_ACTION_DOWN);
|
|
||||||
X("lstick_left", INPUT_ACTION_LEFT);
|
|
||||||
X("lstick_right", INPUT_ACTION_RIGHT);
|
|
||||||
|
|
||||||
X("a", INPUT_ACTION_ACCEPT);
|
|
||||||
X("b", INPUT_ACTION_CANCEL);
|
|
||||||
X("z", INPUT_ACTION_CONSOLE);
|
|
||||||
X("start", INPUT_ACTION_RAGEQUIT);
|
|
||||||
X("start", INPUT_ACTION_PAUSE);
|
|
||||||
|
|
||||||
// TODO: Wiimote, USB Keyboard, probably more.
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error "Unknown Dolphin platform?"
|
#error "Unknown Dolphin platform?"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef X
|
for(
|
||||||
|
const inputbindmapentry_t *entry = INPUT_BIND_MAP;
|
||||||
|
entry->buttonName != NULL;
|
||||||
|
entry++
|
||||||
|
) {
|
||||||
|
inputBind(inputButtonGetByName(entry->buttonName), entry->bind);
|
||||||
|
}
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
#include "input/inputbindmap.h"
|
||||||
|
|
||||||
inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
||||||
#ifdef DUSK_INPUT_GAMEPAD
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
@@ -499,49 +500,13 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
errorret_t inputInitLinux(void) {
|
errorret_t inputInitLinux(void) {
|
||||||
#define X(buttonName, buttonAction) \
|
for(
|
||||||
inputBind(inputButtonGetByName(buttonName), buttonAction);
|
const inputbindmapentry_t *entry = INPUT_BIND_MAP;
|
||||||
|
entry->buttonName != NULL;
|
||||||
#ifdef DUSK_INPUT_KEYBOARD
|
entry++
|
||||||
X("w", INPUT_ACTION_UP);
|
) {
|
||||||
X("s", INPUT_ACTION_DOWN);
|
inputBind(inputButtonGetByName(entry->buttonName), entry->bind);
|
||||||
X("a", INPUT_ACTION_LEFT);
|
}
|
||||||
X("d", INPUT_ACTION_RIGHT);
|
|
||||||
X("left", INPUT_ACTION_LEFT);
|
|
||||||
X("right", INPUT_ACTION_RIGHT);
|
|
||||||
X("up", INPUT_ACTION_UP);
|
|
||||||
X("down", INPUT_ACTION_DOWN);
|
|
||||||
X("enter", INPUT_ACTION_ACCEPT);
|
|
||||||
X("e", INPUT_ACTION_ACCEPT);
|
|
||||||
X("space", INPUT_ACTION_ACCEPT);
|
|
||||||
X("tab", INPUT_ACTION_CANCEL);
|
|
||||||
X("q", INPUT_ACTION_CANCEL);
|
|
||||||
X("escape", INPUT_ACTION_RAGEQUIT);
|
|
||||||
X("enter", INPUT_ACTION_PAUSE);
|
|
||||||
X("`", INPUT_ACTION_CONSOLE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DUSK_INPUT_GAMEPAD
|
|
||||||
X("gamepad_up", INPUT_ACTION_UP);
|
|
||||||
X("gamepad_down", INPUT_ACTION_DOWN);
|
|
||||||
X("gamepad_left", INPUT_ACTION_LEFT);
|
|
||||||
X("gamepad_right", INPUT_ACTION_RIGHT);
|
|
||||||
X("gamepad_a", INPUT_ACTION_ACCEPT);
|
|
||||||
X("gamepad_b", INPUT_ACTION_CANCEL);
|
|
||||||
X("gamepad_back", INPUT_ACTION_RAGEQUIT);
|
|
||||||
X("gamepad_start", INPUT_ACTION_PAUSE);
|
|
||||||
X("gamepad_lstick_up", INPUT_ACTION_UP);
|
|
||||||
X("gamepad_lstick_down", INPUT_ACTION_DOWN);
|
|
||||||
X("gamepad_lstick_left", INPUT_ACTION_LEFT);
|
|
||||||
X("gamepad_lstick_right", INPUT_ACTION_RIGHT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DUSK_INPUT_POINTER
|
|
||||||
X("mouse_x", INPUT_ACTION_POINTERX);
|
|
||||||
X("mouse_y", INPUT_ACTION_POINTERY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
#include "input/inputbindmap.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
|
||||||
@@ -73,22 +74,13 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
errorret_t inputInitPSP(void) {
|
errorret_t inputInitPSP(void) {
|
||||||
#define X(buttonName, buttonAction) \
|
for(
|
||||||
inputBind(inputButtonGetByName(buttonName), buttonAction);
|
const inputbindmapentry_t *entry = INPUT_BIND_MAP;
|
||||||
X("up", INPUT_ACTION_UP);
|
entry->buttonName != NULL;
|
||||||
X("down", INPUT_ACTION_DOWN);
|
entry++
|
||||||
X("left", INPUT_ACTION_LEFT);
|
) {
|
||||||
X("right", INPUT_ACTION_RIGHT);
|
inputBind(inputButtonGetByName(entry->buttonName), entry->bind);
|
||||||
X("accept", INPUT_ACTION_ACCEPT);
|
}
|
||||||
X("cancel", INPUT_ACTION_CANCEL);
|
|
||||||
X("triangle", INPUT_ACTION_CONSOLE);
|
|
||||||
X("select", INPUT_ACTION_RAGEQUIT);
|
|
||||||
X("start", INPUT_ACTION_PAUSE);
|
|
||||||
X("lstick_up", INPUT_ACTION_UP);
|
|
||||||
X("lstick_down", INPUT_ACTION_DOWN);
|
|
||||||
X("lstick_left", INPUT_ACTION_LEFT);
|
|
||||||
X("lstick_right", INPUT_ACTION_RIGHT);
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(game)
|
||||||
|
add_subdirectory(input)
|
||||||
|
add_subdirectory(item)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
game.c
|
||||||
|
)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "game/game.h"
|
||||||
|
|
||||||
|
errorret_t gameInit(void) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t gameUpdate(void) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t gameDispose(void) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Header-only: inputbind.h has no implementation.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
INPUT_BIND_NULL,
|
||||||
|
|
||||||
|
INPUT_BIND_UP,
|
||||||
|
INPUT_BIND_DOWN,
|
||||||
|
INPUT_BIND_LEFT,
|
||||||
|
INPUT_BIND_RIGHT,
|
||||||
|
INPUT_BIND_ACCEPT,
|
||||||
|
INPUT_BIND_CANCEL,
|
||||||
|
INPUT_BIND_PAUSE,
|
||||||
|
INPUT_BIND_RAGEQUIT,
|
||||||
|
INPUT_BIND_CONSOLE,
|
||||||
|
INPUT_BIND_POINTERX,
|
||||||
|
INPUT_BIND_POINTERY,
|
||||||
|
|
||||||
|
INPUT_BIND_COUNT
|
||||||
|
} inputbind_t;
|
||||||
|
|
||||||
|
static const char_t *INPUT_BIND_IDS[] = {
|
||||||
|
[INPUT_BIND_UP] = "UP",
|
||||||
|
[INPUT_BIND_DOWN] = "DOWN",
|
||||||
|
[INPUT_BIND_LEFT] = "LEFT",
|
||||||
|
[INPUT_BIND_RIGHT] = "RIGHT",
|
||||||
|
[INPUT_BIND_ACCEPT] = "ACCEPT",
|
||||||
|
[INPUT_BIND_CANCEL] = "CANCEL",
|
||||||
|
[INPUT_BIND_PAUSE] = "PAUSE",
|
||||||
|
[INPUT_BIND_RAGEQUIT] = "RAGEQUIT",
|
||||||
|
[INPUT_BIND_CONSOLE] = "CONSOLE",
|
||||||
|
[INPUT_BIND_POINTERX] = "POINTERX",
|
||||||
|
[INPUT_BIND_POINTERY] = "POINTERY",
|
||||||
|
};
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "input/inputbind.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char_t *buttonName;
|
||||||
|
inputbind_t bind;
|
||||||
|
} inputbindmapentry_t;
|
||||||
|
|
||||||
|
#ifdef DUSK_LINUX
|
||||||
|
static const inputbindmapentry_t INPUT_BIND_MAP[] = {
|
||||||
|
#ifdef DUSK_INPUT_KEYBOARD
|
||||||
|
{ .buttonName = "w", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "s", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "a", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "d", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "enter", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "e", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "space", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "tab", .bind = INPUT_BIND_CANCEL },
|
||||||
|
{ .buttonName = "q", .bind = INPUT_BIND_CANCEL },
|
||||||
|
{ .buttonName = "escape", .bind = INPUT_BIND_RAGEQUIT },
|
||||||
|
{ .buttonName = "enter", .bind = INPUT_BIND_PAUSE },
|
||||||
|
{ .buttonName = "`", .bind = INPUT_BIND_CONSOLE },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
|
{ .buttonName = "gamepad_up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "gamepad_down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "gamepad_left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "gamepad_right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "gamepad_a", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "gamepad_b", .bind = INPUT_BIND_CANCEL },
|
||||||
|
{ .buttonName = "gamepad_back", .bind = INPUT_BIND_RAGEQUIT },
|
||||||
|
{ .buttonName = "gamepad_start", .bind = INPUT_BIND_PAUSE },
|
||||||
|
{ .buttonName = "gamepad_lstick_up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "gamepad_lstick_down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "gamepad_lstick_left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "gamepad_lstick_right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DUSK_INPUT_POINTER
|
||||||
|
{ .buttonName = "mouse_x", .bind = INPUT_BIND_POINTERX },
|
||||||
|
{ .buttonName = "mouse_y", .bind = INPUT_BIND_POINTERY },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ .buttonName = NULL, .bind = INPUT_BIND_NULL }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DUSK_PSP
|
||||||
|
static const inputbindmapentry_t INPUT_BIND_MAP[] = {
|
||||||
|
{ .buttonName = "up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "accept", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "cancel", .bind = INPUT_BIND_CANCEL },
|
||||||
|
{ .buttonName = "triangle", .bind = INPUT_BIND_CONSOLE },
|
||||||
|
{ .buttonName = "select", .bind = INPUT_BIND_RAGEQUIT },
|
||||||
|
{ .buttonName = "start", .bind = INPUT_BIND_PAUSE },
|
||||||
|
{ .buttonName = "lstick_up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "lstick_down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "lstick_left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "lstick_right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = NULL, .bind = INPUT_BIND_NULL }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GameCube and Wii share the same pad layout for now.
|
||||||
|
// TODO: Wiimote, USB Keyboard, probably more.
|
||||||
|
#if defined(DUSK_GAMECUBE) || defined(DUSK_WII)
|
||||||
|
static const inputbindmapentry_t INPUT_BIND_MAP[] = {
|
||||||
|
{ .buttonName = "up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "lstick_up", .bind = INPUT_BIND_UP },
|
||||||
|
{ .buttonName = "lstick_down", .bind = INPUT_BIND_DOWN },
|
||||||
|
{ .buttonName = "lstick_left", .bind = INPUT_BIND_LEFT },
|
||||||
|
{ .buttonName = "lstick_right", .bind = INPUT_BIND_RIGHT },
|
||||||
|
{ .buttonName = "a", .bind = INPUT_BIND_ACCEPT },
|
||||||
|
{ .buttonName = "b", .bind = INPUT_BIND_CANCEL },
|
||||||
|
{ .buttonName = "z", .bind = INPUT_BIND_CONSOLE },
|
||||||
|
{ .buttonName = "start", .bind = INPUT_BIND_RAGEQUIT },
|
||||||
|
{ .buttonName = "start", .bind = INPUT_BIND_PAUSE },
|
||||||
|
{ .buttonName = NULL, .bind = INPUT_BIND_NULL }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
# itemgive.c/h are not built yet -- they depend on the RPG textbox UI
|
||||||
|
# (ui/rpg/textbox/uitextboxmain.h), which hasn't been restored. Add
|
||||||
|
# itemgive.c back here once that's back.
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
item.c
|
||||||
|
inventory.c
|
||||||
|
backpack.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Item Definitions
|
||||||
|
dusk_run_python(
|
||||||
|
dusk_item_json_defs
|
||||||
|
tools.item
|
||||||
|
--json ${CMAKE_CURRENT_SOURCE_DIR}/item.json
|
||||||
|
--output ${DUSK_GENERATED_HEADERS_DIR}/item/itemdef.h
|
||||||
|
)
|
||||||
|
add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_item_json_defs)
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "backpack.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
backpack_t BACKPACK;
|
||||||
|
|
||||||
|
void backpackInit() {
|
||||||
|
for(uint8_t i = 0; i < ITEM_TYPE_COUNT; i++) {
|
||||||
|
inventoryInit(
|
||||||
|
&BACKPACK.inventories[i],
|
||||||
|
BACKPACK.storage[i],
|
||||||
|
ITEM_TYPE_COUNT_MAX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory_t *backpackGetInventory(const itemtype_t type) {
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null");
|
||||||
|
assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range");
|
||||||
|
return &BACKPACK.inventories[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
void backpackAdd(const itemid_t item, const uint8_t quantity) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
inventoryAdd(backpackGetInventory(ITEMS[item].type), item, quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backpackRemove(const itemid_t item) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
inventoryRemove(backpackGetInventory(ITEMS[item].type), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backpackSet(const itemid_t item, const uint8_t quantity) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
inventorySet(backpackGetInventory(ITEMS[item].type), item, quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t backpackGetCount(const itemid_t item) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
return inventoryGetCount(backpackGetInventory(ITEMS[item].type), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t backpackItemExists(const itemid_t item) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
return inventoryItemExists(backpackGetInventory(ITEMS[item].type), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t backpackIsFull(const itemtype_t type) {
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null");
|
||||||
|
assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range");
|
||||||
|
return inventoryIsFull(backpackGetInventory(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t backpackItemFull(const itemid_t item) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
return inventoryItemFull(backpackGetInventory(ITEMS[item].type), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backpackSort(
|
||||||
|
const itemtype_t type,
|
||||||
|
const inventorysort_t sortBy,
|
||||||
|
const bool_t reverse
|
||||||
|
) {
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null");
|
||||||
|
assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range");
|
||||||
|
inventorySort(backpackGetInventory(type), sortBy, reverse);
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
inventorystack_t storage[ITEM_TYPE_COUNT][ITEM_TYPE_COUNT_MAX];
|
||||||
|
inventory_t inventories[ITEM_TYPE_COUNT];
|
||||||
|
} backpack_t;
|
||||||
|
|
||||||
|
extern backpack_t BACKPACK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the backpack inventory for the player.
|
||||||
|
*/
|
||||||
|
void backpackInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the inventory for a given item type.
|
||||||
|
*
|
||||||
|
* @param type The item type.
|
||||||
|
* @returns Pointer to the inventory for that type.
|
||||||
|
*/
|
||||||
|
inventory_t *backpackGetInventory(const itemtype_t type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a quantity of an item to the backpack.
|
||||||
|
*
|
||||||
|
* @param item The item ID to add.
|
||||||
|
* @param quantity The quantity to add.
|
||||||
|
*/
|
||||||
|
void backpackAdd(const itemid_t item, const uint8_t quantity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an item from the backpack.
|
||||||
|
*
|
||||||
|
* @param item The item ID to remove.
|
||||||
|
*/
|
||||||
|
void backpackRemove(const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the quantity of an item in the backpack.
|
||||||
|
*
|
||||||
|
* @param item The item ID to set.
|
||||||
|
* @param quantity The quantity to set.
|
||||||
|
*/
|
||||||
|
void backpackSet(const itemid_t item, const uint8_t quantity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the quantity of an item in the backpack.
|
||||||
|
*
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @returns The quantity held.
|
||||||
|
*/
|
||||||
|
uint8_t backpackGetCount(const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an item exists in the backpack (quantity > 0).
|
||||||
|
*
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @returns true if the item exists.
|
||||||
|
*/
|
||||||
|
bool_t backpackItemExists(const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory for a given type is full.
|
||||||
|
*
|
||||||
|
* @param type The item type to check.
|
||||||
|
* @returns true if the type's inventory is full.
|
||||||
|
*/
|
||||||
|
bool_t backpackIsFull(const itemtype_t type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an item's stack is full in the backpack.
|
||||||
|
*
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @returns true if the item stack is full.
|
||||||
|
*/
|
||||||
|
bool_t backpackItemFull(const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the inventory for a given item type.
|
||||||
|
*
|
||||||
|
* @param type The item type whose inventory to sort.
|
||||||
|
* @param sortBy The sorting criteria.
|
||||||
|
* @param reverse Whether to sort in reverse order.
|
||||||
|
*/
|
||||||
|
void backpackSort(
|
||||||
|
const itemtype_t type,
|
||||||
|
const inventorysort_t sortBy,
|
||||||
|
const bool_t reverse
|
||||||
|
);
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/sort.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void inventoryInit(
|
||||||
|
inventory_t* inventory,
|
||||||
|
inventorystack_t* storage,
|
||||||
|
uint8_t storageSize
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(storageSize > 0, "Storage size must be greater than zero.");
|
||||||
|
|
||||||
|
inventory->storage = storage;
|
||||||
|
inventory->storageSize = storageSize;
|
||||||
|
|
||||||
|
memoryZero(storage, sizeof(inventorystack_t) * storageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inventoryItemExists(const inventory_t *inventory, const itemid_t item) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL.");
|
||||||
|
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
do {
|
||||||
|
if(stack->item == ITEM_ID_NULL) break;
|
||||||
|
if(stack->item != item) continue;
|
||||||
|
assertTrue(stack->quantity > 0, "Item has quantity zero.");
|
||||||
|
return true;
|
||||||
|
} while(++stack < end);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inventorySet(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemid_t item,
|
||||||
|
const uint8_t quantity
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL.");
|
||||||
|
|
||||||
|
// If quantity 0, remove.
|
||||||
|
if(quantity == 0) return inventoryRemove(inventory, item);
|
||||||
|
|
||||||
|
// Search for existing stack.
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
do {
|
||||||
|
// Not in inventory yet, add as new stack.
|
||||||
|
if(stack->item == ITEM_ID_NULL) {
|
||||||
|
stack->item = item;
|
||||||
|
stack->quantity = quantity;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not the stack we're looking for.
|
||||||
|
if(stack->item != item) continue;
|
||||||
|
|
||||||
|
// Update existing stack.
|
||||||
|
stack->quantity = quantity;
|
||||||
|
return;
|
||||||
|
} while(++stack < end);
|
||||||
|
|
||||||
|
// No space in the inventory.
|
||||||
|
assertUnreachable("Inventory is full, cannot set more items.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void inventoryAdd(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemid_t item,
|
||||||
|
const uint8_t quantity
|
||||||
|
) {
|
||||||
|
uint8_t current = inventoryGetCount(inventory, item);
|
||||||
|
uint16_t newQuantity = (uint16_t)current + (uint16_t)quantity;
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
newQuantity <= UINT8_MAX,
|
||||||
|
"Cannot add item, would overflow maximum quantity."
|
||||||
|
);
|
||||||
|
|
||||||
|
inventorySet(inventory, item, (uint8_t)newQuantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inventoryRemove(inventory_t *inventory, const itemid_t item) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL.");
|
||||||
|
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
|
||||||
|
// Search for existing stack.
|
||||||
|
do {
|
||||||
|
// End of inventory, item not present.
|
||||||
|
if(stack->item == ITEM_ID_NULL) break;
|
||||||
|
|
||||||
|
// Not matching stack.
|
||||||
|
if(stack->item != item) continue;
|
||||||
|
|
||||||
|
// Match found, shift everything else down
|
||||||
|
memoryMove(
|
||||||
|
stack,
|
||||||
|
stack + 1,
|
||||||
|
(end - (stack + 1)) * sizeof(inventorystack_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear last stack.
|
||||||
|
inventorystack_t *last = end - 1;
|
||||||
|
last->item = ITEM_ID_NULL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while(++stack < end);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inventoryGetCount(const inventory_t *inventory, const itemid_t item) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL.");
|
||||||
|
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
do {
|
||||||
|
// End of inventory, item not present.
|
||||||
|
if(stack->item == ITEM_ID_NULL) break;
|
||||||
|
|
||||||
|
// Not matching stack.
|
||||||
|
if(stack->item != item) continue;
|
||||||
|
|
||||||
|
// Match found, return quantity.
|
||||||
|
return stack->quantity;
|
||||||
|
} while(++stack < end);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inventoryIsFull(const inventory_t *inventory) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
do {
|
||||||
|
// Found empty stack, not full.
|
||||||
|
if(stack->item == ITEM_ID_NULL) return false;
|
||||||
|
} while(++stack < end);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item) {
|
||||||
|
return inventoryGetCount(inventory, item) == ITEM_STACK_QUANTITY_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorters
|
||||||
|
int_t inventorySortById(const void *a, const void *b) {
|
||||||
|
const inventorystack_t *stackA = (const inventorystack_t*)a;
|
||||||
|
const inventorystack_t *stackB = (const inventorystack_t*)b;
|
||||||
|
if(stackA->item < stackB->item) return -1;
|
||||||
|
if(stackA->item > stackB->item) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_t inventorySortByIdReverse(const void *a, const void *b) {
|
||||||
|
const inventorystack_t *stackA = (const inventorystack_t*)a;
|
||||||
|
const inventorystack_t *stackB = (const inventorystack_t*)b;
|
||||||
|
if(stackA->item < stackB->item) return 1;
|
||||||
|
if(stackA->item > stackB->item) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_t inventorySortByType(const void *a, const void *b) {
|
||||||
|
const inventorystack_t *stackA = (const inventorystack_t*)a;
|
||||||
|
const inventorystack_t *stackB = (const inventorystack_t*)b;
|
||||||
|
const itemtype_t typeA = ITEMS[stackA->item].type;
|
||||||
|
const itemtype_t typeB = ITEMS[stackB->item].type;
|
||||||
|
if(typeA < typeB) return -1;
|
||||||
|
if(typeA > typeB) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_t inventorySortByTypeReverse(const void *a, const void *b) {
|
||||||
|
const inventorystack_t *stackA = (const inventorystack_t*)a;
|
||||||
|
const inventorystack_t *stackB = (const inventorystack_t*)b;
|
||||||
|
const itemtype_t typeA = ITEMS[stackA->item].type;
|
||||||
|
const itemtype_t typeB = ITEMS[stackB->item].type;
|
||||||
|
if(typeA < typeB) return 1;
|
||||||
|
if(typeA > typeB) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inventorySort(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const inventorysort_t sortBy,
|
||||||
|
const bool_t reverse
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "Inventory pointer is NULL.");
|
||||||
|
assertNotNull(inventory->storage, "Storage pointer is NULL.");
|
||||||
|
assertTrue(inventory->storageSize > 0, "Storage too small.");
|
||||||
|
assertTrue(sortBy < INVENTORY_SORT_COUNT, "Invalid sort type.");
|
||||||
|
|
||||||
|
// Get count of used stacks
|
||||||
|
size_t count = 0;
|
||||||
|
inventorystack_t *stack = inventory->storage;
|
||||||
|
inventorystack_t *end = stack + inventory->storageSize;
|
||||||
|
do {
|
||||||
|
if(stack->item == ITEM_ID_NULL) break;
|
||||||
|
count++;
|
||||||
|
} while(++stack < end);
|
||||||
|
|
||||||
|
if(count == 0) return; // Nothing to sort
|
||||||
|
|
||||||
|
// Comparator
|
||||||
|
sortcompare_t comparator = NULL;
|
||||||
|
switch(sortBy) {
|
||||||
|
case INVENTORY_SORT_BY_ID: {
|
||||||
|
comparator = reverse ? inventorySortByIdReverse : inventorySortById;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case INVENTORY_SORT_BY_TYPE: {
|
||||||
|
comparator = reverse ? inventorySortByTypeReverse : inventorySortByType;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid sort type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(comparator, "Comparator function is NULL.");
|
||||||
|
|
||||||
|
sort((void*)inventory->storage, count, sizeof(inventorystack_t), comparator);
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "item/item.h"
|
||||||
|
|
||||||
|
#define ITEM_STACK_QUANTITY_MAX 99
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
INVENTORY_SORT_BY_ID,
|
||||||
|
INVENTORY_SORT_BY_TYPE,
|
||||||
|
|
||||||
|
INVENTORY_SORT_COUNT
|
||||||
|
} inventorysort_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
itemid_t item;
|
||||||
|
uint8_t quantity;
|
||||||
|
} inventorystack_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
inventorystack_t *storage;
|
||||||
|
uint8_t storageSize;
|
||||||
|
} inventory_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to initialize.
|
||||||
|
* @param storage The storage array for the inventory.
|
||||||
|
* @param storageSize The size of the storage array.
|
||||||
|
*/
|
||||||
|
void inventoryInit(
|
||||||
|
inventory_t* inventory,
|
||||||
|
inventorystack_t* storage,
|
||||||
|
uint8_t storageSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a specific item exists in the inventory (and has quantity > 0).
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to check.
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @return true if the item exists, false otherwise.
|
||||||
|
*/
|
||||||
|
bool_t inventoryItemExists(const inventory_t *inventory, const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the quantity of a specific item in the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to modify.
|
||||||
|
* @param item The item ID to set.
|
||||||
|
* @param quantity The quantity to set.
|
||||||
|
*/
|
||||||
|
void inventorySet(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemid_t item,
|
||||||
|
const uint8_t quantity
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a specific quantity of an item to the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to modify.
|
||||||
|
* @param item The item ID to add.
|
||||||
|
* @param quantity The quantity to add.
|
||||||
|
*/
|
||||||
|
void inventoryAdd(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemid_t item,
|
||||||
|
const uint8_t quantity
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an item from the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to modify.
|
||||||
|
* @param item The item ID to remove.
|
||||||
|
*/
|
||||||
|
void inventoryRemove(inventory_t *inventory, const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count of a specific item in the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to check.
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @return The count of the item in the inventory.
|
||||||
|
*/
|
||||||
|
uint8_t inventoryGetCount(const inventory_t *inventory, const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory is full.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to check.
|
||||||
|
* @return true if full, false otherwise.
|
||||||
|
*/
|
||||||
|
bool_t inventoryIsFull(const inventory_t *inventory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a specific item stack is full in the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to check.
|
||||||
|
* @param item The item ID to check.
|
||||||
|
* @return true if the item stack is full, false otherwise.
|
||||||
|
*/
|
||||||
|
bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the inventory based on the specified criteria.
|
||||||
|
*
|
||||||
|
* @param inventory The inventory to sort.
|
||||||
|
* @param sortBy The sorting criteria.
|
||||||
|
* @param reverse Whether to sort in reverse order.
|
||||||
|
*/
|
||||||
|
void inventorySort(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const inventorysort_t sortBy,
|
||||||
|
const bool_t reverse
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator for sorting inventory stacks by item ID, ascending.
|
||||||
|
*
|
||||||
|
* @param a First inventorystack_t to compare.
|
||||||
|
* @param b Second inventorystack_t to compare.
|
||||||
|
* @return Comparison result for use with sort().
|
||||||
|
*/
|
||||||
|
int_t inventorySortById(const void *a, const void *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator for sorting inventory stacks by item ID, descending.
|
||||||
|
*
|
||||||
|
* @param a First inventorystack_t to compare.
|
||||||
|
* @param b Second inventorystack_t to compare.
|
||||||
|
* @return Comparison result for use with sort().
|
||||||
|
*/
|
||||||
|
int_t inventorySortByIdReverse(const void *a, const void *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator for sorting inventory stacks by item type, ascending.
|
||||||
|
*
|
||||||
|
* @param a First inventorystack_t to compare.
|
||||||
|
* @param b Second inventorystack_t to compare.
|
||||||
|
* @return Comparison result for use with sort().
|
||||||
|
*/
|
||||||
|
int_t inventorySortByType(const void *a, const void *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator for sorting inventory stacks by item type, descending.
|
||||||
|
*
|
||||||
|
* @param a First inventorystack_t to compare.
|
||||||
|
* @param b Second inventorystack_t to compare.
|
||||||
|
* @return Comparison result for use with sort().
|
||||||
|
*/
|
||||||
|
int_t inventorySortByTypeReverse(const void *a, const void *b);
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "item.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "locale/localemanager.h"
|
||||||
|
#include "asset/loader/locale/assetlocaleloader.h"
|
||||||
|
|
||||||
|
errorret_t itemGetName(
|
||||||
|
const itemid_t item,
|
||||||
|
char_t *buffer,
|
||||||
|
const size_t bufferSize
|
||||||
|
) {
|
||||||
|
assertTrue(item > ITEM_ID_NULL, "Item ID must not be null");
|
||||||
|
assertTrue(item < ITEM_ID_COUNT, "Item ID out of range");
|
||||||
|
|
||||||
|
errorChain(assetLocaleGetString(
|
||||||
|
&LOCALE.entry->data.locale,
|
||||||
|
ITEMS[item].name,
|
||||||
|
0,
|
||||||
|
buffer,
|
||||||
|
bufferSize
|
||||||
|
));
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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 "item/itemdef.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the localized display name for an item.
|
||||||
|
*
|
||||||
|
* @param item The item ID to look up. Must not be ITEM_ID_NULL.
|
||||||
|
* @param buffer Buffer to write the localized name into.
|
||||||
|
* @param bufferSize Size of the buffer.
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t itemGetName(
|
||||||
|
const itemid_t item,
|
||||||
|
char_t *buffer,
|
||||||
|
const size_t bufferSize
|
||||||
|
);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
{ "id": "POTION", "type": "MEDICINE", "weight": 1.0, "name": "potion" },
|
||||||
|
{ "id": "POTATO", "type": "FOOD", "weight": 0.5, "name": "potato" },
|
||||||
|
{ "id": "APPLE", "type": "FOOD", "weight": 0.3, "name": "apple" }
|
||||||
|
]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "itemgive.h"
|
||||||
|
#include "item/backpack.h"
|
||||||
|
#include "item/item.h"
|
||||||
|
#include "ui/rpg/textbox/uitextboxmain.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
#include "error/error.h"
|
||||||
|
|
||||||
|
#define ITEM_GIVE_NAME_MAX_CHARS 32
|
||||||
|
|
||||||
|
void itemGive(const itemid_t item, const uint8_t quantity) {
|
||||||
|
backpackAdd(item, quantity);
|
||||||
|
|
||||||
|
char_t name[ITEM_GIVE_NAME_MAX_CHARS];
|
||||||
|
errorCatch(itemGetName(item, name, ITEM_GIVE_NAME_MAX_CHARS));
|
||||||
|
|
||||||
|
char_t msg[ITEM_GIVE_MESSAGE_MAX_CHARS];
|
||||||
|
stringFormat(
|
||||||
|
msg,
|
||||||
|
ITEM_GIVE_MESSAGE_MAX_CHARS - 1,
|
||||||
|
"Received %s x%u",
|
||||||
|
name,
|
||||||
|
(uint32_t)quantity
|
||||||
|
);
|
||||||
|
uiTextboxMainSetText(msg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "item/item.h"
|
||||||
|
|
||||||
|
#define ITEM_GIVE_MESSAGE_MAX_CHARS 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a quantity of an item to the player's backpack and shows a
|
||||||
|
* "Received <item> x<quantity>" message in the main textbox.
|
||||||
|
*
|
||||||
|
* @param item The item ID to give.
|
||||||
|
* @param quantity The quantity to give.
|
||||||
|
*/
|
||||||
|
void itemGive(const itemid_t item, const uint8_t quantity);
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import argparse
|
|
||||||
import csv
|
|
||||||
import os
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Input CSV to .h defines")
|
|
||||||
parser.add_argument("--csv", required=True, help="Path to Input CSV file")
|
|
||||||
parser.add_argument("--output", required=True, help="Path to output .h file")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
def id_enum(name):
|
|
||||||
return "INPUT_ACTION_" + name.upper()
|
|
||||||
|
|
||||||
# Load CSV
|
|
||||||
input_ids = []
|
|
||||||
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:
|
|
||||||
input_id = row["id"]
|
|
||||||
if input_id not in input_ids:
|
|
||||||
input_ids.append(input_id)
|
|
||||||
|
|
||||||
# Assign enum values
|
|
||||||
id_values = {input_id: i + 1 for i, input_id in enumerate(input_ids)}
|
|
||||||
|
|
||||||
# Build output
|
|
||||||
out = [
|
|
||||||
"#pragma once",
|
|
||||||
'#include "dusk.h"',
|
|
||||||
"",
|
|
||||||
"typedef enum {",
|
|
||||||
" INPUT_ACTION_NULL = 0x0,",
|
|
||||||
"",
|
|
||||||
]
|
|
||||||
for input_id in input_ids:
|
|
||||||
out.append(f" {id_enum(input_id)} = 0x{id_values[input_id]:x},")
|
|
||||||
out += [
|
|
||||||
"",
|
|
||||||
f" INPUT_ACTION_COUNT = 0x{len(input_ids) + 1:x}",
|
|
||||||
"} inputaction_t;",
|
|
||||||
"",
|
|
||||||
"static const char_t *INPUT_ACTION_IDS[] = {",
|
|
||||||
]
|
|
||||||
for input_id in input_ids:
|
|
||||||
out.append(f" [{id_enum(input_id)}] = \"{input_id}\",")
|
|
||||||
out += [
|
|
||||||
"};",
|
|
||||||
"",
|
|
||||||
"static const char_t *INPUT_ACTION_SCRIPT =",
|
|
||||||
]
|
|
||||||
for input_id in input_ids:
|
|
||||||
out.append(f" \"var {id_enum(input_id)} = {id_values[input_id]};\\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))
|
|
||||||
Reference in New Issue
Block a user