RingRacers/src/lua_itemroulettelib.c

276 lines
No EOL
7.6 KiB
C

// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2016 by John "JTE" Muniz.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_itemroulettelib.c
/// \brief player item roulette structure library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "d_player.h"
#include "z_zone.h"
#include "k_roulette.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
enum itemroulette {
itemroulette_valid = 0,
itemroulette_active,
itemroulette_itemlist,
itemroulette_playing,
itemroulette_exiting,
itemroulette_dist,
itemroulette_basedist,
itemroulette_firstdist,
itemroulette_seconddist,
itemroulette_secondtofirst,
itemroulette_index,
itemroulette_sound,
itemroulette_speed,
itemroulette_tics,
itemroulette_elapsed,
itemroulette_eggman,
itemroulette_ringbox,
itemroulette_autoroulette,
itemroulette_reserved
};
static const char *const itemroulette_opt[] = {
"valid",
"active",
"itemlist",
"playing",
"exiting",
"dist",
"basedist",
"firstdist",
"seconddist",
"secondtofirst",
"index",
"sound",
"speed",
"tics",
"elapsed",
"eggman",
"ringbox",
"autoroulette",
"reserved",
NULL
};
static int itemroulette_get(lua_State *L)
{
itemroulette_t *itemroulette = *((itemroulette_t **)luaL_checkudata(L, 1, META_ITEMROULETTE));
enum itemroulette field = luaL_checkoption(L, 2, itemroulette_opt[0], itemroulette_opt);
// if this is null, welcome to parking garage rally circuit
I_Assert(itemroulette != NULL);
switch (field)
{
case itemroulette_valid:
lua_pushboolean(L, itemroulette != NULL);
break;
case itemroulette_active:
lua_pushboolean(L, itemroulette->active);
break;
case itemroulette_itemlist:
LUA_PushUserdata(L, &itemroulette->itemList, META_ITEMROULETTE_ITEMLIST);
break;
case itemroulette_playing:
lua_pushinteger(L, itemroulette->playing);
break;
case itemroulette_exiting:
lua_pushinteger(L, itemroulette->exiting);
break;
case itemroulette_dist:
lua_pushinteger(L, itemroulette->dist);
break;
case itemroulette_basedist:
lua_pushinteger(L, itemroulette->baseDist);
break;
case itemroulette_firstdist:
lua_pushinteger(L, itemroulette->firstDist);
break;
case itemroulette_seconddist:
lua_pushinteger(L, itemroulette->secondDist);
break;
case itemroulette_secondtofirst:
lua_pushinteger(L, itemroulette->secondToFirst);
break;
case itemroulette_index:
lua_pushinteger(L, itemroulette->index);
break;
case itemroulette_sound:
lua_pushinteger(L, itemroulette->sound);
break;
case itemroulette_speed:
lua_pushinteger(L, itemroulette->speed);
break;
case itemroulette_tics:
lua_pushinteger(L, itemroulette->tics);
break;
case itemroulette_elapsed:
lua_pushinteger(L, itemroulette->elapsed);
break;
case itemroulette_eggman:
lua_pushboolean(L, itemroulette->eggman);
break;
case itemroulette_ringbox:
lua_pushboolean(L, itemroulette->ringbox);
break;
case itemroulette_autoroulette:
lua_pushboolean(L, itemroulette->autoroulette);
break;
case itemroulette_reserved:
lua_pushinteger(L, itemroulette->reserved);
break;
}
return 1;
}
#define NOSET luaL_error(L, LUA_QL("itemroulette_t") " field " LUA_QS " should not be set directly.", itemroulette_opt[field])
#define UNIMPLEMENTED luaL_error(L, LUA_QL("itemroulette_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", itemroulette_opt[field])
#define NOSETITEMLIST luaL_error(L, LUA_QL("itemroulette_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("K_AddItemToReel") ", " LUA_QL("K_PushToRouletteItemList") ", or " LUA_QL("K_StartItemRoulette") ", or " LUA_QL("K_StopRoulette") " instead.", itemroulette_opt[field])
static int itemroulette_set(lua_State *L)
{
itemroulette_t *itemroulette = *((itemroulette_t **)luaL_checkudata(L, 1, META_ITEMROULETTE));
enum itemroulette field = luaL_checkoption(L, 2, itemroulette_opt[0], itemroulette_opt);
// if this is null, welcome to parking garage rally circuit
I_Assert(itemroulette != NULL);
INLEVEL
if (hud_running)
return luaL_error(L, "Do not alter itemroulette_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter itemroulette_t in CMD building code!");
switch(field)
{
case itemroulette_valid:
return NOSET;
case itemroulette_active:
itemroulette->active = luaL_checkboolean(L, 3);
break;
case itemroulette_itemlist:
return NOSETITEMLIST;
case itemroulette_playing:
itemroulette->playing = luaL_checkinteger(L, 3);
break;
case itemroulette_exiting:
itemroulette->exiting = luaL_checkinteger(L, 3);
break;
case itemroulette_dist:
itemroulette->dist = luaL_checkinteger(L, 3);
break;
case itemroulette_basedist:
itemroulette->baseDist = luaL_checkinteger(L, 3);
break;
case itemroulette_firstdist:
itemroulette->firstDist = luaL_checkinteger(L, 3);
break;
case itemroulette_seconddist:
itemroulette->secondDist = luaL_checkinteger(L, 3);
break;
case itemroulette_secondtofirst:
itemroulette->secondToFirst = luaL_checkinteger(L, 3);
break;
case itemroulette_index:
itemroulette->index = luaL_checkinteger(L, 3);
break;
case itemroulette_sound:
itemroulette->sound = luaL_checkinteger(L, 3);
break;
case itemroulette_speed:
itemroulette->speed = luaL_checkinteger(L, 3);
break;
case itemroulette_tics:
itemroulette->tics = luaL_checkinteger(L, 3);
break;
case itemroulette_elapsed:
itemroulette->elapsed = luaL_checkinteger(L, 3);
break;
case itemroulette_eggman:
itemroulette->eggman = luaL_checkboolean(L, 3);
break;
case itemroulette_ringbox:
itemroulette->ringbox = luaL_checkboolean(L, 3);
break;
case itemroulette_autoroulette:
itemroulette->autoroulette = luaL_checkboolean(L, 3);
break;
case itemroulette_reserved:
itemroulette->reserved = luaL_checkinteger(L, 3);
break;
}
return 0;
}
#undef NOSET
#undef NOSETITEMLIST
#undef UNIMPLEMENTED
// itemlist, i -> itemlist[i]
static int itemrouletteitemlist_get(lua_State *L)
{
itemlist_t *itemlist = *((itemlist_t **)luaL_checkudata(L, 1, META_ITEMROULETTE_ITEMLIST));
size_t index = luaL_checkint(L, 2);
if (!itemlist)
return LUA_ErrInvalid(L, "itemroulette_t.itemlist_t");
if (index == 0 || index > itemlist->len) {
return luaL_error(L, LUA_QL("itemroulette_t.itemlist_t") " index cannot be %d", index);
}
lua_pushinteger(L, itemlist->items[index-1]);
return 1;
}
static int itemrouletteitemlist_set(lua_State *L)
{
return luaL_error(L, LUA_QL("itemroulette_t.itemlist_t") " struct cannot be edited by Lua.");
}
// #itemlist -> itemList.len
static int itemrouletteitemlist_len(lua_State* L)
{
itemlist_t *itemlist = *((itemlist_t **)luaL_checkudata(L, 1, META_ITEMROULETTE_ITEMLIST));
lua_pushinteger(L, itemlist->len);
return 1;
}
int LUA_ItemRouletteLib(lua_State *L)
{
luaL_newmetatable(L, META_ITEMROULETTE);
lua_pushcfunction(L, itemroulette_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, itemroulette_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
luaL_newmetatable(L, META_ITEMROULETTE_ITEMLIST);
lua_pushcfunction(L, itemrouletteitemlist_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, itemrouletteitemlist_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, itemrouletteitemlist_len);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
return 0;
}