1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 2012-2016 by John "JTE" Muniz.
4 // Copyright (C) 2012-2020 by Sonic Team Junior.
5 //
6 // This program is free software distributed under the
7 // terms of the GNU General Public License, version 2.
8 // See the 'LICENSE' file for more details.
9 //-----------------------------------------------------------------------------
10 /// \file  lua_mathlib.c
11 /// \brief basic math library for Lua scripting
12 
13 #include "doomdef.h"
14 //#include "fastcmp.h"
15 #include "tables.h"
16 #include "p_local.h"
17 #include "doomstat.h" // for ALL7EMERALDS
18 #include "r_main.h" // for R_PointToDist2
19 
20 #include "lua_script.h"
21 #include "lua_libs.h"
22 
23 // General math
24 //////////////////
25 
lib_abs(lua_State * L)26 static int lib_abs(lua_State *L)
27 {
28 	int a = (int)luaL_checkinteger(L, 1);
29 	lua_pushinteger(L, abs(a));
30 	return 1;
31 }
32 
lib_min(lua_State * L)33 static int lib_min(lua_State *L)
34 {
35 	int a = luaL_checkinteger(L, 1);
36 	int b = luaL_checkinteger(L, 2);
37 	lua_pushinteger(L, min(a,b));
38 	return 1;
39 }
40 
lib_max(lua_State * L)41 static int lib_max(lua_State *L)
42 {
43 	int a = luaL_checkinteger(L, 1);
44 	int b = luaL_checkinteger(L, 2);
45 	lua_pushinteger(L, max(a,b));
46 	return 1;
47 }
48 
49 // Angle math
50 ////////////////
51 
lib_fixedangle(lua_State * L)52 static int lib_fixedangle(lua_State *L)
53 {
54 	lua_pushangle(L, FixedAngle(luaL_checkfixed(L, 1)));
55 	return 1;
56 }
57 
lib_anglefixed(lua_State * L)58 static int lib_anglefixed(lua_State *L)
59 {
60 	lua_pushfixed(L, AngleFixed(luaL_checkangle(L, 1)));
61 	return 1;
62 }
63 
lib_invangle(lua_State * L)64 static int lib_invangle(lua_State *L)
65 {
66 	lua_pushangle(L, InvAngle(luaL_checkangle(L, 1)));
67 	return 1;
68 }
69 
lib_finesine(lua_State * L)70 static int lib_finesine(lua_State *L)
71 {
72 	lua_pushfixed(L, FINESINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
73 	return 1;
74 }
75 
lib_finecosine(lua_State * L)76 static int lib_finecosine(lua_State *L)
77 {
78 	lua_pushfixed(L, FINECOSINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
79 	return 1;
80 }
81 
lib_finetangent(lua_State * L)82 static int lib_finetangent(lua_State *L)
83 {
84 	// HACK: add ANGLE_90 to make tan() in Lua start at 0 like it should
85 	// use & 4095 instead of & FINEMASK (8191), so it doesn't go out of the array's bounds
86 	lua_pushfixed(L, FINETANGENT(((luaL_checkangle(L, 1)+ANGLE_90)>>ANGLETOFINESHIFT) & 4095));
87 	return 1;
88 }
89 
90 // Fixed math
91 ////////////////
92 
lib_fixedmul(lua_State * L)93 static int lib_fixedmul(lua_State *L)
94 {
95 	lua_pushfixed(L, FixedMul(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
96 	return 1;
97 }
98 
lib_fixedint(lua_State * L)99 static int lib_fixedint(lua_State *L)
100 {
101 	lua_pushinteger(L, FixedInt(luaL_checkfixed(L, 1)));
102 	return 1;
103 }
104 
lib_fixeddiv(lua_State * L)105 static int lib_fixeddiv(lua_State *L)
106 {
107 	fixed_t i = luaL_checkfixed(L, 1);
108 	fixed_t j = luaL_checkfixed(L, 2);
109 	if (j == 0)
110 		return luaL_error(L, "divide by zero");
111 	lua_pushfixed(L, FixedDiv(i, j));
112 	return 1;
113 }
114 
lib_fixedrem(lua_State * L)115 static int lib_fixedrem(lua_State *L)
116 {
117 	LUA_Deprecated(L, "FixedRem(a, b)", "a % b");
118 	lua_pushfixed(L, luaL_checkfixed(L, 1) % luaL_checkfixed(L, 2));
119 	return 1;
120 }
121 
lib_fixedsqrt(lua_State * L)122 static int lib_fixedsqrt(lua_State *L)
123 {
124 	fixed_t i = luaL_checkfixed(L, 1);
125 	if (i < 0)
126 		return luaL_error(L, "square root domain error");
127 	lua_pushfixed(L, FixedSqrt(i));
128 	return 1;
129 }
130 
lib_fixedhypot(lua_State * L)131 static int lib_fixedhypot(lua_State *L)
132 {
133 	lua_pushfixed(L, R_PointToDist2(0, 0, luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
134 	return 1;
135 }
136 
lib_fixedfloor(lua_State * L)137 static int lib_fixedfloor(lua_State *L)
138 {
139 	lua_pushfixed(L, FixedFloor(luaL_checkfixed(L, 1)));
140 	return 1;
141 }
142 
lib_fixedtrunc(lua_State * L)143 static int lib_fixedtrunc(lua_State *L)
144 {
145 	lua_pushfixed(L, FixedTrunc(luaL_checkfixed(L, 1)));
146 	return 1;
147 }
148 
lib_fixedceil(lua_State * L)149 static int lib_fixedceil(lua_State *L)
150 {
151 	lua_pushfixed(L, FixedCeil(luaL_checkfixed(L, 1)));
152 	return 1;
153 }
154 
lib_fixedround(lua_State * L)155 static int lib_fixedround(lua_State *L)
156 {
157 	lua_pushfixed(L, FixedRound(luaL_checkfixed(L, 1)));
158 	return 1;
159 }
160 
161 // Misc. math
162 // (aka extra little funcs that don't quite fit in baselib)
163 //////////////////////////////////////////////////////////////////
164 
lib_getsecspecial(lua_State * L)165 static int lib_getsecspecial(lua_State *L)
166 {
167 	lua_pushinteger(L, GETSECSPECIAL(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2)));
168 	return 1;
169 }
170 
lib_all7emeralds(lua_State * L)171 static int lib_all7emeralds(lua_State *L)
172 {
173 	lua_pushboolean(L, ALL7EMERALDS(luaL_checkinteger(L, 1)));
174 	return 1;
175 }
176 
177 // Returns both color and signpost shade numbers!
lib_coloropposite(lua_State * L)178 static int lib_coloropposite(lua_State *L)
179 {
180 	UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
181 	if (!colornum || colornum >= numskincolors)
182 		return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
183 	lua_pushinteger(L, skincolors[colornum].invcolor); // push color
184 	lua_pushinteger(L, skincolors[colornum].invshade); // push sign shade index, 0-15
185 	return 2;
186 }
187 
188 static luaL_Reg lib[] = {
189 	{"abs", lib_abs},
190 	{"min", lib_min},
191 	{"max", lib_max},
192 	{"sin", lib_finesine},
193 	{"cos", lib_finecosine},
194 	{"tan", lib_finetangent},
195 	{"FixedAngle", lib_fixedangle},
196 	{"fixangle"  , lib_fixedangle},
197 	{"AngleFixed", lib_anglefixed},
198 	{"anglefix"  , lib_anglefixed},
199 	{"InvAngle", lib_invangle},
200 	{"FixedMul", lib_fixedmul},
201 	{"fixmul"  , lib_fixedmul},
202 	{"FixedInt", lib_fixedint},
203 	{"fixint"  , lib_fixedint},
204 	{"FixedDiv", lib_fixeddiv},
205 	{"fixdiv"  , lib_fixeddiv},
206 	{"FixedRem", lib_fixedrem},
207 	{"fixrem"  , lib_fixedrem},
208 	{"FixedSqrt", lib_fixedsqrt},
209 	{"fixsqrt"  , lib_fixedsqrt},
210 	{"FixedHypot", lib_fixedhypot},
211 	{"fixhypot"  , lib_fixedhypot},
212 	{"FixedFloor", lib_fixedfloor},
213 	{"fixfloor"  , lib_fixedfloor},
214 	{"FixedTrunc", lib_fixedtrunc},
215 	{"fixtrunc"  , lib_fixedtrunc},
216 	{"FixedCeil", lib_fixedceil},
217 	{"fixceil"  , lib_fixedceil},
218 	{"FixedRound", lib_fixedround},
219 	{"fixround"  , lib_fixedround},
220 	{"GetSecSpecial", lib_getsecspecial},
221 	{"All7Emeralds", lib_all7emeralds},
222 	{"ColorOpposite", lib_coloropposite},
223 	{NULL, NULL}
224 };
225 
LUA_MathLib(lua_State * L)226 int LUA_MathLib(lua_State *L)
227 {
228 	lua_pushvalue(L, LUA_GLOBALSINDEX);
229 	luaL_register(L, NULL, lib);
230 	return 0;
231 }
232