blankart/src/lua_botvarslib.c
2025-11-17 12:29:27 -05:00

402 lines
9 KiB
C

// BLANKART
//-----------------------------------------------------------------------------
// 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_botvarslib.c
/// \brief player botvars structure library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "k_bot.h"
enum botvars {
botvars_valid = 0,
botvars_style,
botvars_difficulty,
botvars_diffincrease,
botvars_rival,
botvars_rubberband,
};
static const char *const botvars_opt[] = {
"valid",
"style",
"difficulty",
"diffincrease",
"rival",
"rubberband",
NULL
};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("botvars_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", follower_opt[field])
static int botvars_get(lua_State *L)
{
botvars_t *botvars = *((botvars_t **)luaL_checkudata(L, 1, META_BOTVARS));
enum botvars field = luaL_checkoption(L, 2, NULL, botvars_opt);
// This is a property that always exists in a player.
I_Assert(botvars != NULL);
switch (field)
{
case botvars_valid:
lua_pushboolean(L, botvars != NULL);
break;
case botvars_style:
lua_pushinteger(L, botvars->style);
break;
case botvars_difficulty:
lua_pushinteger(L, botvars->difficulty);
break;
case botvars_diffincrease:
lua_pushinteger(L, botvars->diffincrease);
break;
case botvars_rival:
lua_pushboolean(L, botvars->rival);
break;
case botvars_rubberband:
lua_pushfixed(L, botvars->rubberband);
break;
}
return 1;
}
#define NOSET luaL_error(L, LUA_QL("botvars_t") " field " LUA_QS " should not be set directly.", botvars_opt[field])
static int botvars_set(lua_State *L)
{
botvars_t *botvars = *((botvars_t **)luaL_checkudata(L, 1, META_BOTVARS));
enum botvars field = luaL_checkoption(L, 2, botvars_opt[0], botvars_opt);
// This is a property that always exists in a player.
I_Assert(botvars != NULL);
INLEVEL
switch(field)
{
case botvars_valid:
return NOSET;
case botvars_style:
botvars->style = luaL_checkinteger(L, 3);
break;
case botvars_difficulty:
botvars->difficulty = luaL_checkinteger(L, 3);
break;
case botvars_diffincrease:
botvars->diffincrease = luaL_checkinteger(L, 3);
break;
case botvars_rival:
botvars->rival = luaL_checkboolean(L, 3);
break;
case botvars_rubberband:
botvars->rubberband = luaL_checkfixed(L, 3);
break;
}
return 0;
}
#undef NOSET
enum botdata {
botdata_valid,
botdata_itemdelay,
botdata_itemconfirm,
botdata_turnconfirm,
botdata_respawnconfirm,
botdata_driftstate,
botdata_driftturn,
botdata_drifttime,
botdata_driftlockout,
botdata_driftmaxdist,
botdata_driftpowerdiv,
botdata_driftstatedelay,
botdata_driftskill,
botdata_acceldown,
botdata_brakedown,
botdata_driftdown,
botdata_itemdown,
botdata_dolookback,
botdata_itemwasdown,
botdata_itemthrow,
botdata_turnamt,
};
static const char *const botdata_opt[] = {
"valid",
"itemdelay",
"itemconfirm",
"turnconfirm",
"respawnconfirm",
"driftstate",
"driftturn",
"drifttime",
"driftlockout",
"driftmaxdist",
"driftpowerdiv",
"driftstatedelay",
"driftskill",
"acceldown",
"brakedown",
"driftdown",
"itemdown",
"dolookback",
"itemwasdown",
"itemthrow",
"turnamt",
NULL
};
static int botdata_get(lua_State *L)
{
botdata_t *botdata = *((botdata_t **)luaL_checkudata(L, 1, META_BOTDATA));
enum botdata field = luaL_checkoption(L, 2, NULL, botdata_opt);
// it's a static array... i think...
I_Assert(botdata != NULL);
switch (field)
{
case botdata_valid:
lua_pushboolean(L, botdata != NULL);
break;
case botdata_itemdelay:
lua_pushinteger(L, botdata->itemdelay);
break;
case botdata_itemconfirm:
lua_pushinteger(L, botdata->itemconfirm);
break;
case botdata_turnconfirm:
lua_pushinteger(L, botdata->turnconfirm);
break;
case botdata_respawnconfirm:
lua_pushinteger(L, botdata->respawnconfirm);
break;
case botdata_driftstate:
lua_pushinteger(L, botdata->driftstate);
break;
case botdata_driftturn:
lua_pushinteger(L, botdata->driftturn);
break;
case botdata_drifttime:
lua_pushinteger(L, botdata->drifttime);
break;
case botdata_driftlockout:
lua_pushinteger(L, botdata->driftlockout);
break;
case botdata_driftmaxdist:
lua_pushinteger(L, botdata->driftmaxdist);
break;
case botdata_driftpowerdiv:
lua_pushinteger(L, botdata->driftpowerdiv);
break;
case botdata_driftstatedelay:
lua_pushinteger(L, botdata->driftstatedelay);
break;
case botdata_driftskill:
lua_pushfixed(L, botdata->driftskill);
break;
case botdata_acceldown:
lua_pushboolean(L, botdata->acceldown);
break;
case botdata_brakedown:
lua_pushboolean(L, botdata->brakedown);
break;
case botdata_driftdown:
lua_pushboolean(L, botdata->driftdown);
break;
case botdata_itemdown:
lua_pushboolean(L, botdata->itemdown);
break;
case botdata_dolookback:
lua_pushboolean(L, botdata->dolookback);
break;
case botdata_itemwasdown:
lua_pushboolean(L, botdata->itemwasdown);
break;
case botdata_itemthrow:
lua_pushinteger(L, botdata->itemthrow);
break;
case botdata_turnamt:
lua_pushinteger(L, botdata->turnamt);
break;
}
return 1;
}
#define NOSET luaL_error(L, LUA_QL("botdata_t") " field " LUA_QS " should not be set directly.", botdata_opt[field])
static int botdata_set(lua_State *L)
{
botdata_t *botdata = *((botdata_t **)luaL_checkudata(L, 1, META_BOTDATA));
enum botdata field = luaL_checkoption(L, 2, NULL, botdata_opt);
I_Assert(botdata != NULL);
switch (field)
{
case botdata_valid:
return NOSET;
case botdata_itemdelay:
botdata->itemdelay = luaL_checkinteger(L, 3);
break;
case botdata_itemconfirm:
botdata->itemconfirm = luaL_checkinteger(L, 3);
break;
case botdata_turnconfirm:
botdata->turnconfirm = luaL_checkinteger(L, 3);
break;
case botdata_respawnconfirm:
botdata->respawnconfirm = luaL_checkinteger(L, 3);
break;
case botdata_driftstate:
botdata->driftstate = luaL_checkinteger(L, 3);
break;
case botdata_driftturn:
botdata->driftturn = luaL_checkinteger(L, 3);
break;
case botdata_drifttime:
botdata->drifttime = luaL_checkinteger(L, 3);
break;
case botdata_driftlockout:
botdata->driftlockout = luaL_checkinteger(L, 3);
break;
case botdata_driftmaxdist:
botdata->driftmaxdist = luaL_checkinteger(L, 3);
break;
case botdata_driftpowerdiv:
botdata->driftpowerdiv = luaL_checkinteger(L, 3);
break;
case botdata_driftstatedelay:
botdata->driftstatedelay = luaL_checkinteger(L, 3);
break;
case botdata_driftskill:
botdata->driftskill = luaL_checkfixed(L, 3);
break;
case botdata_acceldown:
botdata->acceldown = luaL_checkboolean(L, 3);
break;
case botdata_brakedown:
botdata->brakedown = luaL_checkboolean(L, 3);
break;
case botdata_driftdown:
botdata->driftdown = luaL_checkboolean(L, 3);
break;
case botdata_itemdown:
botdata->itemdown = luaL_checkboolean(L, 3);
break;
case botdata_dolookback:
botdata->dolookback = luaL_checkboolean(L, 3);
break;
case botdata_itemwasdown:
botdata->itemwasdown = luaL_checkboolean(L, 3);
break;
case botdata_itemthrow:
botdata->itemthrow = luaL_checkinteger(L, 3);
break;
case botdata_turnamt:
botdata->turnamt = luaL_checkinteger(L, 3);
break;
}
return 0;
}
#undef NOSET
static int lib_iterateBotData(lua_State *L)
{
INT32 i;
if (lua_gettop(L) < 2)
{
lua_pushcfunction(L, lib_iterateBotData);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (INT32)(*((botdata_t **)luaL_checkudata(L, 1, META_BOTDATA)) - K_GetBotData(0)) + 1;
else
i = 0;
if (i < MAXPLAYERS)
{
LUA_PushUserdata(L, K_GetBotData(i), META_BOTDATA);
return 1;
}
return 0;
}
static int lib_getBotData(lua_State *L)
{
INT32 i;
if (lua_type(L, 2) == LUA_TNUMBER)
{
i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXPLAYERS)
return luaL_error(L, "botdata[] index %d out of range (0 - %d)", i, MAXPLAYERS-1);
LUA_PushUserdata(L, K_GetBotData(i), META_BOTDATA);
return 1;
}
if (fastcmp(luaL_checkstring(L, 2), "iterate"))
{
lua_pushcfunction(L, lib_iterateBotData);
return 1;
}
return 0;
}
static int lib_numBotData(lua_State *L)
{
lua_pushinteger(L, MAXPLAYERS);
return 1;
}
int LUA_BotVarsLib(lua_State *L)
{
luaL_newmetatable(L, META_BOTVARS);
lua_pushcfunction(L, botvars_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, botvars_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
luaL_newmetatable(L, META_BOTDATA);
lua_pushcfunction(L, botdata_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, botdata_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getBotData);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numBotData);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "botdata");
return 0;
}