mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-21 20:11:12 +00:00
361 lines
9.1 KiB
C
361 lines
9.1 KiB
C
// SONIC ROBO BLAST 2
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2012-2016 by John "JTE" Muniz.
|
|
// Copyright (C) 2012-2023 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_mathlib.c
|
|
/// \brief basic math library for Lua scripting
|
|
|
|
#include "doomdef.h"
|
|
//#include "fastcmp.h"
|
|
#include "tables.h"
|
|
#include "p_local.h"
|
|
#include "doomstat.h" // for ALL7EMERALDS
|
|
#include "r_main.h" // for R_PointToDist2
|
|
#include "m_easing.h"
|
|
|
|
#include "lua_script.h"
|
|
#include "lua_libs.h"
|
|
|
|
// General math
|
|
//////////////////
|
|
|
|
static int lib_abs(lua_State *L)
|
|
{
|
|
int a = (int)luaL_checkinteger(L, 1);
|
|
lua_pushinteger(L, abs(a));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_min(lua_State *L)
|
|
{
|
|
int a = luaL_checkinteger(L, 1);
|
|
int b = luaL_checkinteger(L, 2);
|
|
lua_pushinteger(L, min(a,b));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_max(lua_State *L)
|
|
{
|
|
int a = luaL_checkinteger(L, 1);
|
|
int b = luaL_checkinteger(L, 2);
|
|
lua_pushinteger(L, max(a,b));
|
|
return 1;
|
|
}
|
|
|
|
// Angle math
|
|
////////////////
|
|
|
|
static int lib_fixedangle(lua_State *L)
|
|
{
|
|
lua_pushangle(L, FixedAngle(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_anglefixed(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, AngleFixed(luaL_checkangle(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_invangle(lua_State *L)
|
|
{
|
|
lua_pushangle(L, InvAngle(luaL_checkangle(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_finesine(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FINESINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_finecosine(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FINECOSINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_finetangent(lua_State *L)
|
|
{
|
|
// HACK: add ANGLE_90 to make tan() in Lua start at 0 like it should
|
|
// use & 4095 instead of & FINEMASK (8191), so it doesn't go out of the array's bounds
|
|
lua_pushfixed(L, FINETANGENT(((luaL_checkangle(L, 1)+ANGLE_90)>>ANGLETOFINESHIFT) & 4095));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedasin(lua_State *L)
|
|
{
|
|
lua_pushangle(L, -FixedAcos(luaL_checkfixed(L, 1)) + ANGLE_90);
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedacos(lua_State *L)
|
|
{
|
|
lua_pushangle(L, FixedAcos(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
// Fixed math
|
|
////////////////
|
|
|
|
static int lib_fixedmul(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FixedMul(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedint(lua_State *L)
|
|
{
|
|
lua_pushinteger(L, FixedInt(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixeddiv(lua_State *L)
|
|
{
|
|
fixed_t i = luaL_checkfixed(L, 1);
|
|
fixed_t j = luaL_checkfixed(L, 2);
|
|
if (j == 0)
|
|
return luaL_error(L, "divide by zero");
|
|
lua_pushfixed(L, FixedDiv(i, j));
|
|
return 1;
|
|
}
|
|
|
|
// TODO: 2.3: Delete
|
|
static int lib_fixedrem(lua_State *L)
|
|
{
|
|
LUA_Deprecated(L, "FixedRem(a, b)", "a % b");
|
|
lua_pushfixed(L, luaL_checkfixed(L, 1) % luaL_checkfixed(L, 2));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedsqrt(lua_State *L)
|
|
{
|
|
fixed_t i = luaL_checkfixed(L, 1);
|
|
if (i < 0)
|
|
return luaL_error(L, "square root domain error");
|
|
lua_pushfixed(L, FixedSqrt(i));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedhypot(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, R_PointToDist2(0, 0, luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedfloor(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FixedFloor(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedtrunc(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FixedTrunc(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedceil(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FixedCeil(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_fixedround(lua_State *L)
|
|
{
|
|
lua_pushfixed(L, FixedRound(luaL_checkfixed(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
// Misc. math
|
|
// (aka extra little funcs that don't quite fit in baselib)
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
static int lib_getsecspecial(lua_State *L)
|
|
{
|
|
lua_pushinteger(L, GETSECSPECIAL(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int lib_all7emeralds(lua_State *L)
|
|
{
|
|
lua_pushboolean(L, ALL7EMERALDS(luaL_checkinteger(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
// Returns both color and signpost shade numbers!
|
|
static int lib_coloropposite(lua_State *L)
|
|
{
|
|
UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
|
|
if (!colornum || colornum >= numskincolors)
|
|
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
|
|
lua_pushinteger(L, skincolors[colornum].invcolor); // push color
|
|
lua_pushinteger(L, skincolors[colornum].invshade); // push sign shade index, 0-15
|
|
return 2;
|
|
}
|
|
|
|
static luaL_Reg lib_math[] = {
|
|
{"abs", lib_abs},
|
|
{"min", lib_min},
|
|
{"max", lib_max},
|
|
{"sin", lib_finesine},
|
|
{"cos", lib_finecosine},
|
|
{"tan", lib_finetangent},
|
|
{"asin", lib_fixedasin},
|
|
{"acos", lib_fixedacos},
|
|
{"FixedAngle", lib_fixedangle},
|
|
{"fixangle" , lib_fixedangle},
|
|
{"AngleFixed", lib_anglefixed},
|
|
{"anglefix" , lib_anglefixed},
|
|
{"InvAngle", lib_invangle},
|
|
{"FixedMul", lib_fixedmul},
|
|
{"fixmul" , lib_fixedmul},
|
|
{"FixedInt", lib_fixedint},
|
|
{"fixint" , lib_fixedint},
|
|
{"FixedDiv", lib_fixeddiv},
|
|
{"fixdiv" , lib_fixeddiv},
|
|
{"FixedRem", lib_fixedrem},
|
|
{"fixrem" , lib_fixedrem},
|
|
{"FixedSqrt", lib_fixedsqrt},
|
|
{"fixsqrt" , lib_fixedsqrt},
|
|
{"FixedHypot", lib_fixedhypot},
|
|
{"fixhypot" , lib_fixedhypot},
|
|
{"FixedFloor", lib_fixedfloor},
|
|
{"fixfloor" , lib_fixedfloor},
|
|
{"FixedTrunc", lib_fixedtrunc},
|
|
{"fixtrunc" , lib_fixedtrunc},
|
|
{"FixedCeil", lib_fixedceil},
|
|
{"fixceil" , lib_fixedceil},
|
|
{"FixedRound", lib_fixedround},
|
|
{"fixround" , lib_fixedround},
|
|
{"GetSecSpecial", lib_getsecspecial},
|
|
{"All7Emeralds", lib_all7emeralds},
|
|
{"ColorOpposite", lib_coloropposite},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
//
|
|
// Easing functions
|
|
//
|
|
|
|
#define EASINGFUNC(easetype) \
|
|
{ \
|
|
fixed_t start = 0; \
|
|
fixed_t end = FRACUNIT; \
|
|
fixed_t t = luaL_checkfixed(L, 1); \
|
|
int n = lua_gettop(L); \
|
|
if (n == 2) \
|
|
end = luaL_checkfixed(L, 2); \
|
|
else if (n >= 3) \
|
|
{ \
|
|
start = luaL_checkfixed(L, 2); \
|
|
end = luaL_checkfixed(L, 3); \
|
|
} \
|
|
lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \
|
|
return 1; \
|
|
} \
|
|
|
|
static int lib_easelinear(lua_State *L) { EASINGFUNC(Linear) }
|
|
|
|
static int lib_easeinsine(lua_State *L) { EASINGFUNC(InSine) }
|
|
static int lib_easeoutsine(lua_State *L) { EASINGFUNC(OutSine) }
|
|
static int lib_easeinoutsine(lua_State *L) { EASINGFUNC(InOutSine) }
|
|
|
|
static int lib_easeinquad(lua_State *L) { EASINGFUNC(InQuad) }
|
|
static int lib_easeoutquad(lua_State *L) { EASINGFUNC(OutQuad) }
|
|
static int lib_easeinoutquad(lua_State *L) { EASINGFUNC(InOutQuad) }
|
|
|
|
static int lib_easeincubic(lua_State *L) { EASINGFUNC(InCubic) }
|
|
static int lib_easeoutcubic(lua_State *L) { EASINGFUNC(OutCubic) }
|
|
static int lib_easeinoutcubic(lua_State *L) { EASINGFUNC(InOutCubic) }
|
|
|
|
static int lib_easeinquart(lua_State *L) { EASINGFUNC(InQuart) }
|
|
static int lib_easeoutquart(lua_State *L) { EASINGFUNC(OutQuart) }
|
|
static int lib_easeinoutquart(lua_State *L) { EASINGFUNC(InOutQuart) }
|
|
|
|
static int lib_easeinquint(lua_State *L) { EASINGFUNC(InQuint) }
|
|
static int lib_easeoutquint(lua_State *L) { EASINGFUNC(OutQuint) }
|
|
static int lib_easeinoutquint(lua_State *L) { EASINGFUNC(InOutQuint) }
|
|
|
|
static int lib_easeinexpo(lua_State *L) { EASINGFUNC(InExpo) }
|
|
static int lib_easeoutexpo(lua_State *L) { EASINGFUNC(OutExpo) }
|
|
static int lib_easeinoutexpo(lua_State *L) { EASINGFUNC(InOutExpo) }
|
|
|
|
#undef EASINGFUNC
|
|
|
|
#define EASINGFUNC(easetype) \
|
|
{ \
|
|
boolean useparam = false; \
|
|
fixed_t param = 0; \
|
|
fixed_t start = 0; \
|
|
fixed_t end = FRACUNIT; \
|
|
fixed_t t = luaL_checkfixed(L, 1); \
|
|
int n = lua_gettop(L); \
|
|
if (n == 2) \
|
|
end = luaL_checkfixed(L, 2); \
|
|
else if (n >= 3) \
|
|
{ \
|
|
start = (fixed_t)luaL_optinteger(L, 2, start); \
|
|
end = (fixed_t)luaL_optinteger(L, 3, end); \
|
|
if ((n >= 4) && (useparam = (!lua_isnil(L, 4)))) \
|
|
param = luaL_checkfixed(L, 4); \
|
|
} \
|
|
if (useparam) \
|
|
lua_pushfixed(L, (Easing_ ## easetype ## Parameterized)(t, start, end, param)); \
|
|
else \
|
|
lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \
|
|
return 1; \
|
|
} \
|
|
|
|
static int lib_easeinback(lua_State *L) { EASINGFUNC(InBack) }
|
|
static int lib_easeoutback(lua_State *L) { EASINGFUNC(OutBack) }
|
|
static int lib_easeinoutback(lua_State *L) { EASINGFUNC(InOutBack) }
|
|
|
|
#undef EASINGFUNC
|
|
|
|
static luaL_Reg lib_ease[] = {
|
|
{"linear", lib_easelinear},
|
|
|
|
{"insine", lib_easeinsine},
|
|
{"outsine", lib_easeoutsine},
|
|
{"inoutsine", lib_easeinoutsine},
|
|
|
|
{"inquad", lib_easeinquad},
|
|
{"outquad", lib_easeoutquad},
|
|
{"inoutquad", lib_easeinoutquad},
|
|
|
|
{"incubic", lib_easeincubic},
|
|
{"outcubic", lib_easeoutcubic},
|
|
{"inoutcubic", lib_easeinoutcubic},
|
|
|
|
{"inquart", lib_easeinquart},
|
|
{"outquart", lib_easeoutquart},
|
|
{"inoutquart", lib_easeinoutquart},
|
|
|
|
{"inquint", lib_easeinquint},
|
|
{"outquint", lib_easeoutquint},
|
|
{"inoutquint", lib_easeinoutquint},
|
|
|
|
{"inexpo", lib_easeinexpo},
|
|
{"outexpo", lib_easeoutexpo},
|
|
{"inoutexpo", lib_easeinoutexpo},
|
|
|
|
{"inback", lib_easeinback},
|
|
{"outback", lib_easeoutback},
|
|
{"inoutback", lib_easeinoutback},
|
|
|
|
{NULL, NULL}
|
|
};
|
|
|
|
int LUA_MathLib(lua_State *L)
|
|
{
|
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
|
luaL_register(L, NULL, lib_math);
|
|
luaL_register(L, "ease", lib_ease);
|
|
return 0;
|
|
}
|