2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
2016-05-18 00:42:11 +00:00
// Copyright (C) 2012-2016 by John "JTE" Muniz.
2023-03-31 12:53:31 +00:00
// Copyright (C) 2012-2023 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// 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_mobjlib.c
/// \brief mobj/thing library for Lua scripting
# include "doomdef.h"
# include "fastcmp.h"
2021-04-27 03:20:41 +00:00
# include "r_data.h"
2020-03-09 13:54:56 +00:00
# include "r_skins.h"
2014-03-15 16:59:03 +00:00
# include "p_local.h"
# include "g_game.h"
# include "p_setup.h"
# include "lua_script.h"
# include "lua_libs.h"
# include "lua_hud.h" // hud_running errors
2020-07-17 05:08:38 +00:00
# include "lua_hook.h" // hook_cmd_running errors
2014-03-15 16:59:03 +00:00
enum mobj_e {
mobj_valid = 0 ,
mobj_x ,
mobj_y ,
mobj_z ,
mobj_snext ,
mobj_sprev ,
mobj_angle ,
2020-04-19 12:39:16 +00:00
mobj_pitch ,
mobj_roll ,
2019-08-18 17:16:48 +00:00
mobj_rollangle ,
2014-03-15 16:59:03 +00:00
mobj_sprite ,
mobj_frame ,
2016-11-11 21:37:28 +00:00
mobj_sprite2 ,
2016-02-09 10:39:16 +00:00
mobj_anim_duration ,
2020-10-13 15:57:36 +00:00
mobj_spritexscale ,
mobj_spriteyscale ,
mobj_spritexoffset ,
mobj_spriteyoffset ,
2020-10-14 03:57:13 +00:00
mobj_floorspriteslope ,
2014-03-15 16:59:03 +00:00
mobj_touching_sectorlist ,
mobj_subsector ,
mobj_floorz ,
mobj_ceilingz ,
2018-09-15 01:42:52 +00:00
mobj_floorrover ,
mobj_ceilingrover ,
2014-03-15 16:59:03 +00:00
mobj_radius ,
mobj_height ,
mobj_momx ,
mobj_momy ,
mobj_momz ,
mobj_pmomz ,
mobj_tics ,
mobj_state ,
mobj_flags ,
mobj_flags2 ,
mobj_eflags ,
2020-10-12 03:13:22 +00:00
mobj_renderflags ,
2014-03-15 16:59:03 +00:00
mobj_skin ,
mobj_color ,
2020-10-27 03:03:41 +00:00
mobj_blendmode ,
2014-03-15 16:59:03 +00:00
mobj_bnext ,
mobj_bprev ,
mobj_hnext ,
mobj_hprev ,
mobj_type ,
mobj_info ,
mobj_health ,
mobj_movedir ,
mobj_movecount ,
mobj_target ,
mobj_reactiontime ,
mobj_threshold ,
mobj_player ,
mobj_lastlook ,
mobj_spawnpoint ,
mobj_tracer ,
mobj_friction ,
mobj_movefactor ,
mobj_fuse ,
mobj_watertop ,
mobj_waterbottom ,
mobj_mobjnum ,
mobj_scale ,
mobj_destscale ,
mobj_scalespeed ,
mobj_extravalue1 ,
mobj_extravalue2 ,
mobj_cusval ,
2018-10-21 14:12:51 +00:00
mobj_cvmem ,
2019-06-18 16:55:57 +00:00
mobj_standingslope ,
2020-01-12 00:28:15 +00:00
mobj_colorized ,
2020-06-07 20:11:36 +00:00
mobj_mirrored ,
2022-01-13 07:53:26 +00:00
mobj_shadowscale ,
mobj_dispoffset
2014-03-15 16:59:03 +00:00
} ;
static const char * const mobj_opt [ ] = {
" valid " ,
" x " ,
" y " ,
" z " ,
" snext " ,
" sprev " ,
" angle " ,
2020-04-19 12:39:16 +00:00
" pitch " ,
" roll " ,
2019-08-18 17:16:48 +00:00
" rollangle " ,
2014-03-15 16:59:03 +00:00
" sprite " ,
" frame " ,
2016-11-11 21:37:28 +00:00
" sprite2 " ,
2016-02-09 10:39:16 +00:00
" anim_duration " ,
2020-10-13 15:57:36 +00:00
" spritexscale " ,
" spriteyscale " ,
" spritexoffset " ,
" spriteyoffset " ,
2020-10-14 03:57:13 +00:00
" floorspriteslope " ,
2014-03-15 16:59:03 +00:00
" touching_sectorlist " ,
" subsector " ,
" floorz " ,
" ceilingz " ,
2018-09-15 01:42:52 +00:00
" floorrover " ,
" ceilingrover " ,
2014-03-15 16:59:03 +00:00
" radius " ,
" height " ,
" momx " ,
" momy " ,
" momz " ,
" pmomz " ,
" tics " ,
" state " ,
" flags " ,
" flags2 " ,
" eflags " ,
2020-10-12 03:13:22 +00:00
" renderflags " ,
2014-03-15 16:59:03 +00:00
" skin " ,
" color " ,
2020-10-27 03:03:41 +00:00
" blendmode " ,
2014-03-15 16:59:03 +00:00
" bnext " ,
" bprev " ,
" hnext " ,
" hprev " ,
" type " ,
" info " ,
" health " ,
" movedir " ,
" movecount " ,
" target " ,
" reactiontime " ,
" threshold " ,
" player " ,
" lastlook " ,
" spawnpoint " ,
" tracer " ,
" friction " ,
" movefactor " ,
" fuse " ,
" watertop " ,
" waterbottom " ,
" mobjnum " ,
" scale " ,
" destscale " ,
" scalespeed " ,
" extravalue1 " ,
" extravalue2 " ,
" cusval " ,
" cvmem " ,
2018-10-21 14:12:51 +00:00
" standingslope " ,
2019-06-18 16:55:57 +00:00
" colorized " ,
2020-06-07 20:11:36 +00:00
" mirrored " ,
2020-01-12 00:28:15 +00:00
" shadowscale " ,
2022-01-13 07:53:26 +00:00
" dispoffset " ,
2014-03-15 16:59:03 +00:00
NULL } ;
# define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
static int mobj_get ( lua_State * L )
{
mobj_t * mo = * ( ( mobj_t * * ) luaL_checkudata ( L , 1 , META_MOBJ ) ) ;
enum mobj_e field = Lua_optoption ( L , 2 , NULL , mobj_opt ) ;
lua_settop ( L , 2 ) ;
2020-07-14 05:34:57 +00:00
if ( ! mo | | ! ISINLEVEL ) {
2014-03-15 16:59:03 +00:00
if ( field = = mobj_valid ) {
lua_pushboolean ( L , 0 ) ;
return 1 ;
}
2020-07-14 05:34:57 +00:00
if ( ! mo ) {
return LUA_ErrInvalid ( L , " mobj_t " ) ;
} else
return luaL_error ( L , " Do not access an mobj_t field outside a level! " ) ;
2014-03-15 16:59:03 +00:00
}
switch ( field )
{
case mobj_valid :
lua_pushboolean ( L , 1 ) ;
break ;
case mobj_x :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > x ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_y :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > y ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_z :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > z ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_snext :
LUA_PushUserdata ( L , mo - > snext , META_MOBJ ) ;
break ;
case mobj_sprev :
// sprev is actually the previous mobj's snext pointer,
// or the subsector->sector->thing_list if there is no previous mobj,
// i.e. it will always ultimately point to THIS mobj -- so that's actually not useful to Lua and won't be included.
return UNIMPLEMENTED ;
case mobj_angle :
2015-05-21 03:54:04 +00:00
lua_pushangle ( L , mo - > angle ) ;
2014-03-15 16:59:03 +00:00
break ;
2020-04-19 12:39:16 +00:00
case mobj_pitch :
lua_pushangle ( L , mo - > pitch ) ;
break ;
case mobj_roll :
lua_pushangle ( L , mo - > roll ) ;
break ;
2019-08-18 17:16:48 +00:00
case mobj_rollangle :
lua_pushangle ( L , mo - > rollangle ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_sprite :
lua_pushinteger ( L , mo - > sprite ) ;
break ;
case mobj_frame :
lua_pushinteger ( L , mo - > frame ) ;
break ;
2016-11-11 21:37:28 +00:00
case mobj_sprite2 :
lua_pushinteger ( L , mo - > sprite2 ) ;
break ;
2016-02-09 10:39:16 +00:00
case mobj_anim_duration :
lua_pushinteger ( L , mo - > anim_duration ) ;
break ;
2020-10-13 15:57:36 +00:00
case mobj_spritexscale :
lua_pushfixed ( L , mo - > spritexscale ) ;
break ;
case mobj_spriteyscale :
lua_pushfixed ( L , mo - > spriteyscale ) ;
break ;
case mobj_spritexoffset :
lua_pushfixed ( L , mo - > spritexoffset ) ;
break ;
case mobj_spriteyoffset :
lua_pushfixed ( L , mo - > spriteyoffset ) ;
break ;
2020-10-14 03:57:13 +00:00
case mobj_floorspriteslope :
LUA_PushUserdata ( L , mo - > floorspriteslope , META_SLOPE ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_touching_sectorlist :
return UNIMPLEMENTED ;
case mobj_subsector :
LUA_PushUserdata ( L , mo - > subsector , META_SUBSECTOR ) ;
break ;
case mobj_floorz :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > floorz ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_ceilingz :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > ceilingz ) ;
2014-03-15 16:59:03 +00:00
break ;
2018-09-15 01:42:52 +00:00
case mobj_floorrover :
LUA_PushUserdata ( L , mo - > floorrover , META_FFLOOR ) ;
break ;
case mobj_ceilingrover :
LUA_PushUserdata ( L , mo - > ceilingrover , META_FFLOOR ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_radius :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > radius ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_height :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > height ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_momx :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > momx ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_momy :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > momy ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_momz :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > momz ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_pmomz :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > pmomz ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_tics :
lua_pushinteger ( L , mo - > tics ) ;
break ;
case mobj_state : // state number, not struct
lua_pushinteger ( L , mo - > state - states ) ;
break ;
case mobj_flags :
lua_pushinteger ( L , mo - > flags ) ;
break ;
case mobj_flags2 :
lua_pushinteger ( L , mo - > flags2 ) ;
break ;
case mobj_eflags :
lua_pushinteger ( L , mo - > eflags ) ;
break ;
2020-10-12 03:13:22 +00:00
case mobj_renderflags :
lua_pushinteger ( L , mo - > renderflags ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_skin : // skin name or nil, not struct
if ( ! mo - > skin )
return 0 ;
lua_pushstring ( L , ( ( skin_t * ) mo - > skin ) - > name ) ;
break ;
case mobj_color :
lua_pushinteger ( L , mo - > color ) ;
break ;
2020-10-27 03:03:41 +00:00
case mobj_blendmode :
lua_pushinteger ( L , mo - > blendmode ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_bnext :
LUA_PushUserdata ( L , mo - > bnext , META_MOBJ ) ;
break ;
case mobj_bprev :
// bprev -- same deal as sprev above, but for the blockmap.
return UNIMPLEMENTED ;
case mobj_hnext :
2019-07-13 12:43:22 +00:00
if ( mo - > hnext & & P_MobjWasRemoved ( mo - > hnext ) )
{ // don't put invalid mobj back into Lua.
P_SetTarget ( & mo - > hnext , NULL ) ;
return 0 ;
}
2014-03-15 16:59:03 +00:00
LUA_PushUserdata ( L , mo - > hnext , META_MOBJ ) ;
break ;
case mobj_hprev :
2019-07-13 12:43:22 +00:00
if ( mo - > hprev & & P_MobjWasRemoved ( mo - > hprev ) )
{ // don't put invalid mobj back into Lua.
P_SetTarget ( & mo - > hprev , NULL ) ;
return 0 ;
}
2014-03-15 16:59:03 +00:00
LUA_PushUserdata ( L , mo - > hprev , META_MOBJ ) ;
break ;
case mobj_type :
lua_pushinteger ( L , mo - > type ) ;
break ;
case mobj_info :
LUA_PushUserdata ( L , & mobjinfo [ mo - > type ] , META_MOBJINFO ) ;
break ;
case mobj_health :
lua_pushinteger ( L , mo - > health ) ;
break ;
case mobj_movedir :
lua_pushinteger ( L , mo - > movedir ) ;
break ;
case mobj_movecount :
lua_pushinteger ( L , mo - > movecount ) ;
break ;
case mobj_target :
if ( mo - > target & & P_MobjWasRemoved ( mo - > target ) )
{ // don't put invalid mobj back into Lua.
P_SetTarget ( & mo - > target , NULL ) ;
return 0 ;
}
LUA_PushUserdata ( L , mo - > target , META_MOBJ ) ;
break ;
case mobj_reactiontime :
lua_pushinteger ( L , mo - > reactiontime ) ;
break ;
case mobj_threshold :
lua_pushinteger ( L , mo - > threshold ) ;
break ;
case mobj_player :
LUA_PushUserdata ( L , mo - > player , META_PLAYER ) ;
break ;
case mobj_lastlook :
lua_pushinteger ( L , mo - > lastlook ) ;
break ;
case mobj_spawnpoint :
LUA_PushUserdata ( L , mo - > spawnpoint , META_MAPTHING ) ;
break ;
case mobj_tracer :
if ( mo - > tracer & & P_MobjWasRemoved ( mo - > tracer ) )
{ // don't put invalid mobj back into Lua.
P_SetTarget ( & mo - > tracer , NULL ) ;
return 0 ;
}
LUA_PushUserdata ( L , mo - > tracer , META_MOBJ ) ;
break ;
case mobj_friction :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > friction ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_movefactor :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > movefactor ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_fuse :
lua_pushinteger ( L , mo - > fuse ) ;
break ;
case mobj_watertop :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > watertop ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_waterbottom :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > waterbottom ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_mobjnum :
// mobjnum is a networking thing generated for $$$.sav
// and therefore shouldn't be used by Lua.
return UNIMPLEMENTED ;
case mobj_scale :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > scale ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_destscale :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > destscale ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_scalespeed :
2015-05-21 03:54:04 +00:00
lua_pushfixed ( L , mo - > scalespeed ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_extravalue1 :
lua_pushinteger ( L , mo - > extravalue1 ) ;
break ;
case mobj_extravalue2 :
lua_pushinteger ( L , mo - > extravalue2 ) ;
break ;
case mobj_cusval :
lua_pushinteger ( L , mo - > cusval ) ;
break ;
case mobj_cvmem :
lua_pushinteger ( L , mo - > cvmem ) ;
break ;
2018-10-21 14:12:51 +00:00
case mobj_standingslope :
LUA_PushUserdata ( L , mo - > standingslope , META_SLOPE ) ;
break ;
2019-06-18 16:55:57 +00:00
case mobj_colorized :
lua_pushboolean ( L , mo - > colorized ) ;
break ;
2020-06-07 20:11:36 +00:00
case mobj_mirrored :
lua_pushboolean ( L , mo - > mirrored ) ;
break ;
2020-01-12 00:28:15 +00:00
case mobj_shadowscale :
lua_pushfixed ( L , mo - > shadowscale ) ;
break ;
2022-01-13 07:53:26 +00:00
case mobj_dispoffset :
lua_pushinteger ( L , mo - > dispoffset ) ;
break ;
2014-03-15 16:59:03 +00:00
default : // extra custom variables in Lua memory
lua_getfield ( L , LUA_REGISTRYINDEX , LREG_EXTVARS ) ;
I_Assert ( lua_istable ( L , - 1 ) ) ;
lua_pushlightuserdata ( L , mo ) ;
lua_rawget ( L , - 2 ) ;
if ( ! lua_istable ( L , - 1 ) ) { // no extra values table
CONS_Debug ( DBG_LUA , M_GetText ( " '%s' has no extvars table or field named '%s'; returning nil. \n " ) , " mobj_t " , lua_tostring ( L , 2 ) ) ;
return 0 ;
}
lua_pushvalue ( L , 2 ) ; // field name
lua_gettable ( L , - 2 ) ;
if ( lua_isnil ( L , - 1 ) ) // no value for this field
CONS_Debug ( DBG_LUA , M_GetText ( " '%s' has no field named '%s'; returning nil. \n " ) , " mobj_t " , lua_tostring ( L , 2 ) ) ;
break ;
}
return 1 ;
}
# define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
2021-11-29 13:20:27 +00:00
# define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
2014-03-15 16:59:03 +00:00
static int mobj_set ( lua_State * L )
{
mobj_t * mo = * ( ( mobj_t * * ) luaL_checkudata ( L , 1 , META_MOBJ ) ) ;
enum mobj_e field = Lua_optoption ( L , 2 , mobj_opt [ 0 ] , mobj_opt ) ;
lua_settop ( L , 3 ) ;
2019-10-24 20:14:51 +00:00
INLEVEL
2014-03-15 16:59:03 +00:00
if ( ! mo )
return LUA_ErrInvalid ( L , " mobj_t " ) ;
if ( hud_running )
return luaL_error ( L , " Do not alter mobj_t in HUD rendering code! " ) ;
2020-07-17 05:08:38 +00:00
if ( hook_cmd_running )
return luaL_error ( L , " Do not alter mobj_t in CMD building code! " ) ;
2014-03-15 16:59:03 +00:00
switch ( field )
{
case mobj_valid :
return NOSET ;
case mobj_x :
return NOSETPOS ;
case mobj_y :
return NOSETPOS ;
case mobj_z :
{
// z doesn't cross sector bounds so it's okay.
mobj_t * ptmthing = tmthing ;
2015-05-21 03:54:04 +00:00
mo - > z = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
P_CheckPosition ( mo , mo - > x , mo - > y ) ;
mo - > floorz = tmfloorz ;
mo - > ceilingz = tmceilingz ;
2018-09-10 04:35:40 +00:00
mo - > floorrover = tmfloorrover ;
mo - > ceilingrover = tmceilingrover ;
2014-03-15 16:59:03 +00:00
P_SetTarget ( & tmthing , ptmthing ) ;
break ;
}
case mobj_snext :
return NOSETPOS ;
case mobj_sprev :
return UNIMPLEMENTED ;
case mobj_angle :
2015-05-21 03:54:04 +00:00
mo - > angle = luaL_checkangle ( L , 3 ) ;
2020-05-28 16:34:56 +00:00
if ( mo - > player )
P_SetPlayerAngle ( mo - > player , mo - > angle ) ;
2014-03-15 16:59:03 +00:00
break ;
2020-04-19 12:39:16 +00:00
case mobj_pitch :
mo - > pitch = luaL_checkangle ( L , 3 ) ;
break ;
case mobj_roll :
mo - > roll = luaL_checkangle ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
2019-08-18 17:16:48 +00:00
case mobj_rollangle :
mo - > rollangle = luaL_checkangle ( L , 3 ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_sprite :
mo - > sprite = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_frame :
mo - > frame = ( UINT32 ) luaL_checkinteger ( L , 3 ) ;
break ;
2016-11-11 21:37:28 +00:00
case mobj_sprite2 :
2017-07-23 16:49:19 +00:00
mo - > sprite2 = P_GetSkinSprite2 ( ( ( skin_t * ) mo - > skin ) , ( UINT8 ) luaL_checkinteger ( L , 3 ) , mo - > player ) ;
2016-11-11 21:37:28 +00:00
break ;
2016-02-09 10:39:16 +00:00
case mobj_anim_duration :
mo - > anim_duration = ( UINT16 ) luaL_checkinteger ( L , 3 ) ;
break ;
2020-10-13 15:57:36 +00:00
case mobj_spritexscale :
mo - > spritexscale = luaL_checkfixed ( L , 3 ) ;
break ;
case mobj_spriteyscale :
mo - > spriteyscale = luaL_checkfixed ( L , 3 ) ;
break ;
case mobj_spritexoffset :
mo - > spritexoffset = luaL_checkfixed ( L , 3 ) ;
break ;
case mobj_spriteyoffset :
mo - > spriteyoffset = luaL_checkfixed ( L , 3 ) ;
break ;
2020-10-14 03:57:13 +00:00
case mobj_floorspriteslope :
return NOSET ;
2014-03-15 16:59:03 +00:00
case mobj_touching_sectorlist :
return UNIMPLEMENTED ;
case mobj_subsector :
return NOSETPOS ;
case mobj_floorz :
return NOSETPOS ;
case mobj_ceilingz :
return NOSETPOS ;
2018-09-15 01:42:52 +00:00
case mobj_floorrover :
return NOSET ;
case mobj_ceilingrover :
return NOSET ;
2014-03-15 16:59:03 +00:00
case mobj_radius :
{
mobj_t * ptmthing = tmthing ;
2015-05-21 03:54:04 +00:00
mo - > radius = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
if ( mo - > radius < 0 )
mo - > radius = 0 ;
P_CheckPosition ( mo , mo - > x , mo - > y ) ;
mo - > floorz = tmfloorz ;
mo - > ceilingz = tmceilingz ;
2018-09-10 04:35:40 +00:00
mo - > floorrover = tmfloorrover ;
mo - > ceilingrover = tmceilingrover ;
2014-03-15 16:59:03 +00:00
P_SetTarget ( & tmthing , ptmthing ) ;
break ;
}
case mobj_height :
{
mobj_t * ptmthing = tmthing ;
2015-05-21 03:54:04 +00:00
mo - > height = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
if ( mo - > height < 0 )
mo - > height = 0 ;
P_CheckPosition ( mo , mo - > x , mo - > y ) ;
mo - > floorz = tmfloorz ;
mo - > ceilingz = tmceilingz ;
2018-09-10 04:35:40 +00:00
mo - > floorrover = tmfloorrover ;
mo - > ceilingrover = tmceilingrover ;
2014-03-15 16:59:03 +00:00
P_SetTarget ( & tmthing , ptmthing ) ;
break ;
}
case mobj_momx :
2015-05-21 03:54:04 +00:00
mo - > momx = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_momy :
2015-05-21 03:54:04 +00:00
mo - > momy = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_momz :
2015-05-21 03:54:04 +00:00
mo - > momz = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_pmomz :
2015-05-21 03:54:04 +00:00
mo - > pmomz = luaL_checkfixed ( L , 3 ) ;
2015-05-29 17:53:06 +00:00
mo - > eflags | = MFE_APPLYPMOMZ ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_tics :
mo - > tics = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_state : // set state by enum
if ( mo - > player )
P_SetPlayerMobjState ( mo , luaL_checkinteger ( L , 3 ) ) ;
else
P_SetMobjState ( mo , luaL_checkinteger ( L , 3 ) ) ;
break ;
case mobj_flags : // special handling for MF_NOBLOCKMAP and MF_NOSECTOR
{
UINT32 flags = luaL_checkinteger ( L , 3 ) ;
if ( ( flags & ( MF_NOBLOCKMAP | MF_NOSECTOR ) ) ! = ( mo - > flags & ( MF_NOBLOCKMAP | MF_NOSECTOR ) ) )
{
P_UnsetThingPosition ( mo ) ;
mo - > flags = flags ;
if ( flags & MF_NOSECTOR & & sector_list )
{
P_DelSeclist ( sector_list ) ;
sector_list = NULL ;
}
mo - > snext = NULL , mo - > sprev = NULL ;
mo - > bnext = NULL , mo - > bprev = NULL ;
P_SetThingPosition ( mo ) ;
}
else
mo - > flags = flags ;
break ;
}
case mobj_flags2 :
mo - > flags2 = ( UINT32 ) luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_eflags :
mo - > eflags = ( UINT32 ) luaL_checkinteger ( L , 3 ) ;
break ;
2020-10-12 03:13:22 +00:00
case mobj_renderflags :
mo - > renderflags = ( UINT32 ) luaL_checkinteger ( L , 3 ) ;
break ;
2014-03-15 16:59:03 +00:00
case mobj_skin : // set skin by name
{
INT32 i ;
char skin [ SKINNAMESIZE + 1 ] ; // all skin names are limited to this length
strlcpy ( skin , luaL_checkstring ( L , 3 ) , sizeof skin ) ;
strlwr ( skin ) ; // all skin names are lowercase
for ( i = 0 ; i < numskins ; i + + )
if ( fastcmp ( skins [ i ] . name , skin ) )
{
2017-03-18 14:20:42 +00:00
if ( ! mo - > player | | R_SkinUsable ( mo - > player - players , i ) )
2017-03-17 17:18:14 +00:00
mo - > skin = & skins [ i ] ;
2014-03-15 16:59:03 +00:00
return 0 ;
}
return luaL_error ( L , " mobj.skin '%s' not found! " , skin ) ;
}
case mobj_color :
2016-05-14 22:52:40 +00:00
{
2020-05-24 00:29:07 +00:00
UINT16 newcolor = ( UINT16 ) luaL_checkinteger ( L , 3 ) ;
2020-02-15 08:18:41 +00:00
if ( newcolor > = numskincolors )
return luaL_error ( L , " mobj.color %d out of range (0 - %d) . " , newcolor, numskincolors-1) ;
2016-05-14 22:52:40 +00:00
mo - > color = newcolor ;
2014-03-15 16:59:03 +00:00
break ;
2016-05-14 22:52:40 +00:00
}
2020-10-27 03:03:41 +00:00
case mobj_blendmode :
2021-04-27 03:20:41 +00:00
{
INT32 blendmode = ( INT32 ) luaL_checkinteger ( L , 3 ) ;
if ( blendmode < 0 | | blendmode > AST_OVERLAY )
return luaL_error ( L , " mobj.blendmode %d out of range (0 - %d) . " , blendmode, AST_OVERLAY) ;
mo - > blendmode = blendmode ;
2020-10-27 03:03:41 +00:00
break ;
2021-04-27 03:20:41 +00:00
}
2014-03-15 16:59:03 +00:00
case mobj_bnext :
return NOSETPOS ;
case mobj_bprev :
return UNIMPLEMENTED ;
case mobj_hnext :
2018-04-01 19:54:19 +00:00
if ( lua_isnil ( L , 3 ) )
P_SetTarget ( & mo - > hnext , NULL ) ;
else
{
mobj_t * hnext = * ( ( mobj_t * * ) luaL_checkudata ( L , 3 , META_MOBJ ) ) ;
P_SetTarget ( & mo - > hnext , hnext ) ;
}
2014-03-15 16:59:03 +00:00
break ;
case mobj_hprev :
2018-04-01 19:54:19 +00:00
if ( lua_isnil ( L , 3 ) )
P_SetTarget ( & mo - > hprev , NULL ) ;
else
{
mobj_t * hprev = * ( ( mobj_t * * ) luaL_checkudata ( L , 3 , META_MOBJ ) ) ;
P_SetTarget ( & mo - > hprev , hprev ) ;
}
2014-03-15 16:59:03 +00:00
break ;
case mobj_type : // yeah sure, we'll let you change the mobj's type.
{
mobjtype_t newtype = luaL_checkinteger ( L , 3 ) ;
2016-05-14 22:52:40 +00:00
if ( newtype > = NUMMOBJTYPES )
return luaL_error ( L , " mobj.type %d out of range (0 - %d) . " , newtype, NUMMOBJTYPES-1) ;
2014-03-15 16:59:03 +00:00
mo - > type = newtype ;
mo - > info = & mobjinfo [ newtype ] ;
P_SetScale ( mo , mo - > scale ) ;
break ;
}
case mobj_info :
return NOSET ;
case mobj_health :
mo - > health = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_movedir :
mo - > movedir = ( angle_t ) luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_movecount :
mo - > movecount = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_target :
if ( lua_isnil ( L , 3 ) )
P_SetTarget ( & mo - > target , NULL ) ;
else
{
mobj_t * target = * ( ( mobj_t * * ) luaL_checkudata ( L , 3 , META_MOBJ ) ) ;
P_SetTarget ( & mo - > target , target ) ;
}
break ;
case mobj_reactiontime :
mo - > reactiontime = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_threshold :
mo - > threshold = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_player :
return NOSET ;
case mobj_lastlook :
mo - > lastlook = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_spawnpoint :
if ( lua_isnil ( L , 3 ) )
mo - > spawnpoint = NULL ;
else
{
mapthing_t * spawnpoint = * ( ( mapthing_t * * ) luaL_checkudata ( L , 3 , META_MAPTHING ) ) ;
mo - > spawnpoint = spawnpoint ;
}
break ;
case mobj_tracer :
if ( lua_isnil ( L , 3 ) )
P_SetTarget ( & mo - > tracer , NULL ) ;
else
{
mobj_t * tracer = * ( ( mobj_t * * ) luaL_checkudata ( L , 3 , META_MOBJ ) ) ;
P_SetTarget ( & mo - > tracer , tracer ) ;
}
break ;
case mobj_friction :
2015-05-21 03:54:04 +00:00
mo - > friction = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_movefactor :
2015-05-21 03:54:04 +00:00
mo - > movefactor = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_fuse :
mo - > fuse = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_watertop :
2015-05-21 03:54:04 +00:00
mo - > watertop = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_waterbottom :
2015-05-21 03:54:04 +00:00
mo - > waterbottom = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_mobjnum :
return UNIMPLEMENTED ;
case mobj_scale :
{
2015-05-21 03:54:04 +00:00
fixed_t scale = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
if ( scale < FRACUNIT / 100 )
scale = FRACUNIT / 100 ;
mo - > destscale = scale ;
P_SetScale ( mo , scale ) ;
2022-04-28 23:36:10 +00:00
mo - > old_scale = scale ;
2014-03-15 16:59:03 +00:00
break ;
}
case mobj_destscale :
{
2015-05-21 03:54:04 +00:00
fixed_t scale = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
if ( scale < FRACUNIT / 100 )
scale = FRACUNIT / 100 ;
mo - > destscale = scale ;
break ;
}
case mobj_scalespeed :
2015-05-21 03:54:04 +00:00
mo - > scalespeed = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
break ;
case mobj_extravalue1 :
mo - > extravalue1 = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_extravalue2 :
mo - > extravalue2 = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_cusval :
mo - > cusval = luaL_checkinteger ( L , 3 ) ;
break ;
case mobj_cvmem :
mo - > cvmem = luaL_checkinteger ( L , 3 ) ;
break ;
2018-10-21 14:12:51 +00:00
case mobj_standingslope :
return NOSET ;
2019-06-18 16:55:57 +00:00
case mobj_colorized :
mo - > colorized = luaL_checkboolean ( L , 3 ) ;
break ;
2020-06-07 20:11:36 +00:00
case mobj_mirrored :
mo - > mirrored = luaL_checkboolean ( L , 3 ) ;
break ;
2020-01-12 00:28:15 +00:00
case mobj_shadowscale :
mo - > shadowscale = luaL_checkfixed ( L , 3 ) ;
2020-01-17 06:18:00 +00:00
break ;
2022-01-13 07:53:26 +00:00
case mobj_dispoffset :
mo - > dispoffset = luaL_checkinteger ( L , 3 ) ;
break ;
2014-03-15 16:59:03 +00:00
default :
lua_getfield ( L , LUA_REGISTRYINDEX , LREG_EXTVARS ) ;
I_Assert ( lua_istable ( L , - 1 ) ) ;
lua_pushlightuserdata ( L , mo ) ;
lua_rawget ( L , - 2 ) ;
if ( lua_isnil ( L , - 1 ) ) {
// This index doesn't have a table for extra values yet, let's make one.
lua_pop ( L , 1 ) ;
CONS_Debug ( DBG_LUA , M_GetText ( " '%s' has no field named '%s'; adding it as Lua data. \n " ) , " mobj_t " , lua_tostring ( L , 2 ) ) ;
lua_newtable ( L ) ;
lua_pushlightuserdata ( L , mo ) ;
lua_pushvalue ( L , - 2 ) ; // ext value table
lua_rawset ( L , - 4 ) ; // LREG_EXTVARS table
}
lua_pushvalue ( L , 2 ) ; // key
lua_pushvalue ( L , 3 ) ; // value to store
lua_settable ( L , - 3 ) ;
lua_pop ( L , 2 ) ;
break ;
}
return 0 ;
}
# undef UNIMPLEMENTED
# undef NOSET
# undef NOSETPOS
# undef NOFIELD
2020-04-11 10:54:34 +00:00
// args, i -> args[i]
static int thingargs_get ( lua_State * L )
{
INT32 * args = * ( ( INT32 * * ) luaL_checkudata ( L , 1 , META_THINGARGS ) ) ;
int i = luaL_checkinteger ( L , 2 ) ;
if ( i < 0 | | i > = NUMMAPTHINGARGS )
return luaL_error ( L , LUA_QL ( " mapthing_t.args " ) " index cannot be %d " , i ) ;
lua_pushinteger ( L , args [ i ] ) ;
return 1 ;
}
// #args -> NUMMAPTHINGARGS
static int thingargs_len ( lua_State * L )
{
lua_pushinteger ( L , NUMMAPTHINGARGS ) ;
return 1 ;
}
// stringargs, i -> stringargs[i]
static int thingstringargs_get ( lua_State * L )
{
char * * stringargs = * ( ( char * * * ) luaL_checkudata ( L , 1 , META_THINGSTRINGARGS ) ) ;
int i = luaL_checkinteger ( L , 2 ) ;
if ( i < 0 | | i > = NUMMAPTHINGSTRINGARGS )
return luaL_error ( L , LUA_QL ( " mapthing_t.stringargs " ) " index cannot be %d " , i ) ;
lua_pushstring ( L , stringargs [ i ] ) ;
return 1 ;
}
// #stringargs -> NUMMAPTHINGSTRINGARGS
static int thingstringargs_len ( lua_State * L )
{
lua_pushinteger ( L , NUMMAPTHINGSTRINGARGS ) ;
return 1 ;
}
2014-03-15 16:59:03 +00:00
static int mapthing_get ( lua_State * L )
{
mapthing_t * mt = * ( ( mapthing_t * * ) luaL_checkudata ( L , 1 , META_MAPTHING ) ) ;
const char * field = luaL_checkstring ( L , 2 ) ;
lua_Integer number ;
if ( ! mt ) {
if ( fastcmp ( field , " valid " ) ) {
lua_pushboolean ( L , false ) ;
return 1 ;
}
if ( devparm )
return luaL_error ( L , " accessed mapthing_t doesn't exist anymore. " ) ;
return 0 ;
}
if ( fastcmp ( field , " valid " ) ) {
lua_pushboolean ( L , true ) ;
return 1 ;
} else if ( fastcmp ( field , " x " ) )
number = mt - > x ;
else if ( fastcmp ( field , " y " ) )
number = mt - > y ;
else if ( fastcmp ( field , " angle " ) )
number = mt - > angle ;
2020-04-19 15:19:04 +00:00
else if ( fastcmp ( field , " pitch " ) )
number = mt - > pitch ;
else if ( fastcmp ( field , " roll " ) )
number = mt - > roll ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " type " ) )
number = mt - > type ;
else if ( fastcmp ( field , " options " ) )
number = mt - > options ;
2020-04-19 13:56:06 +00:00
else if ( fastcmp ( field , " scale " ) )
number = mt - > scale ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " z " ) )
number = mt - > z ;
else if ( fastcmp ( field , " extrainfo " ) )
number = mt - > extrainfo ;
2020-01-25 08:52:13 +00:00
else if ( fastcmp ( field , " tag " ) )
2020-04-17 20:30:16 +00:00
number = Tag_FGet ( & mt - > tags ) ;
2020-12-04 21:47:22 +00:00
else if ( fastcmp ( field , " taglist " ) )
{
2020-12-05 10:02:06 +00:00
LUA_PushUserdata ( L , & mt - > tags , META_TAGLIST ) ;
2020-12-04 21:47:22 +00:00
return 1 ;
}
2020-04-11 10:54:34 +00:00
else if ( fastcmp ( field , " args " ) )
{
2020-04-19 10:23:51 +00:00
LUA_PushUserdata ( L , mt - > args , META_THINGARGS ) ;
2020-04-11 10:54:34 +00:00
return 1 ;
}
else if ( fastcmp ( field , " stringargs " ) )
{
2020-04-13 08:21:32 +00:00
LUA_PushUserdata ( L , mt - > stringargs , META_THINGSTRINGARGS ) ;
2020-04-11 10:54:34 +00:00
return 1 ;
}
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " mobj " ) ) {
LUA_PushUserdata ( L , mt - > mobj , META_MOBJ ) ;
return 1 ;
} else if ( devparm )
return luaL_error ( L , LUA_QL ( " mapthing_t " ) " has no field named " LUA_QS , field ) ;
else
return 0 ;
lua_pushinteger ( L , number ) ;
return 1 ;
}
static int mapthing_set ( lua_State * L )
{
mapthing_t * mt = * ( ( mapthing_t * * ) luaL_checkudata ( L , 1 , META_MAPTHING ) ) ;
const char * field = luaL_checkstring ( L , 2 ) ;
if ( ! mt )
return luaL_error ( L , " accessed mapthing_t doesn't exist anymore. " ) ;
if ( hud_running )
return luaL_error ( L , " Do not alter mapthing_t in HUD rendering code! " ) ;
2020-07-17 05:08:38 +00:00
if ( hook_cmd_running )
return luaL_error ( L , " Do not alter mapthing_t in CMD building code! " ) ;
2014-03-15 16:59:03 +00:00
if ( fastcmp ( field , " x " ) )
mt - > x = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
else if ( fastcmp ( field , " y " ) )
mt - > y = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
else if ( fastcmp ( field , " angle " ) )
mt - > angle = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
2020-04-19 15:19:04 +00:00
else if ( fastcmp ( field , " pitch " ) )
mt - > pitch = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
else if ( fastcmp ( field , " roll " ) )
mt - > roll = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " type " ) )
mt - > type = ( UINT16 ) luaL_checkinteger ( L , 3 ) ;
else if ( fastcmp ( field , " options " ) )
mt - > options = ( UINT16 ) luaL_checkinteger ( L , 3 ) ;
2020-04-19 13:56:06 +00:00
else if ( fastcmp ( field , " scale " ) )
mt - > scale = luaL_checkfixed ( L , 3 ) ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " z " ) )
mt - > z = ( INT16 ) luaL_checkinteger ( L , 3 ) ;
else if ( fastcmp ( field , " extrainfo " ) )
2019-08-01 17:12:12 +00:00
{
INT32 extrainfo = luaL_checkinteger ( L , 3 ) ;
if ( extrainfo & ~ 15 )
return luaL_error ( L , " mapthing_t extrainfo set %d out of range (%d - %d) " , extrainfo, 0, 15) ;
mt - > extrainfo = ( UINT8 ) extrainfo ;
}
2020-01-25 08:52:13 +00:00
else if ( fastcmp ( field , " tag " ) )
2020-04-17 20:30:16 +00:00
Tag_FSet ( & mt - > tags , ( INT16 ) luaL_checkinteger ( L , 3 ) ) ;
2020-12-04 21:47:22 +00:00
else if ( fastcmp ( field , " taglist " ) )
return LUA_ErrSetDirectly ( L , " mapthing_t " , " taglist " ) ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( field , " mobj " ) )
mt - > mobj = * ( ( mobj_t * * ) luaL_checkudata ( L , 3 , META_MOBJ ) ) ;
else
return luaL_error ( L , LUA_QL ( " mapthing_t " ) " has no field named " LUA_QS , field ) ;
return 0 ;
}
2020-05-22 17:32:34 +00:00
static int mapthing_num ( lua_State * L )
{
mapthing_t * mt = * ( ( mapthing_t * * ) luaL_checkudata ( L , 1 , META_MAPTHING ) ) ;
if ( ! mt )
return luaL_error ( L , " accessed mapthing_t doesn't exist anymore. " ) ;
lua_pushinteger ( L , mt - mapthings ) ;
return 1 ;
}
2014-03-15 16:59:03 +00:00
static int lib_iterateMapthings ( lua_State * L )
{
size_t i = 0 ;
2019-07-30 16:48:13 +00:00
INLEVEL
2014-04-14 05:14:58 +00:00
if ( lua_gettop ( L ) < 2 )
return luaL_error ( L , " Don't call mapthings.iterate() directly , use it as ' for mapthing in mapthings . iterate do < block > end ' . " ) ;
lua_settop ( L , 2 ) ;
2014-03-15 16:59:03 +00:00
lua_remove ( L , 1 ) ; // state is unused.
if ( ! lua_isnil ( L , 1 ) )
i = ( size_t ) ( * ( ( mapthing_t * * ) luaL_checkudata ( L , 1 , META_MAPTHING ) ) - mapthings ) + 1 ;
if ( i < nummapthings )
{
LUA_PushUserdata ( L , & mapthings [ i ] , META_MAPTHING ) ;
return 1 ;
}
return 0 ;
}
static int lib_getMapthing ( lua_State * L )
{
2019-07-30 16:48:13 +00:00
INLEVEL
2020-12-04 08:30:08 +00:00
if ( lua_isnumber ( L , 2 ) )
2014-03-15 16:59:03 +00:00
{
2020-12-04 08:30:08 +00:00
size_t i = lua_tointeger ( L , 2 ) ;
2014-03-15 16:59:03 +00:00
if ( i > = nummapthings )
return 0 ;
LUA_PushUserdata ( L , & mapthings [ i ] , META_MAPTHING ) ;
return 1 ;
}
return 0 ;
}
static int lib_nummapthings ( lua_State * L )
{
lua_pushinteger ( L , nummapthings ) ;
return 1 ;
}
int LUA_MobjLib ( lua_State * L )
{
luaL_newmetatable ( L , META_MOBJ ) ;
lua_pushcfunction ( L , mobj_get ) ;
lua_setfield ( L , - 2 , " __index " ) ;
lua_pushcfunction ( L , mobj_set ) ;
lua_setfield ( L , - 2 , " __newindex " ) ;
lua_pop ( L , 1 ) ;
2020-04-11 10:54:34 +00:00
luaL_newmetatable ( L , META_THINGARGS ) ;
lua_pushcfunction ( L , thingargs_get ) ;
lua_setfield ( L , - 2 , " __index " ) ;
lua_pushcfunction ( L , thingargs_len ) ;
lua_setfield ( L , - 2 , " __len " ) ;
lua_pop ( L , 1 ) ;
luaL_newmetatable ( L , META_THINGSTRINGARGS ) ;
lua_pushcfunction ( L , thingstringargs_get ) ;
lua_setfield ( L , - 2 , " __index " ) ;
lua_pushcfunction ( L , thingstringargs_len ) ;
lua_setfield ( L , - 2 , " __len " ) ;
lua_pop ( L , 1 ) ;
2014-03-15 16:59:03 +00:00
luaL_newmetatable ( L , META_MAPTHING ) ;
lua_pushcfunction ( L , mapthing_get ) ;
lua_setfield ( L , - 2 , " __index " ) ;
lua_pushcfunction ( L , mapthing_set ) ;
lua_setfield ( L , - 2 , " __newindex " ) ;
2020-05-22 17:32:34 +00:00
lua_pushcfunction ( L , mapthing_num ) ;
lua_setfield ( L , - 2 , " __len " ) ;
2014-03-15 16:59:03 +00:00
lua_pop ( L , 1 ) ;
2020-12-04 08:30:08 +00:00
LUA_PushTaggableObjectArray ( L , " mapthings " ,
lib_iterateMapthings ,
lib_getMapthing ,
lib_nummapthings ,
tags_mapthings ,
& nummapthings , & mapthings ,
sizeof ( mapthing_t ) , META_MAPTHING ) ;
2014-03-15 16:59:03 +00:00
return 0 ;
}