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_baselib.c
11 /// \brief basic functions for Lua scripting
12
13 #include "doomdef.h"
14 #include "fastcmp.h"
15 #include "p_local.h"
16 #include "p_setup.h" // So we can have P_SetupLevelSky
17 #include "p_slopes.h" // P_GetSlopeZAt
18 #include "z_zone.h"
19 #include "r_main.h"
20 #include "r_draw.h"
21 #include "r_things.h" // R_Frame2Char etc
22 #include "m_random.h"
23 #include "s_sound.h"
24 #include "g_game.h"
25 #include "m_menu.h"
26 #include "y_inter.h"
27 #include "hu_stuff.h" // HU_AddChatText
28 #include "console.h"
29 #include "d_netcmd.h" // IsPlayerAdmin
30 #include "m_menu.h" // Player Setup menu color stuff
31
32 #include "lua_script.h"
33 #include "lua_libs.h"
34 #include "lua_hud.h" // hud_running errors
35 #include "taglist.h" // P_FindSpecialLineFromTag
36 #include "lua_hook.h" // hook_cmd_running errors
37
38 #define NOHUD if (hud_running)\
39 return luaL_error(L, "HUD rendering code should not call this function!");\
40 else if (hook_cmd_running)\
41 return luaL_error(L, "CMD building code should not call this function!");
42
luaL_checkboolean(lua_State * L,int narg)43 boolean luaL_checkboolean(lua_State *L, int narg) {
44 luaL_checktype(L, narg, LUA_TBOOLEAN);
45 return lua_toboolean(L, narg);
46 }
47
48 // String concatination
lib_concat(lua_State * L)49 static int lib_concat(lua_State *L)
50 {
51 int n = lua_gettop(L); /* number of arguments */
52 int i;
53 char *r = NULL;
54 size_t rl = 0,sl;
55 lua_getglobal(L, "tostring");
56 for (i=1; i<=n; i++) {
57 const char *s;
58 lua_pushvalue(L, -1); /* function to be called */
59 lua_pushvalue(L, i); /* value to print */
60 lua_call(L, 1, 1);
61 s = lua_tolstring(L, -1, &sl); /* get result */
62 if (s == NULL)
63 return luaL_error(L, LUA_QL("tostring") " must return a string to "
64 LUA_QL("__add"));
65 r = Z_Realloc(r, rl+sl, PU_STATIC, NULL);
66 M_Memcpy(r+rl, s, sl);
67 rl += sl;
68 lua_pop(L, 1); /* pop result */
69 }
70 lua_pushlstring(L, r, rl);
71 Z_Free(r);
72 return 1;
73 }
74
75 // Wrapper for CONS_Printf
76 // Copied from base Lua code
lib_print(lua_State * L)77 static int lib_print(lua_State *L)
78 {
79 int n = lua_gettop(L); /* number of arguments */
80 int i;
81 //HUDSAFE
82 lua_getglobal(L, "tostring");
83 for (i=1; i<=n; i++) {
84 const char *s;
85 lua_pushvalue(L, -1); /* function to be called */
86 lua_pushvalue(L, i); /* value to print */
87 lua_call(L, 1, 1);
88 s = lua_tostring(L, -1); /* get result */
89 if (s == NULL)
90 return luaL_error(L, LUA_QL("tostring") " must return a string to "
91 LUA_QL("print"));
92 if (i>1) CONS_Printf("\n");
93 CONS_Printf("%s", s);
94 lua_pop(L, 1); /* pop result */
95 }
96 CONS_Printf("\n");
97 return 0;
98 }
99
100 // Print stuff in the chat, or in the console if we can't.
lib_chatprint(lua_State * L)101 static int lib_chatprint(lua_State *L)
102 {
103 const char *str = luaL_checkstring(L, 1); // retrieve string
104 boolean sound = lua_optboolean(L, 2); // retrieve sound boolean
105 int len = strlen(str);
106
107 if (str == NULL) // error if we don't have a string!
108 return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint"));
109
110 if (len > 255) // string is too long!!!
111 return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
112
113 HU_AddChatText(str, sound);
114 return 0;
115 }
116
117 // Same as above, but do it for only one player.
lib_chatprintf(lua_State * L)118 static int lib_chatprintf(lua_State *L)
119 {
120 int n = lua_gettop(L); /* number of arguments */
121 const char *str = luaL_checkstring(L, 2); // retrieve string
122 boolean sound = lua_optboolean(L, 3); // sound?
123 int len = strlen(str);
124 player_t *plr;
125
126 if (n < 2)
127 return luaL_error(L, "chatprintf requires at least two arguments: player and text.");
128
129 plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
130 if (!plr)
131 return LUA_ErrInvalid(L, "player_t");
132 if (plr != &players[consoleplayer])
133 return 0;
134
135 if (str == NULL) // error if we don't have a string!
136 return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf"));
137
138 if (len > 255) // string is too long!!!
139 return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
140
141 HU_AddChatText(str, sound);
142 return 0;
143 }
144
145 static const struct {
146 const char *meta;
147 const char *utype;
148 } meta2utype[] = {
149 {META_STATE, "state_t"},
150 {META_MOBJINFO, "mobjinfo_t"},
151 {META_SFXINFO, "sfxinfo_t"},
152 {META_SKINCOLOR, "skincolor_t"},
153 {META_COLORRAMP, "skincolor_t.ramp"},
154 {META_SPRITEINFO, "spriteinfo_t"},
155 {META_PIVOTLIST, "spriteframepivot_t[]"},
156 {META_FRAMEPIVOT, "spriteframepivot_t"},
157
158 {META_TAGLIST, "taglist"},
159
160 {META_MOBJ, "mobj_t"},
161 {META_MAPTHING, "mapthing_t"},
162
163 {META_PLAYER, "player_t"},
164 {META_TICCMD, "ticcmd_t"},
165 {META_SKIN, "skin_t"},
166 {META_POWERS, "player_t.powers"},
167 {META_SOUNDSID, "skin_t.soundsid"},
168 {META_SKINSPRITES, "skin_t.sprites"},
169 {META_SKINSPRITESLIST, "skin_t.sprites[]"},
170
171 {META_VERTEX, "vertex_t"},
172 {META_LINE, "line_t"},
173 {META_SIDE, "side_t"},
174 {META_SUBSECTOR, "subsector_t"},
175 {META_SECTOR, "sector_t"},
176 {META_FFLOOR, "ffloor_t"},
177 #ifdef HAVE_LUA_SEGS
178 {META_SEG, "seg_t"},
179 {META_NODE, "node_t"},
180 #endif
181 {META_SLOPE, "slope_t"},
182 {META_VECTOR2, "vector2_t"},
183 {META_VECTOR3, "vector3_t"},
184 {META_MAPHEADER, "mapheader_t"},
185
186 {META_POLYOBJ, "polyobj_t"},
187
188 {META_CVAR, "consvar_t"},
189
190 {META_SECTORLINES, "sector_t.lines"},
191 #ifdef MUTABLE_TAGS
192 {META_SECTORTAGLIST, "sector_t.taglist"},
193 #endif
194 {META_SIDENUM, "line_t.sidenum"},
195 {META_LINEARGS, "line_t.args"},
196 {META_LINESTRINGARGS, "line_t.stringargs"},
197
198 {META_THINGARGS, "mapthing.args"},
199 {META_THINGSTRINGARGS, "mapthing.stringargs"},
200 #ifdef HAVE_LUA_SEGS
201 {META_NODEBBOX, "node_t.bbox"},
202 {META_NODECHILDREN, "node_t.children"},
203 #endif
204
205 {META_BBOX, "bbox"},
206
207 {META_HUDINFO, "hudinfo_t"},
208 {META_PATCH, "patch_t"},
209 {META_COLORMAP, "colormap"},
210 {META_CAMERA, "camera_t"},
211
212 {META_ACTION, "action"},
213
214 {META_LUABANKS, "luabanks[]"},
215 {NULL, NULL}
216 };
217
218 // goes through the above list and returns the utype string for the userdata type
219 // returns "unknown" instead if we couldn't find the right userdata type
GetUserdataUType(lua_State * L)220 static const char *GetUserdataUType(lua_State *L)
221 {
222 UINT8 i;
223 lua_getmetatable(L, -1);
224
225 for (i = 0; meta2utype[i].meta; i++)
226 {
227 luaL_getmetatable(L, meta2utype[i].meta);
228 if (lua_rawequal(L, -1, -2))
229 {
230 lua_pop(L, 2);
231 return meta2utype[i].utype;
232 }
233 lua_pop(L, 1);
234 }
235
236 lua_pop(L, 1);
237 return "unknown";
238 }
239
240 // Return a string representing the type of userdata the given var is
241 // e.g. players[0] -> "player_t"
242 // or players[0].powers -> "player_t.powers"
lib_userdataType(lua_State * L)243 static int lib_userdataType(lua_State *L)
244 {
245 lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more)
246 luaL_checktype(L, 1, LUA_TUSERDATA);
247 lua_pushstring(L, GetUserdataUType(L));
248 return 1;
249 }
250
251 // Takes a metatable as first and only argument
252 // Only callable during script loading
lib_registerMetatable(lua_State * L)253 static int lib_registerMetatable(lua_State *L)
254 {
255 static UINT16 nextid = 1;
256
257 if (!lua_lumploading)
258 return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
259 luaL_checktype(L, 1, LUA_TTABLE);
260
261 if (nextid == 0)
262 return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
263
264 lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
265 // registry.metatables[metatable] = nextid
266 lua_pushvalue(L, 1); // 3
267 lua_pushnumber(L, nextid); // 4
268 lua_settable(L, 2);
269
270 // registry.metatables[nextid] = metatable
271 lua_pushnumber(L, nextid); // 3
272 lua_pushvalue(L, 1); // 4
273 lua_settable(L, 2);
274 lua_pop(L, 1);
275
276 nextid++;
277
278 return 0;
279 }
280
281 // Takes a string as only argument and returns the metatable
282 // associated to the userdata type this string refers to
283 // Returns nil if the string does not refer to a valid userdata type
lib_userdataMetatable(lua_State * L)284 static int lib_userdataMetatable(lua_State *L)
285 {
286 UINT32 i;
287 const char *udname = luaL_checkstring(L, 1);
288
289 // Find internal metatable name
290 for (i = 0; meta2utype[i].meta; i++)
291 if (!strcmp(udname, meta2utype[i].utype))
292 {
293 luaL_getmetatable(L, meta2utype[i].meta);
294 return 1;
295 }
296
297 lua_pushnil(L);
298 return 1;
299 }
300
lib_isPlayerAdmin(lua_State * L)301 static int lib_isPlayerAdmin(lua_State *L)
302 {
303 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
304 //HUDSAFE
305 if (!player)
306 return LUA_ErrInvalid(L, "player_t");
307 lua_pushboolean(L, IsPlayerAdmin(player-players));
308 return 1;
309 }
310
lib_reserveLuabanks(lua_State * L)311 static int lib_reserveLuabanks(lua_State *L)
312 {
313 static boolean reserved = false;
314 if (!lua_lumploading)
315 return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!");
316 if (reserved)
317 return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature.");
318 reserved = true;
319 LUA_PushUserdata(L, &luabanks, META_LUABANKS);
320 return 1;
321 }
322
323 // M_MENU
324 //////////////
325
lib_pMoveColorBefore(lua_State * L)326 static int lib_pMoveColorBefore(lua_State *L)
327 {
328 UINT16 color = (UINT16)luaL_checkinteger(L, 1);
329 UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
330
331 NOHUD
332 M_MoveColorBefore(color, targ);
333 return 0;
334 }
335
lib_pMoveColorAfter(lua_State * L)336 static int lib_pMoveColorAfter(lua_State *L)
337 {
338 UINT16 color = (UINT16)luaL_checkinteger(L, 1);
339 UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
340
341 NOHUD
342 M_MoveColorAfter(color, targ);
343 return 0;
344 }
345
lib_pGetColorBefore(lua_State * L)346 static int lib_pGetColorBefore(lua_State *L)
347 {
348 UINT16 color = (UINT16)luaL_checkinteger(L, 1);
349 lua_pushinteger(L, M_GetColorBefore(color));
350 return 1;
351 }
352
lib_pGetColorAfter(lua_State * L)353 static int lib_pGetColorAfter(lua_State *L)
354 {
355 UINT16 color = (UINT16)luaL_checkinteger(L, 1);
356 lua_pushinteger(L, M_GetColorAfter(color));
357 return 1;
358 }
359
360 // M_RANDOM
361 //////////////
362
lib_pRandomFixed(lua_State * L)363 static int lib_pRandomFixed(lua_State *L)
364 {
365 NOHUD
366 lua_pushfixed(L, P_RandomFixed());
367 return 1;
368 }
369
lib_pRandomByte(lua_State * L)370 static int lib_pRandomByte(lua_State *L)
371 {
372 NOHUD
373 lua_pushinteger(L, P_RandomByte());
374 return 1;
375 }
376
lib_pRandomKey(lua_State * L)377 static int lib_pRandomKey(lua_State *L)
378 {
379 INT32 a = (INT32)luaL_checkinteger(L, 1);
380
381 NOHUD
382 if (a > 65536)
383 LUA_UsageWarning(L, "P_RandomKey: range > 65536 is undefined behavior");
384 lua_pushinteger(L, P_RandomKey(a));
385 return 1;
386 }
387
lib_pRandomRange(lua_State * L)388 static int lib_pRandomRange(lua_State *L)
389 {
390 INT32 a = (INT32)luaL_checkinteger(L, 1);
391 INT32 b = (INT32)luaL_checkinteger(L, 2);
392
393 NOHUD
394 if (b < a) {
395 INT32 c = a;
396 a = b;
397 b = c;
398 }
399 if ((b-a+1) > 65536)
400 LUA_UsageWarning(L, "P_RandomRange: range > 65536 is undefined behavior");
401 lua_pushinteger(L, P_RandomRange(a, b));
402 return 1;
403 }
404
405 // Macros.
lib_pSignedRandom(lua_State * L)406 static int lib_pSignedRandom(lua_State *L)
407 {
408 NOHUD
409 lua_pushinteger(L, P_SignedRandom());
410 return 1;
411 }
412
lib_pRandomChance(lua_State * L)413 static int lib_pRandomChance(lua_State *L)
414 {
415 fixed_t p = luaL_checkfixed(L, 1);
416 NOHUD
417 lua_pushboolean(L, P_RandomChance(p));
418 return 1;
419 }
420
421 // P_MAPUTIL
422 ///////////////
423
lib_pAproxDistance(lua_State * L)424 static int lib_pAproxDistance(lua_State *L)
425 {
426 fixed_t dx = luaL_checkfixed(L, 1);
427 fixed_t dy = luaL_checkfixed(L, 2);
428 //HUDSAFE
429 lua_pushfixed(L, R_PointToDist2(0, 0, dx, dy));
430 return 1;
431 }
432
lib_pClosestPointOnLine(lua_State * L)433 static int lib_pClosestPointOnLine(lua_State *L)
434 {
435 int n = lua_gettop(L);
436 fixed_t x = luaL_checkfixed(L, 1);
437 fixed_t y = luaL_checkfixed(L, 2);
438 vertex_t result;
439 //HUDSAFE
440 if (lua_isuserdata(L, 3)) // use a real linedef to get our points
441 {
442 line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE));
443 if (!line)
444 return LUA_ErrInvalid(L, "line_t");
445 P_ClosestPointOnLine(x, y, line, &result);
446 }
447 else // use custom coordinates of our own!
448 {
449 vertex_t v1, v2; // fake vertexes
450 line_t junk; // fake linedef
451
452 if (n < 6)
453 return luaL_error(L, "arguments 3 to 6 not all given (expected 4 fixed-point integers)");
454
455 v1.x = luaL_checkfixed(L, 3);
456 v1.y = luaL_checkfixed(L, 4);
457 v2.x = luaL_checkfixed(L, 5);
458 v2.y = luaL_checkfixed(L, 6);
459
460 junk.v1 = &v1;
461 junk.v2 = &v2;
462 junk.dx = v2.x - v1.x;
463 junk.dy = v2.y - v1.y;
464 P_ClosestPointOnLine(x, y, &junk, &result);
465 }
466
467 lua_pushfixed(L, result.x);
468 lua_pushfixed(L, result.y);
469 return 2;
470 }
471
lib_pPointOnLineSide(lua_State * L)472 static int lib_pPointOnLineSide(lua_State *L)
473 {
474 int n = lua_gettop(L);
475 fixed_t x = luaL_checkfixed(L, 1);
476 fixed_t y = luaL_checkfixed(L, 2);
477 //HUDSAFE
478 if (lua_isuserdata(L, 3)) // use a real linedef to get our points
479 {
480 line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE));
481 if (!line)
482 return LUA_ErrInvalid(L, "line_t");
483 lua_pushinteger(L, P_PointOnLineSide(x, y, line));
484 }
485 else // use custom coordinates of our own!
486 {
487 vertex_t v1, v2; // fake vertexes
488 line_t junk; // fake linedef
489
490 if (n < 6)
491 return luaL_error(L, "arguments 3 to 6 not all given (expected 4 fixed-point integers)");
492
493 v1.x = luaL_checkfixed(L, 3);
494 v1.y = luaL_checkfixed(L, 4);
495 v2.x = luaL_checkfixed(L, 5);
496 v2.y = luaL_checkfixed(L, 6);
497
498 junk.v1 = &v1;
499 junk.v2 = &v2;
500 junk.dx = v2.x - v1.x;
501 junk.dy = v2.y - v1.y;
502 lua_pushinteger(L, P_PointOnLineSide(x, y, &junk));
503 }
504 return 1;
505 }
506
507 // P_ENEMY
508 /////////////
509
lib_pCheckMeleeRange(lua_State * L)510 static int lib_pCheckMeleeRange(lua_State *L)
511 {
512 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
513 NOHUD
514 INLEVEL
515 if (!actor)
516 return LUA_ErrInvalid(L, "mobj_t");
517 lua_pushboolean(L, P_CheckMeleeRange(actor));
518 return 1;
519 }
520
lib_pJetbCheckMeleeRange(lua_State * L)521 static int lib_pJetbCheckMeleeRange(lua_State *L)
522 {
523 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
524 NOHUD
525 INLEVEL
526 if (!actor)
527 return LUA_ErrInvalid(L, "mobj_t");
528 lua_pushboolean(L, P_JetbCheckMeleeRange(actor));
529 return 1;
530 }
531
lib_pFaceStabCheckMeleeRange(lua_State * L)532 static int lib_pFaceStabCheckMeleeRange(lua_State *L)
533 {
534 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
535 NOHUD
536 INLEVEL
537 if (!actor)
538 return LUA_ErrInvalid(L, "mobj_t");
539 lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor));
540 return 1;
541 }
542
lib_pSkimCheckMeleeRange(lua_State * L)543 static int lib_pSkimCheckMeleeRange(lua_State *L)
544 {
545 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
546 NOHUD
547 INLEVEL
548 if (!actor)
549 return LUA_ErrInvalid(L, "mobj_t");
550 lua_pushboolean(L, P_SkimCheckMeleeRange(actor));
551 return 1;
552 }
553
lib_pCheckMissileRange(lua_State * L)554 static int lib_pCheckMissileRange(lua_State *L)
555 {
556 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
557 NOHUD
558 INLEVEL
559 if (!actor)
560 return LUA_ErrInvalid(L, "mobj_t");
561 lua_pushboolean(L, P_CheckMissileRange(actor));
562 return 1;
563 }
564
lib_pNewChaseDir(lua_State * L)565 static int lib_pNewChaseDir(lua_State *L)
566 {
567 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
568 NOHUD
569 INLEVEL
570 if (!actor)
571 return LUA_ErrInvalid(L, "mobj_t");
572 P_NewChaseDir(actor);
573 return 0;
574 }
575
lib_pLookForPlayers(lua_State * L)576 static int lib_pLookForPlayers(lua_State *L)
577 {
578 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
579 fixed_t dist = (fixed_t)luaL_optinteger(L, 2, 0);
580 boolean allaround = lua_optboolean(L, 3);
581 boolean tracer = lua_optboolean(L, 4);
582 NOHUD
583 INLEVEL
584 if (!actor)
585 return LUA_ErrInvalid(L, "mobj_t");
586 lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist));
587 return 1;
588 }
589
590 // P_MOBJ
591 ////////////
592
lib_pSpawnMobj(lua_State * L)593 static int lib_pSpawnMobj(lua_State *L)
594 {
595 fixed_t x = luaL_checkfixed(L, 1);
596 fixed_t y = luaL_checkfixed(L, 2);
597 fixed_t z = luaL_checkfixed(L, 3);
598 mobjtype_t type = luaL_checkinteger(L, 4);
599 NOHUD
600 INLEVEL
601 if (type >= NUMMOBJTYPES)
602 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
603 LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ);
604 return 1;
605 }
606
lib_pSpawnMobjFromMobj(lua_State * L)607 static int lib_pSpawnMobjFromMobj(lua_State *L)
608 {
609 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
610 fixed_t x = luaL_checkfixed(L, 2);
611 fixed_t y = luaL_checkfixed(L, 3);
612 fixed_t z = luaL_checkfixed(L, 4);
613 mobjtype_t type = luaL_checkinteger(L, 5);
614 NOHUD
615 INLEVEL
616 if (!actor)
617 return LUA_ErrInvalid(L, "mobj_t");
618 if (type >= NUMMOBJTYPES)
619 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
620 LUA_PushUserdata(L, P_SpawnMobjFromMobj(actor, x, y, z, type), META_MOBJ);
621 return 1;
622 }
623
lib_pRemoveMobj(lua_State * L)624 static int lib_pRemoveMobj(lua_State *L)
625 {
626 mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
627 NOHUD
628 INLEVEL
629 if (!th)
630 return LUA_ErrInvalid(L, "mobj_t");
631 if (th->player)
632 return luaL_error(L, "Attempt to remove player mobj with P_RemoveMobj.");
633 P_RemoveMobj(th);
634 return 0;
635 }
636
637 // P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods.
638
lib_pIsValidSprite2(lua_State * L)639 static int lib_pIsValidSprite2(lua_State *L)
640 {
641 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
642 UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2);
643 //HUDSAFE
644 INLEVEL
645 if (!mobj)
646 return LUA_ErrInvalid(L, "mobj_t");
647 lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes)));
648 return 1;
649 }
650
651 // P_SpawnLockOn doesn't exist either, but we want to expose making a local mobj without encouraging hacks.
652
lib_pSpawnLockOn(lua_State * L)653 static int lib_pSpawnLockOn(lua_State *L)
654 {
655 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
656 mobj_t *lockon = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
657 statenum_t state = luaL_checkinteger(L, 3);
658 NOHUD
659 INLEVEL
660 if (!lockon)
661 return LUA_ErrInvalid(L, "mobj_t");
662 if (!player)
663 return LUA_ErrInvalid(L, "player_t");
664 if (state >= NUMSTATES)
665 return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1);
666 if (P_IsLocalPlayer(player)) // Only display it on your own view.
667 {
668 mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
669 P_SetTarget(&visual->target, lockon);
670 visual->flags2 |= MF2_DONTDRAW;
671 P_SetMobjStateNF(visual, state);
672 }
673 return 0;
674 }
675
lib_pSpawnMissile(lua_State * L)676 static int lib_pSpawnMissile(lua_State *L)
677 {
678 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
679 mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
680 mobjtype_t type = luaL_checkinteger(L, 3);
681 NOHUD
682 INLEVEL
683 if (!source || !dest)
684 return LUA_ErrInvalid(L, "mobj_t");
685 if (type >= NUMMOBJTYPES)
686 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
687 LUA_PushUserdata(L, P_SpawnMissile(source, dest, type), META_MOBJ);
688 return 1;
689 }
690
lib_pSpawnXYZMissile(lua_State * L)691 static int lib_pSpawnXYZMissile(lua_State *L)
692 {
693 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
694 mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
695 mobjtype_t type = luaL_checkinteger(L, 3);
696 fixed_t x = luaL_checkfixed(L, 4);
697 fixed_t y = luaL_checkfixed(L, 5);
698 fixed_t z = luaL_checkfixed(L, 6);
699 NOHUD
700 INLEVEL
701 if (!source || !dest)
702 return LUA_ErrInvalid(L, "mobj_t");
703 if (type >= NUMMOBJTYPES)
704 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
705 LUA_PushUserdata(L, P_SpawnXYZMissile(source, dest, type, x, y, z), META_MOBJ);
706 return 1;
707 }
708
lib_pSpawnPointMissile(lua_State * L)709 static int lib_pSpawnPointMissile(lua_State *L)
710 {
711 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
712 fixed_t xa = luaL_checkfixed(L, 2);
713 fixed_t ya = luaL_checkfixed(L, 3);
714 fixed_t za = luaL_checkfixed(L, 4);
715 mobjtype_t type = luaL_checkinteger(L, 5);
716 fixed_t x = luaL_checkfixed(L, 6);
717 fixed_t y = luaL_checkfixed(L, 7);
718 fixed_t z = luaL_checkfixed(L, 8);
719 NOHUD
720 INLEVEL
721 if (!source)
722 return LUA_ErrInvalid(L, "mobj_t");
723 if (type >= NUMMOBJTYPES)
724 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
725 LUA_PushUserdata(L, P_SpawnPointMissile(source, xa, ya, za, type, x, y, z), META_MOBJ);
726 return 1;
727 }
728
lib_pSpawnAlteredDirectionMissile(lua_State * L)729 static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
730 {
731 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
732 mobjtype_t type = luaL_checkinteger(L, 2);
733 fixed_t x = luaL_checkfixed(L, 3);
734 fixed_t y = luaL_checkfixed(L, 4);
735 fixed_t z = luaL_checkfixed(L, 5);
736 INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5);
737 NOHUD
738 INLEVEL
739 if (!source)
740 return LUA_ErrInvalid(L, "mobj_t");
741 if (type >= NUMMOBJTYPES)
742 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
743 LUA_PushUserdata(L, P_SpawnAlteredDirectionMissile(source, type, x, y, z, shiftingAngle), META_MOBJ);
744 return 1;
745 }
746
lib_pColorTeamMissile(lua_State * L)747 static int lib_pColorTeamMissile(lua_State *L)
748 {
749 mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
750 player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
751 NOHUD
752 INLEVEL
753 if (!missile)
754 return LUA_ErrInvalid(L, "mobj_t");
755 if (!source)
756 return LUA_ErrInvalid(L, "player_t");
757 P_ColorTeamMissile(missile, source);
758 return 0;
759 }
760
lib_pSPMAngle(lua_State * L)761 static int lib_pSPMAngle(lua_State *L)
762 {
763 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
764 mobjtype_t type = luaL_checkinteger(L, 2);
765 angle_t angle = luaL_checkangle(L, 3);
766 UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
767 UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
768 NOHUD
769 INLEVEL
770 if (!source)
771 return LUA_ErrInvalid(L, "mobj_t");
772 if (type >= NUMMOBJTYPES)
773 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
774 LUA_PushUserdata(L, P_SPMAngle(source, type, angle, allowaim, flags2), META_MOBJ);
775 return 1;
776 }
777
lib_pSpawnPlayerMissile(lua_State * L)778 static int lib_pSpawnPlayerMissile(lua_State *L)
779 {
780 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
781 mobjtype_t type = luaL_checkinteger(L, 2);
782 UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0);
783 NOHUD
784 INLEVEL
785 if (!source)
786 return LUA_ErrInvalid(L, "mobj_t");
787 if (type >= NUMMOBJTYPES)
788 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
789 LUA_PushUserdata(L, P_SpawnPlayerMissile(source, type, flags2), META_MOBJ);
790 return 1;
791 }
792
lib_pMobjFlip(lua_State * L)793 static int lib_pMobjFlip(lua_State *L)
794 {
795 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
796 //HUDSAFE
797 INLEVEL
798 if (!mobj)
799 return LUA_ErrInvalid(L, "mobj_t");
800 lua_pushinteger(L, P_MobjFlip(mobj));
801 return 1;
802 }
803
lib_pGetMobjGravity(lua_State * L)804 static int lib_pGetMobjGravity(lua_State *L)
805 {
806 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
807 //HUDSAFE
808 INLEVEL
809 if (!mobj)
810 return LUA_ErrInvalid(L, "mobj_t");
811 lua_pushfixed(L, P_GetMobjGravity(mobj));
812 return 1;
813 }
814
lib_pWeaponOrPanel(lua_State * L)815 static int lib_pWeaponOrPanel(lua_State *L)
816 {
817 mobjtype_t type = luaL_checkinteger(L, 1);
818 //HUDSAFE
819 if (type >= NUMMOBJTYPES)
820 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
821 lua_pushboolean(L, P_WeaponOrPanel(type));
822 return 1;
823 }
824
lib_pFlashPal(lua_State * L)825 static int lib_pFlashPal(lua_State *L)
826 {
827 player_t *pl = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
828 UINT16 type = (UINT16)luaL_checkinteger(L, 2);
829 UINT16 duration = (UINT16)luaL_checkinteger(L, 3);
830 NOHUD
831 INLEVEL
832 if (!pl)
833 return LUA_ErrInvalid(L, "player_t");
834 P_FlashPal(pl, type, duration);
835 return 0;
836 }
837
lib_pGetClosestAxis(lua_State * L)838 static int lib_pGetClosestAxis(lua_State *L)
839 {
840 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
841 //HUDSAFE
842 INLEVEL
843 if (!source)
844 return LUA_ErrInvalid(L, "mobj_t");
845 LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ);
846 return 1;
847 }
848
lib_pSpawnParaloop(lua_State * L)849 static int lib_pSpawnParaloop(lua_State *L)
850 {
851 fixed_t x = luaL_checkfixed(L, 1);
852 fixed_t y = luaL_checkfixed(L, 2);
853 fixed_t z = luaL_checkfixed(L, 3);
854 fixed_t radius = luaL_checkfixed(L, 4);
855 INT32 number = (INT32)luaL_checkinteger(L, 5);
856 mobjtype_t type = luaL_checkinteger(L, 6);
857 angle_t rotangle = luaL_checkangle(L, 7);
858 statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
859 boolean spawncenter = lua_optboolean(L, 9);
860 NOHUD
861 INLEVEL
862 if (type >= NUMMOBJTYPES)
863 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
864 if (nstate >= NUMSTATES)
865 return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1);
866 P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter);
867 return 0;
868 }
869
lib_pBossTargetPlayer(lua_State * L)870 static int lib_pBossTargetPlayer(lua_State *L)
871 {
872 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
873 boolean closest = lua_optboolean(L, 2);
874 NOHUD
875 INLEVEL
876 if (!actor)
877 return LUA_ErrInvalid(L, "mobj_t");
878 lua_pushboolean(L, P_BossTargetPlayer(actor, closest));
879 return 1;
880 }
881
lib_pSupermanLook4Players(lua_State * L)882 static int lib_pSupermanLook4Players(lua_State *L)
883 {
884 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
885 NOHUD
886 INLEVEL
887 if (!actor)
888 return LUA_ErrInvalid(L, "mobj_t");
889 lua_pushboolean(L, P_SupermanLook4Players(actor));
890 return 1;
891 }
892
lib_pSetScale(lua_State * L)893 static int lib_pSetScale(lua_State *L)
894 {
895 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
896 fixed_t newscale = luaL_checkfixed(L, 2);
897 NOHUD
898 INLEVEL
899 if (!mobj)
900 return LUA_ErrInvalid(L, "mobj_t");
901 if (newscale < FRACUNIT/100)
902 newscale = FRACUNIT/100;
903 P_SetScale(mobj, newscale);
904 return 0;
905 }
906
lib_pInsideANonSolidFFloor(lua_State * L)907 static int lib_pInsideANonSolidFFloor(lua_State *L)
908 {
909 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
910 ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
911 //HUDSAFE
912 INLEVEL
913 if (!mobj)
914 return LUA_ErrInvalid(L, "mobj_t");
915 if (!rover)
916 return LUA_ErrInvalid(L, "ffloor_t");
917 lua_pushboolean(L, P_InsideANonSolidFFloor(mobj, rover));
918 return 1;
919 }
920
lib_pCheckDeathPitCollide(lua_State * L)921 static int lib_pCheckDeathPitCollide(lua_State *L)
922 {
923 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
924 //HUDSAFE
925 INLEVEL
926 if (!mo)
927 return LUA_ErrInvalid(L, "mobj_t");
928 lua_pushboolean(L, P_CheckDeathPitCollide(mo));
929 return 1;
930 }
931
lib_pCheckSolidLava(lua_State * L)932 static int lib_pCheckSolidLava(lua_State *L)
933 {
934 ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
935 //HUDSAFE
936 INLEVEL
937 if (!rover)
938 return LUA_ErrInvalid(L, "ffloor_t");
939 lua_pushboolean(L, P_CheckSolidLava(rover));
940 return 1;
941 }
942
lib_pCanRunOnWater(lua_State * L)943 static int lib_pCanRunOnWater(lua_State *L)
944 {
945 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
946 ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
947 //HUDSAFE
948 INLEVEL
949 if (!player)
950 return LUA_ErrInvalid(L, "player_t");
951 if (!rover)
952 return LUA_ErrInvalid(L, "ffloor_t");
953 lua_pushboolean(L, P_CanRunOnWater(player, rover));
954 return 1;
955 }
956
lib_pMaceRotate(lua_State * L)957 static int lib_pMaceRotate(lua_State *L)
958 {
959 mobj_t *center = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
960 INT32 baserot = luaL_checkinteger(L, 2);
961 INT32 baseprevrot = luaL_checkinteger(L, 3);
962 NOHUD
963 INLEVEL
964 if (!center)
965 return LUA_ErrInvalid(L, "mobj_t");
966 P_MaceRotate(center, baserot, baseprevrot);
967 return 0;
968 }
969
lib_pCreateFloorSpriteSlope(lua_State * L)970 static int lib_pCreateFloorSpriteSlope(lua_State *L)
971 {
972 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
973 NOHUD
974 INLEVEL
975 if (!mobj)
976 return LUA_ErrInvalid(L, "mobj_t");
977 LUA_PushUserdata(L, (pslope_t *)P_CreateFloorSpriteSlope(mobj), META_SLOPE);
978 return 1;
979 }
980
lib_pRemoveFloorSpriteSlope(lua_State * L)981 static int lib_pRemoveFloorSpriteSlope(lua_State *L)
982 {
983 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
984 NOHUD
985 INLEVEL
986 if (!mobj)
987 return LUA_ErrInvalid(L, "mobj_t");
988 P_RemoveFloorSpriteSlope(mobj);
989 return 1;
990 }
991
lib_pRailThinker(lua_State * L)992 static int lib_pRailThinker(lua_State *L)
993 {
994 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
995 mobj_t *ptmthing = tmthing;
996 NOHUD
997 INLEVEL
998 if (!mobj)
999 return LUA_ErrInvalid(L, "mobj_t");
1000 lua_pushboolean(L, P_RailThinker(mobj));
1001 P_SetTarget(&tmthing, ptmthing);
1002 return 1;
1003 }
1004
lib_pXYMovement(lua_State * L)1005 static int lib_pXYMovement(lua_State *L)
1006 {
1007 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1008 mobj_t *ptmthing = tmthing;
1009 NOHUD
1010 INLEVEL
1011 if (!actor)
1012 return LUA_ErrInvalid(L, "mobj_t");
1013 P_XYMovement(actor);
1014 P_SetTarget(&tmthing, ptmthing);
1015 return 0;
1016 }
1017
lib_pRingXYMovement(lua_State * L)1018 static int lib_pRingXYMovement(lua_State *L)
1019 {
1020 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1021 mobj_t *ptmthing = tmthing;
1022 NOHUD
1023 INLEVEL
1024 if (!actor)
1025 return LUA_ErrInvalid(L, "mobj_t");
1026 P_RingXYMovement(actor);
1027 P_SetTarget(&tmthing, ptmthing);
1028 return 0;
1029 }
1030
lib_pSceneryXYMovement(lua_State * L)1031 static int lib_pSceneryXYMovement(lua_State *L)
1032 {
1033 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1034 mobj_t *ptmthing = tmthing;
1035 NOHUD
1036 INLEVEL
1037 if (!actor)
1038 return LUA_ErrInvalid(L, "mobj_t");
1039 P_SceneryXYMovement(actor);
1040 P_SetTarget(&tmthing, ptmthing);
1041 return 0;
1042 }
1043
lib_pZMovement(lua_State * L)1044 static int lib_pZMovement(lua_State *L)
1045 {
1046 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1047 NOHUD
1048 INLEVEL
1049 if (!actor)
1050 return LUA_ErrInvalid(L, "mobj_t");
1051 lua_pushboolean(L, P_ZMovement(actor));
1052 P_CheckPosition(actor, actor->x, actor->y);
1053 return 1;
1054 }
1055
lib_pRingZMovement(lua_State * L)1056 static int lib_pRingZMovement(lua_State *L)
1057 {
1058 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1059 NOHUD
1060 INLEVEL
1061 if (!actor)
1062 return LUA_ErrInvalid(L, "mobj_t");
1063 P_RingZMovement(actor);
1064 P_CheckPosition(actor, actor->x, actor->y);
1065 return 0;
1066 }
1067
lib_pSceneryZMovement(lua_State * L)1068 static int lib_pSceneryZMovement(lua_State *L)
1069 {
1070 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1071 NOHUD
1072 INLEVEL
1073 if (!actor)
1074 return LUA_ErrInvalid(L, "mobj_t");
1075 lua_pushboolean(L, P_SceneryZMovement(actor));
1076 P_CheckPosition(actor, actor->x, actor->y);
1077 return 1;
1078 }
1079
lib_pPlayerZMovement(lua_State * L)1080 static int lib_pPlayerZMovement(lua_State *L)
1081 {
1082 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1083 NOHUD
1084 INLEVEL
1085 if (!actor)
1086 return LUA_ErrInvalid(L, "mobj_t");
1087 P_PlayerZMovement(actor);
1088 P_CheckPosition(actor, actor->x, actor->y);
1089 return 0;
1090 }
1091
1092 // P_USER
1093 ////////////
1094
lib_pGetPlayerHeight(lua_State * L)1095 static int lib_pGetPlayerHeight(lua_State *L)
1096 {
1097 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1098 //HUDSAFE
1099 INLEVEL
1100 if (!player)
1101 return LUA_ErrInvalid(L, "player_t");
1102 lua_pushfixed(L, P_GetPlayerHeight(player));
1103 return 1;
1104 }
1105
lib_pGetPlayerSpinHeight(lua_State * L)1106 static int lib_pGetPlayerSpinHeight(lua_State *L)
1107 {
1108 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1109 //HUDSAFE
1110 INLEVEL
1111 if (!player)
1112 return LUA_ErrInvalid(L, "player_t");
1113 lua_pushfixed(L, P_GetPlayerSpinHeight(player));
1114 return 1;
1115 }
1116
lib_pGetPlayerControlDirection(lua_State * L)1117 static int lib_pGetPlayerControlDirection(lua_State *L)
1118 {
1119 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1120 //HUDSAFE
1121 INLEVEL
1122 if (!player)
1123 return LUA_ErrInvalid(L, "player_t");
1124 lua_pushinteger(L, P_GetPlayerControlDirection(player));
1125 return 1;
1126 }
1127
lib_pAddPlayerScore(lua_State * L)1128 static int lib_pAddPlayerScore(lua_State *L)
1129 {
1130 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1131 UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
1132 NOHUD
1133 INLEVEL
1134 if (!player)
1135 return LUA_ErrInvalid(L, "player_t");
1136 P_AddPlayerScore(player, amount);
1137 return 0;
1138 }
1139
lib_pStealPlayerScore(lua_State * L)1140 static int lib_pStealPlayerScore(lua_State *L)
1141 {
1142 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1143 UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
1144 NOHUD
1145 INLEVEL
1146 if (!player)
1147 return LUA_ErrInvalid(L, "player_t");
1148 P_StealPlayerScore(player, amount);
1149 return 0;
1150 }
1151
lib_pGetJumpFlags(lua_State * L)1152 static int lib_pGetJumpFlags(lua_State *L)
1153 {
1154 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1155 NOHUD
1156 INLEVEL
1157 if (!player)
1158 return LUA_ErrInvalid(L, "player_t");
1159 lua_pushinteger(L, P_GetJumpFlags(player));
1160 return 1;
1161 }
1162
lib_pPlayerInPain(lua_State * L)1163 static int lib_pPlayerInPain(lua_State *L)
1164 {
1165 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1166 //HUDSAFE
1167 INLEVEL
1168 if (!player)
1169 return LUA_ErrInvalid(L, "player_t");
1170 lua_pushboolean(L, P_PlayerInPain(player));
1171 return 1;
1172 }
1173
lib_pDoPlayerPain(lua_State * L)1174 static int lib_pDoPlayerPain(lua_State *L)
1175 {
1176 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1177 mobj_t *source = NULL, *inflictor = NULL;
1178 NOHUD
1179 INLEVEL
1180 if (!player)
1181 return LUA_ErrInvalid(L, "player_t");
1182 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
1183 source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1184 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
1185 inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
1186 P_DoPlayerPain(player, source, inflictor);
1187 return 0;
1188 }
1189
lib_pResetPlayer(lua_State * L)1190 static int lib_pResetPlayer(lua_State *L)
1191 {
1192 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1193 NOHUD
1194 INLEVEL
1195 if (!player)
1196 return LUA_ErrInvalid(L, "player_t");
1197 P_ResetPlayer(player);
1198 return 0;
1199 }
1200
lib_pPlayerCanDamage(lua_State * L)1201 static int lib_pPlayerCanDamage(lua_State *L)
1202 {
1203 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1204 mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1205 NOHUD // was hud safe but then i added a lua hook
1206 INLEVEL
1207 if (!player)
1208 return LUA_ErrInvalid(L, "player_t");
1209 if (!thing)
1210 return LUA_ErrInvalid(L, "mobj_t");
1211 lua_pushboolean(L, P_PlayerCanDamage(player, thing));
1212 return 1;
1213 }
1214
lib_pPlayerFullbright(lua_State * L)1215 static int lib_pPlayerFullbright(lua_State *L)
1216 {
1217 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1218 INLEVEL
1219 if (!player)
1220 return LUA_ErrInvalid(L, "player_t");
1221 lua_pushboolean(L, P_PlayerFullbright(player));
1222 return 1;
1223 }
1224
1225
lib_pIsObjectInGoop(lua_State * L)1226 static int lib_pIsObjectInGoop(lua_State *L)
1227 {
1228 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1229 //HUDSAFE
1230 INLEVEL
1231 if (!mo)
1232 return LUA_ErrInvalid(L, "mobj_t");
1233 lua_pushboolean(L, P_IsObjectInGoop(mo));
1234 return 1;
1235 }
1236
lib_pIsObjectOnGround(lua_State * L)1237 static int lib_pIsObjectOnGround(lua_State *L)
1238 {
1239 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1240 //HUDSAFE
1241 INLEVEL
1242 if (!mo)
1243 return LUA_ErrInvalid(L, "mobj_t");
1244 lua_pushboolean(L, P_IsObjectOnGround(mo));
1245 return 1;
1246 }
1247
lib_pInSpaceSector(lua_State * L)1248 static int lib_pInSpaceSector(lua_State *L)
1249 {
1250 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1251 //HUDSAFE
1252 INLEVEL
1253 if (!mo)
1254 return LUA_ErrInvalid(L, "mobj_t");
1255 lua_pushboolean(L, P_InSpaceSector(mo));
1256 return 1;
1257 }
1258
lib_pInQuicksand(lua_State * L)1259 static int lib_pInQuicksand(lua_State *L)
1260 {
1261 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1262 //HUDSAFE
1263 INLEVEL
1264 if (!mo)
1265 return LUA_ErrInvalid(L, "mobj_t");
1266 lua_pushboolean(L, P_InQuicksand(mo));
1267 return 1;
1268 }
1269
lib_pSetObjectMomZ(lua_State * L)1270 static int lib_pSetObjectMomZ(lua_State *L)
1271 {
1272 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1273 fixed_t value = luaL_checkfixed(L, 2);
1274 boolean relative = lua_optboolean(L, 3);
1275 NOHUD
1276 INLEVEL
1277 if (!mo)
1278 return LUA_ErrInvalid(L, "mobj_t");
1279 P_SetObjectMomZ(mo, value, relative);
1280 return 0;
1281 }
1282
lib_pPlayJingle(lua_State * L)1283 static int lib_pPlayJingle(lua_State *L)
1284 {
1285 player_t *player = NULL;
1286 jingletype_t jingletype = luaL_checkinteger(L, 2);
1287 //NOHUD
1288 //INLEVEL
1289 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
1290 {
1291 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1292 if (!player)
1293 return LUA_ErrInvalid(L, "player_t");
1294 }
1295 if (jingletype >= NUMJINGLES)
1296 return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1);
1297 P_PlayJingle(player, jingletype);
1298 return 0;
1299 }
1300
lib_pPlayJingleMusic(lua_State * L)1301 static int lib_pPlayJingleMusic(lua_State *L)
1302 {
1303 player_t *player = NULL;
1304 const char *musnamearg = luaL_checkstring(L, 2);
1305 char musname[7], *p = musname;
1306 UINT16 musflags = luaL_optinteger(L, 3, 0);
1307 boolean looping = lua_opttrueboolean(L, 4);
1308 jingletype_t jingletype = luaL_optinteger(L, 5, JT_OTHER);
1309 //NOHUD
1310 //INLEVEL
1311 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
1312 {
1313 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1314 if (!player)
1315 return LUA_ErrInvalid(L, "player_t");
1316 }
1317 if (jingletype >= NUMJINGLES)
1318 return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1);
1319
1320 musname[6] = '\0';
1321 strncpy(musname, musnamearg, 6);
1322
1323 while (*p) {
1324 *p = tolower(*p);
1325 ++p;
1326 }
1327
1328 P_PlayJingleMusic(player, musname, musflags, looping, jingletype);
1329 return 0;
1330 }
1331
lib_pRestoreMusic(lua_State * L)1332 static int lib_pRestoreMusic(lua_State *L)
1333 {
1334 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1335 //NOHUD
1336 //INLEVEL
1337 if (!player)
1338 return LUA_ErrInvalid(L, "player_t");
1339 if (P_IsLocalPlayer(player))
1340 P_RestoreMusic(player);
1341 return 0;
1342 }
1343
lib_pSpawnShieldOrb(lua_State * L)1344 static int lib_pSpawnShieldOrb(lua_State *L)
1345 {
1346 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1347 NOHUD
1348 INLEVEL
1349 if (!player)
1350 return LUA_ErrInvalid(L, "player_t");
1351 P_SpawnShieldOrb(player);
1352 return 0;
1353 }
1354
lib_pSpawnGhostMobj(lua_State * L)1355 static int lib_pSpawnGhostMobj(lua_State *L)
1356 {
1357 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1358 NOHUD
1359 INLEVEL
1360 if (!mobj)
1361 return LUA_ErrInvalid(L, "mobj_t");
1362 LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ);
1363 return 1;
1364 }
1365
lib_pGivePlayerRings(lua_State * L)1366 static int lib_pGivePlayerRings(lua_State *L)
1367 {
1368 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1369 INT32 num_rings = (INT32)luaL_checkinteger(L, 2);
1370 NOHUD
1371 INLEVEL
1372 if (!player)
1373 return LUA_ErrInvalid(L, "player_t");
1374 P_GivePlayerRings(player, num_rings);
1375 return 0;
1376 }
1377
lib_pGivePlayerLives(lua_State * L)1378 static int lib_pGivePlayerLives(lua_State *L)
1379 {
1380 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1381 INT32 numlives = (INT32)luaL_checkinteger(L, 2);
1382 NOHUD
1383 INLEVEL
1384 if (!player)
1385 return LUA_ErrInvalid(L, "player_t");
1386 P_GivePlayerLives(player, numlives);
1387 return 0;
1388 }
1389
lib_pGiveCoopLives(lua_State * L)1390 static int lib_pGiveCoopLives(lua_State *L)
1391 {
1392 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1393 INT32 numlives = (INT32)luaL_checkinteger(L, 2);
1394 boolean sound = (boolean)lua_opttrueboolean(L, 3);
1395 NOHUD
1396 INLEVEL
1397 if (!player)
1398 return LUA_ErrInvalid(L, "player_t");
1399 P_GiveCoopLives(player, numlives, sound);
1400 return 0;
1401 }
1402
lib_pResetScore(lua_State * L)1403 static int lib_pResetScore(lua_State *L)
1404 {
1405 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1406 NOHUD
1407 INLEVEL
1408 if (!player)
1409 return LUA_ErrInvalid(L, "player_t");
1410 P_ResetScore(player);
1411 return 0;
1412 }
1413
lib_pDoJumpShield(lua_State * L)1414 static int lib_pDoJumpShield(lua_State *L)
1415 {
1416 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1417 NOHUD
1418 INLEVEL
1419 if (!player)
1420 return LUA_ErrInvalid(L, "player_t");
1421 P_DoJumpShield(player);
1422 return 0;
1423 }
1424
lib_pDoBubbleBounce(lua_State * L)1425 static int lib_pDoBubbleBounce(lua_State *L)
1426 {
1427 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1428 NOHUD
1429 INLEVEL
1430 if (!player)
1431 return LUA_ErrInvalid(L, "player_t");
1432 P_DoBubbleBounce(player);
1433 return 0;
1434 }
1435
lib_pBlackOw(lua_State * L)1436 static int lib_pBlackOw(lua_State *L)
1437 {
1438 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1439 NOHUD
1440 INLEVEL
1441 if (!player)
1442 return LUA_ErrInvalid(L, "player_t");
1443 P_BlackOw(player);
1444 return 0;
1445 }
1446
lib_pElementalFire(lua_State * L)1447 static int lib_pElementalFire(lua_State *L)
1448 {
1449 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1450 boolean cropcircle = lua_optboolean(L, 2);
1451 NOHUD
1452 INLEVEL
1453 if (!player)
1454 return LUA_ErrInvalid(L, "player_t");
1455 P_ElementalFire(player, cropcircle);
1456 return 0;
1457 }
1458
lib_pSpawnSkidDust(lua_State * L)1459 static int lib_pSpawnSkidDust(lua_State *L)
1460 {
1461 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1462 fixed_t radius = luaL_checkfixed(L, 2);
1463 boolean sound = lua_optboolean(L, 3);
1464 NOHUD
1465 INLEVEL
1466 if (!player)
1467 return LUA_ErrInvalid(L, "player_t");
1468 P_SpawnSkidDust(player, radius, sound);
1469 return 0;
1470 }
1471
lib_pMovePlayer(lua_State * L)1472 static int lib_pMovePlayer(lua_State *L)
1473 {
1474 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1475 NOHUD
1476 INLEVEL
1477 if (!player)
1478 return LUA_ErrInvalid(L, "player_t");
1479 P_MovePlayer(player);
1480 return 0;
1481 }
1482
lib_pDoPlayerFinish(lua_State * L)1483 static int lib_pDoPlayerFinish(lua_State *L)
1484 {
1485 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1486 NOHUD
1487 INLEVEL
1488 if (!player)
1489 return LUA_ErrInvalid(L, "player_t");
1490 P_DoPlayerFinish(player);
1491 return 0;
1492 }
1493
lib_pDoPlayerExit(lua_State * L)1494 static int lib_pDoPlayerExit(lua_State *L)
1495 {
1496 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1497 NOHUD
1498 INLEVEL
1499 if (!player)
1500 return LUA_ErrInvalid(L, "player_t");
1501 P_DoPlayerExit(player);
1502 return 0;
1503 }
1504
lib_pInstaThrust(lua_State * L)1505 static int lib_pInstaThrust(lua_State *L)
1506 {
1507 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1508 angle_t angle = luaL_checkangle(L, 2);
1509 fixed_t move = luaL_checkfixed(L, 3);
1510 NOHUD
1511 INLEVEL
1512 if (!mo)
1513 return LUA_ErrInvalid(L, "mobj_t");
1514 P_InstaThrust(mo, angle, move);
1515 return 0;
1516 }
1517
lib_pReturnThrustX(lua_State * L)1518 static int lib_pReturnThrustX(lua_State *L)
1519 {
1520 angle_t angle;
1521 fixed_t move;
1522 if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
1523 lua_remove(L, 1); // ignore mobj as arg1
1524 angle = luaL_checkangle(L, 1);
1525 move = luaL_checkfixed(L, 2);
1526 //HUDSAFE
1527 lua_pushfixed(L, P_ReturnThrustX(NULL, angle, move));
1528 return 1;
1529 }
1530
lib_pReturnThrustY(lua_State * L)1531 static int lib_pReturnThrustY(lua_State *L)
1532 {
1533 angle_t angle;
1534 fixed_t move;
1535 if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
1536 lua_remove(L, 1); // ignore mobj as arg1
1537 angle = luaL_checkangle(L, 1);
1538 move = luaL_checkfixed(L, 2);
1539 //HUDSAFE
1540 lua_pushfixed(L, P_ReturnThrustY(NULL, angle, move));
1541 return 1;
1542 }
1543
lib_pLookForEnemies(lua_State * L)1544 static int lib_pLookForEnemies(lua_State *L)
1545 {
1546 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1547 boolean nonenemies = lua_opttrueboolean(L, 2);
1548 boolean bullet = lua_optboolean(L, 3);
1549 NOHUD
1550 INLEVEL
1551 if (!player)
1552 return LUA_ErrInvalid(L, "player_t");
1553 LUA_PushUserdata(L, P_LookForEnemies(player, nonenemies, bullet), META_MOBJ);
1554 return 1;
1555 }
1556
lib_pNukeEnemies(lua_State * L)1557 static int lib_pNukeEnemies(lua_State *L)
1558 {
1559 mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1560 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1561 fixed_t radius = luaL_checkfixed(L, 3);
1562 NOHUD
1563 INLEVEL
1564 if (!inflictor || !source)
1565 return LUA_ErrInvalid(L, "mobj_t");
1566 P_NukeEnemies(inflictor, source, radius);
1567 return 0;
1568 }
1569
lib_pEarthquake(lua_State * L)1570 static int lib_pEarthquake(lua_State *L)
1571 {
1572 mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1573 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1574 fixed_t radius = luaL_checkfixed(L, 3);
1575 NOHUD
1576 INLEVEL
1577 if (!inflictor || !source)
1578 return LUA_ErrInvalid(L, "mobj_t");
1579 P_Earthquake(inflictor, source, radius);
1580 return 0;
1581 }
1582
lib_pHomingAttack(lua_State * L)1583 static int lib_pHomingAttack(lua_State *L)
1584 {
1585 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1586 mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1587 NOHUD
1588 INLEVEL
1589 if (!source || !enemy)
1590 return LUA_ErrInvalid(L, "mobj_t");
1591 lua_pushboolean(L, P_HomingAttack(source, enemy));
1592 return 1;
1593 }
1594
lib_pSuperReady(lua_State * L)1595 static int lib_pSuperReady(lua_State *L)
1596 {
1597 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1598 //HUDSAFE
1599 INLEVEL
1600 if (!player)
1601 return LUA_ErrInvalid(L, "player_t");
1602 lua_pushboolean(L, P_SuperReady(player));
1603 return 1;
1604 }
1605
lib_pDoJump(lua_State * L)1606 static int lib_pDoJump(lua_State *L)
1607 {
1608 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1609 boolean soundandstate = (boolean)lua_opttrueboolean(L, 2);
1610 NOHUD
1611 INLEVEL
1612 if (!player)
1613 return LUA_ErrInvalid(L, "player_t");
1614 P_DoJump(player, soundandstate);
1615 return 0;
1616 }
1617
lib_pSpawnThokMobj(lua_State * L)1618 static int lib_pSpawnThokMobj(lua_State *L)
1619 {
1620 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1621 NOHUD
1622 INLEVEL
1623 if (!player)
1624 return LUA_ErrInvalid(L, "player_t");
1625 P_SpawnThokMobj(player);
1626 return 0;
1627 }
1628
lib_pSpawnSpinMobj(lua_State * L)1629 static int lib_pSpawnSpinMobj(lua_State *L)
1630 {
1631 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1632 mobjtype_t type = luaL_checkinteger(L, 2);
1633 NOHUD
1634 INLEVEL
1635 if (!player)
1636 return LUA_ErrInvalid(L, "player_t");
1637 if (type >= NUMMOBJTYPES)
1638 return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
1639 P_SpawnSpinMobj(player, type);
1640 return 0;
1641 }
1642
lib_pTelekinesis(lua_State * L)1643 static int lib_pTelekinesis(lua_State *L)
1644 {
1645 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1646 fixed_t thrust = luaL_checkfixed(L, 2);
1647 fixed_t range = luaL_checkfixed(L, 3);
1648 NOHUD
1649 INLEVEL
1650 if (!player)
1651 return LUA_ErrInvalid(L, "player_t");
1652 P_Telekinesis(player, thrust, range);
1653 return 0;
1654 }
1655
lib_pSwitchShield(lua_State * L)1656 static int lib_pSwitchShield(lua_State *L)
1657 {
1658 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1659 UINT16 shield = luaL_checkinteger(L, 2);
1660 NOHUD
1661 INLEVEL
1662 if (!player)
1663 return LUA_ErrInvalid(L, "player_t");
1664 P_SwitchShield(player, shield);
1665 return 0;
1666 }
1667
lib_pPlayerCanEnterSpinGaps(lua_State * L)1668 static int lib_pPlayerCanEnterSpinGaps(lua_State *L)
1669 {
1670 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1671 INLEVEL
1672 if (!player)
1673 return LUA_ErrInvalid(L, "player_t");
1674 lua_pushboolean(L, P_PlayerCanEnterSpinGaps(player));
1675 return 1;
1676 }
1677
lib_pPlayerShouldUseSpinHeight(lua_State * L)1678 static int lib_pPlayerShouldUseSpinHeight(lua_State *L)
1679 {
1680 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1681 INLEVEL
1682 if (!player)
1683 return LUA_ErrInvalid(L, "player_t");
1684 lua_pushboolean(L, P_PlayerShouldUseSpinHeight(player));
1685 return 1;
1686 }
1687
1688 // P_MAP
1689 ///////////
1690
lib_pCheckPosition(lua_State * L)1691 static int lib_pCheckPosition(lua_State *L)
1692 {
1693 mobj_t *ptmthing = tmthing;
1694 mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1695 fixed_t x = luaL_checkfixed(L, 2);
1696 fixed_t y = luaL_checkfixed(L, 3);
1697 NOHUD
1698 INLEVEL
1699 if (!thing)
1700 return LUA_ErrInvalid(L, "mobj_t");
1701 lua_pushboolean(L, P_CheckPosition(thing, x, y));
1702 LUA_PushUserdata(L, tmthing, META_MOBJ);
1703 P_SetTarget(&tmthing, ptmthing);
1704 return 2;
1705 }
1706
lib_pTryMove(lua_State * L)1707 static int lib_pTryMove(lua_State *L)
1708 {
1709 mobj_t *ptmthing = tmthing;
1710 mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1711 fixed_t x = luaL_checkfixed(L, 2);
1712 fixed_t y = luaL_checkfixed(L, 3);
1713 boolean allowdropoff = lua_optboolean(L, 4);
1714 NOHUD
1715 INLEVEL
1716 if (!thing)
1717 return LUA_ErrInvalid(L, "mobj_t");
1718 lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff));
1719 LUA_PushUserdata(L, tmthing, META_MOBJ);
1720 P_SetTarget(&tmthing, ptmthing);
1721 return 2;
1722 }
1723
lib_pMove(lua_State * L)1724 static int lib_pMove(lua_State *L)
1725 {
1726 mobj_t *ptmthing = tmthing;
1727 mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1728 fixed_t speed = luaL_checkfixed(L, 2);
1729 NOHUD
1730 INLEVEL
1731 if (!actor)
1732 return LUA_ErrInvalid(L, "mobj_t");
1733 lua_pushboolean(L, P_Move(actor, speed));
1734 LUA_PushUserdata(L, tmthing, META_MOBJ);
1735 P_SetTarget(&tmthing, ptmthing);
1736 return 2;
1737 }
1738
lib_pTeleportMove(lua_State * L)1739 static int lib_pTeleportMove(lua_State *L)
1740 {
1741 mobj_t *ptmthing = tmthing;
1742 mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1743 fixed_t x = luaL_checkfixed(L, 2);
1744 fixed_t y = luaL_checkfixed(L, 3);
1745 fixed_t z = luaL_checkfixed(L, 4);
1746 NOHUD
1747 INLEVEL
1748 if (!thing)
1749 return LUA_ErrInvalid(L, "mobj_t");
1750 lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
1751 LUA_PushUserdata(L, tmthing, META_MOBJ);
1752 P_SetTarget(&tmthing, ptmthing);
1753 return 2;
1754 }
1755
lib_pSlideMove(lua_State * L)1756 static int lib_pSlideMove(lua_State *L)
1757 {
1758 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1759 NOHUD
1760 INLEVEL
1761 if (!mo)
1762 return LUA_ErrInvalid(L, "mobj_t");
1763 P_SlideMove(mo);
1764 return 0;
1765 }
1766
lib_pBounceMove(lua_State * L)1767 static int lib_pBounceMove(lua_State *L)
1768 {
1769 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1770 NOHUD
1771 INLEVEL
1772 if (!mo)
1773 return LUA_ErrInvalid(L, "mobj_t");
1774 P_BounceMove(mo);
1775 return 0;
1776 }
1777
lib_pCheckSight(lua_State * L)1778 static int lib_pCheckSight(lua_State *L)
1779 {
1780 mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1781 mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1782 //HUDSAFE?
1783 INLEVEL
1784 if (!t1 || !t2)
1785 return LUA_ErrInvalid(L, "mobj_t");
1786 lua_pushboolean(L, P_CheckSight(t1, t2));
1787 return 1;
1788 }
1789
lib_pCheckHoopPosition(lua_State * L)1790 static int lib_pCheckHoopPosition(lua_State *L)
1791 {
1792 mobj_t *hoopthing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1793 fixed_t x = luaL_checkfixed(L, 2);
1794 fixed_t y = luaL_checkfixed(L, 3);
1795 fixed_t z = luaL_checkfixed(L, 4);
1796 fixed_t radius = luaL_checkfixed(L, 5);
1797 NOHUD
1798 INLEVEL
1799 if (!hoopthing)
1800 return LUA_ErrInvalid(L, "mobj_t");
1801 P_CheckHoopPosition(hoopthing, x, y, z, radius);
1802 return 0;
1803 }
1804
lib_pRadiusAttack(lua_State * L)1805 static int lib_pRadiusAttack(lua_State *L)
1806 {
1807 mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1808 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1809 fixed_t damagedist = luaL_checkfixed(L, 3);
1810 UINT8 damagetype = luaL_optinteger(L, 4, 0);
1811 boolean sightcheck = lua_opttrueboolean(L, 5);
1812 NOHUD
1813 INLEVEL
1814 if (!spot || !source)
1815 return LUA_ErrInvalid(L, "mobj_t");
1816 P_RadiusAttack(spot, source, damagedist, damagetype, sightcheck);
1817 return 0;
1818 }
1819
lib_pFloorzAtPos(lua_State * L)1820 static int lib_pFloorzAtPos(lua_State *L)
1821 {
1822 fixed_t x = luaL_checkfixed(L, 1);
1823 fixed_t y = luaL_checkfixed(L, 2);
1824 fixed_t z = luaL_checkfixed(L, 3);
1825 fixed_t height = luaL_checkfixed(L, 4);
1826 //HUDSAFE
1827 INLEVEL
1828 lua_pushfixed(L, P_FloorzAtPos(x, y, z, height));
1829 return 1;
1830 }
1831
lib_pCeilingzAtPos(lua_State * L)1832 static int lib_pCeilingzAtPos(lua_State *L)
1833 {
1834 fixed_t x = luaL_checkfixed(L, 1);
1835 fixed_t y = luaL_checkfixed(L, 2);
1836 fixed_t z = luaL_checkfixed(L, 3);
1837 fixed_t height = luaL_checkfixed(L, 4);
1838 //HUDSAFE
1839 INLEVEL
1840 lua_pushfixed(L, P_CeilingzAtPos(x, y, z, height));
1841 return 1;
1842 }
1843
lib_pDoSpring(lua_State * L)1844 static int lib_pDoSpring(lua_State *L)
1845 {
1846 mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1847 mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1848 NOHUD
1849 INLEVEL
1850 if (!spring || !object)
1851 return LUA_ErrInvalid(L, "mobj_t");
1852 lua_pushboolean(L, P_DoSpring(spring, object));
1853 return 1;
1854 }
1855
1856 // P_INTER
1857 ////////////
1858
lib_pRemoveShield(lua_State * L)1859 static int lib_pRemoveShield(lua_State *L)
1860 {
1861 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1862 NOHUD
1863 INLEVEL
1864 if (!player)
1865 return LUA_ErrInvalid(L, "player_t");
1866 P_RemoveShield(player);
1867 return 0;
1868 }
1869
lib_pDamageMobj(lua_State * L)1870 static int lib_pDamageMobj(lua_State *L)
1871 {
1872 mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
1873 INT32 damage;
1874 UINT8 damagetype;
1875 NOHUD
1876 INLEVEL
1877 if (!target)
1878 return LUA_ErrInvalid(L, "mobj_t");
1879 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
1880 inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1881 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
1882 source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
1883 damage = (INT32)luaL_optinteger(L, 4, 1);
1884 damagetype = (UINT8)luaL_optinteger(L, 5, 0);
1885 lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage, damagetype));
1886 return 1;
1887 }
1888
lib_pKillMobj(lua_State * L)1889 static int lib_pKillMobj(lua_State *L)
1890 {
1891 mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
1892 UINT8 damagetype;
1893 NOHUD
1894 INLEVEL
1895 if (!target)
1896 return LUA_ErrInvalid(L, "mobj_t");
1897 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
1898 inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
1899 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
1900 source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
1901 damagetype = (UINT8)luaL_optinteger(L, 4, 0);
1902 P_KillMobj(target, inflictor, source, damagetype);
1903 return 0;
1904 }
1905
lib_pPlayerRingBurst(lua_State * L)1906 static int lib_pPlayerRingBurst(lua_State *L)
1907 {
1908 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1909 INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1);
1910 NOHUD
1911 INLEVEL
1912 if (!player)
1913 return LUA_ErrInvalid(L, "player_t");
1914 if (num_rings == -1)
1915 num_rings = player->rings;
1916 P_PlayerRingBurst(player, num_rings);
1917 return 0;
1918 }
1919
lib_pPlayerWeaponPanelBurst(lua_State * L)1920 static int lib_pPlayerWeaponPanelBurst(lua_State *L)
1921 {
1922 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1923 NOHUD
1924 INLEVEL
1925 if (!player)
1926 return LUA_ErrInvalid(L, "player_t");
1927 P_PlayerWeaponPanelBurst(player);
1928 return 0;
1929 }
1930
lib_pPlayerWeaponAmmoBurst(lua_State * L)1931 static int lib_pPlayerWeaponAmmoBurst(lua_State *L)
1932 {
1933 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1934 NOHUD
1935 INLEVEL
1936 if (!player)
1937 return LUA_ErrInvalid(L, "player_t");
1938 P_PlayerWeaponAmmoBurst(player);
1939 return 0;
1940 }
1941
lib_pPlayerWeaponPanelOrAmmoBurst(lua_State * L)1942 static int lib_pPlayerWeaponPanelOrAmmoBurst(lua_State *L)
1943 {
1944 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1945 NOHUD
1946 INLEVEL
1947 if (!player)
1948 return LUA_ErrInvalid(L, "player_t");
1949 P_PlayerWeaponPanelOrAmmoBurst(player);
1950 return 0;
1951 }
1952
lib_pPlayerEmeraldBurst(lua_State * L)1953 static int lib_pPlayerEmeraldBurst(lua_State *L)
1954 {
1955 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1956 boolean toss = lua_optboolean(L, 2);
1957 NOHUD
1958 INLEVEL
1959 if (!player)
1960 return LUA_ErrInvalid(L, "player_t");
1961 P_PlayerEmeraldBurst(player, toss);
1962 return 0;
1963 }
1964
lib_pPlayerFlagBurst(lua_State * L)1965 static int lib_pPlayerFlagBurst(lua_State *L)
1966 {
1967 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
1968 boolean toss = lua_optboolean(L, 2);
1969 NOHUD
1970 INLEVEL
1971 if (!player)
1972 return LUA_ErrInvalid(L, "player_t");
1973 P_PlayerFlagBurst(player, toss);
1974 return 0;
1975 }
1976
lib_pPlayRinglossSound(lua_State * L)1977 static int lib_pPlayRinglossSound(lua_State *L)
1978 {
1979 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1980 player_t *player = NULL;
1981 NOHUD
1982 INLEVEL
1983 if (!source)
1984 return LUA_ErrInvalid(L, "mobj_t");
1985 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
1986 {
1987 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
1988 if (!player)
1989 return LUA_ErrInvalid(L, "player_t");
1990 }
1991 if (!player || P_IsLocalPlayer(player))
1992 P_PlayRinglossSound(source);
1993 return 0;
1994 }
1995
lib_pPlayDeathSound(lua_State * L)1996 static int lib_pPlayDeathSound(lua_State *L)
1997 {
1998 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
1999 player_t *player = NULL;
2000 NOHUD
2001 INLEVEL
2002 if (!source)
2003 return LUA_ErrInvalid(L, "mobj_t");
2004 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
2005 {
2006 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2007 if (!player)
2008 return LUA_ErrInvalid(L, "player_t");
2009 }
2010 if (!player || P_IsLocalPlayer(player))
2011 P_PlayDeathSound(source);
2012 return 0;
2013 }
2014
lib_pPlayVictorySound(lua_State * L)2015 static int lib_pPlayVictorySound(lua_State *L)
2016 {
2017 mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2018 player_t *player = NULL;
2019 NOHUD
2020 INLEVEL
2021 if (!source)
2022 return LUA_ErrInvalid(L, "mobj_t");
2023 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
2024 {
2025 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2026 if (!player)
2027 return LUA_ErrInvalid(L, "player_t");
2028 }
2029 if (!player || P_IsLocalPlayer(player))
2030 P_PlayVictorySound(source);
2031 return 0;
2032 }
2033
lib_pPlayLivesJingle(lua_State * L)2034 static int lib_pPlayLivesJingle(lua_State *L)
2035 {
2036 player_t *player = NULL;
2037 //NOHUD
2038 //INLEVEL
2039 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
2040 {
2041 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2042 if (!player)
2043 return LUA_ErrInvalid(L, "player_t");
2044 }
2045 P_PlayLivesJingle(player);
2046 return 0;
2047 }
2048
lib_pCanPickupItem(lua_State * L)2049 static int lib_pCanPickupItem(lua_State *L)
2050 {
2051 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2052 boolean weapon = lua_optboolean(L, 2);
2053 //HUDSAFE
2054 INLEVEL
2055 if (!player)
2056 return LUA_ErrInvalid(L, "player_t");
2057 lua_pushboolean(L, P_CanPickupItem(player, weapon));
2058 return 1;
2059 }
2060
lib_pDoNightsScore(lua_State * L)2061 static int lib_pDoNightsScore(lua_State *L)
2062 {
2063 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2064 NOHUD
2065 INLEVEL
2066 if (!player)
2067 return LUA_ErrInvalid(L, "player_t");
2068 P_DoNightsScore(player);
2069 return 0;
2070 }
2071
lib_pDoMatchSuper(lua_State * L)2072 static int lib_pDoMatchSuper(lua_State *L)
2073 {
2074 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2075 NOHUD
2076 INLEVEL
2077 if (!player)
2078 return LUA_ErrInvalid(L, "player_t");
2079 P_DoMatchSuper(player);
2080 return 0;
2081 }
2082
2083 // P_SPEC
2084 ////////////
2085
lib_pThrust(lua_State * L)2086 static int lib_pThrust(lua_State *L)
2087 {
2088 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2089 angle_t angle = luaL_checkangle(L, 2);
2090 fixed_t move = luaL_checkfixed(L, 3);
2091 NOHUD
2092 INLEVEL
2093 if (!mo)
2094 return LUA_ErrInvalid(L, "mobj_t");
2095 P_Thrust(mo, angle, move);
2096 return 0;
2097 }
2098
lib_pSetMobjStateNF(lua_State * L)2099 static int lib_pSetMobjStateNF(lua_State *L)
2100 {
2101 mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2102 statenum_t state = luaL_checkinteger(L, 2);
2103 NOHUD
2104 INLEVEL
2105 if (!mobj)
2106 return LUA_ErrInvalid(L, "mobj_t");
2107 if (state >= NUMSTATES)
2108 return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1);
2109 if (mobj->player && state == S_NULL)
2110 return luaL_error(L, "Attempt to remove player mobj with S_NULL.");
2111 lua_pushboolean(L, P_SetMobjStateNF(mobj, state));
2112 return 1;
2113 }
2114
lib_pDoSuperTransformation(lua_State * L)2115 static int lib_pDoSuperTransformation(lua_State *L)
2116 {
2117 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2118 boolean giverings = lua_optboolean(L, 2);
2119 NOHUD
2120 INLEVEL
2121 if (!player)
2122 return LUA_ErrInvalid(L, "player_t");
2123 P_DoSuperTransformation(player, giverings);
2124 return 0;
2125 }
2126
lib_pExplodeMissile(lua_State * L)2127 static int lib_pExplodeMissile(lua_State *L)
2128 {
2129 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2130 NOHUD
2131 INLEVEL
2132 if (!mo)
2133 return LUA_ErrInvalid(L, "mobj_t");
2134 P_ExplodeMissile(mo);
2135 return 0;
2136 }
2137
lib_pPlayerTouchingSectorSpecial(lua_State * L)2138 static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
2139 {
2140 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2141 INT32 section = (INT32)luaL_checkinteger(L, 2);
2142 INT32 number = (INT32)luaL_checkinteger(L, 3);
2143 //HUDSAFE
2144 INLEVEL
2145 if (!player)
2146 return LUA_ErrInvalid(L, "player_t");
2147 LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR);
2148 return 1;
2149 }
2150
lib_pFindLowestFloorSurrounding(lua_State * L)2151 static int lib_pFindLowestFloorSurrounding(lua_State *L)
2152 {
2153 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2154 //HUDSAFE
2155 INLEVEL
2156 if (!sector)
2157 return LUA_ErrInvalid(L, "sector_t");
2158 lua_pushfixed(L, P_FindLowestFloorSurrounding(sector));
2159 return 1;
2160 }
2161
lib_pFindHighestFloorSurrounding(lua_State * L)2162 static int lib_pFindHighestFloorSurrounding(lua_State *L)
2163 {
2164 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2165 //HUDSAFE
2166 INLEVEL
2167 if (!sector)
2168 return LUA_ErrInvalid(L, "sector_t");
2169 lua_pushfixed(L, P_FindHighestFloorSurrounding(sector));
2170 return 1;
2171 }
2172
lib_pFindNextHighestFloor(lua_State * L)2173 static int lib_pFindNextHighestFloor(lua_State *L)
2174 {
2175 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2176 fixed_t currentheight;
2177 //HUDSAFE
2178 INLEVEL
2179 if (!sector)
2180 return LUA_ErrInvalid(L, "sector_t");
2181 // defaults to floorheight of sector arg
2182 currentheight = (fixed_t)luaL_optinteger(L, 2, sector->floorheight);
2183 lua_pushfixed(L, P_FindNextHighestFloor(sector, currentheight));
2184 return 1;
2185 }
2186
lib_pFindNextLowestFloor(lua_State * L)2187 static int lib_pFindNextLowestFloor(lua_State *L)
2188 {
2189 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2190 fixed_t currentheight;
2191 //HUDSAFE
2192 INLEVEL
2193 if (!sector)
2194 return LUA_ErrInvalid(L, "sector_t");
2195 // defaults to floorheight of sector arg
2196 currentheight = (fixed_t)luaL_optinteger(L, 2, sector->floorheight);
2197 lua_pushfixed(L, P_FindNextLowestFloor(sector, currentheight));
2198 return 1;
2199 }
2200
lib_pFindLowestCeilingSurrounding(lua_State * L)2201 static int lib_pFindLowestCeilingSurrounding(lua_State *L)
2202 {
2203 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2204 //HUDSAFE
2205 INLEVEL
2206 if (!sector)
2207 return LUA_ErrInvalid(L, "sector_t");
2208 lua_pushfixed(L, P_FindLowestCeilingSurrounding(sector));
2209 return 1;
2210 }
2211
lib_pFindHighestCeilingSurrounding(lua_State * L)2212 static int lib_pFindHighestCeilingSurrounding(lua_State *L)
2213 {
2214 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2215 //HUDSAFE
2216 INLEVEL
2217 if (!sector)
2218 return LUA_ErrInvalid(L, "sector_t");
2219 lua_pushfixed(L, P_FindHighestCeilingSurrounding(sector));
2220 return 1;
2221 }
2222
lib_pFindSpecialLineFromTag(lua_State * L)2223 static int lib_pFindSpecialLineFromTag(lua_State *L)
2224 {
2225 INT16 special = (INT16)luaL_checkinteger(L, 1);
2226 INT16 line = (INT16)luaL_checkinteger(L, 2);
2227 INT32 start = (INT32)luaL_optinteger(L, 3, -1);
2228 NOHUD
2229 INLEVEL
2230 lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start));
2231 return 1;
2232 }
2233
lib_pSwitchWeather(lua_State * L)2234 static int lib_pSwitchWeather(lua_State *L)
2235 {
2236 INT32 weathernum = (INT32)luaL_checkinteger(L, 1);
2237 player_t *user = NULL;
2238 NOHUD
2239 INLEVEL
2240 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players
2241 user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2242 if (!user) // global
2243 globalweather = weathernum;
2244 if (!user || P_IsLocalPlayer(user))
2245 P_SwitchWeather(weathernum);
2246 return 0;
2247 }
2248
lib_pLinedefExecute(lua_State * L)2249 static int lib_pLinedefExecute(lua_State *L)
2250 {
2251 INT32 tag = (INT16)luaL_checkinteger(L, 1);
2252 mobj_t *actor = NULL;
2253 sector_t *caller = NULL;
2254 NOHUD
2255 INLEVEL
2256 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
2257 actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
2258 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
2259 caller = *((sector_t **)luaL_checkudata(L, 3, META_SECTOR));
2260 P_LinedefExecute(tag, actor, caller);
2261 return 0;
2262 }
2263
lib_pSpawnLightningFlash(lua_State * L)2264 static int lib_pSpawnLightningFlash(lua_State *L)
2265 {
2266 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2267 NOHUD
2268 INLEVEL
2269 if (!sector)
2270 return LUA_ErrInvalid(L, "sector_t");
2271 P_SpawnLightningFlash(sector);
2272 return 0;
2273 }
2274
lib_pFadeLight(lua_State * L)2275 static int lib_pFadeLight(lua_State *L)
2276 {
2277 INT16 tag = (INT16)luaL_checkinteger(L, 1);
2278 INT32 destvalue = (INT32)luaL_checkinteger(L, 2);
2279 INT32 speed = (INT32)luaL_checkinteger(L, 3);
2280 boolean ticbased = lua_optboolean(L, 4);
2281 boolean force = lua_optboolean(L, 5);
2282 NOHUD
2283 INLEVEL
2284 P_FadeLight(tag, destvalue, speed, ticbased, force);
2285 return 0;
2286 }
2287
lib_pThingOnSpecial3DFloor(lua_State * L)2288 static int lib_pThingOnSpecial3DFloor(lua_State *L)
2289 {
2290 mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2291 NOHUD
2292 INLEVEL
2293 if (!mo)
2294 return LUA_ErrInvalid(L, "mobj_t");
2295 LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR);
2296 return 1;
2297 }
2298
lib_pIsFlagAtBase(lua_State * L)2299 static int lib_pIsFlagAtBase(lua_State *L)
2300 {
2301 mobjtype_t flag = luaL_checkinteger(L, 1);
2302 NOHUD
2303 INLEVEL
2304 if (flag >= NUMMOBJTYPES)
2305 return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1);
2306 lua_pushboolean(L, P_IsFlagAtBase(flag));
2307 return 1;
2308 }
2309
lib_pSetupLevelSky(lua_State * L)2310 static int lib_pSetupLevelSky(lua_State *L)
2311 {
2312 INT32 skynum = (INT32)luaL_checkinteger(L, 1);
2313 player_t *user = NULL;
2314 NOHUD
2315 INLEVEL
2316 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players
2317 user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2318 if (!user) // global
2319 P_SetupLevelSky(skynum, true);
2320 else if (P_IsLocalPlayer(user))
2321 P_SetupLevelSky(skynum, false);
2322 return 0;
2323 }
2324
2325 // Shhh, P_SetSkyboxMobj doesn't actually exist yet.
lib_pSetSkyboxMobj(lua_State * L)2326 static int lib_pSetSkyboxMobj(lua_State *L)
2327 {
2328 int n = lua_gettop(L);
2329 mobj_t *mo = NULL;
2330 player_t *user = NULL;
2331 int w = 0;
2332
2333 NOHUD
2334 INLEVEL
2335 if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering.
2336 {
2337 mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj.
2338 if (!mo)
2339 return LUA_ErrInvalid(L, "mobj_t");
2340 }
2341
2342 if (n == 1)
2343 ;
2344 else if (lua_isuserdata(L, 2))
2345 user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2346 else if (lua_isnil(L, 2))
2347 w = 0;
2348 else if (lua_isboolean(L, 2))
2349 {
2350 if (lua_toboolean(L, 2))
2351 w = 1;
2352 else
2353 w = 0;
2354 }
2355 else
2356 w = luaL_optinteger(L, 2, 0);
2357
2358 if (n > 2 && lua_isuserdata(L, 3))
2359 {
2360 user = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
2361 if (!user)
2362 return LUA_ErrInvalid(L, "player_t");
2363 }
2364
2365 if (w > 1 || w < 0)
2366 return luaL_error(L, "skybox mobj index %d is out of range for P_SetSkyboxMobj argument #2 (expected 0 or 1)", w);
2367
2368 if (!user || P_IsLocalPlayer(user))
2369 skyboxmo[w] = mo;
2370 return 0;
2371 }
2372
2373 // Shhh, neither does P_StartQuake.
lib_pStartQuake(lua_State * L)2374 static int lib_pStartQuake(lua_State *L)
2375 {
2376 fixed_t q_intensity = luaL_checkinteger(L, 1);
2377 UINT16 q_time = (UINT16)luaL_checkinteger(L, 2);
2378 static mappoint_t q_epicenter = {0,0,0};
2379
2380 NOHUD
2381 INLEVEL
2382
2383 // While technically we don't support epicenter and radius,
2384 // we get their values anyway if they exist.
2385 // This way when support is added we won't have to change anything.
2386 if (!lua_isnoneornil(L, 3))
2387 {
2388 luaL_checktype(L, 3, LUA_TTABLE);
2389
2390 lua_getfield(L, 3, "x");
2391 if (lua_isnil(L, -1))
2392 {
2393 lua_pop(L, 1);
2394 lua_rawgeti(L, 3, 1);
2395 }
2396 if (!lua_isnil(L, -1))
2397 q_epicenter.x = luaL_checkinteger(L, -1);
2398 else
2399 q_epicenter.x = 0;
2400 lua_pop(L, 1);
2401
2402 lua_getfield(L, 3, "y");
2403 if (lua_isnil(L, -1))
2404 {
2405 lua_pop(L, 1);
2406 lua_rawgeti(L, 3, 2);
2407 }
2408 if (!lua_isnil(L, -1))
2409 q_epicenter.y = luaL_checkinteger(L, -1);
2410 else
2411 q_epicenter.y = 0;
2412 lua_pop(L, 1);
2413
2414 lua_getfield(L, 3, "z");
2415 if (lua_isnil(L, -1))
2416 {
2417 lua_pop(L, 1);
2418 lua_rawgeti(L, 3, 3);
2419 }
2420 if (!lua_isnil(L, -1))
2421 q_epicenter.z = luaL_checkinteger(L, -1);
2422 else
2423 q_epicenter.z = 0;
2424 lua_pop(L, 1);
2425
2426 quake.epicenter = &q_epicenter;
2427 }
2428 else
2429 quake.epicenter = NULL;
2430 quake.radius = luaL_optinteger(L, 4, 512*FRACUNIT);
2431
2432 // These things are actually used in 2.1.
2433 quake.intensity = q_intensity;
2434 quake.time = q_time;
2435 return 0;
2436 }
2437
lib_evCrumbleChain(lua_State * L)2438 static int lib_evCrumbleChain(lua_State *L)
2439 {
2440 sector_t *sec = NULL;
2441 ffloor_t *rover = NULL;
2442 NOHUD
2443 INLEVEL
2444 if (!lua_isnone(L, 2))
2445 {
2446 if (!lua_isnil(L, 1))
2447 {
2448 sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2449 if (!sec)
2450 return LUA_ErrInvalid(L, "sector_t");
2451 }
2452 rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
2453 }
2454 else
2455 rover = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
2456 if (!rover)
2457 return LUA_ErrInvalid(L, "ffloor_t");
2458 EV_CrumbleChain(sec, rover);
2459 return 0;
2460 }
2461
lib_evStartCrumble(lua_State * L)2462 static int lib_evStartCrumble(lua_State *L)
2463 {
2464 sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2465 ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
2466 boolean floating = lua_optboolean(L, 3);
2467 player_t *player = NULL;
2468 fixed_t origalpha;
2469 boolean crumblereturn = lua_optboolean(L, 6);
2470 NOHUD
2471 if (!sec)
2472 return LUA_ErrInvalid(L, "sector_t");
2473 if (!rover)
2474 return LUA_ErrInvalid(L, "ffloor_t");
2475 if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
2476 {
2477 player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
2478 if (!player)
2479 return LUA_ErrInvalid(L, "player_t");
2480 }
2481 if (!lua_isnone(L,5))
2482 origalpha = luaL_checkfixed(L, 5);
2483 else
2484 origalpha = rover->alpha;
2485 lua_pushboolean(L, EV_StartCrumble(sec, rover, floating, player, origalpha, crumblereturn) != 0);
2486 return 0;
2487 }
2488
2489 // P_SLOPES
2490 ////////////
2491
lib_pGetZAt(lua_State * L)2492 static int lib_pGetZAt(lua_State *L)
2493 {
2494 fixed_t x = luaL_checkfixed(L, 2);
2495 fixed_t y = luaL_checkfixed(L, 3);
2496 //HUDSAFE
2497 if (lua_isnil(L, 1))
2498 {
2499 fixed_t z = luaL_checkfixed(L, 4);
2500 lua_pushfixed(L, P_GetZAt(NULL, x, y, z));
2501 }
2502 else
2503 {
2504 pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
2505 lua_pushfixed(L, P_GetSlopeZAt(slope, x, y));
2506 }
2507
2508 return 1;
2509 }
2510
2511 // R_DEFS
2512 ////////////
2513
lib_rPointToAngle(lua_State * L)2514 static int lib_rPointToAngle(lua_State *L)
2515 {
2516 fixed_t x = luaL_checkfixed(L, 1);
2517 fixed_t y = luaL_checkfixed(L, 2);
2518 //HUDSAFE
2519 lua_pushangle(L, R_PointToAngle(x, y));
2520 return 1;
2521 }
2522
lib_rPointToAngle2(lua_State * L)2523 static int lib_rPointToAngle2(lua_State *L)
2524 {
2525 fixed_t px2 = luaL_checkfixed(L, 1);
2526 fixed_t py2 = luaL_checkfixed(L, 2);
2527 fixed_t px1 = luaL_checkfixed(L, 3);
2528 fixed_t py1 = luaL_checkfixed(L, 4);
2529 //HUDSAFE
2530 lua_pushangle(L, R_PointToAngle2(px2, py2, px1, py1));
2531 return 1;
2532 }
2533
lib_rPointToDist(lua_State * L)2534 static int lib_rPointToDist(lua_State *L)
2535 {
2536 fixed_t x = luaL_checkfixed(L, 1);
2537 fixed_t y = luaL_checkfixed(L, 2);
2538 //HUDSAFE
2539 lua_pushfixed(L, R_PointToDist(x, y));
2540 return 1;
2541 }
2542
lib_rPointToDist2(lua_State * L)2543 static int lib_rPointToDist2(lua_State *L)
2544 {
2545 fixed_t px2 = luaL_checkfixed(L, 1);
2546 fixed_t py2 = luaL_checkfixed(L, 2);
2547 fixed_t px1 = luaL_checkfixed(L, 3);
2548 fixed_t py1 = luaL_checkfixed(L, 4);
2549 //HUDSAFE
2550 lua_pushfixed(L, R_PointToDist2(px2, py2, px1, py1));
2551 return 1;
2552 }
2553
lib_rPointInSubsector(lua_State * L)2554 static int lib_rPointInSubsector(lua_State *L)
2555 {
2556 fixed_t x = luaL_checkfixed(L, 1);
2557 fixed_t y = luaL_checkfixed(L, 2);
2558 //HUDSAFE
2559 INLEVEL
2560 LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR);
2561 return 1;
2562 }
2563
lib_rPointInSubsectorOrNil(lua_State * L)2564 static int lib_rPointInSubsectorOrNil(lua_State *L)
2565 {
2566 fixed_t x = luaL_checkfixed(L, 1);
2567 fixed_t y = luaL_checkfixed(L, 2);
2568 subsector_t *sub = R_PointInSubsectorOrNull(x, y);
2569 //HUDSAFE
2570 INLEVEL
2571 if (sub)
2572 LUA_PushUserdata(L, sub, META_SUBSECTOR);
2573 else
2574 lua_pushnil(L);
2575 return 1;
2576 }
2577
2578 // R_THINGS
2579 ////////////
2580
lib_rChar2Frame(lua_State * L)2581 static int lib_rChar2Frame(lua_State *L)
2582 {
2583 const char *p = luaL_checkstring(L, 1);
2584 //HUDSAFE
2585 lua_pushinteger(L, R_Char2Frame(*p)); // first character only
2586 return 1;
2587 }
2588
lib_rFrame2Char(lua_State * L)2589 static int lib_rFrame2Char(lua_State *L)
2590 {
2591 UINT8 ch = (UINT8)luaL_checkinteger(L, 1);
2592 char c[2] = "";
2593 //HUDSAFE
2594
2595 c[0] = R_Frame2Char(ch);
2596 c[1] = 0;
2597
2598 lua_pushstring(L, c);
2599 lua_pushinteger(L, c[0]);
2600 return 2;
2601 }
2602
2603 // R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience
lib_rSetPlayerSkin(lua_State * L)2604 static int lib_rSetPlayerSkin(lua_State *L)
2605 {
2606 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2607 INT32 i = -1, j = -1;
2608 NOHUD
2609 INLEVEL
2610 if (!player)
2611 return LUA_ErrInvalid(L, "player_t");
2612
2613 j = (player-players);
2614
2615 if (lua_isnoneornil(L, 2))
2616 return luaL_error(L, "argument #2 not given (expected number or string)");
2617 else if (lua_type(L, 2) == LUA_TNUMBER) // skin number
2618 {
2619 i = luaL_checkinteger(L, 2);
2620 if (i < 0 || i >= numskins)
2621 return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, numskins-1);
2622 }
2623 else // skin name
2624 {
2625 const char *skinname = luaL_checkstring(L, 2);
2626 i = R_SkinAvailable(skinname);
2627 if (i == -1)
2628 return luaL_error(L, "skin %s (argument 2) is not loaded", skinname);
2629 }
2630
2631 if (!R_SkinUsable(j, i))
2632 return luaL_error(L, "skin %d (argument 2) not usable - check with R_SkinUsable(player_t, skin) first.", i);
2633 SetPlayerSkinByNum(j, i);
2634 return 0;
2635 }
2636
lib_rSkinUsable(lua_State * L)2637 static int lib_rSkinUsable(lua_State *L)
2638 {
2639 player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2640 INT32 i = -1, j = -1;
2641 if (player)
2642 j = (player-players);
2643 else if (netgame || multiplayer)
2644 return luaL_error(L, "player_t (argument #1) must be provided in multiplayer games");
2645 if (lua_isnoneornil(L, 2))
2646 return luaL_error(L, "argument #2 not given (expected number or string)");
2647 else if (lua_type(L, 2) == LUA_TNUMBER) // skin number
2648 {
2649 i = luaL_checkinteger(L, 2);
2650 if (i < 0 || i >= numskins)
2651 return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, numskins-1);
2652 }
2653 else // skin name
2654 {
2655 const char *skinname = luaL_checkstring(L, 2);
2656 i = R_SkinAvailable(skinname);
2657 if (i == -1)
2658 return luaL_error(L, "skin %s (argument 2) is not loaded", skinname);
2659 }
2660
2661 lua_pushboolean(L, R_SkinUsable(j, i));
2662 return 1;
2663 }
2664
2665 // R_DATA
2666 ////////////
2667
lib_rCheckTextureNumForName(lua_State * L)2668 static int lib_rCheckTextureNumForName(lua_State *L)
2669 {
2670 const char *name = luaL_checkstring(L, 1);
2671 //HUDSAFE
2672 lua_pushinteger(L, R_CheckTextureNumForName(name));
2673 return 1;
2674 }
2675
lib_rTextureNumForName(lua_State * L)2676 static int lib_rTextureNumForName(lua_State *L)
2677 {
2678 const char *name = luaL_checkstring(L, 1);
2679 //HUDSAFE
2680 lua_pushinteger(L, R_TextureNumForName(name));
2681 return 1;
2682 }
2683
2684 // R_DRAW
2685 ////////////
lib_rGetColorByName(lua_State * L)2686 static int lib_rGetColorByName(lua_State *L)
2687 {
2688 const char* colorname = luaL_checkstring(L, 1);
2689 //HUDSAFE
2690 lua_pushinteger(L, R_GetColorByName(colorname));
2691 return 1;
2692 }
2693
lib_rGetSuperColorByName(lua_State * L)2694 static int lib_rGetSuperColorByName(lua_State *L)
2695 {
2696 const char* colorname = luaL_checkstring(L, 1);
2697 //HUDSAFE
2698 lua_pushinteger(L, R_GetSuperColorByName(colorname));
2699 return 1;
2700 }
2701
2702 // Lua exclusive function, returns the name of a color from the SKINCOLOR_ constant.
2703 // SKINCOLOR_GREEN > "Green" for example
lib_rGetNameByColor(lua_State * L)2704 static int lib_rGetNameByColor(lua_State *L)
2705 {
2706 UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
2707 if (!colornum || colornum >= numskincolors)
2708 return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
2709 lua_pushstring(L, skincolors[colornum].name);
2710 return 1;
2711 }
2712
2713 // S_SOUND
2714 ////////////
GetValidSoundOrigin(lua_State * L,void ** origin)2715 static int GetValidSoundOrigin(lua_State *L, void **origin)
2716 {
2717 const char *type;
2718
2719 lua_settop(L, 1);
2720 type = GetUserdataUType(L);
2721
2722 if (fasticmp(type, "mobj_t"))
2723 {
2724 *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
2725 if (!(*origin))
2726 return LUA_ErrInvalid(L, "mobj_t");
2727 return 1;
2728 }
2729 else if (fasticmp(type, "sector_t"))
2730 {
2731 *origin = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
2732 if (!(*origin))
2733 return LUA_ErrInvalid(L, "sector_t");
2734
2735 *origin = &((sector_t *)(*origin))->soundorg;
2736 return 1;
2737 }
2738
2739 return LUA_ErrInvalid(L, "mobj_t/sector_t");
2740 }
2741
lib_sStartSound(lua_State * L)2742 static int lib_sStartSound(lua_State *L)
2743 {
2744 void *origin = NULL;
2745 sfxenum_t sound_id = luaL_checkinteger(L, 2);
2746 player_t *player = NULL;
2747 //NOHUD
2748
2749 if (sound_id >= NUMSFX)
2750 return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
2751
2752 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
2753 {
2754 player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
2755 if (!player)
2756 return LUA_ErrInvalid(L, "player_t");
2757 }
2758 if (!lua_isnil(L, 1))
2759 if (!GetValidSoundOrigin(L, &origin))
2760 return 0;
2761 if (!player || P_IsLocalPlayer(player))
2762 {
2763 if (hud_running || hook_cmd_running)
2764 origin = NULL; // HUD rendering and CMD building startsound shouldn't have an origin, just remove it instead of having a retarded error.
2765
2766 S_StartSound(origin, sound_id);
2767 }
2768 return 0;
2769 }
2770
lib_sStartSoundAtVolume(lua_State * L)2771 static int lib_sStartSoundAtVolume(lua_State *L)
2772 {
2773 void *origin = NULL;
2774 sfxenum_t sound_id = luaL_checkinteger(L, 2);
2775 INT32 volume = (INT32)luaL_checkinteger(L, 3);
2776 player_t *player = NULL;
2777 //NOHUD
2778
2779 if (sound_id >= NUMSFX)
2780 return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
2781 if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
2782 {
2783 player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
2784 if (!player)
2785 return LUA_ErrInvalid(L, "player_t");
2786 }
2787 if (!lua_isnil(L, 1))
2788 if (!GetValidSoundOrigin(L, &origin))
2789 return LUA_ErrInvalid(L, "mobj_t/sector_t");
2790
2791 if (!player || P_IsLocalPlayer(player))
2792 S_StartSoundAtVolume(origin, sound_id, volume);
2793 return 0;
2794 }
2795
lib_sStopSound(lua_State * L)2796 static int lib_sStopSound(lua_State *L)
2797 {
2798 void *origin = NULL;
2799 //NOHUD
2800 if (!GetValidSoundOrigin(L, &origin))
2801 return LUA_ErrInvalid(L, "mobj_t/sector_t");
2802
2803 S_StopSound(origin);
2804 return 0;
2805 }
2806
lib_sStopSoundByID(lua_State * L)2807 static int lib_sStopSoundByID(lua_State *L)
2808 {
2809 void *origin = NULL;
2810 sfxenum_t sound_id = luaL_checkinteger(L, 2);
2811 //NOHUD
2812
2813 if (sound_id >= NUMSFX)
2814 return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
2815 if (!lua_isnil(L, 1))
2816 if (!GetValidSoundOrigin(L, &origin))
2817 return LUA_ErrInvalid(L, "mobj_t/sector_t");
2818
2819 S_StopSoundByID(origin, sound_id);
2820 return 0;
2821 }
2822
lib_sChangeMusic(lua_State * L)2823 static int lib_sChangeMusic(lua_State *L)
2824 {
2825 #ifdef MUSICSLOT_COMPATIBILITY
2826 const char *music_name;
2827 UINT32 music_num, position, prefadems, fadeinms;
2828 char music_compat_name[7];
2829
2830 boolean looping;
2831 player_t *player = NULL;
2832 UINT16 music_flags = 0;
2833 //NOHUD
2834
2835 if (lua_isnumber(L, 1))
2836 {
2837 music_num = (UINT32)luaL_checkinteger(L, 1);
2838 music_flags = (UINT16)(music_num & 0x0000FFFF);
2839 if (music_flags && music_flags <= 1035)
2840 snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
2841 else if (music_flags && music_flags <= 1050)
2842 strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
2843 else
2844 music_compat_name[0] = 0; // becomes empty string
2845 music_compat_name[6] = 0;
2846 music_name = (const char *)&music_compat_name;
2847 music_flags = 0;
2848 }
2849 else
2850 {
2851 music_num = 0;
2852 music_name = luaL_checkstring(L, 1);
2853 }
2854
2855 looping = (boolean)lua_opttrueboolean(L, 2);
2856
2857 #else
2858 const char *music_name = luaL_checkstring(L, 1);
2859 boolean looping = (boolean)lua_opttrueboolean(L, 2);
2860 player_t *player = NULL;
2861 UINT16 music_flags = 0;
2862 //NOHUD
2863
2864 #endif
2865 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
2866 {
2867 player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
2868 if (!player)
2869 return LUA_ErrInvalid(L, "player_t");
2870 }
2871
2872 #ifdef MUSICSLOT_COMPATIBILITY
2873 if (music_num)
2874 music_flags = (UINT16)((music_num & 0x7FFF0000) >> 16);
2875 else
2876 #endif
2877 music_flags = (UINT16)luaL_optinteger(L, 4, 0);
2878
2879 position = (UINT32)luaL_optinteger(L, 5, 0);
2880 prefadems = (UINT32)luaL_optinteger(L, 6, 0);
2881 fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
2882
2883 if (!player || P_IsLocalPlayer(player))
2884 S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
2885 return 0;
2886 }
2887
lib_sSpeedMusic(lua_State * L)2888 static int lib_sSpeedMusic(lua_State *L)
2889 {
2890 fixed_t fixedspeed = luaL_checkfixed(L, 1);
2891 float speed = FIXED_TO_FLOAT(fixedspeed);
2892 player_t *player = NULL;
2893 //NOHUD
2894 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
2895 {
2896 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2897 if (!player)
2898 return LUA_ErrInvalid(L, "player_t");
2899 }
2900 if (!player || P_IsLocalPlayer(player))
2901 S_SpeedMusic(speed);
2902 return 0;
2903 }
2904
lib_sStopMusic(lua_State * L)2905 static int lib_sStopMusic(lua_State *L)
2906 {
2907 player_t *player = NULL;
2908 //NOHUD
2909 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
2910 {
2911 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2912 if (!player)
2913 return LUA_ErrInvalid(L, "player_t");
2914 }
2915 if (!player || P_IsLocalPlayer(player))
2916 S_StopMusic();
2917 return 0;
2918 }
2919
lib_sSetInternalMusicVolume(lua_State * L)2920 static int lib_sSetInternalMusicVolume(lua_State *L)
2921 {
2922 UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
2923 player_t *player = NULL;
2924 //NOHUD
2925 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
2926 {
2927 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
2928 if (!player)
2929 return LUA_ErrInvalid(L, "player_t");
2930 }
2931 if (!player || P_IsLocalPlayer(player))
2932 {
2933 S_SetInternalMusicVolume(volume);
2934 lua_pushboolean(L, true);
2935 }
2936 else
2937 lua_pushnil(L);
2938 return 1;
2939 }
2940
lib_sStopFadingMusic(lua_State * L)2941 static int lib_sStopFadingMusic(lua_State *L)
2942 {
2943 player_t *player = NULL;
2944 //NOHUD
2945 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
2946 {
2947 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
2948 if (!player)
2949 return LUA_ErrInvalid(L, "player_t");
2950 }
2951 if (!player || P_IsLocalPlayer(player))
2952 {
2953 S_StopFadingMusic();
2954 lua_pushboolean(L, true);
2955 }
2956 else
2957 lua_pushnil(L);
2958 return 1;
2959 }
2960
lib_sFadeMusic(lua_State * L)2961 static int lib_sFadeMusic(lua_State *L)
2962 {
2963 UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1);
2964 UINT32 ms;
2965 INT32 source_volume;
2966 player_t *player = NULL;
2967 //NOHUD
2968 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
2969 {
2970 player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
2971 if (!player)
2972 return LUA_ErrInvalid(L, "player_t");
2973 ms = (UINT32)luaL_checkinteger(L, 2);
2974 source_volume = -1;
2975 }
2976 else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
2977 {
2978 player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
2979 if (!player)
2980 return LUA_ErrInvalid(L, "player_t");
2981 source_volume = (INT32)luaL_checkinteger(L, 2);
2982 ms = (UINT32)luaL_checkinteger(L, 3);
2983 }
2984 else if (luaL_optinteger(L, 3, INT32_MAX) == INT32_MAX)
2985 {
2986 ms = (UINT32)luaL_checkinteger(L, 2);
2987 source_volume = -1;
2988 }
2989 else
2990 {
2991 source_volume = (INT32)luaL_checkinteger(L, 2);
2992 ms = (UINT32)luaL_checkinteger(L, 3);
2993 }
2994
2995 if (!player || P_IsLocalPlayer(player))
2996 lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
2997 else
2998 lua_pushnil(L);
2999 return 1;
3000 }
3001
lib_sFadeOutStopMusic(lua_State * L)3002 static int lib_sFadeOutStopMusic(lua_State *L)
3003 {
3004 UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
3005 player_t *player = NULL;
3006 //NOHUD
3007 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
3008 {
3009 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
3010 if (!player)
3011 return LUA_ErrInvalid(L, "player_t");
3012 }
3013 if (!player || P_IsLocalPlayer(player))
3014 {
3015 lua_pushboolean(L, S_FadeOutStopMusic(ms));
3016 }
3017 else
3018 lua_pushnil(L);
3019 return 1;
3020 }
3021
lib_sGetMusicLength(lua_State * L)3022 static int lib_sGetMusicLength(lua_State *L)
3023 {
3024 lua_pushinteger(L, S_GetMusicLength());
3025 return 1;
3026 }
3027
lib_sGetMusicPosition(lua_State * L)3028 static int lib_sGetMusicPosition(lua_State *L)
3029 {
3030 lua_pushinteger(L, S_GetMusicPosition());
3031 return 1;
3032 }
3033
lib_sSetMusicPosition(lua_State * L)3034 static int lib_sSetMusicPosition(lua_State *L)
3035 {
3036 UINT32 pos = (UINT32)luaL_checkinteger(L, 1);
3037 lua_pushboolean(L, S_SetMusicPosition(pos));
3038 return 1;
3039 }
3040
lib_sOriginPlaying(lua_State * L)3041 static int lib_sOriginPlaying(lua_State *L)
3042 {
3043 void *origin = NULL;
3044 //NOHUD
3045 INLEVEL
3046 if (!GetValidSoundOrigin(L, &origin))
3047 return LUA_ErrInvalid(L, "mobj_t/sector_t");
3048
3049 lua_pushboolean(L, S_OriginPlaying(origin));
3050 return 1;
3051 }
3052
lib_sIdPlaying(lua_State * L)3053 static int lib_sIdPlaying(lua_State *L)
3054 {
3055 sfxenum_t id = luaL_checkinteger(L, 1);
3056 //NOHUD
3057 if (id >= NUMSFX)
3058 return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
3059 lua_pushboolean(L, S_IdPlaying(id));
3060 return 1;
3061 }
3062
lib_sSoundPlaying(lua_State * L)3063 static int lib_sSoundPlaying(lua_State *L)
3064 {
3065 void *origin = NULL;
3066 sfxenum_t id = luaL_checkinteger(L, 2);
3067 //NOHUD
3068 INLEVEL
3069 if (id >= NUMSFX)
3070 return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
3071 if (!GetValidSoundOrigin(L, &origin))
3072 return LUA_ErrInvalid(L, "mobj_t/sector_t");
3073
3074 lua_pushboolean(L, S_SoundPlaying(origin, id));
3075 return 1;
3076 }
3077
3078 // This doesn't really exist, but we're providing it as a handy netgame-safe wrapper for stuff that should be locally handled.
3079
lib_sStartMusicCaption(lua_State * L)3080 static int lib_sStartMusicCaption(lua_State *L)
3081 {
3082 player_t *player = NULL;
3083 const char *caption = luaL_checkstring(L, 1);
3084 UINT16 lifespan = (UINT16)luaL_checkinteger(L, 2);
3085 //HUDSAFE
3086 //INLEVEL
3087
3088 if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
3089 {
3090 player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
3091 if (!player)
3092 return LUA_ErrInvalid(L, "player_t");
3093 }
3094
3095 if (lifespan && (!player || P_IsLocalPlayer(player)))
3096 {
3097 strlcpy(S_sfx[sfx_None].caption, caption, sizeof(S_sfx[sfx_None].caption));
3098 S_StartCaption(sfx_None, -1, lifespan);
3099 }
3100 return 0;
3101 }
3102
lib_sMusicType(lua_State * L)3103 static int lib_sMusicType(lua_State *L)
3104 {
3105 player_t *player = NULL;
3106 NOHUD
3107 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3108 {
3109 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3110 if (!player)
3111 return LUA_ErrInvalid(L, "player_t");
3112 }
3113 if (!player || P_IsLocalPlayer(player))
3114 lua_pushinteger(L, S_MusicType());
3115 else
3116 lua_pushnil(L);
3117 return 1;
3118 }
3119
lib_sMusicPlaying(lua_State * L)3120 static int lib_sMusicPlaying(lua_State *L)
3121 {
3122 player_t *player = NULL;
3123 NOHUD
3124 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3125 {
3126 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3127 if (!player)
3128 return LUA_ErrInvalid(L, "player_t");
3129 }
3130 if (!player || P_IsLocalPlayer(player))
3131 lua_pushboolean(L, S_MusicPlaying());
3132 else
3133 lua_pushnil(L);
3134 return 1;
3135 }
3136
lib_sMusicPaused(lua_State * L)3137 static int lib_sMusicPaused(lua_State *L)
3138 {
3139 player_t *player = NULL;
3140 NOHUD
3141 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3142 {
3143 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3144 if (!player)
3145 return LUA_ErrInvalid(L, "player_t");
3146 }
3147 if (!player || P_IsLocalPlayer(player))
3148 lua_pushboolean(L, S_MusicPaused());
3149 else
3150 lua_pushnil(L);
3151 return 1;
3152 }
3153
lib_sMusicName(lua_State * L)3154 static int lib_sMusicName(lua_State *L)
3155 {
3156 player_t *player = NULL;
3157 NOHUD
3158 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3159 {
3160 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3161 if (!player)
3162 return LUA_ErrInvalid(L, "player_t");
3163 }
3164 if (!player || P_IsLocalPlayer(player))
3165 lua_pushstring(L, S_MusicName());
3166 else
3167 lua_pushnil(L);
3168 return 1;
3169 }
3170
lib_sMusicExists(lua_State * L)3171 static int lib_sMusicExists(lua_State *L)
3172 {
3173 boolean checkMIDI = lua_opttrueboolean(L, 2);
3174 boolean checkDigi = lua_opttrueboolean(L, 3);
3175 #ifdef MUSICSLOT_COMPATIBILITY
3176 const char *music_name;
3177 UINT32 music_num;
3178 char music_compat_name[7];
3179 UINT16 music_flags = 0;
3180 NOHUD
3181 if (lua_isnumber(L, 1))
3182 {
3183 music_num = (UINT32)luaL_checkinteger(L, 1);
3184 music_flags = (UINT16)(music_num & 0x0000FFFF);
3185 if (music_flags && music_flags <= 1035)
3186 snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
3187 else if (music_flags && music_flags <= 1050)
3188 strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
3189 else
3190 music_compat_name[0] = 0; // becomes empty string
3191 music_compat_name[6] = 0;
3192 music_name = (const char *)&music_compat_name;
3193 }
3194 else
3195 {
3196 music_num = 0;
3197 music_name = luaL_checkstring(L, 1);
3198 }
3199 #else
3200 const char *music_name = luaL_checkstring(L, 1);
3201 #endif
3202 NOHUD
3203 lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
3204 return 1;
3205 }
3206
lib_sSetMusicLoopPoint(lua_State * L)3207 static int lib_sSetMusicLoopPoint(lua_State *L)
3208 {
3209 UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
3210 player_t *player = NULL;
3211 NOHUD
3212 if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
3213 {
3214 player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
3215 if (!player)
3216 return LUA_ErrInvalid(L, "player_t");
3217 }
3218 if (!player || P_IsLocalPlayer(player))
3219 lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
3220 else
3221 lua_pushnil(L);
3222 return 1;
3223 }
3224
lib_sGetMusicLoopPoint(lua_State * L)3225 static int lib_sGetMusicLoopPoint(lua_State *L)
3226 {
3227 player_t *player = NULL;
3228 NOHUD
3229 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3230 {
3231 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3232 if (!player)
3233 return LUA_ErrInvalid(L, "player_t");
3234 }
3235 if (!player || P_IsLocalPlayer(player))
3236 lua_pushinteger(L, (int)S_GetMusicLoopPoint());
3237 else
3238 lua_pushnil(L);
3239 return 1;
3240 }
3241
lib_sPauseMusic(lua_State * L)3242 static int lib_sPauseMusic(lua_State *L)
3243 {
3244 player_t *player = NULL;
3245 NOHUD
3246 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3247 {
3248 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3249 if (!player)
3250 return LUA_ErrInvalid(L, "player_t");
3251 }
3252 if (!player || P_IsLocalPlayer(player))
3253 {
3254 S_PauseAudio();
3255 lua_pushboolean(L, true);
3256 }
3257 else
3258 lua_pushnil(L);
3259 return 1;
3260 }
3261
lib_sResumeMusic(lua_State * L)3262 static int lib_sResumeMusic(lua_State *L)
3263 {
3264 player_t *player = NULL;
3265 NOHUD
3266 if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
3267 {
3268 player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
3269 if (!player)
3270 return LUA_ErrInvalid(L, "player_t");
3271 }
3272 if (!player || P_IsLocalPlayer(player))
3273 {
3274 S_ResumeAudio();
3275 lua_pushboolean(L, true);
3276 }
3277 else
3278 lua_pushnil(L);
3279 return 1;
3280 }
3281
3282 // G_GAME
3283 ////////////
3284
3285 // Copypasted from lib_cvRegisterVar :]
lib_gAddGametype(lua_State * L)3286 static int lib_gAddGametype(lua_State *L)
3287 {
3288 const char *k;
3289 lua_Integer i;
3290
3291 const char *gtname = NULL;
3292 const char *gtconst = NULL;
3293 const char *gtdescription = NULL;
3294 INT16 newgtidx = 0;
3295 UINT32 newgtrules = 0;
3296 UINT32 newgttol = 0;
3297 INT32 newgtpointlimit = 0;
3298 INT32 newgttimelimit = 0;
3299 UINT8 newgtleftcolor = 0;
3300 UINT8 newgtrightcolor = 0;
3301 INT16 newgtrankingstype = -1;
3302 int newgtinttype = 0;
3303
3304 luaL_checktype(L, 1, LUA_TTABLE);
3305 lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
3306
3307 if (!lua_lumploading)
3308 return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
3309
3310 // Ran out of gametype slots
3311 if (gametypecount == NUMGAMETYPEFREESLOTS)
3312 return luaL_error(L, "Ran out of free gametype slots!");
3313
3314 #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e);
3315 #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
3316
3317 lua_pushnil(L);
3318 while (lua_next(L, 1)) {
3319 // stack: gametype table, key/index, value
3320 // 1 2 3
3321 i = 0;
3322 k = NULL;
3323 if (lua_isnumber(L, 2))
3324 i = lua_tointeger(L, 2);
3325 else if (lua_isstring(L, 2))
3326 k = lua_tostring(L, 2);
3327
3328 // Sorry, no gametype rules as key names.
3329 if (i == 1 || (k && fasticmp(k, "name"))) {
3330 if (!lua_isstring(L, 3))
3331 TYPEERROR("name", LUA_TSTRING)
3332 gtname = Z_StrDup(lua_tostring(L, 3));
3333 } else if (i == 2 || (k && fasticmp(k, "identifier"))) {
3334 if (!lua_isstring(L, 3))
3335 TYPEERROR("identifier", LUA_TSTRING)
3336 gtconst = Z_StrDup(lua_tostring(L, 3));
3337 } else if (i == 3 || (k && fasticmp(k, "rules"))) {
3338 if (!lua_isnumber(L, 3))
3339 TYPEERROR("rules", LUA_TNUMBER)
3340 newgtrules = (UINT32)lua_tointeger(L, 3);
3341 } else if (i == 4 || (k && fasticmp(k, "typeoflevel"))) {
3342 if (!lua_isnumber(L, 3))
3343 TYPEERROR("typeoflevel", LUA_TNUMBER)
3344 newgttol = (UINT32)lua_tointeger(L, 3);
3345 } else if (i == 5 || (k && fasticmp(k, "rankingtype"))) {
3346 if (!lua_isnumber(L, 3))
3347 TYPEERROR("rankingtype", LUA_TNUMBER)
3348 newgtrankingstype = (INT16)lua_tointeger(L, 3);
3349 } else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) {
3350 if (!lua_isnumber(L, 3))
3351 TYPEERROR("intermissiontype", LUA_TNUMBER)
3352 newgtinttype = (int)lua_tointeger(L, 3);
3353 } else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) {
3354 if (!lua_isnumber(L, 3))
3355 TYPEERROR("defaultpointlimit", LUA_TNUMBER)
3356 newgtpointlimit = (INT32)lua_tointeger(L, 3);
3357 } else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) {
3358 if (!lua_isnumber(L, 3))
3359 TYPEERROR("defaulttimelimit", LUA_TNUMBER)
3360 newgttimelimit = (INT32)lua_tointeger(L, 3);
3361 } else if (i == 9 || (k && fasticmp(k, "description"))) {
3362 if (!lua_isstring(L, 3))
3363 TYPEERROR("description", LUA_TSTRING)
3364 gtdescription = Z_StrDup(lua_tostring(L, 3));
3365 } else if (i == 10 || (k && fasticmp(k, "headerleftcolor"))) {
3366 if (!lua_isnumber(L, 3))
3367 TYPEERROR("headerleftcolor", LUA_TNUMBER)
3368 newgtleftcolor = (UINT8)lua_tointeger(L, 3);
3369 } else if (i == 11 || (k && fasticmp(k, "headerrightcolor"))) {
3370 if (!lua_isnumber(L, 3))
3371 TYPEERROR("headerrightcolor", LUA_TNUMBER)
3372 newgtrightcolor = (UINT8)lua_tointeger(L, 3);
3373 // Key name specified
3374 } else if ((!i) && (k && fasticmp(k, "headercolor"))) {
3375 if (!lua_isnumber(L, 3))
3376 TYPEERROR("headercolor", LUA_TNUMBER)
3377 newgtleftcolor = newgtrightcolor = (UINT8)lua_tointeger(L, 3);
3378 }
3379 lua_pop(L, 1);
3380 }
3381
3382 #undef FIELDERROR
3383 #undef TYPEERROR
3384
3385 // pop gametype table
3386 lua_pop(L, 1);
3387
3388 // Set defaults
3389 if (gtname == NULL)
3390 gtname = Z_StrDup("Unnamed gametype");
3391 if (gtdescription == NULL)
3392 gtdescription = Z_StrDup("???");
3393
3394 // Add the new gametype
3395 newgtidx = G_AddGametype(newgtrules);
3396 G_AddGametypeTOL(newgtidx, newgttol);
3397 G_SetGametypeDescription(newgtidx, NULL, newgtleftcolor, newgtrightcolor);
3398 strncpy(gametypedesc[newgtidx].notes, gtdescription, 441);
3399
3400 // Not covered by G_AddGametype alone.
3401 if (newgtrankingstype == -1)
3402 newgtrankingstype = newgtidx;
3403 gametyperankings[newgtidx] = newgtrankingstype;
3404 intermissiontypes[newgtidx] = newgtinttype;
3405 pointlimits[newgtidx] = newgtpointlimit;
3406 timelimits[newgtidx] = newgttimelimit;
3407
3408 // Write the new gametype name.
3409 Gametype_Names[newgtidx] = gtname;
3410
3411 // Write the constant name.
3412 if (gtconst == NULL)
3413 gtconst = gtname;
3414 G_AddGametypeConstant(newgtidx, gtconst);
3415
3416 // Update gametype_cons_t accordingly.
3417 G_UpdateGametypeSelections();
3418
3419 // done
3420 CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]);
3421 return 0;
3422 }
3423
Lcheckmapnumber(lua_State * L,int idx,const char * fun)3424 static int Lcheckmapnumber (lua_State *L, int idx, const char *fun)
3425 {
3426 if (ISINLEVEL)
3427 return luaL_optinteger(L, idx, gamemap);
3428 else
3429 {
3430 if (lua_isnoneornil(L, idx))
3431 {
3432 return luaL_error(L,
3433 "%s can only be used without a parameter while in a level.",
3434 fun
3435 );
3436 }
3437 else
3438 return luaL_checkinteger(L, idx);
3439 }
3440 }
3441
lib_gBuildMapName(lua_State * L)3442 static int lib_gBuildMapName(lua_State *L)
3443 {
3444 INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapName");
3445 //HUDSAFE
3446 lua_pushstring(L, G_BuildMapName(map));
3447 return 1;
3448 }
3449
lib_gBuildMapTitle(lua_State * L)3450 static int lib_gBuildMapTitle(lua_State *L)
3451 {
3452 INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapTitle");
3453 char *name;
3454 if (map < 1 || map > NUMMAPS)
3455 {
3456 return luaL_error(L,
3457 "map number %d out of range (1 - %d)",
3458 map,
3459 NUMMAPS
3460 );
3461 }
3462 name = G_BuildMapTitle(map);
3463 lua_pushstring(L, name);
3464 Z_Free(name);
3465 return 1;
3466 }
3467
3468 static void
Lpushdim(lua_State * L,int c,struct searchdim * v)3469 Lpushdim (lua_State *L, int c, struct searchdim *v)
3470 {
3471 int i;
3472 lua_createtable(L, c, 0);/* I guess narr is numeric indices??? */
3473 for (i = 0; i < c; ++i)
3474 {
3475 lua_createtable(L, 0, 2);/* and hashed indices (field)... */
3476 lua_pushnumber(L, v[i].pos);
3477 lua_setfield(L, -2, "pos");
3478
3479 lua_pushnumber(L, v[i].siz);
3480 lua_setfield(L, -2, "siz");
3481 lua_rawseti(L, -2, 1 + i);
3482 }
3483 }
3484
3485 /*
3486 I decided to make this return a table because userdata
3487 is scary and tables let the user set their own fields.
3488 */
3489 /*
3490 Returns:
3491
3492 [1] => map number
3493 [2] => map title
3494 [3] => search frequency table
3495
3496 The frequency table is unsorted. It has the following format:
3497
3498 {
3499 ['mapnum'],
3500
3501 ['matchd'] => matches in map title string
3502 ['keywhd'] => matches in map keywords
3503
3504 The above two tables have the following format:
3505
3506 {
3507 ['pos'] => offset from start of string
3508 ['siz'] => length of match
3509 }...
3510
3511 ['total'] => the total matches
3512 }...
3513 */
lib_gFindMap(lua_State * L)3514 static int lib_gFindMap(lua_State *L)
3515 {
3516 const char *query = luaL_checkstring(L, 1);
3517
3518 INT32 map;
3519 char *realname;
3520 INT32 frc;
3521 mapsearchfreq_t *frv;
3522
3523 INT32 i;
3524
3525 map = G_FindMap(query, &realname, &frv, &frc);
3526
3527 lua_settop(L, 0);
3528
3529 lua_pushnumber(L, map);
3530 lua_pushstring(L, realname);
3531
3532 lua_createtable(L, frc, 0);
3533 for (i = 0; i < frc; ++i)
3534 {
3535 lua_createtable(L, 0, 4);
3536 lua_pushnumber(L, frv[i].mapnum);
3537 lua_setfield(L, -2, "mapnum");
3538
3539 Lpushdim(L, frv[i].matchc, frv[i].matchd);
3540 lua_setfield(L, -2, "matchd");
3541
3542 Lpushdim(L, frv[i].keywhc, frv[i].keywhd);
3543 lua_setfield(L, -2, "keywhd");
3544
3545 lua_pushnumber(L, frv[i].total);
3546 lua_setfield(L, -2, "total");
3547 lua_rawseti(L, -2, 1 + i);
3548 }
3549
3550 G_FreeMapSearch(frv, frc);
3551 Z_Free(realname);
3552
3553 return 3;
3554 }
3555
3556 /*
3557 Returns:
3558
3559 [1] => map number
3560 [2] => map title
3561 */
lib_gFindMapByNameOrCode(lua_State * L)3562 static int lib_gFindMapByNameOrCode(lua_State *L)
3563 {
3564 const char *query = luaL_checkstring(L, 1);
3565 INT32 map;
3566 char *realname;
3567 map = G_FindMapByNameOrCode(query, &realname);
3568 lua_pushnumber(L, map);
3569 if (map)
3570 {
3571 lua_pushstring(L, realname);
3572 Z_Free(realname);
3573 return 2;
3574 }
3575 else
3576 return 1;
3577 }
3578
lib_gDoReborn(lua_State * L)3579 static int lib_gDoReborn(lua_State *L)
3580 {
3581 INT32 playernum = luaL_checkinteger(L, 1);
3582 NOHUD
3583 INLEVEL
3584 if (playernum >= MAXPLAYERS)
3585 return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1);
3586 G_DoReborn(playernum);
3587 return 0;
3588 }
3589
3590 // Another Lua function that doesn't actually exist!
3591 // Sets nextmapoverride & skipstats without instantly ending the level, for instances where other sources should be exiting the level, like normal signposts.
lib_gSetCustomExitVars(lua_State * L)3592 static int lib_gSetCustomExitVars(lua_State *L)
3593 {
3594 int n = lua_gettop(L); // Num arguments
3595 NOHUD
3596 INLEVEL
3597
3598 // LUA EXTENSION: Custom exit like support
3599 // Supported:
3600 // G_SetCustomExitVars(); [reset to defaults]
3601 // G_SetCustomExitVars(int) [nextmap override only]
3602 // G_SetCustomExitVars(nil, int) [skipstats only]
3603 // G_SetCustomExitVars(int, int) [both of the above]
3604
3605 nextmapoverride = 0;
3606 skipstats = 0;
3607
3608 if (n >= 1)
3609 {
3610 nextmapoverride = (INT16)luaL_optinteger(L, 1, 0);
3611 skipstats = (INT16)luaL_optinteger(L, 2, 0);
3612 }
3613
3614 return 0;
3615 }
3616
lib_gEnoughPlayersFinished(lua_State * L)3617 static int lib_gEnoughPlayersFinished(lua_State *L)
3618 {
3619 INLEVEL
3620 lua_pushboolean(L, G_EnoughPlayersFinished());
3621 return 1;
3622 }
3623
lib_gExitLevel(lua_State * L)3624 static int lib_gExitLevel(lua_State *L)
3625 {
3626 int n = lua_gettop(L); // Num arguments
3627 NOHUD
3628 // Moved this bit to G_SetCustomExitVars
3629 if (n >= 1) // Don't run the reset to defaults option
3630 lib_gSetCustomExitVars(L);
3631 G_ExitLevel();
3632 return 0;
3633 }
3634
lib_gIsSpecialStage(lua_State * L)3635 static int lib_gIsSpecialStage(lua_State *L)
3636 {
3637 INT32 mapnum = luaL_optinteger(L, 1, gamemap);
3638 //HUDSAFE
3639 INLEVEL
3640 lua_pushboolean(L, G_IsSpecialStage(mapnum));
3641 return 1;
3642 }
3643
lib_gGametypeUsesLives(lua_State * L)3644 static int lib_gGametypeUsesLives(lua_State *L)
3645 {
3646 //HUDSAFE
3647 INLEVEL
3648 lua_pushboolean(L, G_GametypeUsesLives());
3649 return 1;
3650 }
3651
lib_gGametypeUsesCoopLives(lua_State * L)3652 static int lib_gGametypeUsesCoopLives(lua_State *L)
3653 {
3654 //HUDSAFE
3655 INLEVEL
3656 lua_pushboolean(L, G_GametypeUsesCoopLives());
3657 return 1;
3658 }
3659
lib_gGametypeUsesCoopStarposts(lua_State * L)3660 static int lib_gGametypeUsesCoopStarposts(lua_State *L)
3661 {
3662 //HUDSAFE
3663 INLEVEL
3664 lua_pushboolean(L, G_GametypeUsesCoopStarposts());
3665 return 1;
3666 }
3667
lib_gGametypeHasTeams(lua_State * L)3668 static int lib_gGametypeHasTeams(lua_State *L)
3669 {
3670 //HUDSAFE
3671 INLEVEL
3672 lua_pushboolean(L, G_GametypeHasTeams());
3673 return 1;
3674 }
3675
lib_gGametypeHasSpectators(lua_State * L)3676 static int lib_gGametypeHasSpectators(lua_State *L)
3677 {
3678 //HUDSAFE
3679 INLEVEL
3680 lua_pushboolean(L, G_GametypeHasSpectators());
3681 return 1;
3682 }
3683
lib_gRingSlingerGametype(lua_State * L)3684 static int lib_gRingSlingerGametype(lua_State *L)
3685 {
3686 //HUDSAFE
3687 INLEVEL
3688 lua_pushboolean(L, G_RingSlingerGametype());
3689 return 1;
3690 }
3691
lib_gPlatformGametype(lua_State * L)3692 static int lib_gPlatformGametype(lua_State *L)
3693 {
3694 //HUDSAFE
3695 INLEVEL
3696 lua_pushboolean(L, G_PlatformGametype());
3697 return 1;
3698 }
3699
lib_gCoopGametype(lua_State * L)3700 static int lib_gCoopGametype(lua_State *L)
3701 {
3702 //HUDSAFE
3703 INLEVEL
3704 lua_pushboolean(L, G_CoopGametype());
3705 return 1;
3706 }
3707
lib_gTagGametype(lua_State * L)3708 static int lib_gTagGametype(lua_State *L)
3709 {
3710 //HUDSAFE
3711 INLEVEL
3712 lua_pushboolean(L, G_TagGametype());
3713 return 1;
3714 }
3715
lib_gCompetitionGametype(lua_State * L)3716 static int lib_gCompetitionGametype(lua_State *L)
3717 {
3718 //HUDSAFE
3719 INLEVEL
3720 lua_pushboolean(L, G_CompetitionGametype());
3721 return 1;
3722 }
3723
lib_gTicsToHours(lua_State * L)3724 static int lib_gTicsToHours(lua_State *L)
3725 {
3726 tic_t rtic = luaL_checkinteger(L, 1);
3727 //HUDSAFE
3728 lua_pushinteger(L, G_TicsToHours(rtic));
3729 return 1;
3730 }
3731
lib_gTicsToMinutes(lua_State * L)3732 static int lib_gTicsToMinutes(lua_State *L)
3733 {
3734 tic_t rtic = luaL_checkinteger(L, 1);
3735 boolean rfull = lua_optboolean(L, 2);
3736 //HUDSAFE
3737 lua_pushinteger(L, G_TicsToMinutes(rtic, rfull));
3738 return 1;
3739 }
3740
lib_gTicsToSeconds(lua_State * L)3741 static int lib_gTicsToSeconds(lua_State *L)
3742 {
3743 tic_t rtic = luaL_checkinteger(L, 1);
3744 //HUDSAFE
3745 lua_pushinteger(L, G_TicsToSeconds(rtic));
3746 return 1;
3747 }
3748
lib_gTicsToCentiseconds(lua_State * L)3749 static int lib_gTicsToCentiseconds(lua_State *L)
3750 {
3751 tic_t rtic = luaL_checkinteger(L, 1);
3752 //HUDSAFE
3753 lua_pushinteger(L, G_TicsToCentiseconds(rtic));
3754 return 1;
3755 }
3756
lib_gTicsToMilliseconds(lua_State * L)3757 static int lib_gTicsToMilliseconds(lua_State *L)
3758 {
3759 tic_t rtic = luaL_checkinteger(L, 1);
3760 //HUDSAFE
3761 lua_pushinteger(L, G_TicsToMilliseconds(rtic));
3762 return 1;
3763 }
3764
3765 static luaL_Reg lib[] = {
3766 {"print", lib_print},
3767 {"chatprint", lib_chatprint},
3768 {"chatprintf", lib_chatprintf},
3769 {"userdataType", lib_userdataType},
3770 {"registerMetatable", lib_registerMetatable},
3771 {"userdataMetatable", lib_userdataMetatable},
3772 {"IsPlayerAdmin", lib_isPlayerAdmin},
3773 {"reserveLuabanks", lib_reserveLuabanks},
3774
3775 // m_menu
3776 {"M_MoveColorAfter",lib_pMoveColorAfter},
3777 {"M_MoveColorBefore",lib_pMoveColorBefore},
3778 {"M_GetColorAfter",lib_pGetColorAfter},
3779 {"M_GetColorBefore",lib_pGetColorBefore},
3780
3781 // m_random
3782 {"P_RandomFixed",lib_pRandomFixed},
3783 {"P_RandomByte",lib_pRandomByte},
3784 {"P_RandomKey",lib_pRandomKey},
3785 {"P_RandomRange",lib_pRandomRange},
3786 {"P_SignedRandom",lib_pSignedRandom}, // MACRO
3787 {"P_RandomChance",lib_pRandomChance}, // MACRO
3788
3789 // p_maputil
3790 {"P_AproxDistance",lib_pAproxDistance},
3791 {"P_ClosestPointOnLine",lib_pClosestPointOnLine},
3792 {"P_PointOnLineSide",lib_pPointOnLineSide},
3793
3794 // p_enemy
3795 {"P_CheckMeleeRange", lib_pCheckMeleeRange},
3796 {"P_JetbCheckMeleeRange", lib_pJetbCheckMeleeRange},
3797 {"P_FaceStabCheckMeleeRange", lib_pFaceStabCheckMeleeRange},
3798 {"P_SkimCheckMeleeRange", lib_pSkimCheckMeleeRange},
3799 {"P_CheckMissileRange", lib_pCheckMissileRange},
3800 {"P_NewChaseDir", lib_pNewChaseDir},
3801 {"P_LookForPlayers", lib_pLookForPlayers},
3802
3803 // p_mobj
3804 // don't add P_SetMobjState or P_SetPlayerMobjState, use "mobj.state = S_NEWSTATE" instead.
3805 {"P_SpawnMobj",lib_pSpawnMobj},
3806 {"P_SpawnMobjFromMobj",lib_pSpawnMobjFromMobj},
3807 {"P_RemoveMobj",lib_pRemoveMobj},
3808 {"P_IsValidSprite2", lib_pIsValidSprite2},
3809 {"P_SpawnLockOn", lib_pSpawnLockOn},
3810 {"P_SpawnMissile",lib_pSpawnMissile},
3811 {"P_SpawnXYZMissile",lib_pSpawnXYZMissile},
3812 {"P_SpawnPointMissile",lib_pSpawnPointMissile},
3813 {"P_SpawnAlteredDirectionMissile",lib_pSpawnAlteredDirectionMissile},
3814 {"P_ColorTeamMissile",lib_pColorTeamMissile},
3815 {"P_SPMAngle",lib_pSPMAngle},
3816 {"P_SpawnPlayerMissile",lib_pSpawnPlayerMissile},
3817 {"P_MobjFlip",lib_pMobjFlip},
3818 {"P_GetMobjGravity",lib_pGetMobjGravity},
3819 {"P_WeaponOrPanel",lib_pWeaponOrPanel},
3820 {"P_FlashPal",lib_pFlashPal},
3821 {"P_GetClosestAxis",lib_pGetClosestAxis},
3822 {"P_SpawnParaloop",lib_pSpawnParaloop},
3823 {"P_BossTargetPlayer",lib_pBossTargetPlayer},
3824 {"P_SupermanLook4Players",lib_pSupermanLook4Players},
3825 {"P_SetScale",lib_pSetScale},
3826 {"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor},
3827 {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
3828 {"P_CheckSolidLava",lib_pCheckSolidLava},
3829 {"P_CanRunOnWater",lib_pCanRunOnWater},
3830 {"P_MaceRotate",lib_pMaceRotate},
3831 {"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope},
3832 {"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope},
3833 {"P_RailThinker",lib_pRailThinker},
3834 {"P_XYMovement",lib_pXYMovement},
3835 {"P_RingXYMovement",lib_pRingXYMovement},
3836 {"P_SceneryXYMovement",lib_pSceneryXYMovement},
3837 {"P_ZMovement",lib_pZMovement},
3838 {"P_RingZMovement",lib_pRingZMovement},
3839 {"P_SceneryZMovement",lib_pSceneryZMovement},
3840 {"P_PlayerZMovement",lib_pPlayerZMovement},
3841
3842 // p_user
3843 {"P_GetPlayerHeight",lib_pGetPlayerHeight},
3844 {"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight},
3845 {"P_GetPlayerControlDirection",lib_pGetPlayerControlDirection},
3846 {"P_AddPlayerScore",lib_pAddPlayerScore},
3847 {"P_StealPlayerScore",lib_pStealPlayerScore},
3848 {"P_GetJumpFlags",lib_pGetJumpFlags},
3849 {"P_PlayerInPain",lib_pPlayerInPain},
3850 {"P_DoPlayerPain",lib_pDoPlayerPain},
3851 {"P_ResetPlayer",lib_pResetPlayer},
3852 {"P_PlayerCanDamage",lib_pPlayerCanDamage},
3853 {"P_PlayerFullbright",lib_pPlayerFullbright},
3854 {"P_IsObjectInGoop",lib_pIsObjectInGoop},
3855 {"P_IsObjectOnGround",lib_pIsObjectOnGround},
3856 {"P_InSpaceSector",lib_pInSpaceSector},
3857 {"P_InQuicksand",lib_pInQuicksand},
3858 {"P_SetObjectMomZ",lib_pSetObjectMomZ},
3859 {"P_PlayJingle",lib_pPlayJingle},
3860 {"P_PlayJingleMusic",lib_pPlayJingleMusic},
3861 {"P_RestoreMusic",lib_pRestoreMusic},
3862 {"P_SpawnShieldOrb",lib_pSpawnShieldOrb},
3863 {"P_SpawnGhostMobj",lib_pSpawnGhostMobj},
3864 {"P_GivePlayerRings",lib_pGivePlayerRings},
3865 {"P_GivePlayerLives",lib_pGivePlayerLives},
3866 {"P_GiveCoopLives",lib_pGiveCoopLives},
3867 {"P_ResetScore",lib_pResetScore},
3868 {"P_DoJumpShield",lib_pDoJumpShield},
3869 {"P_DoBubbleBounce",lib_pDoBubbleBounce},
3870 {"P_BlackOw",lib_pBlackOw},
3871 {"P_ElementalFire",lib_pElementalFire},
3872 {"P_SpawnSkidDust", lib_pSpawnSkidDust},
3873 {"P_MovePlayer",lib_pMovePlayer},
3874 {"P_DoPlayerFinish",lib_pDoPlayerFinish},
3875 {"P_DoPlayerExit",lib_pDoPlayerExit},
3876 {"P_InstaThrust",lib_pInstaThrust},
3877 {"P_ReturnThrustX",lib_pReturnThrustX},
3878 {"P_ReturnThrustY",lib_pReturnThrustY},
3879 {"P_LookForEnemies",lib_pLookForEnemies},
3880 {"P_NukeEnemies",lib_pNukeEnemies},
3881 {"P_Earthquake",lib_pEarthquake},
3882 {"P_HomingAttack",lib_pHomingAttack},
3883 {"P_SuperReady",lib_pSuperReady},
3884 {"P_DoJump",lib_pDoJump},
3885 {"P_SpawnThokMobj",lib_pSpawnThokMobj},
3886 {"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
3887 {"P_Telekinesis",lib_pTelekinesis},
3888 {"P_SwitchShield",lib_pSwitchShield},
3889 {"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps},
3890 {"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight},
3891
3892 // p_map
3893 {"P_CheckPosition",lib_pCheckPosition},
3894 {"P_TryMove",lib_pTryMove},
3895 {"P_Move",lib_pMove},
3896 {"P_TeleportMove",lib_pTeleportMove},
3897 {"P_SlideMove",lib_pSlideMove},
3898 {"P_BounceMove",lib_pBounceMove},
3899 {"P_CheckSight", lib_pCheckSight},
3900 {"P_CheckHoopPosition",lib_pCheckHoopPosition},
3901 {"P_RadiusAttack",lib_pRadiusAttack},
3902 {"P_FloorzAtPos",lib_pFloorzAtPos},
3903 {"P_CeilingzAtPos",lib_pCeilingzAtPos},
3904 {"P_DoSpring",lib_pDoSpring},
3905
3906 // p_inter
3907 {"P_RemoveShield",lib_pRemoveShield},
3908 {"P_DamageMobj",lib_pDamageMobj},
3909 {"P_KillMobj",lib_pKillMobj},
3910 {"P_PlayerRingBurst",lib_pPlayerRingBurst},
3911 {"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst},
3912 {"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst},
3913 {"P_PlayerWeaponPanelOrAmmoBurst", lib_pPlayerWeaponPanelOrAmmoBurst},
3914 {"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst},
3915 {"P_PlayerFlagBurst",lib_pPlayerFlagBurst},
3916 {"P_PlayRinglossSound",lib_pPlayRinglossSound},
3917 {"P_PlayDeathSound",lib_pPlayDeathSound},
3918 {"P_PlayVictorySound",lib_pPlayVictorySound},
3919 {"P_PlayLivesJingle",lib_pPlayLivesJingle},
3920 {"P_CanPickupItem",lib_pCanPickupItem},
3921 {"P_DoNightsScore",lib_pDoNightsScore},
3922 {"P_DoMatchSuper",lib_pDoMatchSuper},
3923
3924 // p_spec
3925 {"P_Thrust",lib_pThrust},
3926 {"P_SetMobjStateNF",lib_pSetMobjStateNF},
3927 {"P_DoSuperTransformation",lib_pDoSuperTransformation},
3928 {"P_ExplodeMissile",lib_pExplodeMissile},
3929 {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial},
3930 {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding},
3931 {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding},
3932 {"P_FindNextHighestFloor",lib_pFindNextHighestFloor},
3933 {"P_FindNextLowestFloor",lib_pFindNextLowestFloor},
3934 {"P_FindLowestCeilingSurrounding",lib_pFindLowestCeilingSurrounding},
3935 {"P_FindHighestCeilingSurrounding",lib_pFindHighestCeilingSurrounding},
3936 {"P_FindSpecialLineFromTag",lib_pFindSpecialLineFromTag},
3937 {"P_SwitchWeather",lib_pSwitchWeather},
3938 {"P_LinedefExecute",lib_pLinedefExecute},
3939 {"P_SpawnLightningFlash",lib_pSpawnLightningFlash},
3940 {"P_FadeLight",lib_pFadeLight},
3941 {"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor},
3942 {"P_IsFlagAtBase",lib_pIsFlagAtBase},
3943 {"P_SetupLevelSky",lib_pSetupLevelSky},
3944 {"P_SetSkyboxMobj",lib_pSetSkyboxMobj},
3945 {"P_StartQuake",lib_pStartQuake},
3946 {"EV_CrumbleChain",lib_evCrumbleChain},
3947 {"EV_StartCrumble",lib_evStartCrumble},
3948
3949 // p_slopes
3950 {"P_GetZAt",lib_pGetZAt},
3951
3952 // r_defs
3953 {"R_PointToAngle",lib_rPointToAngle},
3954 {"R_PointToAngle2",lib_rPointToAngle2},
3955 {"R_PointToDist",lib_rPointToDist},
3956 {"R_PointToDist2",lib_rPointToDist2},
3957 {"R_PointInSubsector",lib_rPointInSubsector},
3958 {"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil},
3959
3960 // r_things (sprite)
3961 {"R_Char2Frame",lib_rChar2Frame},
3962 {"R_Frame2Char",lib_rFrame2Char},
3963 {"R_SetPlayerSkin",lib_rSetPlayerSkin},
3964 {"R_SkinUsable",lib_rSkinUsable},
3965
3966 // r_data
3967 {"R_CheckTextureNumForName",lib_rCheckTextureNumForName},
3968 {"R_TextureNumForName",lib_rTextureNumForName},
3969
3970 // r_draw
3971 {"R_GetColorByName", lib_rGetColorByName},
3972 {"R_GetSuperColorByName", lib_rGetSuperColorByName},
3973 {"R_GetNameByColor", lib_rGetNameByColor},
3974
3975 // s_sound
3976 {"S_StartSound",lib_sStartSound},
3977 {"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
3978 {"S_StopSound",lib_sStopSound},
3979 {"S_StopSoundByID",lib_sStopSoundByID},
3980 {"S_ChangeMusic",lib_sChangeMusic},
3981 {"S_SpeedMusic",lib_sSpeedMusic},
3982 {"S_StopMusic",lib_sStopMusic},
3983 {"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume},
3984 {"S_StopFadingMusic",lib_sStopFadingMusic},
3985 {"S_FadeMusic",lib_sFadeMusic},
3986 {"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
3987 {"S_GetMusicLength",lib_sGetMusicLength},
3988 {"S_GetMusicPosition",lib_sGetMusicPosition},
3989 {"S_SetMusicPosition",lib_sSetMusicPosition},
3990 {"S_OriginPlaying",lib_sOriginPlaying},
3991 {"S_IdPlaying",lib_sIdPlaying},
3992 {"S_SoundPlaying",lib_sSoundPlaying},
3993 {"S_StartMusicCaption", lib_sStartMusicCaption},
3994 {"S_MusicType",lib_sMusicType},
3995 {"S_MusicPlaying",lib_sMusicPlaying},
3996 {"S_MusicPaused",lib_sMusicPaused},
3997 {"S_MusicName",lib_sMusicName},
3998 {"S_MusicExists",lib_sMusicExists},
3999 {"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
4000 {"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
4001 {"S_PauseMusic",lib_sPauseMusic},
4002 {"S_ResumeMusic", lib_sResumeMusic},
4003
4004 // g_game
4005 {"G_AddGametype", lib_gAddGametype},
4006 {"G_BuildMapName",lib_gBuildMapName},
4007 {"G_BuildMapTitle",lib_gBuildMapTitle},
4008 {"G_FindMap",lib_gFindMap},
4009 {"G_FindMapByNameOrCode",lib_gFindMapByNameOrCode},
4010 {"G_DoReborn",lib_gDoReborn},
4011 {"G_SetCustomExitVars",lib_gSetCustomExitVars},
4012 {"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},
4013 {"G_ExitLevel",lib_gExitLevel},
4014 {"G_IsSpecialStage",lib_gIsSpecialStage},
4015 {"G_GametypeUsesLives",lib_gGametypeUsesLives},
4016 {"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives},
4017 {"G_GametypeUsesCoopStarposts",lib_gGametypeUsesCoopStarposts},
4018 {"G_GametypeHasTeams",lib_gGametypeHasTeams},
4019 {"G_GametypeHasSpectators",lib_gGametypeHasSpectators},
4020 {"G_RingSlingerGametype",lib_gRingSlingerGametype},
4021 {"G_PlatformGametype",lib_gPlatformGametype},
4022 {"G_CoopGametype",lib_gCoopGametype},
4023 {"G_TagGametype",lib_gTagGametype},
4024 {"G_CompetitionGametype",lib_gCompetitionGametype},
4025 {"G_TicsToHours",lib_gTicsToHours},
4026 {"G_TicsToMinutes",lib_gTicsToMinutes},
4027 {"G_TicsToSeconds",lib_gTicsToSeconds},
4028 {"G_TicsToCentiseconds",lib_gTicsToCentiseconds},
4029 {"G_TicsToMilliseconds",lib_gTicsToMilliseconds},
4030
4031 {NULL, NULL}
4032 };
4033
LUA_BaseLib(lua_State * L)4034 int LUA_BaseLib(lua_State *L)
4035 {
4036 // Set metatable for string
4037 lua_pushliteral(L, ""); // dummy string
4038 lua_getmetatable(L, -1); // get string metatable
4039 lua_pushcfunction(L,lib_concat); // push concatination function
4040 lua_setfield(L,-2,"__add"); // ... store it as mathematical addition
4041 lua_pop(L, 2); // pop metatable and dummy string
4042
4043 lua_newtable(L);
4044 lua_setfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
4045
4046 // Set global functions
4047 lua_pushvalue(L, LUA_GLOBALSINDEX);
4048 luaL_register(L, NULL, lib);
4049 return 0;
4050 }
4051