blankart/src/lua_playerlib.c
2025-04-08 12:18:12 -04:00

2556 lines
59 KiB
C

// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2012-2016 by John "JTE" Muniz.
// Copyright (C) 2012-2020 by Sonic Team Junior.
//
// 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_playerlib.c
/// \brief player object library for Lua scripting
#include "blua/lua.h"
#include "doomdef.h"
#include "fastcmp.h"
#include "p_mobj.h"
#include "d_player.h"
#include "g_game.h"
#include "p_local.h"
#include "d_clisrv.h"
#include "k_kart.h" // K_GetDriftAngleOffset
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
static int lib_iteratePlayers(lua_State *L)
{
INT32 i = -1;
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
lua_pushcfunction(L, lib_iteratePlayers);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players);
i++;
if (i == serverplayer)
{
return LUA_PushServerPlayer(L);
}
for (; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
LUA_PushUserdata(L, &players[i], META_PLAYER);
return 1;
}
return 0;
}
static int lib_getPlayer(lua_State *L)
{
const char *field;
// i -> players[i]
if (lua_type(L, 2) == LUA_TNUMBER)
{
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXPLAYERS)
return luaL_error(L, "players[] index %d out of range (0 - %d)", i, MAXPLAYERS-1);
if (i == serverplayer)
return LUA_PushServerPlayer(L);
if (!playeringame[i])
return 0;
LUA_PushUserdata(L, &players[i], META_PLAYER);
return 1;
}
field = luaL_checkstring(L, 2);
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iteratePlayers);
return 1;
}
return 0;
}
// #players -> MAXPLAYERS
static int lib_lenPlayer(lua_State *L)
{
lua_pushinteger(L, MAXPLAYERS);
return 1;
}
// Same deal as the three functions above but for displayplayers
static int lib_iterateDisplayplayers(lua_State *L)
{
INT32 i = -1;
INT32 temp = -1;
INT32 iter = 0;
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call displayplayers.iterate() directly, use it as 'for player in displayplayers.iterate do <block> end'.");
lua_pushcfunction(L, lib_iterateDisplayplayers);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
{
temp = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players); // get the player # of the last iterated player.
// @FIXME:
// I didn't quite find a better way for this; Here, we go back to which player in displayplayers we last iterated to resume the for loop below for this new function call
// I don't understand enough about how the Lua stacks work to get this to work in possibly a single line.
// So anyone feel free to correct this!
for (; iter < MAXSPLITSCREENPLAYERS; iter++)
{
if (displayplayers[iter] == temp)
{
i = iter;
break;
}
}
}
for (i++; i < MAXSPLITSCREENPLAYERS; i++)
{
if (i > r_splitscreen || !playeringame[displayplayers[i]])
return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers.
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
lua_pushinteger(L, i); // push this to recall what number we were on for the next function call. I suppose this also means you can retrieve the splitscreen player number with 'for p, n in displayplayers.iterate'!
return 2;
}
return 0;
}
static int lib_getDisplayplayers(lua_State *L)
{
const char *field;
// i -> players[i]
if (lua_type(L, 2) == LUA_TNUMBER)
{
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXSPLITSCREENPLAYERS)
return luaL_error(L, "displayplayers[] index %d out of range (0 - %d)", i, MAXSPLITSCREENPLAYERS-1);
if (i > r_splitscreen)
return 0;
if (!playeringame[displayplayers[i]])
return 0;
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
return 1;
}
field = luaL_checkstring(L, 2);
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iterateDisplayplayers);
return 1;
}
return 0;
}
// #displayplayers -> MAXSPLITSCREENPLAYERS
static int lib_lenDisplayplayers(lua_State *L)
{
lua_pushinteger(L, MAXSPLITSCREENPLAYERS);
return 1;
}
enum player_e
{
player_valid,
player_name,
player_realmo,
player_mo,
player_cmd,
player_oldcmd,
player_playerstate,
player_health,
player_viewz,
player_viewheight,
player_viewrollangle,
player_aiming,
player_drawangle,
player_frameangle,
player_powers,
player_kartstuff,
player_karthud,
player_nocontrol,
player_carry,
player_dye,
player_position,
player_oldposition,
player_positiondelay,
player_prevcheck,
player_nextcheck,
player_distancetofinish,
player_distancetofinishprev,
player_airtime,
player_flashing,
player_spinouttimer,
player_spinouttype,
player_instashield,
player_wipeoutslow,
player_justbumped,
player_itemflags,
player_outrun,
player_outruntime,
player_drift,
player_driftcharge,
player_driftboost,
player_boostcharge,
player_startboost,
player_dropdash,
player_respawn,
player_aizdriftstrat,
player_aizdrifttilt,
player_aizdriftturn,
player_slipdashcharge,
player_slipdashdir,
player_offroad,
player_pogospring,
player_brakestop,
player_waterskip,
player_dashpadcooldown,
player_boostpower,
player_speedboost,
player_accelboost,
player_boostangle,
player_boostinfo,
player_numsneakers,
player_numboosts,
player_tripwireState,
player_tripwirePass,
player_tripwireLeniency,
player_tripwireReboundDelay,
player_itemroulette,
player_itemblink,
player_itemblinkmode,
player_roulettetype,
player_itemtype,
player_itemamount,
player_throwdir,
player_sadtimer,
player_rings,
player_pickuprings,
player_ringdelay,
player_ringboost,
player_superring,
player_nextringaward,
player_ringvolume,
player_ringtransparency,
player_curshield,
player_bubblecool,
player_bubbleblowup,
player_bubblepop,
player_flamedash,
player_flametimer,
player_flamestore,
player_hyudorotimer,
player_stealingtimer,
player_stolentimer,
player_sneakertimer,
player_realsneakertimer,
player_floorboost,
player_chaintimer,
player_growshrinktimer,
player_growcancel,
player_squishedtimer,
player_rocketsneakertimer,
player_invincibilitytimer,
player_eggmanexplode,
player_eggmanblame,
player_bananadrag,
player_lastjawztarget,
player_jawztargetdelay,
player_confirmVictim,
player_confirmVictimDelay,
player_glanceDir,
player_breathTimer,
player_lastsafelap,
player_lastsafestarpost,
player_roundscore,
player_marescore,
player_emeralds,
player_bumpers,
player_karmadelay,
player_pflags,
player_panim,
player_flashcount,
player_flashpal,
player_skincolor,
player_skin,
player_availabilities,
player_score,
player_kartspeed,
player_kartweight,
player_followerskin,
player_followerready,
player_followercolor,
player_follower,
player_charflags,
player_followitem,
player_followmobj,
player_lives,
player_xtralife,
player_speed,
player_lastspeed,
player_deadtimer,
player_exiting,
player_cmomx,
player_cmomy,
player_rmomx,
player_rmomy,
player_totalring,
player_realtime,
player_laps,
player_latestlap,
player_ctfteam,
player_checkskip,
player_starpostx,
player_starposty,
player_starpostz,
player_starpostangle,
player_starpostflip,
player_starpostnum,
player_starposttime,
player_lastsidehit,
player_lastlinehit,
player_onconveyor,
player_awayviewmobj,
player_awayviewtics,
player_awayviewaiming,
player_spectator,
player_spectatewait,
player_bot,
player_jointime,
player_spectatorreentry,
player_grieftime,
player_griefstrikes,
player_splitscreenindex,
player_bumpertime,
player_ping,
#ifdef HWRENDER
player_fovadd,
#endif
};
static const char *const player_opt[] = {
"valid",
"name",
"realmo",
"mo",
"cmd",
"oldcmd",
"playerstate",
"health",
"viewz",
"viewheight",
"viewrollangle",
"aiming",
"drawangle",
"frameangle",
"powers",
"kartstuff",
"karthud",
"nocontrol",
"carry",
"dye",
"position",
"oldposition",
"positiondelay",
"prevcheck",
"nextcheck",
"distancetofinish",
"distancetofinishprev",
"airtime",
"flashing",
"spinouttimer",
"spinouttype",
"instashield",
"wipeoutslow",
"justbumped",
"itemflags",
"outrun",
"outruntime",
"drift",
"driftcharge",
"driftboost",
"boostcharge",
"startboost",
"dropdash",
"respawn",
"aizdriftstrat",
"aizdrifttilt",
"aizdriftturn",
"slipdashcharge",
"slipdashdir",
"offroad",
"pogospring",
"brakestop",
"waterskip",
"dashpadcooldown",
"boostpower",
"speedboost",
"accelboost",
"boostangle",
"boostinfo",
"numsneakers",
"numboosts",
"tripwireState",
"tripwirePass",
"tripwireLeniency",
"tripwireReboundDelay",
"itemroulette",
"itemblink",
"itemblinkmode",
"roulettetype",
"itemtype",
"itemamount",
"throwdir",
"sadtimer",
"rings",
"pickuprings",
"ringdelay",
"ringboost",
"superring",
"nextringaward",
"ringvolume",
"ringtransparency",
"curshield",
"bubblecool",
"bubbleblowup",
"bubblepop",
"flamedash",
"flametimer",
"flamestore",
"hyudorotimer",
"stealingtimer",
"stolentimer",
"sneakertimer",
"realsneakertimer",
"floorboost",
"chaintimer",
"growshrinktimer",
"growcancel",
"squishedtimer",
"rocketsneakertimer",
"invincibilitytimer",
"eggmanexplode",
"eggmanblame",
"bananadrag",
"lastjawztarget",
"jawztargetdelay",
"confirmVictim",
"confirmVictimDelay",
"glanceDir",
"breathTimer",
"lastsafelap",
"lastsafestarpost",
"roundscore",
"marescore",
"emeralds",
"bumpers",
"karmadelay",
"pflags",
"panim",
"flashcount",
"flashpal",
"skincolor",
"skin",
"availabilities",
"score",
"kartspeed",
"kartweight",
"followerskin",
"followerready",
"followercolor",
"follower",
"charflags",
"followitem",
"followmobj",
"lives",
"xtralife",
"speed",
"lastspeed",
"deadtimer",
"exiting",
"cmomx",
"cmomy",
"rmomx",
"rmomy",
"totalring",
"realtime",
"laps",
"latestlap",
"ctfteam",
"checkskip",
"starpostx",
"starposty",
"starpostz",
"starpostangle",
"starpostflip",
"starpostnum",
"starposttime",
"lastsidehit",
"lastlinehit",
"onconveyor",
"awayviewmobj",
"awayviewtics",
"awayviewaiming",
"spectator",
"spectatewait",
"bot",
"jointime",
"spectatorreentry",
"grieftime",
"griefstrikes",
"splitscreenindex",
"bumpertime",
"ping",
#ifdef HWRENDER
"fovadd",
#endif
NULL,
};
static int player_get(lua_State *L)
{
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
enum player_e field = Lua_optoption(L, 2, NULL, player_opt);
lua_settop(L, 2);
if (!plr)
{
if (field == player_valid)
{
lua_pushboolean(L, false);
return 1;
}
return LUA_ErrInvalid(L, "player_t");
}
switch (field)
{
case player_valid:
lua_pushboolean(L, true);
break;
case player_name:
lua_pushstring(L, player_names[plr-players]);
break;
case player_realmo:
LUA_PushUserdata(L, plr->mo, META_MOBJ);
break;
case player_mo:
if (plr->spectator)
lua_pushnil(L); // sigh
else
LUA_PushUserdata(L, plr->mo, META_MOBJ);
break;
case player_cmd:
LUA_PushUserdata(L, &plr->cmd, META_TICCMD);
break;
case player_oldcmd:
LUA_PushUserdata(L, &plr->oldcmd, META_TICCMD);
break;
case player_playerstate:
lua_pushinteger(L, plr->playerstate);
break;
case player_health:
{
if (plr->mo)
lua_pushinteger(L, plr->mo->health);
else
lua_pushinteger(L, 0);
break;
}
case player_viewz:
lua_pushfixed(L, plr->viewz);
break;
case player_viewheight:
lua_pushfixed(L, plr->viewheight);
break;
case player_viewrollangle:
lua_pushangle(L, plr->viewrollangle);
break;
case player_aiming:
lua_pushangle(L, plr->aiming);
break;
case player_drawangle:
case player_frameangle:
lua_pushangle(L, plr->drawangle);
break;
case player_powers:
LUA_PushUserdata(L, plr->powers, META_POWERS);
break;
case player_kartstuff:
LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF);
break;
case player_karthud:
LUA_PushUserdata(L, plr->karthud, META_KARTHUD);
break;
case player_nocontrol:
lua_pushinteger(L, plr->nocontrol);
break;
case player_carry:
lua_pushinteger(L, plr->carry);
break;
case player_dye:
lua_pushinteger(L, plr->dye);
break;
case player_position:
lua_pushinteger(L, plr->position);
break;
case player_oldposition:
lua_pushinteger(L, plr->oldposition);
break;
case player_positiondelay:
lua_pushinteger(L, plr->positiondelay);
break;
case player_prevcheck:
lua_pushinteger(L, plr->prevcheck);
break;
case player_nextcheck:
lua_pushinteger(L, plr->nextcheck);
break;
case player_distancetofinish:
lua_pushinteger(L, plr->distancetofinish);
break;
case player_distancetofinishprev:
lua_pushinteger(L, plr->distancetofinishprev);
break;
case player_airtime:
lua_pushinteger(L, plr->airtime);
break;
case player_flashing:
lua_pushinteger(L, plr->flashing);
break;
case player_spinouttimer:
lua_pushinteger(L, plr->spinouttimer);
break;
case player_spinouttype:
lua_pushinteger(L, plr->spinouttype);
break;
case player_instashield:
lua_pushinteger(L, plr->instashield);
break;
case player_wipeoutslow:
lua_pushinteger(L, plr->wipeoutslow);
break;
case player_justbumped:
lua_pushinteger(L, plr->justbumped);
break;
case player_itemflags:
lua_pushinteger(L, plr->itemflags);
break;
case player_outrun:
lua_pushinteger(L, plr->outrun);
break;
case player_outruntime:
lua_pushinteger(L, plr->outruntime);
break;
case player_drift:
lua_pushinteger(L, plr->drift);
break;
case player_driftcharge:
lua_pushinteger(L, plr->driftcharge);
break;
case player_driftboost:
lua_pushinteger(L, plr->driftboost);
break;
case player_boostcharge:
lua_pushinteger(L, plr->boostcharge);
break;
case player_startboost:
lua_pushinteger(L, plr->startboost);
break;
case player_dropdash:
lua_pushinteger(L, plr->dropdash);
break;
case player_respawn:
lua_pushinteger(L, plr->respawn);
break;
case player_aizdriftstrat:
lua_pushinteger(L, plr->aizdriftstrat);
break;
case player_aizdrifttilt:
lua_pushinteger(L, plr->aizdrifttilt);
break;
case player_aizdriftturn:
lua_pushinteger(L, plr->aizdriftturn);
break;
case player_slipdashcharge:
lua_pushfixed(L, plr->slipdashcharge);
break;
case player_slipdashdir:
lua_pushinteger(L, plr->slipdashdir);
break;
case player_offroad:
lua_pushinteger(L, plr->offroad);
break;
case player_pogospring:
lua_pushinteger(L, plr->pogospring);
break;
case player_brakestop:
lua_pushinteger(L, plr->brakestop);
break;
case player_waterskip:
lua_pushinteger(L, plr->waterskip);
break;
case player_dashpadcooldown:
lua_pushinteger(L, plr->dashpadcooldown);
break;
case player_boostpower:
lua_pushinteger(L, plr->boostpower);
break;
case player_speedboost:
lua_pushinteger(L, plr->speedboost);
break;
case player_accelboost:
lua_pushinteger(L, plr->accelboost);
break;
case player_boostangle:
lua_pushangle(L, plr->boostangle);
break;
case player_boostinfo:
luaL_error(L, "Don't directly read boostinfo. Use speedboost, accelboost and numboosts instead,\n");
break;
case player_numsneakers:
lua_pushinteger(L, plr->numsneakers);
break;
case player_numboosts:
lua_pushinteger(L, plr->numboosts);
break;
case player_tripwireState:
lua_pushinteger(L, plr->tripwireState);
break;
case player_tripwirePass:
lua_pushinteger(L, plr->tripwirePass);
break;
case player_tripwireLeniency:
lua_pushinteger(L, plr->tripwireLeniency);
break;
case player_tripwireReboundDelay:
lua_pushinteger(L, plr->tripwireReboundDelay);
break;
case player_itemroulette:
lua_pushinteger(L, plr->itemroulette);
break;
case player_itemblink:
lua_pushinteger(L, plr->itemblink);
break;
case player_itemblinkmode:
lua_pushinteger(L, plr->itemblinkmode);
break;
case player_roulettetype:
lua_pushinteger(L, plr->roulettetype);
break;
case player_itemtype:
lua_pushinteger(L, plr->itemtype);
break;
case player_itemamount:
lua_pushinteger(L, plr->itemamount);
break;
case player_throwdir:
lua_pushinteger(L, plr->throwdir);
break;
case player_sadtimer:
lua_pushinteger(L, plr->sadtimer);
break;
case player_rings:
lua_pushinteger(L, plr->rings);
break;
case player_pickuprings:
lua_pushinteger(L, plr->pickuprings);
break;
case player_ringdelay:
lua_pushinteger(L, plr->ringdelay);
break;
case player_ringboost:
lua_pushinteger(L, plr->ringboost);
break;
case player_superring:
lua_pushinteger(L, plr->superring);
break;
case player_nextringaward:
lua_pushinteger(L, plr->nextringaward);
break;
case player_ringvolume:
lua_pushinteger(L, plr->ringvolume);
break;
case player_ringtransparency:
lua_pushinteger(L, plr->ringtransparency);
break;
case player_curshield:
lua_pushinteger(L, plr->curshield);
break;
case player_bubblecool:
lua_pushinteger(L, plr->bubblecool);
break;
case player_bubbleblowup:
lua_pushinteger(L, plr->bubbleblowup);
break;
case player_bubblepop:
lua_pushinteger(L, plr->bubblepop);
break;
case player_flamedash:
lua_pushinteger(L, plr->flamedash);
break;
case player_flametimer:
lua_pushinteger(L, plr->flametimer);
break;
case player_flamestore:
lua_pushinteger(L, plr->flamestore);
break;
case player_hyudorotimer:
lua_pushinteger(L, plr->hyudorotimer);
break;
case player_stealingtimer:
lua_pushinteger(L, plr->stealingtimer);
break;
case player_stolentimer:
lua_pushinteger(L, plr->stolentimer);
break;
case player_sneakertimer:
lua_pushinteger(L, plr->sneakertimer);
break;
case player_realsneakertimer:
lua_pushinteger(L, plr->realsneakertimer);
break;
case player_floorboost:
lua_pushinteger(L, plr->floorboost);
break;
case player_chaintimer:
lua_pushinteger(L, plr->chaintimer);
break;
case player_growshrinktimer:
lua_pushinteger(L, plr->growshrinktimer);
break;
case player_growcancel:
lua_pushinteger(L, plr->growcancel);
break;
case player_squishedtimer:
lua_pushinteger(L, plr->squishedtimer);
break;
case player_rocketsneakertimer:
lua_pushinteger(L, plr->rocketsneakertimer);
break;
case player_invincibilitytimer:
lua_pushinteger(L, plr->invincibilitytimer);
break;
case player_eggmanexplode:
lua_pushinteger(L, plr->eggmanexplode);
break;
case player_eggmanblame:
lua_pushinteger(L, plr->eggmanblame);
break;
case player_bananadrag:
lua_pushinteger(L, plr->bananadrag);
break;
case player_lastjawztarget:
lua_pushinteger(L, plr->lastjawztarget);
break;
case player_jawztargetdelay:
lua_pushinteger(L, plr->jawztargetdelay);
break;
case player_confirmVictim:
lua_pushinteger(L, plr->confirmVictim);
break;
case player_confirmVictimDelay:
lua_pushinteger(L, plr->confirmVictimDelay);
break;
case player_glanceDir:
lua_pushinteger(L, plr->glanceDir);
break;
case player_breathTimer:
lua_pushinteger(L, plr->breathTimer);
break;
case player_lastsafelap:
lua_pushinteger(L, plr->lastsafelap);
break;
case player_lastsafestarpost:
lua_pushinteger(L, plr->lastsafestarpost);
break;
case player_roundscore:
case player_marescore:
lua_pushinteger(L, plr->roundscore);
break;
case player_emeralds:
lua_pushinteger(L, plr->emeralds);
break;
case player_bumpers:
lua_pushinteger(L, plr->bumper);
break;
case player_karmadelay:
lua_pushinteger(L, plr->karmadelay);
break;
case player_pflags:
{
UINT32 pflags = plr->pflags;
if (lua_compatmode && (plr->carry & CR_SLIDING) == CR_SLIDING)
pflags |= PF_SLIDING;
if (lua_compatmode && (plr->oldcmd.buttons & BT_ATTACK))
pflags |= PF_ATTACKDOWN;
lua_pushinteger(L, pflags);
break;
}
case player_panim:
lua_pushinteger(L, plr->panim);
break;
case player_flashcount:
lua_pushinteger(L, plr->flashcount);
break;
case player_flashpal:
lua_pushinteger(L, plr->flashpal);
break;
case player_skincolor:
lua_pushinteger(L, plr->skincolor);
break;
case player_skin:
lua_pushinteger(L, plr->skin);
break;
case player_availabilities:
lua_pushinteger(L, plr->availabilities);
break;
case player_score:
lua_pushinteger(L, plr->score);
break;
// SRB2kart
case player_kartspeed:
lua_pushinteger(L, plr->kartspeed);
break;
case player_kartweight:
lua_pushinteger(L, plr->kartweight);
break;
case player_followerskin:
lua_pushinteger(L, plr->followerskin);
break;
case player_followerready:
lua_pushboolean(L, plr->followerready);
break;
case player_followercolor:
lua_pushinteger(L, plr->followercolor);
break;
case player_follower:
LUA_PushUserdata(L, plr->follower, META_MOBJ);
break;
//
case player_charflags:
lua_pushinteger(L, plr->charflags);
break;
case player_followitem:
lua_pushinteger(L, plr->followitem);
break;
case player_followmobj:
LUA_PushUserdata(L, plr->followmobj, META_MOBJ);
break;
case player_lives:
lua_pushinteger(L, plr->lives);
break;
case player_xtralife:
lua_pushinteger(L, plr->xtralife);
break;
case player_speed:
lua_pushfixed(L, plr->speed);
break;
case player_lastspeed:
lua_pushfixed(L, plr->lastspeed);
break;
case player_deadtimer:
lua_pushinteger(L, plr->deadtimer);
break;
case player_exiting:
lua_pushinteger(L, plr->exiting);
break;
case player_cmomx:
lua_pushfixed(L, plr->cmomx);
break;
case player_cmomy:
lua_pushfixed(L, plr->cmomy);
break;
case player_rmomx:
lua_pushfixed(L, plr->rmomx);
break;
case player_rmomy:
lua_pushfixed(L, plr->rmomy);
break;
case player_totalring:
lua_pushinteger(L, plr->totalring);
break;
case player_realtime:
lua_pushinteger(L, plr->realtime);
break;
case player_laps:
{
if (lua_compatmode)
lua_pushinteger(L, max(plr->laps - 1, 0));
else
lua_pushinteger(L, plr->laps);
break;
}
case player_latestlap:
{
if (lua_compatmode)
lua_pushinteger(L, max(plr->latestlap - 1, 0));
else
lua_pushinteger(L, plr->latestlap);
break;
}
case player_ctfteam:
lua_pushinteger(L, plr->ctfteam);
break;
case player_checkskip:
lua_pushinteger(L, plr->checkskip);
break;
case player_starpostx:
lua_pushfixed(L, plr->starpostx);
break;
case player_starposty:
lua_pushfixed(L, plr->starposty);
break;
case player_starpostz:
lua_pushfixed(L, plr->starpostz);
break;
case player_starpostangle:
lua_pushangle(L, plr->starpostangle);
break;
case player_starpostflip:
lua_pushboolean(L, plr->starpostflip);
break;
case player_starpostnum:
lua_pushinteger(L, plr->starpostnum);
break;
case player_starposttime:
lua_pushinteger(L, plr->starposttime);
break;
case player_lastsidehit:
lua_pushinteger(L, plr->lastsidehit);
break;
case player_lastlinehit:
lua_pushinteger(L, plr->lastlinehit);
break;
case player_onconveyor:
lua_pushinteger(L, plr->onconveyor);
break;
case player_awayviewmobj:
LUA_PushUserdata(L, plr->awayviewmobj, META_MOBJ);
break;
case player_awayviewtics:
lua_pushinteger(L, plr->awayviewtics);
break;
case player_awayviewaiming:
lua_pushangle(L, plr->awayviewaiming);
break;
case player_spectator:
lua_pushboolean(L, plr->spectator);
break;
case player_spectatewait:
lua_pushinteger(L, plr->spectatewait);
break;
case player_bot:
lua_pushboolean(L, plr->bot);
break;
case player_jointime:
lua_pushinteger(L, plr->jointime);
break;
case player_spectatorreentry:
lua_pushinteger(L, plr->spectatorreentry);
break;
case player_grieftime:
lua_pushinteger(L, plr->grieftime);
break;
case player_griefstrikes:
lua_pushinteger(L, plr->griefstrikes);
break;
case player_splitscreenindex:
lua_pushinteger(L, plr->splitscreenindex);
break;
case player_bumpertime:
lua_pushinteger(L, plr->bumpertime);
break;
case player_ping:
lua_pushinteger(L, playerpingtable[( plr - players )]);
break;
#ifdef HWRENDER
case player_fovadd:
lua_pushfixed(L, plr->fovadd);
break;
#endif
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, plr);
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"), "player_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"), "player_t", lua_tostring(L, 2));
break;
}
return 1;
}
#define NOSET luaL_error(L, LUA_QL("player_t") " field " LUA_QS " should not be set directly.", field)
static int player_set(lua_State *L)
{
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
enum player_e field = Lua_optoption(L, 2, player_opt[player_cmd], player_opt);
if (!plr)
return LUA_ErrInvalid(L, "player_t");
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
switch (field)
{
case player_mo:
case player_realmo:
{
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = NULL; // remove player pointer from old mobj
(newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj
break;
}
case player_cmd:
return NOSET;
case player_oldcmd:
return NOSET;
case player_playerstate:
plr->playerstate = luaL_checkinteger(L, 3);
break;
case player_health:
if (plr->mo)
plr->mo->health = luaL_checkinteger(L, 3);
break;
case player_viewz:
plr->viewz = luaL_checkfixed(L, 3);
break;
case player_viewheight:
plr->viewheight = luaL_checkfixed(L, 3);
break;
case player_viewrollangle:
plr->viewrollangle = luaL_checkangle(L, 3);
break;
case player_aiming:
{
UINT8 i;
plr->aiming = luaL_checkangle(L, 3);
for (i = 0; i <= r_splitscreen; i++)
{
if (plr == &players[displayplayers[i]])
{
localaiming[i] = plr->aiming;
break;
}
}
break;
}
case player_drawangle:
case player_frameangle:
{
angle_t angle = luaL_checkangle(L, 3);
if (lua_compatmode && plr->mo && angle == plr->mo->angle)
// attempt to fix e.g. acrobasics not accounting for drift when resetting frameangle
angle += K_GetDriftAngleOffset(plr);
plr->drawangle = angle;
break;
}
case player_pflags:
{
UINT32 pflags = luaL_checkinteger(L, 3);
if (lua_compatmode)
{
if (pflags & PF_SLIDING)
plr->carry |= CR_SLIDING;
else
plr->carry &= ~CR_SLIDING;
if (pflags & PF_ATTACKDOWN)
plr->oldcmd.buttons |= BT_ATTACK;
else
plr->oldcmd.buttons &= ~BT_ATTACK;
}
plr->pflags = pflags;
break;
}
case player_panim:
plr->panim = luaL_checkinteger(L, 3);
break;
case player_flashcount:
plr->flashcount = luaL_checkinteger(L, 3);
break;
case player_flashpal:
plr->flashpal = luaL_checkinteger(L, 3);
break;
case player_skincolor:
{
UINT16 newcolor = luaL_checkinteger(L,3);
if (newcolor >= numskincolors)
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1);
plr->skincolor = newcolor;
break;
}
case player_skin:
return NOSET;
case player_availabilities:
return NOSET;
case player_score:
plr->score = luaL_checkinteger(L, 3);
break;
// SRB2kart
case player_kartstuff:
return NOSET;
case player_nocontrol:
plr->nocontrol = luaL_checkinteger(L, 3);
break;
case player_carry:
plr->carry = luaL_checkinteger(L, 3);
break;
case player_dye:
plr->dye = luaL_checkinteger(L, 3);
break;
case player_position:
plr->position = luaL_checkinteger(L, 3);
break;
case player_oldposition:
plr->oldposition = luaL_checkinteger(L, 3);
break;
case player_positiondelay:
plr->positiondelay = luaL_checkinteger(L, 3);
break;
case player_prevcheck:
plr->prevcheck = luaL_checkinteger(L, 3);
break;
case player_nextcheck:
plr->nextcheck = luaL_checkinteger(L, 3);
break;
case player_distancetofinish:
return NOSET;
case player_distancetofinishprev:
return NOSET;
case player_airtime:
plr->airtime = luaL_checkinteger(L, 3);
break;
case player_flashing:
plr->flashing = luaL_checkinteger(L, 3);
break;
case player_spinouttimer:
plr->spinouttimer = luaL_checkinteger(L, 3);
break;
case player_spinouttype:
plr->spinouttype = luaL_checkinteger(L, 3);
break;
case player_instashield:
plr->instashield = luaL_checkinteger(L, 3);
break;
case player_wipeoutslow:
plr->wipeoutslow = luaL_checkinteger(L, 3);
break;
case player_justbumped:
plr->justbumped = luaL_checkinteger(L, 3);
break;
case player_itemflags:
plr->itemflags = luaL_checkinteger(L, 3);
break;
case player_outrun:
plr->outrun = luaL_checkinteger(L, 3);
break;
case player_outruntime:
plr->outruntime = luaL_checkinteger(L, 3);
break;
case player_drift:
plr->drift = luaL_checkinteger(L, 3);
break;
case player_driftcharge:
plr->driftcharge = luaL_checkinteger(L, 3);
break;
case player_driftboost:
plr->driftboost = luaL_checkinteger(L, 3);
break;
case player_boostcharge:
plr->boostcharge = luaL_checkinteger(L, 3);
break;
case player_startboost:
plr->startboost = luaL_checkinteger(L, 3);
break;
case player_dropdash:
plr->dropdash = luaL_checkinteger(L, 3);
break;
case player_respawn:
plr->respawn = luaL_checkinteger(L, 3);
break;
case player_aizdriftstrat:
plr->aizdriftstrat = luaL_checkinteger(L, 3);
break;
case player_aizdrifttilt:
plr->aizdrifttilt = luaL_checkinteger(L, 3);
break;
case player_aizdriftturn:
plr->aizdriftturn = luaL_checkinteger(L, 3);
break;
case player_slipdashcharge:
plr->slipdashcharge = luaL_checkfixed(L, 3);
break;
case player_slipdashdir:
plr->slipdashdir = luaL_checkinteger(L, 3);
break;
case player_offroad:
plr->offroad = luaL_checkinteger(L, 3);
break;
case player_pogospring:
plr->pogospring = luaL_checkinteger(L, 3);
break;
case player_brakestop:
plr->brakestop = luaL_checkinteger(L, 3);
break;
case player_waterskip:
plr->waterskip = luaL_checkinteger(L, 3);
break;
case player_dashpadcooldown:
plr->dashpadcooldown = luaL_checkinteger(L, 3);
break;
case player_boostpower:
plr->boostpower = luaL_checkinteger(L, 3);
break;
case player_speedboost:
plr->speedboost = luaL_checkinteger(L, 3);
break;
case player_accelboost:
plr->accelboost = luaL_checkinteger(L, 3);
break;
case player_boostangle:
plr->boostangle = luaL_checkangle(L, 3);
break;
case player_boostinfo:
NOSET;
break;
case player_numsneakers:
plr->numsneakers = luaL_checkinteger(L, 3);
break;
case player_numboosts:
plr->numboosts = luaL_checkinteger(L, 3);
break;
case player_tripwireState:
plr->tripwireState = luaL_checkinteger(L, 3);
break;
case player_tripwirePass:
plr->tripwirePass = luaL_checkinteger(L, 3);
break;
case player_tripwireLeniency:
plr->tripwireLeniency = luaL_checkinteger(L, 3);
break;
case player_tripwireReboundDelay:
plr->tripwireReboundDelay = luaL_checkinteger(L, 3);
break;
case player_itemroulette:
plr->itemroulette = luaL_checkinteger(L, 3);
break;
case player_itemblink:
plr->itemblink = luaL_checkinteger(L, 3);
break;
case player_itemblinkmode:
plr->itemblinkmode = luaL_checkinteger(L, 3);
break;
case player_roulettetype:
plr->roulettetype = luaL_checkinteger(L, 3);
break;
case player_itemtype:
plr->itemtype = luaL_checkinteger(L, 3);
break;
case player_itemamount:
plr->itemamount = luaL_checkinteger(L, 3);
break;
case player_throwdir:
plr->throwdir = luaL_checkinteger(L, 3);
break;
case player_sadtimer:
plr->sadtimer = luaL_checkinteger(L, 3);
break;
case player_rings:
plr->rings = luaL_checkinteger(L, 3);
break;
case player_pickuprings:
plr->pickuprings = luaL_checkinteger(L, 3);
break;
case player_ringdelay:
plr->ringdelay = luaL_checkinteger(L, 3);
break;
case player_ringboost:
plr->ringboost = luaL_checkinteger(L, 3);
break;
case player_superring:
plr->superring = luaL_checkinteger(L, 3);
break;
case player_nextringaward:
plr->nextringaward = luaL_checkinteger(L, 3);
break;
case player_ringvolume:
plr->ringvolume = luaL_checkinteger(L, 3);
break;
case player_ringtransparency:
plr->ringtransparency = luaL_checkinteger(L, 3);
break;
case player_curshield:
plr->curshield = luaL_checkinteger(L, 3);
break;
case player_bubblecool:
plr->bubblecool = luaL_checkinteger(L, 3);
break;
case player_bubbleblowup:
plr->bubbleblowup = luaL_checkinteger(L, 3);
break;
case player_bubblepop:
plr->bubblepop = luaL_checkinteger(L, 3);
break;
case player_flamedash:
plr->flamedash = luaL_checkinteger(L, 3);
break;
case player_flametimer:
plr->flametimer = luaL_checkinteger(L, 3);
break;
case player_flamestore:
plr->flamestore = luaL_checkinteger(L, 3);
break;
case player_hyudorotimer:
plr->hyudorotimer = luaL_checkinteger(L, 3);
break;
case player_stealingtimer:
plr->stealingtimer = luaL_checkinteger(L, 3);
break;
case player_stolentimer:
plr->stealingtimer = luaL_checkinteger(L, 3);
break;
case player_sneakertimer:
plr->sneakertimer = luaL_checkinteger(L, 3);
break;
case player_realsneakertimer:
plr->realsneakertimer = luaL_checkinteger(L, 3);
break;
case player_floorboost:
plr->floorboost = luaL_checkinteger(L, 3);
break;
case player_chaintimer:
plr->chaintimer = luaL_checkinteger(L, 3);
break;
case player_growshrinktimer:
plr->growshrinktimer = luaL_checkinteger(L, 3);
break;
case player_growcancel:
plr->growcancel = luaL_checkinteger(L, 3);
break;
case player_squishedtimer:
plr->squishedtimer = luaL_checkinteger(L, 3);
break;
case player_rocketsneakertimer:
plr->rocketsneakertimer = luaL_checkinteger(L, 3);
break;
case player_invincibilitytimer:
plr->invincibilitytimer = luaL_checkinteger(L, 3);
break;
case player_eggmanexplode:
plr->eggmanexplode = luaL_checkinteger(L, 3);
break;
case player_eggmanblame:
plr->eggmanblame = luaL_checkinteger(L, 3);
break;
case player_bananadrag:
plr->bananadrag = luaL_checkinteger(L, 3);
break;
case player_lastjawztarget:
plr->lastjawztarget = luaL_checkinteger(L, 3);
break;
case player_jawztargetdelay:
plr->jawztargetdelay = luaL_checkinteger(L, 3);
break;
case player_confirmVictim:
plr->confirmVictim = luaL_checkinteger(L, 3);
break;
case player_confirmVictimDelay:
plr->confirmVictimDelay = luaL_checkinteger(L, 3);
break;
case player_glanceDir:
plr->glanceDir = luaL_checkinteger(L, 3);
break;
case player_breathTimer:
plr->breathTimer = luaL_checkinteger(L, 3);
break;
case player_lastsafelap:
plr->lastsafelap = luaL_checkinteger(L, 3);
break;
case player_lastsafestarpost:
plr->lastsafestarpost = luaL_checkinteger(L, 3);
break;
case player_roundscore:
case player_marescore:
plr->roundscore = luaL_checkinteger(L, 3);
break;
case player_emeralds:
plr->emeralds = luaL_checkinteger(L, 3);
break;
case player_bumpers:
plr->bumper = luaL_checkinteger(L, 3);
break;
case player_karmadelay:
plr->karmadelay = luaL_checkinteger(L, 3);
break;
case player_kartspeed:
plr->kartspeed = luaL_checkinteger(L, 3);
break;
case player_kartweight:
plr->kartweight = luaL_checkinteger(L, 3);
break;
case player_followerskin:
plr->followerskin = luaL_checkinteger(L, 3);
break;
case player_followercolor:
plr->followercolor = luaL_checkinteger(L, 3);
break;
case player_followerready:
plr->followerready = luaL_checkboolean(L, 3);
break;
case player_follower: // it's probably best we don't allow the follower mobj to change.
return NOSET;
//
case player_charflags:
plr->charflags = (UINT32)luaL_checkinteger(L, 3);
break;
case player_followitem:
plr->followitem = luaL_checkinteger(L, 3);
break;
case player_followmobj:
{
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->followmobj, mo);
break;
}
case player_lives:
plr->lives = (SINT8)luaL_checkinteger(L, 3);
break;
case player_xtralife:
plr->xtralife = (SINT8)luaL_checkinteger(L, 3);
break;
case player_speed:
plr->speed = luaL_checkfixed(L, 3);
break;
case player_lastspeed:
plr->lastspeed = luaL_checkfixed(L, 3);
break;
case player_deadtimer:
plr->deadtimer = (INT32)luaL_checkinteger(L, 3);
break;
case player_exiting:
plr->exiting = (tic_t)luaL_checkinteger(L, 3);
break;
case player_cmomx:
plr->cmomx = luaL_checkfixed(L, 3);
break;
case player_cmomy:
plr->cmomy = luaL_checkfixed(L, 3);
break;
case player_rmomx:
plr->rmomx = luaL_checkfixed(L, 3);
break;
case player_rmomy:
plr->rmomy = luaL_checkfixed(L, 3);
break;
case player_totalring:
plr->totalring = (INT16)luaL_checkinteger(L, 3);
break;
case player_realtime:
plr->realtime = (tic_t)luaL_checkinteger(L, 3);
break;
case player_laps:
{
UINT8 laps = (UINT8)luaL_checkinteger(L, 3);
if (lua_compatmode)
plr->laps = max(laps +1, 0);
else
plr->laps = laps;
break;
}
case player_latestlap:
{
UINT8 laps = (UINT8)luaL_checkinteger(L, 3);
if (lua_compatmode)
plr->latestlap = max(laps + 1, 0);
else
plr->latestlap = laps;
break;
}
case player_ctfteam:
plr->ctfteam = (INT32)luaL_checkinteger(L, 3);
break;
case player_checkskip:
plr->checkskip = (INT32)luaL_checkinteger(L, 3);
break;
case player_starpostx:
plr->starpostx = luaL_checkfixed(L, 3);
break;
case player_starposty:
plr->starposty = luaL_checkfixed(L, 3);
break;
case player_starpostz:
plr->starpostz = luaL_checkfixed(L, 3);
break;
case player_starpostangle:
plr->starpostangle = luaL_checkangle(L, 3);
break;
case player_starpostflip:
plr->starpostflip = luaL_checkboolean(L, 3);
break;
case player_starpostnum:
plr->starpostnum = (INT32)luaL_checkinteger(L, 3);
break;
case player_starposttime:
plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
break;
case player_lastsidehit:
plr->lastsidehit = (INT16)luaL_checkinteger(L, 3);
break;
case player_lastlinehit:
plr->lastlinehit = (INT16)luaL_checkinteger(L, 3);
break;
case player_onconveyor:
plr->onconveyor = (INT32)luaL_checkinteger(L, 3);
break;
case player_awayviewmobj:
{
mobj_t *mo = NULL;
if (!lua_isnil(L, 3))
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->awayviewmobj, mo);
break;
}
case player_awayviewtics:
{
plr->awayviewtics = (INT32)luaL_checkinteger(L, 3);
if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!!
P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now.
break;
}
case player_awayviewaiming:
plr->awayviewaiming = luaL_checkangle(L, 3);
break;
case player_spectator:
plr->spectator = lua_toboolean(L, 3);
break;
case player_spectatewait:
plr->spectatewait = luaL_checkinteger(L, 3);
break;
case player_bot:
return NOSET;
case player_jointime:
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
break;
case player_spectatorreentry:
plr->spectatorreentry = (tic_t)luaL_checkinteger(L, 3);
break;
case player_grieftime:
plr->grieftime = (tic_t)luaL_checkinteger(L, 3);
break;
case player_griefstrikes:
plr->griefstrikes = (UINT8)luaL_checkinteger(L, 3);
break;
case player_splitscreenindex:
return NOSET;
case player_bumpertime:
plr->bumpertime = (tic_t)luaL_checkinteger(L, 3);
break;
#ifdef HWRENDER
case player_fovadd:
plr->fovadd = luaL_checkfixed(L, 3);
break;
#endif
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, plr);
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"), "player_t", lua_tostring(L, 2));
lua_newtable(L);
lua_pushlightuserdata(L, plr);
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 NOSET
static int player_num(lua_State *L)
{
player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!plr)
return luaL_error(L, "accessed player_t doesn't exist anymore.");
lua_pushinteger(L, plr-players);
return 1;
}
// powers, p -> powers[p]
static int power_get(lua_State *L)
{
UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS));
powertype_t p = luaL_checkinteger(L, 2);
player_t *plr = (player_t*)((void*)powers - offsetof(player_t, powers));
if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
switch (p)
{
case pw_flashing:
lua_pushinteger(L, plr->flashing);
return 1;
case pw_nocontrol:
lua_pushinteger(L, plr->nocontrol);
return 1;
default:
lua_pushinteger(L, powers[p]);
return 1;
}
return 1;
}
#define NOSET luaL_error(L, LUA_QL("powertype_t") " field " LUA_QS " should not be set directly.", p)
// powers, p, value -> powers[p] = value
static int power_set(lua_State *L)
{
UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS));
powertype_t p = luaL_checkinteger(L, 2);
player_t *plr = (player_t*)((void*)powers - offsetof(player_t, powers));
UINT16 i = (UINT16)luaL_checkinteger(L, 3);
if (p >= NUMPOWERS)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
switch (p)
{
case pw_flashing:
plr->flashing = i;
break;
case pw_nocontrol:
plr->nocontrol = i;
break;
default:
powers[p] = i;
break;
}
return 0;
}
#undef NOSET
// #powers -> NUMPOWERS
static int power_len(lua_State *L)
{
lua_pushinteger(L, NUMPOWERS);
return 1;
}
// ???, ks -> kartstuff[ks]
static int kartstuff_get(lua_State *L)
{
INT32 *kartstuff = *((INT32 **)luaL_checkudata(L, 1, META_KARTSTUFF));
player_t *plr = (player_t*)((void*)kartstuff - offsetof(player_t, kartstuff));
kartstufftype_t ks = luaL_checkinteger(L, 2);
if (ks >= NUMKARTSTUFF)
return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks);
switch (ks)
{
case k_position:
lua_pushinteger(L, plr->position);
return 1;
case k_oldposition:
lua_pushinteger(L, plr->oldposition);
return 1;
case k_positiondelay:
lua_pushinteger(L, plr->positiondelay);
return 1;
case k_prevcheck:
lua_pushinteger(L, plr->prevcheck);
return 1;
case k_nextcheck:
lua_pushinteger(L, plr->nextcheck);
return 1;
/*case k_waypoint:
lua_pushinteger(L, plr->waypoint);
return 1;*/
/*case k_starpostwp:
lua_pushinteger(L, plr->starpostwp);
return 1;*/
case k_starpostflip:
lua_pushinteger(L, plr->starpostflip);
return 1;
case k_respawn:
lua_pushinteger(L, plr->respawn);
return 1;
case k_dropdash:
lua_pushinteger(L, plr->dropdash);
return 1;
case k_throwdir:
lua_pushinteger(L, plr->throwdir);
return 1;
case k_lapanimation:
lua_pushinteger(L, plr->karthud[khud_lapanimation]);
return 1;
case k_laphand:
lua_pushinteger(L, plr->karthud[khud_laphand]);
return 1;
case k_cardanimation:
lua_pushinteger(L, plr->karthud[khud_cardanimation]);
return 1;
case k_voices:
lua_pushinteger(L, plr->karthud[khud_voices]);
return 1;
case k_tauntvoices:
lua_pushinteger(L, plr->karthud[khud_tauntvoices]);
return 1;
case k_instashield:
lua_pushinteger(L, plr->instashield);
return 1;
case k_enginesnd:
lua_pushinteger(L, plr->karthud[khud_enginesnd]);
return 1;
case k_floorboost:
lua_pushinteger(L, plr->floorboost);
return 1;
case k_spinouttype:
lua_pushinteger(L, plr->spinouttype);
return 1;
case k_drift:
lua_pushinteger(L, plr->drift);
return 1;
case k_driftend:
lua_pushinteger(L, (plr->pflags & PF_DRIFTEND));
return 1;
case k_driftcharge:
lua_pushinteger(L, plr->driftcharge);
return 1;
case k_driftboost:
lua_pushinteger(L, plr->driftboost);
return 1;
case k_boostcharge:
lua_pushinteger(L, plr->boostcharge);
return 1;
case k_startboost:
lua_pushinteger(L, plr->startboost);
return 1;
case k_jmp:
lua_pushinteger(L, (plr->pflags & PF_DRIFTINPUT));
return 1;
case k_offroad:
lua_pushinteger(L, plr->offroad);
return 1;
case k_pogospring:
lua_pushinteger(L, plr->pogospring);
return 1;
case k_brakestop:
lua_pushinteger(L, plr->brakestop);
return 1;
case k_waterskip:
lua_pushinteger(L, plr->waterskip);
return 1;
case k_dashpadcooldown:
lua_pushinteger(L, plr->dashpadcooldown);
return 1;
case k_boostpower:
lua_pushinteger(L, plr->boostpower);
return 1;
case k_speedboost:
lua_pushinteger(L, plr->speedboost);
return 1;
case k_accelboost:
lua_pushinteger(L, plr->accelboost);
return 1;
case k_boostangle:
lua_pushinteger(L, plr->boostangle);
return 1;
case k_boostcam:
lua_pushinteger(L, plr->karthud[khud_boostcam]);
return 1;
case k_destboostcam:
lua_pushinteger(L, plr->karthud[khud_destboostcam]);
return 1;
case k_timeovercam:
lua_pushinteger(L, plr->karthud[khud_timeovercam]);
return 1;
case k_aizdriftstrat:
lua_pushinteger(L, plr->aizdriftstrat);
return 1;
case k_brakedrift:
lua_pushinteger(L, (plr->pflags & PF_BRAKEDRIFT));
return 1;
case k_itemroulette:
lua_pushinteger(L, plr->itemroulette);
return 1;
case k_roulettetype:
lua_pushinteger(L, plr->roulettetype);
return 1;
case k_itemtype:
lua_pushinteger(L, plr->itemtype);
return 1;
case k_itemamount:
lua_pushinteger(L, plr->itemamount);
return 1;
case k_itemheld:
lua_pushinteger(L, (plr->itemflags & IF_ITEMOUT));
return 1;
case k_curshield:
lua_pushinteger(L, plr->curshield);
return 1;
case k_hyudorotimer:
lua_pushinteger(L, plr->hyudorotimer);
return 1;
case k_stealingtimer:
lua_pushinteger(L, plr->stealingtimer);
return 1;
case k_stolentimer:
lua_pushinteger(L, plr->stolentimer);
return 1;
case k_sneakertimer:
lua_pushinteger(L, plr->sneakertimer);
return 1;
case k_growshrinktimer:
lua_pushinteger(L, plr->growshrinktimer);
return 1;
case k_squishedtimer:
lua_pushinteger(L, plr->squishedtimer);
return 1;
case k_rocketsneakertimer:
lua_pushinteger(L, plr->rocketsneakertimer);
return 1;
case k_invincibilitytimer:
lua_pushinteger(L, plr->invincibilitytimer);
return 1;
case k_eggmanheld:
lua_pushinteger(L, (plr->itemflags & IF_EGGMANOUT));
return 1;
case k_eggmanexplode:
lua_pushinteger(L, plr->eggmanexplode);
return 1;
case k_eggmanblame:
lua_pushinteger(L, plr->eggmanblame);
return 1;
case k_lastjawztarget:
lua_pushinteger(L, plr->lastjawztarget);
return 1;
case k_bananadrag:
lua_pushinteger(L, plr->bananadrag);
return 1;
case k_spinouttimer:
lua_pushinteger(L, plr->spinouttimer);
return 1;
case k_wipeoutslow:
lua_pushinteger(L, plr->wipeoutslow);
return 1;
case k_justbumped:
lua_pushinteger(L, plr->justbumped);
return 1;
case k_comebacktimer:
lua_pushinteger(L, plr->karmadelay);
return 1;
case k_sadtimer:
lua_pushinteger(L, plr->sadtimer);
return 1;
// Battle Mode vars
case k_bumper:
lua_pushinteger(L, plr->bumper);
return 1;
case k_comebackpoints:
lua_pushinteger(L, plr->karmapoints);
return 1;
case k_comebackmode:
lua_pushinteger(L, plr->karmamode);
return 1;
case k_wanted:
lua_pushinteger(L, plr->wanted);
return 1;
case k_yougotem:
lua_pushinteger(L, plr->karthud[khud_yougotem]);
return 1;
// v1.0.2+ vars
case k_itemblink:
lua_pushinteger(L, plr->itemblink);
return 1;
case k_itemblinkmode:
lua_pushinteger(L, plr->itemblinkmode);
return 1;
case k_getsparks:
lua_pushinteger(L, (plr->pflags & PF_GETSPARKS));
return 1;
case k_jawztargetdelay:
lua_pushinteger(L, plr->jawztargetdelay);
return 1;
case k_spectatewait:
lua_pushinteger(L, plr->spectatewait);
return 1;
case k_growcancel:
lua_pushinteger(L, plr->growcancel);
return 1;
default:
lua_pushinteger(L, kartstuff[ks]);
return 1;
}
return 1;
}
// kartstuff, ks, value -> plt->??? = value
static int kartstuff_set(lua_State *L)
{
INT32 *kartstuff = *((INT32 **)luaL_checkudata(L, 1, META_KARTSTUFF));
player_t *plr = (player_t*)((void*)kartstuff - offsetof(player_t, kartstuff));
kartstufftype_t ks = luaL_checkinteger(L, 2);
INT32 i = (INT32)luaL_checkinteger(L, 3);
if (ks >= NUMKARTSTUFF)
return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
switch (ks)
{
case k_position:
plr->position = i;
break;
case k_oldposition:
plr->oldposition = i;
break;
case k_positiondelay:
plr->positiondelay = i;
break;
case k_prevcheck:
plr->prevcheck = i;
break;
case k_nextcheck:
plr->nextcheck = i;
break;
/*case k_waypoint:
* lua_pushinteger(L, plr->waypoint);
* break;*/
/*case k_starpostwp:
* lua_pushinteger(L, plr->starpostwp);
* break;*/
case k_starpostflip:
plr->starpostflip = i;
break;
case k_respawn:
plr->respawn = i;
break;
case k_dropdash:
plr->dropdash = i;
break;
case k_throwdir:
plr->throwdir = i;
break;
case k_lapanimation:
plr->karthud[khud_lapanimation] = i;
break;
case k_laphand:
plr->karthud[khud_laphand] = i;
break;
case k_cardanimation:
plr->karthud[khud_cardanimation] = i;
break;
case k_voices:
plr->karthud[khud_voices] = i;
break;
case k_tauntvoices:
plr->karthud[khud_tauntvoices] = i;
break;
case k_instashield:
plr->instashield = i;
break;
case k_enginesnd:
plr->karthud[khud_enginesnd] = i;
break;
case k_floorboost:
plr->floorboost = i;
break;
case k_spinouttype:
plr->spinouttype = i;
break;
case k_drift:
plr->drift = i;
break;
case k_driftend:
if (i > 0)
plr->pflags |= PF_DRIFTEND;
break;
case k_driftcharge:
plr->driftcharge = i;
break;
case k_driftboost:
plr->driftboost = i;
break;
case k_boostcharge:
plr->boostcharge = i;
break;
case k_startboost:
plr->startboost = i;
break;
/*case k_jmp:
plr->pflags |= PF_DRIFTINPUT;
return 1;*/
case k_offroad:
plr->offroad = i;
break;
case k_pogospring:
plr->pogospring = i;
break;
case k_brakestop:
plr->brakestop = i;
break;
case k_waterskip:
plr->waterskip = i;
break;
case k_dashpadcooldown:
plr->dashpadcooldown = i;
break;
case k_boostpower:
plr->boostpower = i;
break;
case k_speedboost:
plr->speedboost = i;
break;
case k_accelboost:
plr->accelboost = i;
break;
case k_boostangle:
plr->boostangle = i;
break;
case k_boostcam:
plr->karthud[khud_boostcam] = i;
break;
case k_destboostcam:
plr->karthud[khud_destboostcam] = i;
break;
case k_timeovercam:
plr->karthud[khud_timeovercam] = i;
break;
case k_aizdriftstrat:
plr->aizdriftstrat = i;
break;
case k_brakedrift:
if (i > 0)
plr->pflags |= PF_BRAKEDRIFT;
break;
case k_itemroulette:
plr->itemroulette = i;
break;
case k_roulettetype:
plr->roulettetype = i;
break;
case k_itemtype:
plr->itemtype = i;
break;
case k_itemamount:
plr->itemamount = i;
break;
case k_itemheld:
if (i > 0)
plr->itemflags |= IF_ITEMOUT;
break;
case k_curshield:
plr->curshield = i;
break;
case k_hyudorotimer:
plr->hyudorotimer = i;
break;
case k_stealingtimer:
plr->stealingtimer = i;
break;
case k_stolentimer:
plr->stolentimer = i;
break;
case k_sneakertimer:
plr->sneakertimer = i;
break;
case k_growshrinktimer:
plr->growshrinktimer = i;
break;
case k_squishedtimer:
plr->squishedtimer = i;
break;
case k_rocketsneakertimer:
plr->rocketsneakertimer = i;
break;
case k_invincibilitytimer:
plr->invincibilitytimer = i;
break;
case k_eggmanheld:
if (i > 0)
plr->itemflags |= IF_EGGMANOUT;
break;
case k_eggmanexplode:
plr->eggmanexplode = i;
break;
case k_eggmanblame:
plr->eggmanblame = i;
break;
case k_lastjawztarget:
plr->lastjawztarget = i;
break;
case k_bananadrag:
plr->bananadrag = i;
break;
case k_spinouttimer:
plr->spinouttimer = i;
break;
case k_wipeoutslow:
plr->wipeoutslow = i;
break;
case k_justbumped:
plr->justbumped = i;
break;;
case k_comebacktimer:
plr->karmadelay = i;
break;
case k_sadtimer:
plr->sadtimer = i;
break;
// Battle Mode vars
case k_bumper:
plr->bumper = i;
break;
case k_comebackpoints:
plr->karmapoints = i;
break;
case k_comebackmode:
plr->karmamode = i;
break;
case k_wanted:
plr->wanted = i;
break;
case k_yougotem:
plr->karthud[khud_yougotem] = i;
break;
// v1.0.2+ vars
case k_itemblink:
plr->itemblink = i;
break;
case k_itemblinkmode:
plr->itemblinkmode = i;
break;
case k_getsparks:
if (i > 0)
plr->pflags |= PF_GETSPARKS;
break;
case k_jawztargetdelay:
plr->jawztargetdelay = i;
break;
case k_spectatewait:
plr->spectatewait = i;
break;
case k_growcancel:
plr->growcancel = i;
break;
default:
kartstuff[ks] = i;
break;
}
return 0;
}
// #kartstuff -> NUMKARTSTUFF
static int kartstuff_len(lua_State *L)
{
lua_pushinteger(L, NUMKARTSTUFF);
return 1;
}
// karthud, ks -> karthud[ks]
static int karthud_get(lua_State *L)
{
INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD));
karthudtype_t ks = luaL_checkinteger(L, 2);
if (ks >= NUMKARTHUD)
return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks);
lua_pushinteger(L, karthud[ks]);
return 1;
}
// karthud, ks, value -> karthud[ks] = value
static int karthud_set(lua_State *L)
{
INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD));
karthudtype_t ks = luaL_checkinteger(L, 2);
INT32 i = (INT32)luaL_checkinteger(L, 3);
if (ks >= NUMKARTHUD)
return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
karthud[ks] = i;
return 0;
}
// #karthud -> NUMKARTHUD
static int karthud_len(lua_State *L)
{
lua_pushinteger(L, NUMKARTHUD);
return 1;
}
// player.cmd get/set
#define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field)
#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " cannot be set.", field)
enum ticcmd_e
{
ticcmd_forwardmove,
ticcmd_sidemove,
ticcmd_turning,
ticcmd_driftturn,
ticcmd_angle,
ticcmd_angleturn,
ticcmd_throwdir,
ticcmd_aiming,
ticcmd_buttons,
ticcmd_latency,
ticcmd_flags,
};
static const char *const ticcmd_opt[] = {
"forwardmove",
"sidemove",
"turning",
"driftturn",
"angle",
"angleturn",
"throwdir",
"aiming",
"buttons",
"latency",
"flags",
NULL,
};
static int ticcmd_get(lua_State *L)
{
ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD));
enum ticcmd_e field = Lua_optoption(L, 2, NULL, ticcmd_opt);
if (!cmd)
return LUA_ErrInvalid(L, "player_t");
if (field == (enum ticcmd_e)-1)
return LUA_ErrInvalid(L, "fields");
switch (field)
{
case ticcmd_forwardmove:
lua_pushinteger(L, cmd->forwardmove);
break;
case ticcmd_sidemove:
lua_pushinteger(L, cmd->sidemove);
break;
case ticcmd_turning:
case ticcmd_driftturn:
lua_pushinteger(L, cmd->turning);
break;
case ticcmd_angle:
case ticcmd_angleturn:
lua_pushinteger(L, cmd->angle);
break;
case ticcmd_throwdir:
lua_pushinteger(L, cmd->throwdir);
break;
case ticcmd_aiming:
lua_pushinteger(L, cmd->aiming);
break;
case ticcmd_buttons:
lua_pushinteger(L, cmd->buttons);
break;
case ticcmd_latency:
lua_pushinteger(L, cmd->latency);
break;
case ticcmd_flags:
lua_pushinteger(L, cmd->flags);
break;
default:
return NOFIELD;
}
return 1;
}
static int ticcmd_set(lua_State *L)
{
ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD));
enum ticcmd_e field = Lua_optoption(L, 2, ticcmd_opt[0], ticcmd_opt);
if (!cmd)
return LUA_ErrInvalid(L, "ticcmd_t");
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
switch (field)
{
case ticcmd_forwardmove:
cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3);
break;
case ticcmd_sidemove:
cmd->sidemove = (SINT8)luaL_checkinteger(L, 3);
break;
case ticcmd_turning:
case ticcmd_driftturn:
cmd->turning = (INT16)luaL_checkinteger(L, 3);
break;
case ticcmd_angle:
case ticcmd_angleturn:
cmd->angle = (INT16)luaL_checkinteger(L, 3);
break;
case ticcmd_throwdir:
cmd->throwdir = (INT16)luaL_checkinteger(L, 3);
break;
case ticcmd_aiming:
cmd->aiming = (INT16)luaL_checkinteger(L, 3);
break;
case ticcmd_buttons:
cmd->buttons = (UINT16)luaL_checkinteger(L, 3);
break;
case ticcmd_latency:
return NOSET;
case ticcmd_flags:
return NOSET;
default:
return NOFIELD;
}
return 0;
}
#undef NOFIELD
int LUA_PlayerLib(lua_State *L)
{
luaL_newmetatable(L, META_PLAYER);
lua_pushcfunction(L, player_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, player_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, player_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_POWERS);
lua_pushcfunction(L, power_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, power_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, power_len);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_KARTSTUFF);
lua_pushcfunction(L, kartstuff_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, kartstuff_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, kartstuff_len);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_KARTHUD);
lua_pushcfunction(L, karthud_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, karthud_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, karthud_len);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_TICCMD);
lua_pushcfunction(L, ticcmd_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, ticcmd_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getPlayer);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_lenPlayer);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "players");
// push displayplayers in the same fashion
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getDisplayplayers);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_lenDisplayplayers);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "displayplayers");
return 0;
}