item
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
module('platform')
|
||||
module('input')
|
||||
module('scene')
|
||||
module('item')
|
||||
|
||||
-- Default Input bindings.
|
||||
if PLATFORM == "psp" then
|
||||
@@ -34,8 +35,17 @@ else
|
||||
inputBind("q", "cancel")
|
||||
|
||||
inputBind("z", "ragequit")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sceneSet('map')
|
||||
print("Backpack:", BACKPACK)
|
||||
print('Has Potion?', inventoryItemExists(BACKPACK, 1))
|
||||
inventoryAdd(BACKPACK, 1, 3)
|
||||
print('Has Potion?', inventoryItemExists(BACKPACK, 1))
|
||||
inventoryRemove(BACKPACK, 1)
|
||||
print('Has Potion?', inventoryItemExists(BACKPACK, 1))
|
||||
print('Potion Count:', inventoryGetCount(BACKPACK, 1))
|
||||
print('Is Backpack Full?', inventoryIsFull(BACKPACK))
|
||||
|
||||
-- sceneSet('map')
|
||||
-- mapLoad('map/testmap/testmap.dmf')
|
||||
66
cmake/modules/csvtoenum.cmake
Normal file
66
cmake/modules/csvtoenum.cmake
Normal file
@@ -0,0 +1,66 @@
|
||||
# csvtoenum(<CSV_FILE> <OUT_HEADER> <C_TYPE> <TAKE_COLUMN> <PREFIX_COLUMN>)
|
||||
# Example:
|
||||
# csvtoenum(myfile.csv outhead.h itemtype_t id ITEM_TYPE_)
|
||||
#
|
||||
# Will generate a header with:
|
||||
# typedef enum {
|
||||
# ITEM_TYPE_NULL,
|
||||
# ITEM_TYPE_FOO,
|
||||
# ...
|
||||
# ITEM_TYPE_COUNT,
|
||||
# } itemtype_t;
|
||||
|
||||
function(csvtoenum CSV_FILE OUT_HEADER C_TYPE TAKE_COLUMN PREFIX_COLUMN)
|
||||
# Read the CSV file
|
||||
file(READ "${CSV_FILE}" CSV_CONTENTS)
|
||||
string(REPLACE "\r\n" "\n" CSV_CONTENTS "${CSV_CONTENTS}")
|
||||
string(REPLACE "\r" "\n" CSV_CONTENTS "${CSV_CONTENTS}")
|
||||
string(REGEX REPLACE "\n+$" "" CSV_CONTENTS "${CSV_CONTENTS}")
|
||||
string(REPLACE "\n" ";" CSV_LINES "${CSV_CONTENTS}")
|
||||
|
||||
# Get header row and find column indices
|
||||
list(GET CSV_LINES 0 HEADER_ROW)
|
||||
string(REPLACE "," ";" HEADER_LIST "${HEADER_ROW}")
|
||||
set(COLUMN_INDEX -1)
|
||||
set(PREFIX_INDEX -1)
|
||||
set(IDX 0)
|
||||
foreach(COL ${HEADER_LIST})
|
||||
if(COL STREQUAL "${TAKE_COLUMN}")
|
||||
set(COLUMN_INDEX ${IDX})
|
||||
endif()
|
||||
if(COL STREQUAL "${PREFIX_COLUMN}")
|
||||
set(PREFIX_INDEX ${IDX})
|
||||
endif()
|
||||
math(EXPR IDX "${IDX} + 1")
|
||||
endforeach()
|
||||
if(COLUMN_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "csvtoenum: TAKE_COLUMN '${TAKE_COLUMN}' not found in header of ${CSV_FILE}")
|
||||
endif()
|
||||
if(PREFIX_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "csvtoenum: PREFIX_COLUMN '${PREFIX_COLUMN}' not found in header of ${CSV_FILE}")
|
||||
endif()
|
||||
|
||||
# Prepare enum entries
|
||||
set(ENUM_ENTRIES " ${PREFIX_COLUMN}NULL,")
|
||||
set(ROW_IDX 1)
|
||||
list(LENGTH CSV_LINES NUM_LINES)
|
||||
while(ROW_IDX LESS NUM_LINES)
|
||||
list(GET CSV_LINES ${ROW_IDX} ROW)
|
||||
string(REPLACE "," ";" ROW_LIST "${ROW}")
|
||||
list(LENGTH ROW_LIST ROW_LEN)
|
||||
if(ROW_LEN GREATER COLUMN_INDEX)
|
||||
list(GET ROW_LIST ${COLUMN_INDEX} ENTRY)
|
||||
list(GET ROW_LIST ${PREFIX_INDEX} PREFIX)
|
||||
# Only add if ENTRY is not empty
|
||||
string(STRIP "${ENTRY}" ENTRY)
|
||||
if(NOT ENTRY STREQUAL "")
|
||||
set(ENUM_ENTRIES "${ENUM_ENTRIES}\n ${PREFIX}${ENTRY},")
|
||||
endif()
|
||||
endif()
|
||||
math(EXPR ROW_IDX "${ROW_IDX} + 1")
|
||||
endwhile()
|
||||
set(ENUM_ENTRIES "${ENUM_ENTRIES}\n ${PREFIX_COLUMN}COUNT,")
|
||||
|
||||
# Write header file
|
||||
file(WRITE "${OUT_HEADER}" "/**\n * Auto-generated by csvtoenum.cmake\n * Source: ${CSV_FILE}\n */\n\ntypedef enum {\n${ENUM_ENTRIES}\n} ${C_TYPE};\n")
|
||||
endfunction()
|
||||
@@ -1,3 +1,8 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
if(NOT DEFINED ENV_FILE)
|
||||
message(FATAL_ERROR "ENV_FILE is not set")
|
||||
endif()
|
||||
|
||||
@@ -18,11 +18,6 @@ errorret_t assetInit(void) {
|
||||
|
||||
// Engine may have been provided the launch path
|
||||
if(ENGINE.argc > 0) {
|
||||
// This first arg is the executable, so on most platforms it is say
|
||||
// "/path/file" or "C:\Path\file.exe". On PSP this would be something
|
||||
// like "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or if we are debugging it is
|
||||
// "host0:/Dusk.prx"
|
||||
|
||||
// Get the directory of the executable
|
||||
char_t buffer[FILENAME_MAX];
|
||||
stringCopy(buffer, ENGINE.argv[0], FILENAME_MAX);
|
||||
@@ -55,11 +50,15 @@ errorret_t assetInit(void) {
|
||||
// Default system path, intended to be overridden by the platform
|
||||
stringCopy(ASSET.systemPath, ".", FILENAME_MAX);
|
||||
|
||||
// PSP specific time.
|
||||
// PSP specific asset loading.
|
||||
#if PSP
|
||||
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
|
||||
|
||||
// PSP is given either host0:/Dusk.prx (debugging) OR the PBP file.
|
||||
// PSP is given either the prx OR the PBP file.
|
||||
// In the format of "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or "host0:/Dusk.prx"
|
||||
// IF the file is the PBP file, we are loading directly on the PSP itself.
|
||||
// IF the file is the .prx then we are debugging and fopen will return
|
||||
// relative filepaths correctly, e.g. host0:/dusk.dsk will be on host.
|
||||
if(
|
||||
stringEndsWithCaseInsensitive(ENGINE.argv[0], ".pbp") ||
|
||||
ASSET_PBP_READ_PBP_FROM_HOST
|
||||
@@ -143,7 +142,6 @@ errorret_t assetInit(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Open zip file
|
||||
char_t searchPath[FILENAME_MAX];
|
||||
const char_t **path = ASSET_SEARCH_PATHS;
|
||||
|
||||
@@ -56,6 +56,7 @@ typedef struct {
|
||||
char_t systemPath[FILENAME_MAX];
|
||||
uint8_t assetCount;
|
||||
|
||||
// PSP specific information.
|
||||
#if PSP
|
||||
FILE *pbpFile;
|
||||
assetpbp_t pbpHeader;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// #include "rpg/rpg.h"
|
||||
#include "script/scriptmanager.h"
|
||||
#include "debug/debug.h"
|
||||
#include "item/backpack.h"
|
||||
|
||||
engine_t ENGINE;
|
||||
|
||||
@@ -38,6 +39,8 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
||||
// errorChain(rpgInit());
|
||||
errorChain(sceneInit());
|
||||
|
||||
backpackInit();
|
||||
|
||||
// Run the initial script.
|
||||
scriptcontext_t ctx;
|
||||
errorChain(scriptContextInit(&ctx));
|
||||
|
||||
@@ -24,44 +24,6 @@ void inputInit(void) {
|
||||
}
|
||||
|
||||
INPUT.deadzone = 0.2f;
|
||||
|
||||
// Setup Default Binds
|
||||
// #if INPUT_SDL2 == 1
|
||||
// #if INPUT_KEYBOARD == 1
|
||||
// inputBind(inputButtonGetByName("up"), INPUT_ACTION_UP);
|
||||
// inputBind(inputButtonGetByName("down"), INPUT_ACTION_DOWN);
|
||||
// inputBind(inputButtonGetByName("left"), INPUT_ACTION_LEFT);
|
||||
// inputBind(inputButtonGetByName("right"), INPUT_ACTION_RIGHT);
|
||||
// inputBind(inputButtonGetByName("w"), INPUT_ACTION_UP);
|
||||
// inputBind(inputButtonGetByName("s"), INPUT_ACTION_DOWN);
|
||||
// inputBind(inputButtonGetByName("a"), INPUT_ACTION_LEFT);
|
||||
// inputBind(inputButtonGetByName("d"), INPUT_ACTION_RIGHT);
|
||||
// inputBind(inputButtonGetByName("enter"), INPUT_ACTION_ACCEPT);
|
||||
// inputBind(inputButtonGetByName("escape"), INPUT_ACTION_RAGEQUIT);
|
||||
// inputBind(inputButtonGetByName("space"), INPUT_ACTION_ACCEPT);
|
||||
// inputBind(inputButtonGetByName("backspace"), INPUT_ACTION_CANCEL);
|
||||
// inputBind(inputButtonGetByName("e"), INPUT_ACTION_ACCEPT);
|
||||
// inputBind(inputButtonGetByName("q"), INPUT_ACTION_CANCEL);
|
||||
// #endif
|
||||
|
||||
// #if INPUT_GAMEPAD == 1
|
||||
// #if PSP
|
||||
// INPUT.deadzone = 0.2890625f;// Taken from the PSP firmware
|
||||
|
||||
// inputBind(inputButtonGetByName("up"), INPUT_ACTION_UP);
|
||||
// inputBind(inputButtonGetByName("down"), INPUT_ACTION_DOWN);
|
||||
// inputBind(inputButtonGetByName("left"), INPUT_ACTION_LEFT);
|
||||
// inputBind(inputButtonGetByName("right"), INPUT_ACTION_RIGHT);
|
||||
// inputBind(inputButtonGetByName("circle"), INPUT_ACTION_CANCEL);
|
||||
// inputBind(inputButtonGetByName("cross"), INPUT_ACTION_ACCEPT);
|
||||
// inputBind(inputButtonGetByName("lstick_negative_y"), INPUT_ACTION_UP);
|
||||
// inputBind(inputButtonGetByName("lstick_positive_y"), INPUT_ACTION_DOWN);
|
||||
// inputBind(inputButtonGetByName("lstick_negative_x"), INPUT_ACTION_LEFT);
|
||||
// inputBind(inputButtonGetByName("lstick_positive_x"), INPUT_ACTION_RIGHT);
|
||||
// inputBind(inputButtonGetByName("select"), INPUT_ACTION_RAGEQUIT);
|
||||
// #endif
|
||||
// #endif
|
||||
// #endif
|
||||
}
|
||||
|
||||
void inputUpdate(void) {
|
||||
|
||||
@@ -3,9 +3,29 @@
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
include(cmake/modules/csvtoenum.cmake)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
item.c
|
||||
inventory.c
|
||||
)
|
||||
backpack.c
|
||||
)
|
||||
|
||||
# Generate itemtype_t enum from CSV
|
||||
set(ITEM_CSV "${CMAKE_CURRENT_LIST_DIR}/itemtypes.csv")
|
||||
set(ITEM_HEADER "${CMAKE_CURRENT_LIST_DIR}/itemtypes2.h")
|
||||
csvtoenum(${ITEM_CSV} ${ITEM_HEADER} itemtype_t id ITEM_TYPE_)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${OUTPUT_FULL_PATH}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DENV_FILE=${INPUT_FULL_PATH}
|
||||
-DOUT_HEADER=${OUTPUT_FULL_PATH}
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/modules/envtoh.cmake
|
||||
DEPENDS ${INPUT_FULL_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules/envtoh.cmake
|
||||
COMMENT "Generating ${OUTPUT_NAME_RELATIVE}"
|
||||
)
|
||||
add_custom_target(${OUTPUT_NAME_RELATIVE}_header DEPENDS ${OUTPUT_FULL_PATH})
|
||||
add_dependencies(${DUSK_LIBRARY_TARGET_NAME} ${OUTPUT_NAME_RELATIVE}_header)
|
||||
15
src/item/backpack.c
Normal file
15
src/item/backpack.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "backpack.h"
|
||||
|
||||
inventorystack_t BACKPACK_STORAGE[BACKPACK_STORAGE_SIZE_MAX];
|
||||
inventory_t BACKPACK;
|
||||
|
||||
void backpackInit() {
|
||||
inventoryInit(&BACKPACK, BACKPACK_STORAGE, BACKPACK_STORAGE_SIZE_MAX);
|
||||
}
|
||||
@@ -6,4 +6,14 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "inventory.h"
|
||||
#include "inventory.h"
|
||||
|
||||
#define BACKPACK_STORAGE_SIZE_MAX 20
|
||||
|
||||
extern inventorystack_t BACKPACK_STORAGE[BACKPACK_STORAGE_SIZE_MAX];
|
||||
extern inventory_t BACKPACK;
|
||||
|
||||
/**
|
||||
* Initializes the backpack inventory for the player.
|
||||
*/
|
||||
void backpackInit();
|
||||
4
src/item/item.csv
Normal file
4
src/item/item.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
id,type,
|
||||
POTION,MEDICINE,
|
||||
POTATO,FOOD,
|
||||
APPLE,FOOD,
|
||||
|
259
src/script/module/moduleitem.h
Normal file
259
src/script/module/moduleitem.h
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "script/scriptcontext.h"
|
||||
#include "item/inventory.h"
|
||||
#include "item/backpack.h"
|
||||
|
||||
int moduleInventoryItemExists(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Expect inventory pointer and item ID
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryItemExists: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventoryItemExists: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
|
||||
// Error if item is ITEM_ID_NULL
|
||||
if(item == ITEM_ID_NULL) {
|
||||
luaL_error(L, "inventoryItemExists: Item ID cannot be ITEM_ID_NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool_t hasItem = inventoryItemExists(inventory, item);
|
||||
lua_pushboolean(L, hasItem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moduleInventorySet(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer, item ID and quantity (uint8_t)
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventorySet: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventorySet: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 3)) {
|
||||
luaL_error(L, "inventorySet: Expected quantity as third argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
uint8_t quantity = (uint8_t)lua_tointeger(L, 3);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
inventorySet(inventory, item, quantity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int moduleInventoryAdd(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer, item ID and quantity (uint8_t)
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryAdd: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventoryAdd: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 3)) {
|
||||
luaL_error(L, "inventoryAdd: Expected quantity as third argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
uint8_t quantity = (uint8_t)lua_tointeger(L, 3);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
inventoryAdd(inventory, item, quantity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int moduleInventoryRemove(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer and item ID
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryRemove: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventoryRemove: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
|
||||
// if there is a third argument (quantity), then we are actually doing a
|
||||
// partial removal.
|
||||
if(lua_gettop(L) >= 3) {
|
||||
if(!lua_isinteger(L, 3)) {
|
||||
luaL_error(L, "inventoryRemove: Expected quantity as third argument");
|
||||
return 0;
|
||||
}
|
||||
uint8_t amount = (uint8_t)lua_tointeger(L, 3);
|
||||
uint8_t currentQuantity = inventoryGetCount(inventory, item);
|
||||
if(amount >= currentQuantity) {
|
||||
// Remove entire stack
|
||||
inventoryRemove(inventory, item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set new quantity
|
||||
inventorySet(inventory, item, currentQuantity - amount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventoryRemove(inventory, item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int moduleInventoryGetCount(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer and item ID
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryGetCount: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventoryGetCount: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
|
||||
uint8_t count = inventoryGetCount(inventory, item);
|
||||
lua_pushinteger(L, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moduleInventoryIsFull(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryIsFull: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
|
||||
bool_t isFull = inventoryIsFull(inventory);
|
||||
lua_pushboolean(L, isFull);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moduleInventoryItemFull(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer and item ID
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventoryItemFull: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventoryItemFull: Expected item ID as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
itemid_t item = (itemid_t)lua_tointeger(L, 2);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
|
||||
bool_t isFull = inventoryItemFull(inventory, item);
|
||||
lua_pushboolean(L, isFull);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moduleInventorySort(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
// Requires inventory pointer, sort type and reverse flag
|
||||
if(!lua_islightuserdata(L, 1)) {
|
||||
luaL_error(L, "inventorySort: Expected inventory pointer as first argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!lua_isinteger(L, 2)) {
|
||||
luaL_error(L, "inventorySort: Expected sort type as second argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Optional, reverse
|
||||
bool_t reverse = false;
|
||||
if(lua_gettop(L) >= 3) {
|
||||
if(!lua_isboolean(L, 3)) {
|
||||
luaL_error(L, "inventorySort: Expected reverse flag as third argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
reverse = (bool_t)lua_toboolean(L, 3);
|
||||
}
|
||||
|
||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
||||
inventorysort_t sortBy = (inventorysort_t)lua_tointeger(L, 2);
|
||||
|
||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||
inventorySort(inventory, sortBy, reverse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void moduleItem(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
|
||||
// Item information
|
||||
|
||||
// Bind BACKPACK const pointer
|
||||
scriptContextRegPointer(context, "BACKPACK", (void *)&BACKPACK);
|
||||
|
||||
// Bind Methods
|
||||
scriptContextRegFunc(
|
||||
context, "inventoryItemExists", moduleInventoryItemExists
|
||||
);
|
||||
scriptContextRegFunc(context, "inventoryAdd", moduleInventoryAdd);
|
||||
scriptContextRegFunc(context, "inventorySet", moduleInventorySet);
|
||||
scriptContextRegFunc(context, "inventoryRemove", moduleInventoryRemove);
|
||||
scriptContextRegFunc(context, "inventoryGetCount", moduleInventoryGetCount);
|
||||
scriptContextRegFunc(context, "inventoryIsFull", moduleInventoryIsFull);
|
||||
scriptContextRegFunc(context, "inventoryItemFull", moduleInventoryItemFull);
|
||||
scriptContextRegFunc(context, "inventorySort", moduleInventorySort);
|
||||
}
|
||||
@@ -49,6 +49,19 @@ void scriptContextRegFunc(
|
||||
lua_register(context->luaState, fnName, function);
|
||||
}
|
||||
|
||||
void scriptContextRegPointer(
|
||||
scriptcontext_t *context,
|
||||
const char_t *name,
|
||||
void *pointer
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(name, "Name cannot be NULL");
|
||||
assertNotNull(pointer, "Pointer cannot be NULL");
|
||||
|
||||
lua_pushlightuserdata(context->luaState, pointer);
|
||||
lua_setglobal(context->luaState, name);
|
||||
}
|
||||
|
||||
errorret_t scriptContextCallFunc(
|
||||
scriptcontext_t *context,
|
||||
const char_t *fnName,
|
||||
|
||||
@@ -37,6 +37,19 @@ void scriptContextRegFunc(
|
||||
lua_CFunction function
|
||||
);
|
||||
|
||||
/**
|
||||
* Register a pointer within a script context.
|
||||
*
|
||||
* @param context The script context to use.
|
||||
* @param name The name of the pointer in Lua.
|
||||
* @param pointer The pointer to register.
|
||||
*/
|
||||
void scriptContextRegPointer(
|
||||
scriptcontext_t *context,
|
||||
const char_t *name,
|
||||
void *pointer
|
||||
);
|
||||
|
||||
/**
|
||||
* Call a Lua function within a script context.
|
||||
*
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include "script/module/moduleinput.h"
|
||||
#include "script/module/moduleplatform.h"
|
||||
#include "script/module/modulescene.h"
|
||||
#include "script/module/moduleitem.h"
|
||||
|
||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||
{ .name = "system", .callback = moduleSystem },
|
||||
{ .name = "input", .callback = moduleInput },
|
||||
{ .name = "platform", .callback = modulePlatform },
|
||||
{ .name = "scene", .callback = moduleScene },
|
||||
{ .name = "item", .callback = moduleItem },
|
||||
};
|
||||
|
||||
#define SCRIPT_MODULE_COUNT ( \
|
||||
|
||||
@@ -42,7 +42,6 @@ void uiRender(void) {
|
||||
// Render UI elements here
|
||||
if(UI.fontTexture.width > 0) {
|
||||
uiDebugRender(UI.fontTileset, &UI.fontTexture);
|
||||
// uiTextboxRender();
|
||||
}
|
||||
cameraPopMatrix();
|
||||
}
|
||||
|
||||
49
tools/csvtoenum.py
Normal file
49
tools/csvtoenum.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
csvtoenum.py: Generate a C enum header from a CSV file.
|
||||
Usage:
|
||||
python csvtoenum.py <csv_file> <out_header> <c_type> <take_column> <prefix_column>
|
||||
"""
|
||||
import sys
|
||||
import csv
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 6:
|
||||
print("Usage: csvtoenum.py <csv_file> <out_header> <c_type> <take_column> <prefix_column>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
csv_file, out_header, c_type, take_column, prefix_column = sys.argv[1:6]
|
||||
|
||||
with open(csv_file, newline='') as f:
|
||||
reader = csv.DictReader(f)
|
||||
if take_column not in reader.fieldnames:
|
||||
print(f"TAKE_COLUMN '{take_column}' not found in CSV header", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
if prefix_column not in reader.fieldnames:
|
||||
print(f"PREFIX_COLUMN '{prefix_column}' not found in CSV header", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
entries = []
|
||||
for row in reader:
|
||||
entry = row[take_column].strip()
|
||||
prefix = row[prefix_column].strip()
|
||||
if entry:
|
||||
entries.append(f" {prefix}{entry},")
|
||||
|
||||
# Compose enum
|
||||
enum_entries = [f" {prefix_column}NULL,"]
|
||||
enum_entries.extend(entries)
|
||||
enum_entries.append(f" {prefix_column}COUNT,")
|
||||
enum_body = "\n".join(enum_entries)
|
||||
header = f"""/**
|
||||
* Auto-generated by csvtoenum.py
|
||||
* Source: {csv_file}
|
||||
*/
|
||||
|
||||
typedef enum {{
|
||||
{enum_body}
|
||||
}} {c_type};
|
||||
"""
|
||||
with open(out_header, 'w') as f:
|
||||
f.write(header)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user