mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
293 lines
6.9 KiB
C
293 lines
6.9 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_waypointslib.c
|
|
/// \brief wapoint structure library for Lua scripting
|
|
|
|
#include "doomdef.h"
|
|
#include "fastcmp.h"
|
|
|
|
#include "lua_script.h"
|
|
#include "lua_libs.h"
|
|
|
|
enum waypointvars {
|
|
waypointvars_valid = 0,
|
|
waypointvars_mobj,
|
|
waypointvars_x,
|
|
waypointvars_y,
|
|
waypointvars_z,
|
|
waypointvars_onaline,
|
|
waypointvars_nextwaypoints,
|
|
waypointvars_prevwaypoints,
|
|
waypointvars_nextwaypointdistances,
|
|
waypointvars_prevwaypointdistances,
|
|
waypointvars_numnextwaypoints,
|
|
waypointvars_numprevwaypoints,
|
|
};
|
|
|
|
static const char *const waypointvars_opt[] = {
|
|
"valid",
|
|
"mobj",
|
|
"x",
|
|
"y",
|
|
"z",
|
|
"onaline",
|
|
"nextwaypoints",
|
|
"prevwaypoints",
|
|
"nextwaypointdistances",
|
|
"prevwaypointdistances",
|
|
"numnextwaypoints",
|
|
"numprevwaypoints",
|
|
NULL
|
|
};
|
|
|
|
#define RNOFIELD luaL_error(L, LUA_QL("waypoint_t") " has no field named " LUA_QS, field)
|
|
#define RNOSET luaL_error(L, LUA_QL("waypoint_t") " field " LUA_QS " cannot be set.", field)
|
|
#define RNOGET luaL_error(L, LUA_QL("waypoint_t") " field " LUA_QS " cannot be get.", field)
|
|
|
|
static int waypoint_get(lua_State *L)
|
|
{
|
|
waypoint_t *waypoint = *((waypoint_t **)luaL_checkudata(L, 1, META_WAYPOINT));
|
|
enum waypointvars field = luaL_checkoption(L, 2, NULL, waypointvars_opt);
|
|
|
|
if (!waypoint)
|
|
{
|
|
switch (field)
|
|
{
|
|
case waypointvars_valid:
|
|
lua_pushboolean(L, false);
|
|
return 1;
|
|
default:
|
|
return LUA_ErrInvalid(L, "waypoint_t");
|
|
}
|
|
}
|
|
|
|
// It could totally happen that some scripter just deletes the mobj,
|
|
// which would have us check a null pointer, so we're checking against that
|
|
// just in case.
|
|
mobj_t *waypointMobj = NULL;
|
|
if (waypoint->mobj != NULL && P_MobjWasRemoved(waypoint->mobj) == false)
|
|
waypointMobj = waypoint->mobj;
|
|
|
|
switch (field)
|
|
{
|
|
case waypointvars_valid:
|
|
lua_pushboolean(L, true);
|
|
break;
|
|
case waypointvars_mobj:
|
|
return RNOGET;
|
|
case waypointvars_x:
|
|
if (waypointMobj)
|
|
lua_pushfixed(L, waypointMobj->x);
|
|
else
|
|
lua_pushnil(L);
|
|
break;
|
|
case waypointvars_y:
|
|
if (waypointMobj)
|
|
lua_pushinteger(L, waypointMobj->y);
|
|
else
|
|
lua_pushnil(L);
|
|
break;
|
|
case waypointvars_z:
|
|
if (waypointMobj)
|
|
lua_pushinteger(L, waypointMobj->z);
|
|
else
|
|
lua_pushnil(L);
|
|
break;
|
|
case waypointvars_onaline:
|
|
lua_pushboolean(L, waypoint->onaline);
|
|
break;
|
|
case waypointvars_nextwaypoints:
|
|
lua_createtable(L, waypoint->numnextwaypoints, 0);
|
|
for (size_t i = 0; i < waypoint->numnextwaypoints; i++)
|
|
{
|
|
LUA_PushUserdata(L, waypoint->nextwaypoints[i], META_WAYPOINT);
|
|
lua_rawseti(L, -2, 1 + i);
|
|
}
|
|
break;
|
|
case waypointvars_prevwaypoints:
|
|
lua_createtable(L, waypoint->numprevwaypoints, 0);
|
|
for (size_t i = 0; i < waypoint->numprevwaypoints; i++)
|
|
{
|
|
LUA_PushUserdata(L, waypoint->prevwaypoints[i], META_WAYPOINT);
|
|
lua_rawseti(L, -2, 1 + i);
|
|
}
|
|
break;
|
|
case waypointvars_nextwaypointdistances:
|
|
lua_createtable(L, waypoint->numnextwaypoints, 0);
|
|
for (size_t i = 0; i < waypoint->numnextwaypoints; i++)
|
|
{
|
|
lua_pushinteger(L, waypoint->nextwaypointdistances[i]);
|
|
lua_rawseti(L, -2, 1 + i);
|
|
}
|
|
break;
|
|
case waypointvars_prevwaypointdistances:
|
|
lua_createtable(L, waypoint->numprevwaypoints, 0);
|
|
for (size_t i = 0; i < waypoint->numprevwaypoints; i++)
|
|
{
|
|
lua_pushinteger(L, waypoint->prevwaypointdistances[i]);
|
|
lua_rawseti(L, -2, 1 + i);
|
|
}
|
|
break;
|
|
case waypointvars_numnextwaypoints:
|
|
lua_pushinteger(L, waypoint->numnextwaypoints);
|
|
break;
|
|
case waypointvars_numprevwaypoints:
|
|
lua_pushinteger(L, waypoint->numprevwaypoints);
|
|
break;
|
|
default:
|
|
return RNOFIELD;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int waypoint_set(lua_State *L)
|
|
{
|
|
waypoint_t *waypoint = *((waypoint_t **)luaL_checkudata(L, 1, META_WAYPOINT));
|
|
enum waypointvars field = luaL_checkoption(L, 2, waypointvars_opt[0], waypointvars_opt);
|
|
|
|
if (!waypoint)
|
|
return LUA_ErrInvalid(L, "waypoint_t");
|
|
|
|
INLEVEL
|
|
|
|
switch (field)
|
|
{
|
|
case waypointvars_mobj:
|
|
return RNOSET;
|
|
case waypointvars_x:
|
|
return RNOSET;
|
|
case waypointvars_y:
|
|
return RNOSET;
|
|
case waypointvars_z:
|
|
return RNOSET;
|
|
case waypointvars_onaline:
|
|
return RNOSET;
|
|
// A function should be used to set these instead.
|
|
case waypointvars_nextwaypoints:
|
|
return RNOSET;
|
|
case waypointvars_prevwaypoints:
|
|
return RNOSET;
|
|
case waypointvars_nextwaypointdistances:
|
|
return RNOSET;
|
|
case waypointvars_prevwaypointdistances:
|
|
return RNOSET;
|
|
case waypointvars_numnextwaypoints:
|
|
return RNOSET;
|
|
case waypointvars_numprevwaypoints:
|
|
return RNOSET;
|
|
default:
|
|
return RNOFIELD;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#undef RNOSET
|
|
#undef RNOFIELD
|
|
|
|
static int waypoint_num(lua_State *L)
|
|
{
|
|
waypoint_t *waypoint = *((waypoint_t **)luaL_checkudata(L, 1, META_WAYPOINT));
|
|
|
|
if (!waypoint)
|
|
return LUA_ErrInvalid(L, "waypoint_t");
|
|
|
|
lua_pushinteger(L, K_GetWaypointHeapIndex(waypoint));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_iterateWaypoints(lua_State *L)
|
|
{
|
|
size_t i;
|
|
|
|
if (lua_gettop(L) < 2)
|
|
{
|
|
lua_pushcfunction(L, lib_iterateWaypoints);
|
|
return 1;
|
|
}
|
|
|
|
lua_settop(L, 2);
|
|
lua_remove(L, 1); // state is unused.
|
|
|
|
if (!lua_isnil(L, 1))
|
|
i = K_GetWaypointHeapIndex(*(waypoint_t **)luaL_checkudata(L, 1, META_WAYPOINT)) + 1;
|
|
else
|
|
i = 0;
|
|
|
|
if (i < K_GetNumWaypoints())
|
|
{
|
|
LUA_PushUserdata(L, K_GetWaypointFromIndex(i), META_WAYPOINT);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int lib_getWaypoint(lua_State *L)
|
|
{
|
|
const char *field;
|
|
size_t i;
|
|
|
|
// find waypoint by number
|
|
if (lua_type(L, 2) == LUA_TNUMBER)
|
|
{
|
|
i = luaL_checkinteger(L, 2);
|
|
if (i >= K_GetNumWaypoints())
|
|
return luaL_error(L, "waypoints[] index %d out of range (0 - %d)", i, K_GetNumWaypoints()-1);
|
|
LUA_PushUserdata(L, K_GetWaypointFromIndex(i), META_WAYPOINT);
|
|
return 1;
|
|
}
|
|
|
|
field = luaL_checkstring(L, 2);
|
|
|
|
// special function iterate
|
|
if (fastcmp(field,"iterate"))
|
|
{
|
|
lua_pushcfunction(L, lib_iterateWaypoints);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int lib_numWaypoints(lua_State *L)
|
|
{
|
|
lua_pushinteger(L, K_GetNumWaypoints());
|
|
return 1;
|
|
}
|
|
|
|
|
|
int LUA_WaypointLib(lua_State *L)
|
|
{
|
|
luaL_newmetatable(L, META_WAYPOINT);
|
|
lua_pushcfunction(L, waypoint_get);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
lua_pushcfunction(L, waypoint_set);
|
|
lua_setfield(L, -2, "__newindex");
|
|
|
|
lua_pushcfunction(L, waypoint_num);
|
|
lua_setfield(L, -2, "__len");
|
|
lua_pop(L,1);
|
|
|
|
lua_newuserdata(L, 0);
|
|
lua_createtable(L, 0, 2);
|
|
lua_pushcfunction(L, lib_getWaypoint);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
lua_pushcfunction(L, lib_numWaypoints);
|
|
lua_setfield(L, -2, "__len");
|
|
lua_setmetatable(L, -2);
|
|
lua_setglobal(L, "waypoints");
|
|
|
|
return 0;
|
|
}
|