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_maplib.c
11 /// \brief game map library for Lua scripting
12
13 #include "doomdef.h"
14 #include "r_state.h"
15 #include "p_local.h"
16 #include "p_setup.h"
17 #include "z_zone.h"
18 #include "p_slopes.h"
19 #include "p_polyobj.h"
20 #include "r_main.h"
21
22 #include "lua_script.h"
23 #include "lua_libs.h"
24 #include "lua_hud.h" // hud_running errors
25 #include "lua_hook.h" // hook_cmd_running errors
26
27 #include "dehacked.h"
28 #include "fastcmp.h"
29 #include "doomstat.h"
30
31 enum sector_e {
32 sector_valid = 0,
33 sector_floorheight,
34 sector_ceilingheight,
35 sector_floorpic,
36 sector_ceilingpic,
37 sector_lightlevel,
38 sector_special,
39 sector_tag,
40 sector_taglist,
41 sector_thinglist,
42 sector_heightsec,
43 sector_camsec,
44 sector_lines,
45 sector_ffloors,
46 sector_fslope,
47 sector_cslope
48 };
49
50 static const char *const sector_opt[] = {
51 "valid",
52 "floorheight",
53 "ceilingheight",
54 "floorpic",
55 "ceilingpic",
56 "lightlevel",
57 "special",
58 "tag",
59 "taglist",
60 "thinglist",
61 "heightsec",
62 "camsec",
63 "lines",
64 "ffloors",
65 "f_slope",
66 "c_slope",
67 NULL};
68
69 enum subsector_e {
70 subsector_valid = 0,
71 subsector_sector,
72 subsector_numlines,
73 subsector_firstline,
74 subsector_polyList
75 };
76
77 static const char *const subsector_opt[] = {
78 "valid",
79 "sector",
80 "numlines",
81 "firstline",
82 "polyList",
83 NULL};
84
85 enum line_e {
86 line_valid = 0,
87 line_v1,
88 line_v2,
89 line_dx,
90 line_dy,
91 line_flags,
92 line_special,
93 line_tag,
94 line_taglist,
95 line_args,
96 line_stringargs,
97 line_sidenum,
98 line_frontside,
99 line_backside,
100 line_alpha,
101 line_executordelay,
102 line_slopetype,
103 line_frontsector,
104 line_backsector,
105 line_polyobj,
106 line_text,
107 line_callcount
108 };
109
110 static const char *const line_opt[] = {
111 "valid",
112 "v1",
113 "v2",
114 "dx",
115 "dy",
116 "flags",
117 "special",
118 "tag",
119 "taglist",
120 "args",
121 "stringargs",
122 "sidenum",
123 "frontside",
124 "backside",
125 "alpha",
126 "executordelay",
127 "slopetype",
128 "frontsector",
129 "backsector",
130 "polyobj",
131 "text",
132 "callcount",
133 NULL};
134
135 enum side_e {
136 side_valid = 0,
137 side_textureoffset,
138 side_rowoffset,
139 side_toptexture,
140 side_bottomtexture,
141 side_midtexture,
142 side_line,
143 side_sector,
144 side_special,
145 side_repeatcnt,
146 side_text
147 };
148
149 static const char *const side_opt[] = {
150 "valid",
151 "textureoffset",
152 "rowoffset",
153 "toptexture",
154 "bottomtexture",
155 "midtexture",
156 "line",
157 "sector",
158 "special",
159 "repeatcnt",
160 "text",
161 NULL};
162
163 enum vertex_e {
164 vertex_valid = 0,
165 vertex_x,
166 vertex_y,
167 vertex_floorz,
168 vertex_floorzset,
169 vertex_ceilingz,
170 vertex_ceilingzset
171 };
172
173 static const char *const vertex_opt[] = {
174 "valid",
175 "x",
176 "y",
177 "floorz",
178 "floorzset",
179 "ceilingz",
180 "ceilingzset",
181 NULL};
182
183 enum ffloor_e {
184 ffloor_valid = 0,
185 ffloor_topheight,
186 ffloor_toppic,
187 ffloor_toplightlevel,
188 ffloor_bottomheight,
189 ffloor_bottompic,
190 ffloor_tslope,
191 ffloor_bslope,
192 ffloor_sector,
193 ffloor_flags,
194 ffloor_master,
195 ffloor_target,
196 ffloor_next,
197 ffloor_prev,
198 ffloor_alpha,
199 };
200
201 static const char *const ffloor_opt[] = {
202 "valid",
203 "topheight",
204 "toppic",
205 "toplightlevel",
206 "bottomheight",
207 "bottompic",
208 "t_slope",
209 "b_slope",
210 "sector", // secnum pushed as control sector userdata
211 "flags",
212 "master", // control linedef
213 "target", // target sector
214 "next",
215 "prev",
216 "alpha",
217 NULL};
218
219 #ifdef HAVE_LUA_SEGS
220 enum seg_e {
221 seg_valid = 0,
222 seg_v1,
223 seg_v2,
224 seg_side,
225 seg_offset,
226 seg_angle,
227 seg_sidedef,
228 seg_linedef,
229 seg_frontsector,
230 seg_backsector,
231 seg_polyseg
232 };
233
234 static const char *const seg_opt[] = {
235 "valid",
236 "v1",
237 "v2",
238 "side",
239 "offset",
240 "angle",
241 "sidedef",
242 "linedef",
243 "frontsector",
244 "backsector",
245 "polyseg",
246 NULL};
247
248 enum node_e {
249 node_valid = 0,
250 node_x,
251 node_y,
252 node_dx,
253 node_dy,
254 node_bbox,
255 node_children,
256 };
257
258 static const char *const node_opt[] = {
259 "valid",
260 "x",
261 "y",
262 "dx",
263 "dy",
264 "bbox",
265 "children",
266 NULL};
267
268 enum nodechild_e {
269 nodechild_valid = 0,
270 nodechild_right,
271 nodechild_left,
272 };
273
274 static const char *const nodechild_opt[] = {
275 "valid",
276 "right",
277 "left",
278 NULL};
279 #endif
280
281 enum bbox_e {
282 bbox_valid = 0,
283 bbox_top,
284 bbox_bottom,
285 bbox_left,
286 bbox_right,
287 };
288
289 static const char *const bbox_opt[] = {
290 "valid",
291 "top",
292 "bottom",
293 "left",
294 "right",
295 NULL};
296
297 enum slope_e {
298 slope_valid = 0,
299 slope_o,
300 slope_d,
301 slope_zdelta,
302 slope_normal,
303 slope_zangle,
304 slope_xydirection,
305 slope_flags
306 };
307
308 static const char *const slope_opt[] = {
309 "valid",
310 "o",
311 "d",
312 "zdelta",
313 "normal",
314 "zangle",
315 "xydirection",
316 "flags",
317 NULL};
318
319 // shared by both vector2_t and vector3_t
320 enum vector_e {
321 vector_x = 0,
322 vector_y,
323 vector_z
324 };
325
326 static const char *const vector_opt[] = {
327 "x",
328 "y",
329 "z",
330 NULL};
331
332 static const char *const array_opt[] ={"iterate",NULL};
333 static const char *const valid_opt[] ={"valid",NULL};
334
335 /////////////////////////////////////////////
336 // sector/subsector list iterate functions //
337 /////////////////////////////////////////////
338
339 // iterates through a sector's thinglist!
lib_iterateSectorThinglist(lua_State * L)340 static int lib_iterateSectorThinglist(lua_State *L)
341 {
342 mobj_t *state = NULL;
343 mobj_t *thing = NULL;
344
345 INLEVEL
346
347 if (lua_gettop(L) < 2)
348 return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
349
350 if (!lua_isnil(L, 1))
351 state = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
352 else
353 return 0; // no thinglist to iterate through sorry!
354
355 lua_settop(L, 2);
356 lua_remove(L, 1); // remove state now.
357
358 if (!lua_isnil(L, 1))
359 {
360 thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
361 thing = thing->snext;
362 }
363 else
364 thing = state; // state is used as the "start" of the thinglist
365
366 if (thing)
367 {
368 LUA_PushUserdata(L, thing, META_MOBJ);
369 return 1;
370 }
371 return 0;
372 }
373
374 // iterates through the ffloors list in a sector!
lib_iterateSectorFFloors(lua_State * L)375 static int lib_iterateSectorFFloors(lua_State *L)
376 {
377 ffloor_t *state = NULL;
378 ffloor_t *ffloor = NULL;
379
380 INLEVEL
381
382 if (lua_gettop(L) < 2)
383 return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
384
385 if (!lua_isnil(L, 1))
386 state = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
387 else
388 return 0; // no ffloors to iterate through sorry!
389
390 lua_settop(L, 2);
391 lua_remove(L, 1); // remove state now.
392
393 if (!lua_isnil(L, 1))
394 {
395 ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
396 ffloor = ffloor->next;
397 }
398 else
399 ffloor = state; // state is used as the "start" of the ffloor list
400
401 if (ffloor)
402 {
403 LUA_PushUserdata(L, ffloor, META_FFLOOR);
404 return 1;
405 }
406 return 0;
407 }
408
409 // iterates through a subsector's polyList! (for polyobj_t)
lib_iterateSubSectorPolylist(lua_State * L)410 static int lib_iterateSubSectorPolylist(lua_State *L)
411 {
412 polyobj_t *state = NULL;
413 polyobj_t *po = NULL;
414
415 INLEVEL
416
417 if (lua_gettop(L) < 2)
418 return luaL_error(L, "Don't call subsector.polyList() directly, use it as 'for polyobj in subsector.polyList do <block> end'.");
419
420 if (!lua_isnil(L, 1))
421 state = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
422 else
423 return 0; // no polylist to iterate through sorry!
424
425 lua_settop(L, 2);
426 lua_remove(L, 1); // remove state now.
427
428 if (!lua_isnil(L, 1))
429 {
430 po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
431 po = (polyobj_t *)(po->link.next);
432 }
433 else
434 po = state; // state is used as the "start" of the polylist
435
436 if (po)
437 {
438 LUA_PushUserdata(L, po, META_POLYOBJ);
439 return 1;
440 }
441 return 0;
442 }
443
sector_iterate(lua_State * L)444 static int sector_iterate(lua_State *L)
445 {
446 lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator"
447 lua_pushvalue(L, lua_upvalueindex(2)); // state (used as the "start" of the list for our purposes
448 lua_pushnil(L); // initial value (unused)
449 return 3;
450 }
451
452 ////////////////////
453 // sector.lines[] //
454 ////////////////////
455
456 // sector.lines, i -> sector.lines[i]
457 // sector.lines.valid, for validity checking
458 //
459 // 25/9/19 Monster Iestyn
460 // Modified this and _num to use triple pointers, to allow for a new hack of mine involving offsetof
461 // this way we don't need to check frontsector or backsector of line #0 in the array
462 //
sectorlines_get(lua_State * L)463 static int sectorlines_get(lua_State *L)
464 {
465 line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
466 size_t i;
467 size_t numoflines = 0;
468 lua_settop(L, 2);
469 if (!lua_isnumber(L, 2))
470 {
471 int field = luaL_checkoption(L, 2, NULL, valid_opt);
472 if (!seclines || !(*seclines))
473 {
474 if (field == 0) {
475 lua_pushboolean(L, 0);
476 return 1;
477 }
478 return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
479 } else if (field == 0) {
480 lua_pushboolean(L, 1);
481 return 1;
482 }
483 }
484
485 /* a snip from sector_t struct in r_defs.h, for reference
486 size_t linecount;
487 struct line_s **lines; // [linecount] size
488 */
489 // get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result
490 // we need this to determine the array's actual size, and therefore also the maximum value allowed as an index
491 // this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
492 numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
493
494 /* OLD HACK
495 // check first linedef to figure which of its sectors owns this sector->lines pointer
496 // then check that sector's linecount to get a maximum index
497 //if (!(*seclines)[0])
498 //return luaL_error(L, "no lines found!"); // no first linedef?????
499 if ((*seclines)[0]->frontsector->lines == *seclines)
500 numoflines = (*seclines)[0]->frontsector->linecount;
501 else if ((*seclines)[0]->backsector && *seclines[0]->backsector->lines == *seclines) // check backsector exists first
502 numoflines = (*seclines)[0]->backsector->linecount;
503 //if neither sector has it then ???
504 */
505
506 if (!numoflines)
507 return luaL_error(L, "no lines found!");
508
509 i = (size_t)lua_tointeger(L, 2);
510 if (i >= numoflines)
511 return 0;
512 LUA_PushUserdata(L, (*seclines)[i], META_LINE);
513 return 1;
514 }
515
516 // #(sector.lines) -> sector.linecount
sectorlines_num(lua_State * L)517 static int sectorlines_num(lua_State *L)
518 {
519 line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
520 size_t numoflines = 0;
521
522 if (!seclines || !(*seclines))
523 return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
524
525 // see comments in the _get function above
526 numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
527 lua_pushinteger(L, numoflines);
528 return 1;
529 }
530
531 //////////////
532 // sector_t //
533 //////////////
534
sector_get(lua_State * L)535 static int sector_get(lua_State *L)
536 {
537 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
538 enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
539 INT16 i;
540
541 if (!sector)
542 {
543 if (field == sector_valid) {
544 lua_pushboolean(L, 0);
545 return 1;
546 }
547 return luaL_error(L, "accessed sector_t doesn't exist anymore.");
548 }
549
550 switch(field)
551 {
552 case sector_valid: // valid
553 lua_pushboolean(L, 1);
554 return 1;
555 case sector_floorheight:
556 lua_pushfixed(L, sector->floorheight);
557 return 1;
558 case sector_ceilingheight:
559 lua_pushfixed(L, sector->ceilingheight);
560 return 1;
561 case sector_floorpic: // floorpic
562 {
563 levelflat_t *levelflat = &levelflats[sector->floorpic];
564 for (i = 0; i < 8; i++)
565 if (!levelflat->name[i])
566 break;
567 lua_pushlstring(L, levelflat->name, i);
568 return 1;
569 }
570 case sector_ceilingpic: // ceilingpic
571 {
572 levelflat_t *levelflat = &levelflats[sector->ceilingpic];
573 for (i = 0; i < 8; i++)
574 if (!levelflat->name[i])
575 break;
576 lua_pushlstring(L, levelflat->name, i);
577 return 1;
578 }
579 case sector_lightlevel:
580 lua_pushinteger(L, sector->lightlevel);
581 return 1;
582 case sector_special:
583 lua_pushinteger(L, sector->special);
584 return 1;
585 case sector_tag:
586 lua_pushinteger(L, (UINT16)Tag_FGet(§or->tags));
587 return 1;
588 case sector_taglist:
589 LUA_PushUserdata(L, §or->tags, META_SECTORTAGLIST);
590 return 1;
591 case sector_thinglist: // thinglist
592 lua_pushcfunction(L, lib_iterateSectorThinglist);
593 LUA_PushUserdata(L, sector->thinglist, META_MOBJ);
594 lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSectorThinglist and sector->thinglist as upvalues for the function
595 return 1;
596 case sector_heightsec: // heightsec - fake floor heights
597 if (sector->heightsec < 0)
598 return 0;
599 LUA_PushUserdata(L, §ors[sector->heightsec], META_SECTOR);
600 return 1;
601 case sector_camsec: // camsec - camera clipping heights
602 if (sector->camsec < 0)
603 return 0;
604 LUA_PushUserdata(L, §ors[sector->camsec], META_SECTOR);
605 return 1;
606 case sector_lines: // lines
607 LUA_PushUserdata(L, §or->lines, META_SECTORLINES); // push the address of the "lines" member in the struct, to allow our hacks in sectorlines_get/_num to work
608 return 1;
609 case sector_ffloors: // ffloors
610 lua_pushcfunction(L, lib_iterateSectorFFloors);
611 LUA_PushUserdata(L, sector->ffloors, META_FFLOOR);
612 lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function
613 return 1;
614 case sector_fslope: // f_slope
615 LUA_PushUserdata(L, sector->f_slope, META_SLOPE);
616 return 1;
617 case sector_cslope: // c_slope
618 LUA_PushUserdata(L, sector->c_slope, META_SLOPE);
619 return 1;
620 }
621 return 0;
622 }
623
sector_set(lua_State * L)624 static int sector_set(lua_State *L)
625 {
626 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
627 enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
628
629 if (!sector)
630 return luaL_error(L, "accessed sector_t doesn't exist anymore.");
631
632 if (hud_running)
633 return luaL_error(L, "Do not alter sector_t in HUD rendering code!");
634 if (hook_cmd_running)
635 return luaL_error(L, "Do not alter sector_t in CMD building code!");
636
637 switch(field)
638 {
639 case sector_valid: // valid
640 case sector_thinglist: // thinglist
641 case sector_heightsec: // heightsec
642 case sector_camsec: // camsec
643 case sector_lines: // lines
644 case sector_ffloors: // ffloors
645 case sector_fslope: // f_slope
646 case sector_cslope: // c_slope
647 default:
648 return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
649 case sector_floorheight: { // floorheight
650 boolean flag;
651 mobj_t *ptmthing = tmthing;
652 fixed_t lastpos = sector->floorheight;
653 sector->floorheight = luaL_checkfixed(L, 3);
654 flag = P_CheckSector(sector, true);
655 if (flag && sector->numattached)
656 {
657 sector->floorheight = lastpos;
658 P_CheckSector(sector, true);
659 }
660 P_SetTarget(&tmthing, ptmthing);
661 break;
662 }
663 case sector_ceilingheight: { // ceilingheight
664 boolean flag;
665 mobj_t *ptmthing = tmthing;
666 fixed_t lastpos = sector->ceilingheight;
667 sector->ceilingheight = luaL_checkfixed(L, 3);
668 flag = P_CheckSector(sector, true);
669 if (flag && sector->numattached)
670 {
671 sector->ceilingheight = lastpos;
672 P_CheckSector(sector, true);
673 }
674 P_SetTarget(&tmthing, ptmthing);
675 break;
676 }
677 case sector_floorpic:
678 sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
679 break;
680 case sector_ceilingpic:
681 sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
682 break;
683 case sector_lightlevel:
684 sector->lightlevel = (INT16)luaL_checkinteger(L, 3);
685 break;
686 case sector_special:
687 sector->special = (INT16)luaL_checkinteger(L, 3);
688 break;
689 case sector_tag:
690 Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
691 break;
692 case sector_taglist:
693 return LUA_ErrSetDirectly(L, "sector_t", "taglist");
694 }
695 return 0;
696 }
697
sector_num(lua_State * L)698 static int sector_num(lua_State *L)
699 {
700 sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
701 lua_pushinteger(L, sector-sectors);
702 return 1;
703 }
704
705 /////////////////
706 // subsector_t //
707 /////////////////
708
subsector_get(lua_State * L)709 static int subsector_get(lua_State *L)
710 {
711 subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
712 enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt);
713
714 if (!subsector)
715 {
716 if (field == subsector_valid) {
717 lua_pushboolean(L, 0);
718 return 1;
719 }
720 return luaL_error(L, "accessed subsector_t doesn't exist anymore.");
721 }
722
723 switch(field)
724 {
725 case subsector_valid: // valid
726 lua_pushboolean(L, 1);
727 return 1;
728 case subsector_sector:
729 LUA_PushUserdata(L, subsector->sector, META_SECTOR);
730 return 1;
731 case subsector_numlines:
732 lua_pushinteger(L, subsector->numlines);
733 return 1;
734 case subsector_firstline:
735 lua_pushinteger(L, subsector->firstline);
736 return 1;
737 case subsector_polyList: // polyList
738 lua_pushcfunction(L, lib_iterateSubSectorPolylist);
739 LUA_PushUserdata(L, subsector->polyList, META_POLYOBJ);
740 lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSubSectorPolylist and subsector->polyList as upvalues for the function
741 return 1;
742 }
743 return 0;
744 }
745
subsector_num(lua_State * L)746 static int subsector_num(lua_State *L)
747 {
748 subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
749 lua_pushinteger(L, subsector-subsectors);
750 return 1;
751 }
752
753 ////////////
754 // line_t //
755 ////////////
756
757 // args, i -> args[i]
lineargs_get(lua_State * L)758 static int lineargs_get(lua_State *L)
759 {
760 INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_LINEARGS));
761 int i = luaL_checkinteger(L, 2);
762 if (i < 0 || i >= NUMLINEARGS)
763 return luaL_error(L, LUA_QL("line_t.args") " index cannot be %d", i);
764 lua_pushinteger(L, args[i]);
765 return 1;
766 }
767
768 // #args -> NUMLINEARGS
lineargs_len(lua_State * L)769 static int lineargs_len(lua_State* L)
770 {
771 lua_pushinteger(L, NUMLINEARGS);
772 return 1;
773 }
774
775 // stringargs, i -> stringargs[i]
linestringargs_get(lua_State * L)776 static int linestringargs_get(lua_State *L)
777 {
778 char **stringargs = *((char***)luaL_checkudata(L, 1, META_LINESTRINGARGS));
779 int i = luaL_checkinteger(L, 2);
780 if (i < 0 || i >= NUMLINESTRINGARGS)
781 return luaL_error(L, LUA_QL("line_t.stringargs") " index cannot be %d", i);
782 lua_pushstring(L, stringargs[i]);
783 return 1;
784 }
785
786 // #stringargs -> NUMLINESTRINGARGS
linestringargs_len(lua_State * L)787 static int linestringargs_len(lua_State *L)
788 {
789 lua_pushinteger(L, NUMLINESTRINGARGS);
790 return 1;
791 }
792
line_get(lua_State * L)793 static int line_get(lua_State *L)
794 {
795 line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
796 enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt);
797
798 if (!line)
799 {
800 if (field == line_valid) {
801 lua_pushboolean(L, 0);
802 return 1;
803 }
804 return luaL_error(L, "accessed line_t doesn't exist anymore.");
805 }
806
807 switch(field)
808 {
809 case line_valid: // valid
810 lua_pushboolean(L, 1);
811 return 1;
812 case line_v1:
813 LUA_PushUserdata(L, line->v1, META_VERTEX);
814 return 1;
815 case line_v2:
816 LUA_PushUserdata(L, line->v2, META_VERTEX);
817 return 1;
818 case line_dx:
819 lua_pushfixed(L, line->dx);
820 return 1;
821 case line_dy:
822 lua_pushfixed(L, line->dy);
823 return 1;
824 case line_flags:
825 lua_pushinteger(L, line->flags);
826 return 1;
827 case line_special:
828 lua_pushinteger(L, line->special);
829 return 1;
830 case line_tag:
831 // HELLO
832 // THIS IS LJ SONIC
833 // HOW IS YOUR DAY?
834 // BY THE WAY WHEN 2.3 OR 3.0 OR 4.0 OR SRB3 OR SRB4 OR WHATEVER IS OUT
835 // YOU SHOULD REMEMBER TO CHANGE THIS SO IT ALWAYS RETURNS A UNSIGNED VALUE
836 // HAVE A NICE DAY
837 //
838 //
839 //
840 //
841 // you are ugly
842 lua_pushinteger(L, Tag_FGet(&line->tags));
843 return 1;
844 case line_taglist:
845 LUA_PushUserdata(L, &line->tags, META_TAGLIST);
846 return 1;
847 case line_args:
848 LUA_PushUserdata(L, line->args, META_LINEARGS);
849 return 1;
850 case line_stringargs:
851 LUA_PushUserdata(L, line->stringargs, META_LINESTRINGARGS);
852 return 1;
853 case line_sidenum:
854 LUA_PushUserdata(L, line->sidenum, META_SIDENUM);
855 return 1;
856 case line_frontside: // frontside
857 LUA_PushUserdata(L, &sides[line->sidenum[0]], META_SIDE);
858 return 1;
859 case line_backside: // backside
860 if (line->sidenum[1] == 0xffff)
861 return 0;
862 LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE);
863 return 1;
864 case line_alpha:
865 lua_pushfixed(L, line->alpha);
866 return 1;
867 case line_executordelay:
868 lua_pushinteger(L, line->executordelay);
869 return 1;
870 case line_slopetype:
871 switch(line->slopetype)
872 {
873 case ST_HORIZONTAL:
874 lua_pushliteral(L, "horizontal");
875 break;
876 case ST_VERTICAL:
877 lua_pushliteral(L, "vertical");
878 break;
879 case ST_POSITIVE:
880 lua_pushliteral(L, "positive");
881 break;
882 case ST_NEGATIVE:
883 lua_pushliteral(L, "negative");
884 break;
885 }
886 return 1;
887 case line_frontsector:
888 LUA_PushUserdata(L, line->frontsector, META_SECTOR);
889 return 1;
890 case line_backsector:
891 LUA_PushUserdata(L, line->backsector, META_SECTOR);
892 return 1;
893 case line_polyobj:
894 LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
895 return 1;
896 case line_text:
897 lua_pushstring(L, line->text);
898 return 1;
899 case line_callcount:
900 lua_pushinteger(L, line->callcount);
901 return 1;
902 }
903 return 0;
904 }
905
line_num(lua_State * L)906 static int line_num(lua_State *L)
907 {
908 line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
909 lua_pushinteger(L, line-lines);
910 return 1;
911 }
912
913 ////////////////////
914 // line.sidenum[] //
915 ////////////////////
916
sidenum_get(lua_State * L)917 static int sidenum_get(lua_State *L)
918 {
919 UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM));
920 int i;
921 lua_settop(L, 2);
922 if (!lua_isnumber(L, 2))
923 {
924 int field = luaL_checkoption(L, 2, NULL, valid_opt);
925 if (!sidenum)
926 {
927 if (field == 0) {
928 lua_pushboolean(L, 0);
929 return 1;
930 }
931 return luaL_error(L, "accessed line_t doesn't exist anymore.");
932 } else if (field == 0) {
933 lua_pushboolean(L, 1);
934 return 1;
935 }
936 }
937
938 i = lua_tointeger(L, 2);
939 if (i < 0 || i > 1)
940 return 0;
941 lua_pushinteger(L, sidenum[i]);
942 return 1;
943 }
944
945 ////////////
946 // side_t //
947 ////////////
948
side_get(lua_State * L)949 static int side_get(lua_State *L)
950 {
951 side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
952 enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
953
954 if (!side)
955 {
956 if (field == side_valid) {
957 lua_pushboolean(L, 0);
958 return 1;
959 }
960 return luaL_error(L, "accessed side_t doesn't exist anymore.");
961 }
962
963 switch(field)
964 {
965 case side_valid: // valid
966 lua_pushboolean(L, 1);
967 return 1;
968 case side_textureoffset:
969 lua_pushfixed(L, side->textureoffset);
970 return 1;
971 case side_rowoffset:
972 lua_pushfixed(L, side->rowoffset);
973 return 1;
974 case side_toptexture:
975 lua_pushinteger(L, side->toptexture);
976 return 1;
977 case side_bottomtexture:
978 lua_pushinteger(L, side->bottomtexture);
979 return 1;
980 case side_midtexture:
981 lua_pushinteger(L, side->midtexture);
982 return 1;
983 case side_line:
984 LUA_PushUserdata(L, side->line, META_LINE);
985 return 1;
986 case side_sector:
987 LUA_PushUserdata(L, side->sector, META_SECTOR);
988 return 1;
989 case side_special:
990 lua_pushinteger(L, side->special);
991 return 1;
992 case side_repeatcnt:
993 lua_pushinteger(L, side->repeatcnt);
994 return 1;
995 case side_text:
996 lua_pushstring(L, side->text);
997 return 1;
998 }
999 return 0;
1000 }
1001
side_set(lua_State * L)1002 static int side_set(lua_State *L)
1003 {
1004 side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
1005 enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
1006
1007 if (!side)
1008 {
1009 if (field == side_valid) {
1010 lua_pushboolean(L, 0);
1011 return 1;
1012 }
1013 return luaL_error(L, "accessed side_t doesn't exist anymore.");
1014 }
1015
1016 switch(field)
1017 {
1018 case side_valid: // valid
1019 case side_line:
1020 case side_sector:
1021 case side_special:
1022 case side_text:
1023 default:
1024 return luaL_error(L, "side_t field " LUA_QS " cannot be set.", side_opt[field]);
1025 case side_textureoffset:
1026 side->textureoffset = luaL_checkfixed(L, 3);
1027 break;
1028 case side_rowoffset:
1029 side->rowoffset = luaL_checkfixed(L, 3);
1030 break;
1031 case side_toptexture:
1032 side->toptexture = luaL_checkinteger(L, 3);
1033 break;
1034 case side_bottomtexture:
1035 side->bottomtexture = luaL_checkinteger(L, 3);
1036 break;
1037 case side_midtexture:
1038 side->midtexture = luaL_checkinteger(L, 3);
1039 break;
1040 case side_repeatcnt:
1041 side->repeatcnt = luaL_checkinteger(L, 3);
1042 break;
1043 }
1044 return 0;
1045 }
1046
side_num(lua_State * L)1047 static int side_num(lua_State *L)
1048 {
1049 side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
1050 lua_pushinteger(L, side-sides);
1051 return 1;
1052 }
1053
1054 //////////////
1055 // vertex_t //
1056 //////////////
1057
vertex_get(lua_State * L)1058 static int vertex_get(lua_State *L)
1059 {
1060 vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
1061 enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt);
1062
1063 if (!vertex)
1064 {
1065 if (field == vertex_valid) {
1066 lua_pushboolean(L, 0);
1067 return 1;
1068 }
1069 return luaL_error(L, "accessed vertex_t doesn't exist anymore.");
1070 }
1071
1072 switch(field)
1073 {
1074 case vertex_valid: // valid
1075 lua_pushboolean(L, 1);
1076 return 1;
1077 case vertex_x:
1078 lua_pushfixed(L, vertex->x);
1079 return 1;
1080 case vertex_y:
1081 lua_pushfixed(L, vertex->y);
1082 return 1;
1083 case vertex_floorzset:
1084 lua_pushboolean(L, vertex->floorzset);
1085 return 1;
1086 case vertex_ceilingzset:
1087 lua_pushboolean(L, vertex->ceilingzset);
1088 return 1;
1089 case vertex_floorz:
1090 lua_pushfixed(L, vertex->floorz);
1091 return 1;
1092 case vertex_ceilingz:
1093 lua_pushfixed(L, vertex->ceilingz);
1094 return 1;
1095 }
1096 return 0;
1097 }
1098
vertex_num(lua_State * L)1099 static int vertex_num(lua_State *L)
1100 {
1101 vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
1102 lua_pushinteger(L, vertex-vertexes);
1103 return 1;
1104 }
1105
1106 #ifdef HAVE_LUA_SEGS
1107
1108 ///////////
1109 // seg_t //
1110 ///////////
1111
seg_get(lua_State * L)1112 static int seg_get(lua_State *L)
1113 {
1114 seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
1115 enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt);
1116
1117 if (!seg)
1118 {
1119 if (field == seg_valid) {
1120 lua_pushboolean(L, 0);
1121 return 1;
1122 }
1123 return luaL_error(L, "accessed seg_t doesn't exist anymore.");
1124 }
1125
1126 switch(field)
1127 {
1128 case seg_valid: // valid
1129 lua_pushboolean(L, 1);
1130 return 1;
1131 case seg_v1:
1132 LUA_PushUserdata(L, seg->v1, META_VERTEX);
1133 return 1;
1134 case seg_v2:
1135 LUA_PushUserdata(L, seg->v2, META_VERTEX);
1136 return 1;
1137 case seg_side:
1138 lua_pushinteger(L, seg->side);
1139 return 1;
1140 case seg_offset:
1141 lua_pushfixed(L, seg->offset);
1142 return 1;
1143 case seg_angle:
1144 lua_pushangle(L, seg->angle);
1145 return 1;
1146 case seg_sidedef:
1147 LUA_PushUserdata(L, seg->sidedef, META_SIDE);
1148 return 1;
1149 case seg_linedef:
1150 LUA_PushUserdata(L, seg->linedef, META_LINE);
1151 return 1;
1152 case seg_frontsector:
1153 LUA_PushUserdata(L, seg->frontsector, META_SECTOR);
1154 return 1;
1155 case seg_backsector:
1156 LUA_PushUserdata(L, seg->backsector, META_SECTOR);
1157 return 1;
1158 case seg_polyseg:
1159 LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ);
1160 return 1;
1161 }
1162 return 0;
1163 }
1164
seg_num(lua_State * L)1165 static int seg_num(lua_State *L)
1166 {
1167 seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
1168 lua_pushinteger(L, seg-segs);
1169 return 1;
1170 }
1171
1172 ////////////
1173 // node_t //
1174 ////////////
1175
node_get(lua_State * L)1176 static int node_get(lua_State *L)
1177 {
1178 node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
1179 enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt);
1180
1181 if (!node)
1182 {
1183 if (field == node_valid) {
1184 lua_pushboolean(L, 0);
1185 return 1;
1186 }
1187 return luaL_error(L, "accessed node_t doesn't exist anymore.");
1188 }
1189
1190 switch(field)
1191 {
1192 case node_valid: // valid
1193 lua_pushboolean(L, 1);
1194 return 1;
1195 case node_x:
1196 lua_pushfixed(L, node->x);
1197 return 1;
1198 case node_y:
1199 lua_pushfixed(L, node->y);
1200 return 1;
1201 case node_dx:
1202 lua_pushfixed(L, node->x);
1203 return 1;
1204 case node_dy:
1205 lua_pushfixed(L, node->x);
1206 return 1;
1207 case node_bbox:
1208 LUA_PushUserdata(L, node->bbox, META_NODEBBOX);
1209 return 1;
1210 case node_children:
1211 LUA_PushUserdata(L, node->children, META_NODECHILDREN);
1212 return 1;
1213 }
1214 return 0;
1215 }
1216
node_num(lua_State * L)1217 static int node_num(lua_State *L)
1218 {
1219 node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
1220 lua_pushinteger(L, node-nodes);
1221 return 1;
1222 }
1223
1224 ///////////////
1225 // node.bbox //
1226 ///////////////
1227
1228 /*
1229 // node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3
1230 // NOTE: 2D arrays are NOT double pointers,
1231 // the second bbox will be directly after the first in memory (hence the way the bbox is pushed here)
1232 // this function handles the [i] part, bbox_get handles the [j] part
1233 static int nodebbox_get(lua_State *L)
1234 {
1235 fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
1236 int i;
1237 lua_settop(L, 2);
1238 if (!lua_isnumber(L, 2))
1239 {
1240 int field = luaL_checkoption(L, 2, NULL, valid_opt);
1241 if (!bbox)
1242 {
1243 if (field == 0) {
1244 lua_pushboolean(L, 0);
1245 return 1;
1246 }
1247 return luaL_error(L, "accessed node_t doesn't exist anymore.");
1248 } else if (field == 0) {
1249 lua_pushboolean(L, 1);
1250 return 1;
1251 }
1252 }
1253
1254 i = lua_tointeger(L, 2);
1255 if (i < 0 || i > 1)
1256 return 0;
1257 LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX);
1258 return 1;
1259 }
1260 */
nodebbox_call(lua_State * L)1261 static int nodebbox_call(lua_State *L)
1262 {
1263 fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
1264 int i, j;
1265 int n = lua_gettop(L);
1266
1267 if (!bbox)
1268 return luaL_error(L, "accessed node bbox doesn't exist anymore.");
1269 if (n < 3)
1270 return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))");
1271 // get child
1272 if (!lua_isnumber(L, 2)) {
1273 enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
1274 switch (field) {
1275 case nodechild_right: i = 0; break;
1276 case nodechild_left: i = 1; break;
1277 default:
1278 return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2));
1279 }
1280 }
1281 else {
1282 i = lua_tointeger(L, 2);
1283 if (i < 0 || i > 1)
1284 return 0;
1285 }
1286 // get bbox coord
1287 if (!lua_isnumber(L, 3)) {
1288 enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt);
1289 switch (field) {
1290 case bbox_top: j = BOXTOP; break;
1291 case bbox_bottom: j = BOXBOTTOM; break;
1292 case bbox_left: j = BOXLEFT; break;
1293 case bbox_right: j = BOXRIGHT; break;
1294 default:
1295 return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3));
1296 }
1297 }
1298 else {
1299 j = lua_tointeger(L, 3);
1300 if (j < 0 || j > 3)
1301 return 0;
1302 }
1303 lua_pushinteger(L, bbox[i*4 + j]);
1304 return 1;
1305 }
1306
1307 /////////////////////
1308 // node.children[] //
1309 /////////////////////
1310
1311 // node.children[i]: i = 0 or 1
nodechildren_get(lua_State * L)1312 static int nodechildren_get(lua_State *L)
1313 {
1314 UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN));
1315 int i;
1316 lua_settop(L, 2);
1317 if (!lua_isnumber(L, 2))
1318 {
1319 enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
1320 if (!children)
1321 {
1322 if (field == nodechild_valid) {
1323 lua_pushboolean(L, 0);
1324 return 1;
1325 }
1326 return luaL_error(L, "accessed node_t doesn't exist anymore.");
1327 } else if (field == nodechild_valid) {
1328 lua_pushboolean(L, 1);
1329 return 1;
1330 } else switch (field) {
1331 case nodechild_right: i = 0; break;
1332 case nodechild_left: i = 1; break;
1333 default: return 0;
1334 }
1335 }
1336 else {
1337 i = lua_tointeger(L, 2);
1338 if (i < 0 || i > 1)
1339 return 0;
1340 }
1341 lua_pushinteger(L, children[i]);
1342 return 1;
1343 }
1344 #endif
1345
1346 //////////
1347 // bbox //
1348 //////////
1349
1350 // bounding box (aka fixed_t array with four elements)
1351 // NOTE: may be useful for polyobjects or other things later
bbox_get(lua_State * L)1352 static int bbox_get(lua_State *L)
1353 {
1354 fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_BBOX));
1355 int i;
1356 lua_settop(L, 2);
1357 if (!lua_isnumber(L, 2))
1358 {
1359 enum bbox_e field = luaL_checkoption(L, 2, bbox_opt[0], bbox_opt);
1360 if (!bbox)
1361 {
1362 if (field == bbox_valid) {
1363 lua_pushboolean(L, 0);
1364 return 1;
1365 }
1366 return luaL_error(L, "accessed bbox doesn't exist anymore.");
1367 } else if (field == bbox_valid) {
1368 lua_pushboolean(L, 1);
1369 return 1;
1370 } else switch (field) {
1371 case bbox_top: i = BOXTOP; break;
1372 case bbox_bottom: i = BOXBOTTOM; break;
1373 case bbox_left: i = BOXLEFT; break;
1374 case bbox_right: i = BOXRIGHT; break;
1375 default: return 0;
1376 }
1377 }
1378 else {
1379 i = lua_tointeger(L, 2);
1380 if (i < 0 || i > 3)
1381 return 0;
1382 }
1383 lua_pushinteger(L, bbox[i]);
1384 return 1;
1385 }
1386
1387 ///////////////
1388 // sectors[] //
1389 ///////////////
1390
lib_iterateSectors(lua_State * L)1391 static int lib_iterateSectors(lua_State *L)
1392 {
1393 size_t i = 0;
1394 INLEVEL
1395 if (lua_gettop(L) < 2)
1396 return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'.");
1397 lua_settop(L, 2);
1398 lua_remove(L, 1); // state is unused.
1399 if (!lua_isnil(L, 1))
1400 i = (size_t)(*((sector_t **)luaL_checkudata(L, 1, META_SECTOR)) - sectors)+1;
1401 if (i < numsectors)
1402 {
1403 LUA_PushUserdata(L, §ors[i], META_SECTOR);
1404 return 1;
1405 }
1406 return 0;
1407 }
1408
lib_getSector(lua_State * L)1409 static int lib_getSector(lua_State *L)
1410 {
1411 INLEVEL
1412 if (lua_isnumber(L, 2))
1413 {
1414 size_t i = lua_tointeger(L, 2);
1415 if (i >= numsectors)
1416 return 0;
1417 LUA_PushUserdata(L, §ors[i], META_SECTOR);
1418 return 1;
1419 }
1420 return 0;
1421 }
1422
lib_numsectors(lua_State * L)1423 static int lib_numsectors(lua_State *L)
1424 {
1425 lua_pushinteger(L, numsectors);
1426 return 1;
1427 }
1428
1429 //////////////////
1430 // subsectors[] //
1431 //////////////////
1432
lib_iterateSubsectors(lua_State * L)1433 static int lib_iterateSubsectors(lua_State *L)
1434 {
1435 size_t i = 0;
1436 INLEVEL
1437 if (lua_gettop(L) < 2)
1438 return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'.");
1439 lua_settop(L, 2);
1440 lua_remove(L, 1); // state is unused.
1441 if (!lua_isnil(L, 1))
1442 i = (size_t)(*((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)) - subsectors)+1;
1443 if (i < numsubsectors)
1444 {
1445 LUA_PushUserdata(L, &subsectors[i], META_SUBSECTOR);
1446 return 1;
1447 }
1448 return 0;
1449 }
1450
lib_getSubsector(lua_State * L)1451 static int lib_getSubsector(lua_State *L)
1452 {
1453 int field;
1454 INLEVEL
1455 lua_settop(L, 2);
1456 lua_remove(L, 1); // dummy userdata table is unused.
1457 if (lua_isnumber(L, 1))
1458 {
1459 size_t i = lua_tointeger(L, 1);
1460 if (i >= numsubsectors)
1461 return 0;
1462 LUA_PushUserdata(L, &subsectors[i], META_SUBSECTOR);
1463 return 1;
1464 }
1465 field = luaL_checkoption(L, 1, NULL, array_opt);
1466 switch(field)
1467 {
1468 case 0: // iterate
1469 lua_pushcfunction(L, lib_iterateSubsectors);
1470 return 1;
1471 }
1472 return 0;
1473 }
1474
lib_numsubsectors(lua_State * L)1475 static int lib_numsubsectors(lua_State *L)
1476 {
1477 lua_pushinteger(L, numsubsectors);
1478 return 1;
1479 }
1480
1481 /////////////
1482 // lines[] //
1483 /////////////
1484
lib_iterateLines(lua_State * L)1485 static int lib_iterateLines(lua_State *L)
1486 {
1487 size_t i = 0;
1488 INLEVEL
1489 if (lua_gettop(L) < 2)
1490 return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'.");
1491 lua_settop(L, 2);
1492 lua_remove(L, 1); // state is unused.
1493 if (!lua_isnil(L, 1))
1494 i = (size_t)(*((line_t **)luaL_checkudata(L, 1, META_LINE)) - lines)+1;
1495 if (i < numlines)
1496 {
1497 LUA_PushUserdata(L, &lines[i], META_LINE);
1498 return 1;
1499 }
1500 return 0;
1501 }
1502
lib_getLine(lua_State * L)1503 static int lib_getLine(lua_State *L)
1504 {
1505 INLEVEL
1506 if (lua_isnumber(L, 2))
1507 {
1508 size_t i = lua_tointeger(L, 2);
1509 if (i >= numlines)
1510 return 0;
1511 LUA_PushUserdata(L, &lines[i], META_LINE);
1512 return 1;
1513 }
1514 return 0;
1515 }
1516
lib_numlines(lua_State * L)1517 static int lib_numlines(lua_State *L)
1518 {
1519 lua_pushinteger(L, numlines);
1520 return 1;
1521 }
1522
1523 /////////////
1524 // sides[] //
1525 /////////////
1526
lib_iterateSides(lua_State * L)1527 static int lib_iterateSides(lua_State *L)
1528 {
1529 size_t i = 0;
1530 INLEVEL
1531 if (lua_gettop(L) < 2)
1532 return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'.");
1533 lua_settop(L, 2);
1534 lua_remove(L, 1); // state is unused.
1535 if (!lua_isnil(L, 1))
1536 i = (size_t)(*((side_t **)luaL_checkudata(L, 1, META_SIDE)) - sides)+1;
1537 if (i < numsides)
1538 {
1539 LUA_PushUserdata(L, &sides[i], META_SIDE);
1540 return 1;
1541 }
1542 return 0;
1543 }
1544
lib_getSide(lua_State * L)1545 static int lib_getSide(lua_State *L)
1546 {
1547 int field;
1548 INLEVEL
1549 lua_settop(L, 2);
1550 lua_remove(L, 1); // dummy userdata table is unused.
1551 if (lua_isnumber(L, 1))
1552 {
1553 size_t i = lua_tointeger(L, 1);
1554 if (i >= numsides)
1555 return 0;
1556 LUA_PushUserdata(L, &sides[i], META_SIDE);
1557 return 1;
1558 }
1559 field = luaL_checkoption(L, 1, NULL, array_opt);
1560 switch(field)
1561 {
1562 case 0: // iterate
1563 lua_pushcfunction(L, lib_iterateSides);
1564 return 1;
1565 }
1566 return 0;
1567 }
1568
lib_numsides(lua_State * L)1569 static int lib_numsides(lua_State *L)
1570 {
1571 lua_pushinteger(L, numsides);
1572 return 1;
1573 }
1574
1575 ////////////////
1576 // vertexes[] //
1577 ////////////////
1578
lib_iterateVertexes(lua_State * L)1579 static int lib_iterateVertexes(lua_State *L)
1580 {
1581 size_t i = 0;
1582 INLEVEL
1583 if (lua_gettop(L) < 2)
1584 return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'.");
1585 lua_settop(L, 2);
1586 lua_remove(L, 1); // state is unused.
1587 if (!lua_isnil(L, 1))
1588 i = (size_t)(*((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)) - vertexes)+1;
1589 if (i < numvertexes)
1590 {
1591 LUA_PushUserdata(L, &vertexes[i], META_VERTEX);
1592 return 1;
1593 }
1594 return 0;
1595 }
1596
lib_getVertex(lua_State * L)1597 static int lib_getVertex(lua_State *L)
1598 {
1599 int field;
1600 INLEVEL
1601 lua_settop(L, 2);
1602 lua_remove(L, 1); // dummy userdata table is unused.
1603 if (lua_isnumber(L, 1))
1604 {
1605 size_t i = lua_tointeger(L, 1);
1606 if (i >= numvertexes)
1607 return 0;
1608 LUA_PushUserdata(L, &vertexes[i], META_VERTEX);
1609 return 1;
1610 }
1611 field = luaL_checkoption(L, 1, NULL, array_opt);
1612 switch(field)
1613 {
1614 case 0: // iterate
1615 lua_pushcfunction(L, lib_iterateVertexes);
1616 return 1;
1617 }
1618 return 0;
1619 }
1620
lib_numvertexes(lua_State * L)1621 static int lib_numvertexes(lua_State *L)
1622 {
1623 lua_pushinteger(L, numvertexes);
1624 return 1;
1625 }
1626
1627 #ifdef HAVE_LUA_SEGS
1628
1629 ////////////
1630 // segs[] //
1631 ////////////
1632
lib_iterateSegs(lua_State * L)1633 static int lib_iterateSegs(lua_State *L)
1634 {
1635 size_t i = 0;
1636 INLEVEL
1637 if (lua_gettop(L) < 2)
1638 return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
1639 lua_settop(L, 2);
1640 lua_remove(L, 1); // state is unused.
1641 if (!lua_isnil(L, 1))
1642 i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1;
1643 if (i < numsegs)
1644 {
1645 LUA_PushUserdata(L, &segs[i], META_SEG);
1646 return 1;
1647 }
1648 return 0;
1649 }
1650
lib_getSeg(lua_State * L)1651 static int lib_getSeg(lua_State *L)
1652 {
1653 int field;
1654 INLEVEL
1655 lua_settop(L, 2);
1656 lua_remove(L, 1); // dummy userdata table is unused.
1657 if (lua_isnumber(L, 1))
1658 {
1659 size_t i = lua_tointeger(L, 1);
1660 if (i >= numsegs)
1661 return 0;
1662 LUA_PushUserdata(L, &segs[i], META_SEG);
1663 return 1;
1664 }
1665 field = luaL_checkoption(L, 1, NULL, array_opt);
1666 switch(field)
1667 {
1668 case 0: // iterate
1669 lua_pushcfunction(L, lib_iterateSegs);
1670 return 1;
1671 }
1672 return 0;
1673 }
1674
lib_numsegs(lua_State * L)1675 static int lib_numsegs(lua_State *L)
1676 {
1677 lua_pushinteger(L, numsegs);
1678 return 1;
1679 }
1680
1681 /////////////
1682 // nodes[] //
1683 /////////////
1684
lib_iterateNodes(lua_State * L)1685 static int lib_iterateNodes(lua_State *L)
1686 {
1687 size_t i = 0;
1688 INLEVEL
1689 if (lua_gettop(L) < 2)
1690 return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
1691 lua_settop(L, 2);
1692 lua_remove(L, 1); // state is unused.
1693 if (!lua_isnil(L, 1))
1694 i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1;
1695 if (i < numsegs)
1696 {
1697 LUA_PushUserdata(L, &nodes[i], META_NODE);
1698 return 1;
1699 }
1700 return 0;
1701 }
1702
lib_getNode(lua_State * L)1703 static int lib_getNode(lua_State *L)
1704 {
1705 int field;
1706 INLEVEL
1707 lua_settop(L, 2);
1708 lua_remove(L, 1); // dummy userdata table is unused.
1709 if (lua_isnumber(L, 1))
1710 {
1711 size_t i = lua_tointeger(L, 1);
1712 if (i >= numnodes)
1713 return 0;
1714 LUA_PushUserdata(L, &nodes[i], META_NODE);
1715 return 1;
1716 }
1717 field = luaL_checkoption(L, 1, NULL, array_opt);
1718 switch(field)
1719 {
1720 case 0: // iterate
1721 lua_pushcfunction(L, lib_iterateNodes);
1722 return 1;
1723 }
1724 return 0;
1725 }
1726
lib_numnodes(lua_State * L)1727 static int lib_numnodes(lua_State *L)
1728 {
1729 lua_pushinteger(L, numnodes);
1730 return 1;
1731 }
1732 #endif
1733
1734 //////////////
1735 // ffloor_t //
1736 //////////////
1737
ffloor_get(lua_State * L)1738 static int ffloor_get(lua_State *L)
1739 {
1740 ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
1741 enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
1742 INT16 i;
1743
1744 if (!ffloor)
1745 {
1746 if (field == ffloor_valid) {
1747 lua_pushboolean(L, 0);
1748 return 1;
1749 }
1750 return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
1751 }
1752
1753 switch(field)
1754 {
1755 case ffloor_valid: // valid
1756 lua_pushboolean(L, 1);
1757 return 1;
1758 case ffloor_topheight:
1759 lua_pushfixed(L, *ffloor->topheight);
1760 return 1;
1761 case ffloor_toppic: { // toppic
1762 levelflat_t *levelflat = &levelflats[*ffloor->toppic];
1763 for (i = 0; i < 8; i++)
1764 if (!levelflat->name[i])
1765 break;
1766 lua_pushlstring(L, levelflat->name, i);
1767 return 1;
1768 }
1769 case ffloor_toplightlevel:
1770 lua_pushinteger(L, *ffloor->toplightlevel);
1771 return 1;
1772 case ffloor_bottomheight:
1773 lua_pushfixed(L, *ffloor->bottomheight);
1774 return 1;
1775 case ffloor_bottompic: { // bottompic
1776 levelflat_t *levelflat = &levelflats[*ffloor->bottompic];
1777 for (i = 0; i < 8; i++)
1778 if (!levelflat->name[i])
1779 break;
1780 lua_pushlstring(L, levelflat->name, i);
1781 return 1;
1782 }
1783 case ffloor_tslope:
1784 LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE);
1785 return 1;
1786 case ffloor_bslope:
1787 LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE);
1788 return 1;
1789 case ffloor_sector:
1790 LUA_PushUserdata(L, §ors[ffloor->secnum], META_SECTOR);
1791 return 1;
1792 case ffloor_flags:
1793 lua_pushinteger(L, ffloor->flags);
1794 return 1;
1795 case ffloor_master:
1796 LUA_PushUserdata(L, ffloor->master, META_LINE);
1797 return 1;
1798 case ffloor_target:
1799 LUA_PushUserdata(L, ffloor->target, META_SECTOR);
1800 return 1;
1801 case ffloor_next:
1802 LUA_PushUserdata(L, ffloor->next, META_FFLOOR);
1803 return 1;
1804 case ffloor_prev:
1805 LUA_PushUserdata(L, ffloor->prev, META_FFLOOR);
1806 return 1;
1807 case ffloor_alpha:
1808 lua_pushinteger(L, ffloor->alpha);
1809 return 1;
1810 }
1811 return 0;
1812 }
1813
ffloor_set(lua_State * L)1814 static int ffloor_set(lua_State *L)
1815 {
1816 ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
1817 enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
1818
1819 if (!ffloor)
1820 return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
1821
1822 if (hud_running)
1823 return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!");
1824 if (hook_cmd_running)
1825 return luaL_error(L, "Do not alter ffloor_t in CMD building code!");
1826
1827 switch(field)
1828 {
1829 case ffloor_valid: // valid
1830 case ffloor_tslope: // t_slope
1831 case ffloor_bslope: // b_slope
1832 case ffloor_sector: // sector
1833 case ffloor_master: // master
1834 case ffloor_target: // target
1835 case ffloor_next: // next
1836 case ffloor_prev: // prev
1837 default:
1838 return luaL_error(L, "ffloor_t field " LUA_QS " cannot be set.", ffloor_opt[field]);
1839 case ffloor_topheight: { // topheight
1840 boolean flag;
1841 fixed_t lastpos = *ffloor->topheight;
1842 mobj_t *ptmthing = tmthing;
1843 sector_t *sector = §ors[ffloor->secnum];
1844 sector->ceilingheight = luaL_checkfixed(L, 3);
1845 flag = P_CheckSector(sector, true);
1846 if (flag && sector->numattached)
1847 {
1848 *ffloor->topheight = lastpos;
1849 P_CheckSector(sector, true);
1850 }
1851 P_SetTarget(&tmthing, ptmthing);
1852 break;
1853 }
1854 case ffloor_toppic:
1855 *ffloor->toppic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
1856 break;
1857 case ffloor_toplightlevel:
1858 *ffloor->toplightlevel = (INT16)luaL_checkinteger(L, 3);
1859 break;
1860 case ffloor_bottomheight: { // bottomheight
1861 boolean flag;
1862 fixed_t lastpos = *ffloor->bottomheight;
1863 mobj_t *ptmthing = tmthing;
1864 sector_t *sector = §ors[ffloor->secnum];
1865 sector->floorheight = luaL_checkfixed(L, 3);
1866 flag = P_CheckSector(sector, true);
1867 if (flag && sector->numattached)
1868 {
1869 *ffloor->bottomheight = lastpos;
1870 P_CheckSector(sector, true);
1871 }
1872 P_SetTarget(&tmthing, ptmthing);
1873 break;
1874 }
1875 case ffloor_bottompic:
1876 *ffloor->bottompic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
1877 break;
1878 case ffloor_flags: {
1879 ffloortype_e oldflags = ffloor->flags; // store FOF's old flags
1880 ffloor->flags = luaL_checkinteger(L, 3);
1881 if (ffloor->flags != oldflags)
1882 ffloor->target->moved = true; // reset target sector's lightlist
1883 break;
1884 }
1885 case ffloor_alpha:
1886 ffloor->alpha = (INT32)luaL_checkinteger(L, 3);
1887 break;
1888 }
1889 return 0;
1890 }
1891
1892 //////////////
1893 // pslope_t //
1894 //////////////
1895
slope_get(lua_State * L)1896 static int slope_get(lua_State *L)
1897 {
1898 pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
1899 enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
1900
1901 if (!slope)
1902 {
1903 if (field == slope_valid) {
1904 lua_pushboolean(L, 0);
1905 return 1;
1906 }
1907 return luaL_error(L, "accessed pslope_t doesn't exist anymore.");
1908 }
1909
1910 switch(field)
1911 {
1912 case slope_valid: // valid
1913 lua_pushboolean(L, 1);
1914 return 1;
1915 case slope_o: // o
1916 LUA_PushUserdata(L, &slope->o, META_VECTOR3);
1917 return 1;
1918 case slope_d: // d
1919 LUA_PushUserdata(L, &slope->d, META_VECTOR2);
1920 return 1;
1921 case slope_zdelta: // zdelta
1922 lua_pushfixed(L, slope->zdelta);
1923 return 1;
1924 case slope_normal: // normal
1925 LUA_PushUserdata(L, &slope->normal, META_VECTOR3);
1926 return 1;
1927 case slope_zangle: // zangle
1928 lua_pushangle(L, slope->zangle);
1929 return 1;
1930 case slope_xydirection: // xydirection
1931 lua_pushangle(L, slope->xydirection);
1932 return 1;
1933 case slope_flags: // flags
1934 lua_pushinteger(L, slope->flags);
1935 return 1;
1936 }
1937 return 0;
1938 }
1939
slope_set(lua_State * L)1940 static int slope_set(lua_State *L)
1941 {
1942 pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
1943 enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
1944
1945 if (!slope)
1946 return luaL_error(L, "accessed pslope_t doesn't exist anymore.");
1947
1948 if (hud_running)
1949 return luaL_error(L, "Do not alter pslope_t in HUD rendering code!");
1950 if (hook_cmd_running)
1951 return luaL_error(L, "Do not alter pslope_t in CMD building code!");
1952
1953 switch(field) // todo: reorganize this shit
1954 {
1955 case slope_valid: // valid
1956 case slope_d: // d
1957 case slope_flags: // flags
1958 case slope_normal: // normal
1959 default:
1960 return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]);
1961 case slope_o: { // o
1962 luaL_checktype(L, 3, LUA_TTABLE);
1963
1964 lua_getfield(L, 3, "x");
1965 if (lua_isnil(L, -1))
1966 {
1967 lua_pop(L, 1);
1968 lua_rawgeti(L, 3, 1);
1969 }
1970 if (!lua_isnil(L, -1))
1971 slope->o.x = luaL_checkfixed(L, -1);
1972 else
1973 slope->o.x = 0;
1974 lua_pop(L, 1);
1975
1976 lua_getfield(L, 3, "y");
1977 if (lua_isnil(L, -1))
1978 {
1979 lua_pop(L, 1);
1980 lua_rawgeti(L, 3, 2);
1981 }
1982 if (!lua_isnil(L, -1))
1983 slope->o.y = luaL_checkfixed(L, -1);
1984 else
1985 slope->o.y = 0;
1986 lua_pop(L, 1);
1987
1988 lua_getfield(L, 3, "z");
1989 if (lua_isnil(L, -1))
1990 {
1991 lua_pop(L, 1);
1992 lua_rawgeti(L, 3, 3);
1993 }
1994 if (!lua_isnil(L, -1))
1995 slope->o.z = luaL_checkfixed(L, -1);
1996 else
1997 slope->o.z = 0;
1998 lua_pop(L, 1);
1999 break;
2000 }
2001 case slope_zdelta: { // zdelta, this is temp until i figure out wtf to do
2002 slope->zdelta = luaL_checkfixed(L, 3);
2003 slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, -slope->zdelta);
2004 P_CalculateSlopeNormal(slope);
2005 break;
2006 }
2007 case slope_zangle: { // zangle
2008 angle_t zangle = luaL_checkangle(L, 3);
2009 if (zangle == ANGLE_90 || zangle == ANGLE_270)
2010 return luaL_error(L, "invalid zangle for slope!");
2011 slope->zangle = zangle;
2012 slope->zdelta = -FINETANGENT(((slope->zangle+ANGLE_90)>>ANGLETOFINESHIFT) & 4095);
2013 P_CalculateSlopeNormal(slope);
2014 break;
2015 }
2016 case slope_xydirection: // xydirection
2017 slope->xydirection = luaL_checkangle(L, 3);
2018 slope->d.x = -FINECOSINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK);
2019 slope->d.y = -FINESINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK);
2020 P_CalculateSlopeNormal(slope);
2021 break;
2022 }
2023 return 0;
2024 }
2025
2026 ///////////////
2027 // vector*_t //
2028 ///////////////
2029
vector2_get(lua_State * L)2030 static int vector2_get(lua_State *L)
2031 {
2032 vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2));
2033 enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
2034
2035 if (!vec)
2036 return luaL_error(L, "accessed vector2_t doesn't exist anymore.");
2037
2038 switch(field)
2039 {
2040 case vector_x: lua_pushfixed(L, vec->x); return 1;
2041 case vector_y: lua_pushfixed(L, vec->y); return 1;
2042 default: break;
2043 }
2044
2045 return 0;
2046 }
2047
vector3_get(lua_State * L)2048 static int vector3_get(lua_State *L)
2049 {
2050 vector3_t *vec = *((vector3_t **)luaL_checkudata(L, 1, META_VECTOR3));
2051 enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
2052
2053 if (!vec)
2054 return luaL_error(L, "accessed vector3_t doesn't exist anymore.");
2055
2056 switch(field)
2057 {
2058 case vector_x: lua_pushfixed(L, vec->x); return 1;
2059 case vector_y: lua_pushfixed(L, vec->y); return 1;
2060 case vector_z: lua_pushfixed(L, vec->z); return 1;
2061 default: break;
2062 }
2063
2064 return 0;
2065 }
2066
2067 /////////////////////
2068 // mapheaderinfo[] //
2069 /////////////////////
2070
lib_getMapheaderinfo(lua_State * L)2071 static int lib_getMapheaderinfo(lua_State *L)
2072 {
2073 // i -> mapheaderinfo[i-1]
2074
2075 //int field;
2076 lua_settop(L, 2);
2077 lua_remove(L, 1); // dummy userdata table is unused.
2078 if (lua_isnumber(L, 1))
2079 {
2080 size_t i = lua_tointeger(L, 1)-1;
2081 if (i >= NUMMAPS)
2082 return 0;
2083 LUA_PushUserdata(L, mapheaderinfo[i], META_MAPHEADER);
2084 //CONS_Printf(mapheaderinfo[i]->lvlttl);
2085 return 1;
2086 }/*
2087 field = luaL_checkoption(L, 1, NULL, array_opt);
2088 switch(field)
2089 {
2090 case 0: // iterate
2091 lua_pushcfunction(L, lib_iterateSubsectors);
2092 return 1;
2093 }*/
2094 return 0;
2095 }
2096
lib_nummapheaders(lua_State * L)2097 static int lib_nummapheaders(lua_State *L)
2098 {
2099 lua_pushinteger(L, NUMMAPS);
2100 return 1;
2101 }
2102
2103 /////////////////
2104 // mapheader_t //
2105 /////////////////
2106
mapheaderinfo_get(lua_State * L)2107 static int mapheaderinfo_get(lua_State *L)
2108 {
2109 mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
2110 const char *field = luaL_checkstring(L, 2);
2111 INT16 i;
2112 if (fastcmp(field,"lvlttl"))
2113 lua_pushstring(L, header->lvlttl);
2114 else if (fastcmp(field,"subttl"))
2115 lua_pushstring(L, header->subttl);
2116 else if (fastcmp(field,"actnum"))
2117 lua_pushinteger(L, header->actnum);
2118 else if (fastcmp(field,"typeoflevel"))
2119 lua_pushinteger(L, header->typeoflevel);
2120 else if (fastcmp(field,"nextlevel"))
2121 lua_pushinteger(L, header->nextlevel);
2122 else if (fastcmp(field,"marathonnext"))
2123 lua_pushinteger(L, header->marathonnext);
2124 else if (fastcmp(field,"keywords"))
2125 lua_pushstring(L, header->keywords);
2126 else if (fastcmp(field,"musname"))
2127 lua_pushstring(L, header->musname);
2128 else if (fastcmp(field,"mustrack"))
2129 lua_pushinteger(L, header->mustrack);
2130 else if (fastcmp(field,"muspos"))
2131 lua_pushinteger(L, header->muspos);
2132 else if (fastcmp(field,"musinterfadeout"))
2133 lua_pushinteger(L, header->musinterfadeout);
2134 else if (fastcmp(field,"musintername"))
2135 lua_pushstring(L, header->musintername);
2136 else if (fastcmp(field,"muspostbossname"))
2137 lua_pushstring(L, header->muspostbossname);
2138 else if (fastcmp(field,"muspostbosstrack"))
2139 lua_pushinteger(L, header->muspostbosstrack);
2140 else if (fastcmp(field,"muspostbosspos"))
2141 lua_pushinteger(L, header->muspostbosspos);
2142 else if (fastcmp(field,"muspostbossfadein"))
2143 lua_pushinteger(L, header->muspostbossfadein);
2144 else if (fastcmp(field,"musforcereset"))
2145 lua_pushinteger(L, header->musforcereset);
2146 else if (fastcmp(field,"forcecharacter"))
2147 lua_pushstring(L, header->forcecharacter);
2148 else if (fastcmp(field,"weather"))
2149 lua_pushinteger(L, header->weather);
2150 else if (fastcmp(field,"skynum"))
2151 lua_pushinteger(L, header->skynum);
2152 else if (fastcmp(field,"skybox_scalex"))
2153 lua_pushinteger(L, header->skybox_scalex);
2154 else if (fastcmp(field,"skybox_scaley"))
2155 lua_pushinteger(L, header->skybox_scaley);
2156 else if (fastcmp(field,"skybox_scalez"))
2157 lua_pushinteger(L, header->skybox_scalez);
2158 else if (fastcmp(field,"interscreen")) {
2159 for (i = 0; i < 8; i++)
2160 if (!header->interscreen[i])
2161 break;
2162 lua_pushlstring(L, header->interscreen, i);
2163 } else if (fastcmp(field,"runsoc"))
2164 lua_pushstring(L, header->runsoc);
2165 else if (fastcmp(field,"scriptname"))
2166 lua_pushstring(L, header->scriptname);
2167 else if (fastcmp(field,"precutscenenum"))
2168 lua_pushinteger(L, header->precutscenenum);
2169 else if (fastcmp(field,"cutscenenum"))
2170 lua_pushinteger(L, header->cutscenenum);
2171 else if (fastcmp(field,"countdown"))
2172 lua_pushinteger(L, header->countdown);
2173 else if (fastcmp(field,"palette"))
2174 lua_pushinteger(L, header->palette);
2175 else if (fastcmp(field,"numlaps"))
2176 lua_pushinteger(L, header->numlaps);
2177 else if (fastcmp(field,"unlockrequired"))
2178 lua_pushinteger(L, header->unlockrequired);
2179 else if (fastcmp(field,"levelselect"))
2180 lua_pushinteger(L, header->levelselect);
2181 else if (fastcmp(field,"bonustype"))
2182 lua_pushinteger(L, header->bonustype);
2183 else if (fastcmp(field,"ltzzpatch"))
2184 lua_pushstring(L, header->ltzzpatch);
2185 else if (fastcmp(field,"ltzztext"))
2186 lua_pushstring(L, header->ltzztext);
2187 else if (fastcmp(field,"ltactdiamond"))
2188 lua_pushstring(L, header->ltactdiamond);
2189 else if (fastcmp(field,"maxbonuslives"))
2190 lua_pushinteger(L, header->maxbonuslives);
2191 else if (fastcmp(field,"levelflags"))
2192 lua_pushinteger(L, header->levelflags);
2193 else if (fastcmp(field,"menuflags"))
2194 lua_pushinteger(L, header->menuflags);
2195 else if (fastcmp(field,"selectheading"))
2196 lua_pushstring(L, header->selectheading);
2197 else if (fastcmp(field,"startrings"))
2198 lua_pushinteger(L, header->startrings);
2199 else if (fastcmp(field, "sstimer"))
2200 lua_pushinteger(L, header->sstimer);
2201 else if (fastcmp(field, "ssspheres"))
2202 lua_pushinteger(L, header->ssspheres);
2203 else if (fastcmp(field, "gravity"))
2204 lua_pushfixed(L, header->gravity);
2205 // TODO add support for reading numGradedMares and grades
2206 else {
2207 // Read custom vars now
2208 // (note: don't include the "LUA." in your lua scripts!)
2209 UINT8 j = 0;
2210 for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j);
2211
2212 if(j < header->numCustomOptions)
2213 lua_pushstring(L, header->customopts[j].value);
2214 else
2215 lua_pushnil(L);
2216 }
2217 return 1;
2218 }
2219
LUA_MapLib(lua_State * L)2220 int LUA_MapLib(lua_State *L)
2221 {
2222 luaL_newmetatable(L, META_SECTORLINES);
2223 lua_pushcfunction(L, sectorlines_get);
2224 lua_setfield(L, -2, "__index");
2225
2226 lua_pushcfunction(L, sectorlines_num);
2227 lua_setfield(L, -2, "__len");
2228 lua_pop(L, 1);
2229
2230 luaL_newmetatable(L, META_SECTOR);
2231 lua_pushcfunction(L, sector_get);
2232 lua_setfield(L, -2, "__index");
2233
2234 lua_pushcfunction(L, sector_set);
2235 lua_setfield(L, -2, "__newindex");
2236
2237 lua_pushcfunction(L, sector_num);
2238 lua_setfield(L, -2, "__len");
2239 lua_pop(L, 1);
2240
2241 luaL_newmetatable(L, META_SUBSECTOR);
2242 lua_pushcfunction(L, subsector_get);
2243 lua_setfield(L, -2, "__index");
2244
2245 lua_pushcfunction(L, subsector_num);
2246 lua_setfield(L, -2, "__len");
2247 lua_pop(L, 1);
2248
2249 luaL_newmetatable(L, META_LINE);
2250 lua_pushcfunction(L, line_get);
2251 lua_setfield(L, -2, "__index");
2252
2253 lua_pushcfunction(L, line_num);
2254 lua_setfield(L, -2, "__len");
2255 lua_pop(L, 1);
2256
2257 luaL_newmetatable(L, META_LINEARGS);
2258 lua_pushcfunction(L, lineargs_get);
2259 lua_setfield(L, -2, "__index");
2260
2261 lua_pushcfunction(L, lineargs_len);
2262 lua_setfield(L, -2, "__len");
2263 lua_pop(L, 1);
2264
2265 luaL_newmetatable(L, META_LINESTRINGARGS);
2266 lua_pushcfunction(L, linestringargs_get);
2267 lua_setfield(L, -2, "__index");
2268
2269 lua_pushcfunction(L, linestringargs_len);
2270 lua_setfield(L, -2, "__len");
2271 lua_pop(L, 1);
2272
2273 luaL_newmetatable(L, META_SIDENUM);
2274 lua_pushcfunction(L, sidenum_get);
2275 lua_setfield(L, -2, "__index");
2276 lua_pop(L, 1);
2277
2278 luaL_newmetatable(L, META_SIDE);
2279 lua_pushcfunction(L, side_get);
2280 lua_setfield(L, -2, "__index");
2281
2282 lua_pushcfunction(L, side_set);
2283 lua_setfield(L, -2, "__newindex");
2284
2285 lua_pushcfunction(L, side_num);
2286 lua_setfield(L, -2, "__len");
2287 lua_pop(L, 1);
2288
2289 luaL_newmetatable(L, META_VERTEX);
2290 lua_pushcfunction(L, vertex_get);
2291 lua_setfield(L, -2, "__index");
2292
2293 lua_pushcfunction(L, vertex_num);
2294 lua_setfield(L, -2, "__len");
2295 lua_pop(L, 1);
2296
2297 luaL_newmetatable(L, META_FFLOOR);
2298 lua_pushcfunction(L, ffloor_get);
2299 lua_setfield(L, -2, "__index");
2300
2301 lua_pushcfunction(L, ffloor_set);
2302 lua_setfield(L, -2, "__newindex");
2303 lua_pop(L, 1);
2304
2305 #ifdef HAVE_LUA_SEGS
2306 luaL_newmetatable(L, META_SEG);
2307 lua_pushcfunction(L, seg_get);
2308 lua_setfield(L, -2, "__index");
2309
2310 lua_pushcfunction(L, seg_num);
2311 lua_setfield(L, -2, "__len");
2312 lua_pop(L, 1);
2313
2314 luaL_newmetatable(L, META_NODE);
2315 lua_pushcfunction(L, node_get);
2316 lua_setfield(L, -2, "__index");
2317
2318 lua_pushcfunction(L, node_num);
2319 lua_setfield(L, -2, "__len");
2320 lua_pop(L, 1);
2321
2322 luaL_newmetatable(L, META_NODEBBOX);
2323 //lua_pushcfunction(L, nodebbox_get);
2324 //lua_setfield(L, -2, "__index");
2325 lua_pushcfunction(L, nodebbox_call);
2326 lua_setfield(L, -2, "__call");
2327 lua_pop(L, 1);
2328
2329 luaL_newmetatable(L, META_NODECHILDREN);
2330 lua_pushcfunction(L, nodechildren_get);
2331 lua_setfield(L, -2, "__index");
2332 lua_pop(L, 1);
2333 #endif
2334
2335 luaL_newmetatable(L, META_BBOX);
2336 lua_pushcfunction(L, bbox_get);
2337 lua_setfield(L, -2, "__index");
2338 lua_pop(L, 1);
2339
2340 luaL_newmetatable(L, META_SLOPE);
2341 lua_pushcfunction(L, slope_get);
2342 lua_setfield(L, -2, "__index");
2343
2344 lua_pushcfunction(L, slope_set);
2345 lua_setfield(L, -2, "__newindex");
2346 lua_pop(L, 1);
2347
2348 luaL_newmetatable(L, META_VECTOR2);
2349 lua_pushcfunction(L, vector2_get);
2350 lua_setfield(L, -2, "__index");
2351 lua_pop(L, 1);
2352
2353 luaL_newmetatable(L, META_VECTOR3);
2354 lua_pushcfunction(L, vector3_get);
2355 lua_setfield(L, -2, "__index");
2356 lua_pop(L, 1);
2357
2358 luaL_newmetatable(L, META_MAPHEADER);
2359 lua_pushcfunction(L, mapheaderinfo_get);
2360 lua_setfield(L, -2, "__index");
2361
2362 //lua_pushcfunction(L, mapheaderinfo_num);
2363 //lua_setfield(L, -2, "__len");
2364 lua_pop(L, 1);
2365
2366 LUA_PushTaggableObjectArray(L, "sectors",
2367 lib_iterateSectors,
2368 lib_getSector,
2369 lib_numsectors,
2370 tags_sectors,
2371 &numsectors, §ors,
2372 sizeof (sector_t), META_SECTOR);
2373
2374 lua_newuserdata(L, 0);
2375 lua_createtable(L, 0, 2);
2376 lua_pushcfunction(L, lib_getSubsector);
2377 lua_setfield(L, -2, "__index");
2378
2379 lua_pushcfunction(L, lib_numsubsectors);
2380 lua_setfield(L, -2, "__len");
2381 lua_setmetatable(L, -2);
2382 lua_setglobal(L, "subsectors");
2383
2384 LUA_PushTaggableObjectArray(L, "lines",
2385 lib_iterateLines,
2386 lib_getLine,
2387 lib_numlines,
2388 tags_lines,
2389 &numlines, &lines,
2390 sizeof (line_t), META_LINE);
2391
2392 lua_newuserdata(L, 0);
2393 lua_createtable(L, 0, 2);
2394 lua_pushcfunction(L, lib_getSide);
2395 lua_setfield(L, -2, "__index");
2396
2397 lua_pushcfunction(L, lib_numsides);
2398 lua_setfield(L, -2, "__len");
2399 lua_setmetatable(L, -2);
2400 lua_setglobal(L, "sides");
2401
2402 lua_newuserdata(L, 0);
2403 lua_createtable(L, 0, 2);
2404 lua_pushcfunction(L, lib_getVertex);
2405 lua_setfield(L, -2, "__index");
2406
2407 lua_pushcfunction(L, lib_numvertexes);
2408 lua_setfield(L, -2, "__len");
2409 lua_setmetatable(L, -2);
2410 lua_setglobal(L, "vertexes");
2411
2412 #ifdef HAVE_LUA_SEGS
2413 lua_newuserdata(L, 0);
2414 lua_createtable(L, 0, 2);
2415 lua_pushcfunction(L, lib_getSeg);
2416 lua_setfield(L, -2, "__index");
2417
2418 lua_pushcfunction(L, lib_numsegs);
2419 lua_setfield(L, -2, "__len");
2420 lua_setmetatable(L, -2);
2421 lua_setglobal(L, "segs");
2422
2423 lua_newuserdata(L, 0);
2424 lua_createtable(L, 0, 2);
2425 lua_pushcfunction(L, lib_getNode);
2426 lua_setfield(L, -2, "__index");
2427
2428 lua_pushcfunction(L, lib_numnodes);
2429 lua_setfield(L, -2, "__len");
2430 lua_setmetatable(L, -2);
2431 lua_setglobal(L, "nodes");
2432 #endif
2433
2434 lua_newuserdata(L, 0);
2435 lua_createtable(L, 0, 2);
2436 lua_pushcfunction(L, lib_getMapheaderinfo);
2437 lua_setfield(L, -2, "__index");
2438
2439 lua_pushcfunction(L, lib_nummapheaders);
2440 lua_setfield(L, -2, "__len");
2441 lua_setmetatable(L, -2);
2442 lua_setglobal(L, "mapheaderinfo");
2443 return 0;
2444 }
2445