1 /*
2 LUA_MAP.CPP
3
4 Copyright (C) 2008 by Gregory Smith
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 This license is contained in the file "COPYING",
17 which is included with this source code; it is available online at
18 http://www.gnu.org/licenses/gpl.html
19
20 Implements Lua map classes
21 */
22
23 #include <unordered_map>
24
25 #include "interface.h" // get_game_state
26 #include "network.h" // game_info
27 #include "lua_map.h"
28 #include "lua_monsters.h"
29 #include "lua_objects.h"
30 #include "lua_templates.h"
31 #include "lightsource.h"
32 #include "map.h"
33 #include "media.h"
34 #include "platforms.h"
35 #include "OGL_Setup.h"
36 #include "SoundManager.h"
37
38 #include "collection_definition.h"
39
40 #include <boost/bind.hpp>
41
42 #ifdef HAVE_LUA
43
44 char Lua_AmbientSound_Name[] = "ambient_sound";
45 char Lua_AmbientSounds_Name[] = "AmbientSounds";
46
47 extern collection_definition *get_collection_definition(short);
48
49 char Lua_Collection_Name[] = "collection";
50
Lua_Collection_Get_Bitmap_Count(lua_State * L)51 static int Lua_Collection_Get_Bitmap_Count(lua_State *L)
52 {
53 collection_definition *collection = get_collection_definition(Lua_Collection::Index(L, 1));
54 lua_pushnumber(L, collection->bitmap_count);
55 return 1;
56 }
57
58 const luaL_Reg Lua_Collection_Get[] = {
59 {"bitmap_count", Lua_Collection_Get_Bitmap_Count},
60 {0, 0},
61 };
62
63 char Lua_Collections_Name[] = "Collections";
64
65 char Lua_ControlPanelClass_Name[] = "control_panel_class";
66 char Lua_ControlPanelClasses_Name[] = "ControlPanelClasses";
67
68 char Lua_ControlPanelType_Name[] = "control_panel_type";
69
70 extern short get_panel_class(short panel_type);
71
72 // no devices.h, so copy this from devices.cpp:
73
74 enum // control panel sounds
75 {
76 _activating_sound,
77 _deactivating_sound,
78 _unusuable_sound,
79
80 NUMBER_OF_CONTROL_PANEL_SOUNDS
81 };
82
83 struct control_panel_definition
84 {
85 int16 _class;
86 uint16 flags;
87
88 int16 collection;
89 int16 active_shape, inactive_shape;
90
91 int16 sounds[NUMBER_OF_CONTROL_PANEL_SOUNDS];
92 _fixed sound_frequency;
93
94 int16 item;
95 };
96
97 extern control_panel_definition* get_control_panel_definition(int16);
98
Lua_ControlPanelType_Get_Active_Texture_Index(lua_State * L)99 static int Lua_ControlPanelType_Get_Active_Texture_Index(lua_State *L)
100 {
101 control_panel_definition *definition = get_control_panel_definition(Lua_ControlPanelType::Index(L, 1));
102 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(definition->active_shape));
103 return 1;
104 }
105
Lua_ControlPanelType_Get_Inactive_Texture_Index(lua_State * L)106 static int Lua_ControlPanelType_Get_Inactive_Texture_Index(lua_State *L)
107 {
108 control_panel_definition *definition = get_control_panel_definition(Lua_ControlPanelType::Index(L, 1));
109 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(definition->inactive_shape));
110 return 1;
111 }
112
Lua_ControlPanelType_Get_Class(lua_State * L)113 static int Lua_ControlPanelType_Get_Class(lua_State *L)
114 {
115 Lua_ControlPanelClass::Push(L, get_panel_class(Lua_ControlPanelType::Index(L, 1)));
116 return 1;
117 }
118
Lua_ControlPanelType_Get_Collection(lua_State * L)119 static int Lua_ControlPanelType_Get_Collection(lua_State *L)
120 {
121 control_panel_definition *definition = get_control_panel_definition(Lua_ControlPanelType::Index(L, 1));
122 Lua_Collection::Push(L, definition->collection);
123 return 1;
124 }
125
126 const luaL_Reg Lua_ControlPanelType_Get[] = {
127 {"active_texture_index", Lua_ControlPanelType_Get_Active_Texture_Index},
128 {"class", Lua_ControlPanelType_Get_Class},
129 {"collection", Lua_ControlPanelType_Get_Collection},
130 {"inactive_texture_index", Lua_ControlPanelType_Get_Inactive_Texture_Index},
131 {0, 0}
132 };
133
134 char Lua_ControlPanelTypes_Name[] = "ControlPanelTypes";
135
136 char Lua_DamageType_Name[] = "damage_type";
137 char Lua_DamageTypes_Name[] = "DamageTypes";
138
139 char Lua_Endpoint_Name[] = "endpoint";
140 typedef L_Class<Lua_Endpoint_Name> Lua_Endpoint;
141
Lua_Endpoint_Get_X(lua_State * L)142 static int Lua_Endpoint_Get_X(lua_State *L)
143 {
144 endpoint_data *endpoint = get_endpoint_data(Lua_Endpoint::Index(L, 1));
145 lua_pushnumber(L, (double) endpoint->vertex.x / WORLD_ONE);
146 return 1;
147 }
148
Lua_Endpoint_Get_Y(lua_State * L)149 static int Lua_Endpoint_Get_Y(lua_State *L)
150 {
151 endpoint_data *endpoint = get_endpoint_data(Lua_Endpoint::Index(L, 1));
152 lua_pushnumber(L, (double) endpoint->vertex.y / WORLD_ONE);
153 return 1;
154 }
155
Lua_Endpoint_Valid(int16 index)156 static bool Lua_Endpoint_Valid(int16 index)
157 {
158 return index >= 0 && index < EndpointList.size();
159 }
160
161 const luaL_Reg Lua_Endpoint_Get[] = {
162 {"x", Lua_Endpoint_Get_X},
163 {"y", Lua_Endpoint_Get_Y},
164 {0, 0}
165 };
166
167 char Lua_Endpoints_Name[] = "Endpoints";
168 typedef L_Container<Lua_Endpoints_Name, Lua_Endpoint> Lua_Endpoints;
Lua_Endpoints_Length()169 int16 Lua_Endpoints_Length() { return EndpointList.size(); }
170
171 char Lua_Line_Endpoints_Name[] = "line_endpoints";
172 typedef L_Class<Lua_Line_Endpoints_Name> Lua_Line_Endpoints;
173
Lua_Line_Endpoints_Get(lua_State * L)174 static int Lua_Line_Endpoints_Get(lua_State *L)
175 {
176 if (lua_isnumber(L, 2))
177 {
178 short line_index = Lua_Line::Index(L, 1);
179 line_data *line = get_line_data(line_index);
180 int endpoint_index = static_cast<int>(lua_tonumber(L, 2));
181 if (endpoint_index == 0 || endpoint_index == 1)
182 {
183 Lua_Endpoint::Push(L, line->endpoint_indexes[endpoint_index]);
184 }
185 else
186 {
187 lua_pushnil(L);
188 }
189 }
190
191 return 1;
192 }
193
Lua_Line_Endpoints_Length(lua_State * L)194 static int Lua_Line_Endpoints_Length(lua_State *L)
195 {
196 lua_pushnumber(L, 2);
197 return 1;
198 }
199
200 const luaL_Reg Lua_Line_Endpoints_Metatable[] = {
201 {"__index", Lua_Line_Endpoints_Get},
202 {"__len", Lua_Line_Endpoints_Length},
203 {0, 0}
204 };
205
206 char Lua_Line_Name[] = "line";
207
Lua_Line_Get_Clockwise_Polygon(lua_State * L)208 static int Lua_Line_Get_Clockwise_Polygon(lua_State *L)
209 {
210 Lua_Polygon::Push(L, get_line_data(Lua_Line::Index(L, 1))->clockwise_polygon_owner);
211 return 1;
212 }
213
Lua_Line_Get_Counterclockwise_Polygon(lua_State * L)214 static int Lua_Line_Get_Counterclockwise_Polygon(lua_State *L)
215 {
216 Lua_Polygon::Push(L, get_line_data(Lua_Line::Index(L, 1))->counterclockwise_polygon_owner);
217 return 1;
218 }
219
Lua_Line_Get_Clockwise_Side(lua_State * L)220 static int Lua_Line_Get_Clockwise_Side(lua_State *L)
221 {
222 Lua_Side::Push(L, get_line_data(Lua_Line::Index(L, 1))->clockwise_polygon_side_index);
223 return 1;
224 }
225
Lua_Line_Get_Counterclockwise_Side(lua_State * L)226 static int Lua_Line_Get_Counterclockwise_Side(lua_State *L)
227 {
228 Lua_Side::Push(L, get_line_data(Lua_Line::Index(L, 1))->counterclockwise_polygon_side_index);
229 return 1;
230 }
231
Lua_Line_Get_Endpoints(lua_State * L)232 static int Lua_Line_Get_Endpoints(lua_State *L)
233 {
234 Lua_Line_Endpoints::Push(L, Lua_Line::Index(L, 1));
235 return 1;
236 }
237
Lua_Line_Get_Has_Transparent_Side(lua_State * L)238 static int Lua_Line_Get_Has_Transparent_Side(lua_State *L)
239 {
240 lua_pushboolean(L, LINE_HAS_TRANSPARENT_SIDE(get_line_data(Lua_Line::Index(L, 1))));
241 return 1;
242 }
243
Lua_Line_Get_Highest_Adjacent_Floor(lua_State * L)244 static int Lua_Line_Get_Highest_Adjacent_Floor(lua_State *L)
245 {
246 lua_pushnumber(L, (double) get_line_data(Lua_Line::Index(L, 1))->highest_adjacent_floor / WORLD_ONE);
247 return 1;
248 }
249
Lua_Line_Get_Length(lua_State * L)250 static int Lua_Line_Get_Length(lua_State *L)
251 {
252 lua_pushnumber(L, (double) get_line_data(Lua_Line::Index(L, 1))->length / WORLD_ONE);
253 return 1;
254 }
255
Lua_Line_Get_Lowest_Adjacent_Ceiling(lua_State * L)256 static int Lua_Line_Get_Lowest_Adjacent_Ceiling(lua_State *L)
257 {
258 lua_pushnumber(L, (double) get_line_data(Lua_Line::Index(L, 1))->lowest_adjacent_ceiling / WORLD_ONE);
259 return 1;
260 }
261
Lua_Line_Get_Solid(lua_State * L)262 static int Lua_Line_Get_Solid(lua_State *L)
263 {
264 line_data *line = get_line_data(Lua_Line::Index(L, 1));
265 lua_pushboolean(L, LINE_IS_SOLID(line));
266 return 1;
267 }
268
Lua_Line_Get_Visible_On_Automap(lua_State * L)269 static int Lua_Line_Get_Visible_On_Automap(lua_State *L)
270 {
271 lua_pushboolean(L, LINE_IS_IN_AUTOMAP(Lua_Line::Index(L, 1)));
272 return 1;
273 }
274
Lua_Line_Set_Visible_On_Automap(lua_State * L)275 static int Lua_Line_Set_Visible_On_Automap(lua_State *L)
276 {
277 if (!lua_isboolean(L, 2))
278 return luaL_error(L, ("visible_on_automap: incorrect argument type"));
279
280 if (lua_toboolean(L, 2))
281 ADD_LINE_TO_AUTOMAP(Lua_Line::Index(L, 1));
282 else
283 CLEAR_LINE_FROM_AUTOMAP(Lua_Line::Index(L, 1));
284 return 0;
285 }
286
287
288 const luaL_Reg Lua_Line_Get[] = {
289 {"cw_polygon", Lua_Line_Get_Clockwise_Polygon},
290 {"ccw_polygon", Lua_Line_Get_Counterclockwise_Polygon},
291 {"cw_side", Lua_Line_Get_Clockwise_Side},
292 {"ccw_side", Lua_Line_Get_Counterclockwise_Side},
293 {"clockwise_polygon", Lua_Line_Get_Clockwise_Polygon},
294 {"clockwise_side", Lua_Line_Get_Clockwise_Side},
295 {"counterclockwise_polygon", Lua_Line_Get_Counterclockwise_Polygon},
296 {"counterclockwise_side", Lua_Line_Get_Counterclockwise_Side},
297 {"endpoints", Lua_Line_Get_Endpoints},
298 {"has_transparent_side", Lua_Line_Get_Has_Transparent_Side},
299 {"highest_adjacent_floor", Lua_Line_Get_Highest_Adjacent_Floor},
300 {"length", Lua_Line_Get_Length},
301 {"lowest_adjacent_ceiling", Lua_Line_Get_Lowest_Adjacent_Ceiling},
302 {"solid", Lua_Line_Get_Solid},
303 {"visible_on_automap", Lua_Line_Get_Visible_On_Automap},
304 {0, 0}
305 };
306
307 const luaL_Reg Lua_Line_Set[] = {
308 {"visible_on_automap", Lua_Line_Set_Visible_On_Automap},
309 {0, 0}
310 };
311
Lua_Line_Valid(int16 index)312 static bool Lua_Line_Valid(int16 index)
313 {
314 return index >= 0 && index < LineList.size();
315 }
316
317 char Lua_Lines_Name[] = "Lines";
Lua_Lines_Length()318 static int16 Lua_Lines_Length() { return LineList.size(); }
319
320 char Lua_PlatformType_Name[] = "platform_type";
321 char Lua_PlatformTypes_Name[] = "PlatformTypes";
322
323 char Lua_Platform_Name[] = "platform";
Lua_Platform_Valid(int16 index)324 bool Lua_Platform_Valid(int16 index)
325 {
326 return index >= 0 && index < dynamic_world->platform_count;
327 }
328
329 template<int flag_bit> int
Lua_Platform_Get_Static_Flag(lua_State * L)330 Lua_Platform_Get_Static_Flag(lua_State* L)
331 {
332 platform_data* platform = get_platform_data(Lua_Platform::Index(L, 1));
333 lua_pushboolean(L, platform->static_flags & (1 << flag_bit));
334 return 1;
335 }
336
337 template<int flag_bit> int
Lua_Platform_Set_Static_Flag(lua_State * L)338 Lua_Platform_Set_Static_Flag(lua_State* L)
339 {
340 if (!lua_isboolean(L, 2))
341 return luaL_error(L, "platform: incorrect argument type");
342
343 platform_data* platform = get_platform_data(Lua_Platform::Index(L, 1));
344 bool flag = lua_toboolean(L, 2);
345 if (flag)
346 platform->static_flags |= (1 << flag_bit);
347 else
348 platform->static_flags &= ~(1 << flag_bit);
349
350 return 0;
351 }
352
Lua_Platform_Get_Active(lua_State * L)353 static int Lua_Platform_Get_Active(lua_State *L)
354 {
355 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
356 lua_pushboolean(L, PLATFORM_IS_ACTIVE(platform));
357 return 1;
358 }
359
Lua_Platform_Get_Ceiling_Height(lua_State * L)360 static int Lua_Platform_Get_Ceiling_Height(lua_State *L)
361 {
362 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
363 lua_pushnumber(L, (double) platform->ceiling_height / WORLD_ONE);
364 return 1;
365 }
366
Lua_Platform_Get_Contracting(lua_State * L)367 static int Lua_Platform_Get_Contracting(lua_State *L)
368 {
369 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
370 lua_pushboolean(L, !PLATFORM_IS_EXTENDING(platform));
371 return 1;
372 }
373
Lua_Platform_Get_Extending(lua_State * L)374 static int Lua_Platform_Get_Extending(lua_State *L)
375 {
376 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
377 lua_pushboolean(L, PLATFORM_IS_EXTENDING(platform));
378 return 1;
379 }
380
Lua_Platform_Get_Floor_Height(lua_State * L)381 static int Lua_Platform_Get_Floor_Height(lua_State *L)
382 {
383 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
384 lua_pushnumber(L, (double) platform->floor_height / WORLD_ONE);
385 return 1;
386 }
387
Lua_Platform_Get_Polygon(lua_State * L)388 static int Lua_Platform_Get_Polygon(lua_State *L)
389 {
390 Lua_Polygon::Push(L, get_platform_data(Lua_Platform::Index(L, 1))->polygon_index);
391 return 1;
392 }
393
Lua_Platform_Get_Speed(lua_State * L)394 static int Lua_Platform_Get_Speed(lua_State *L)
395 {
396 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
397 lua_pushnumber(L, (double) platform->speed / WORLD_ONE);
398 return 1;
399 }
400
Lua_Platform_Get_Type(lua_State * L)401 static int Lua_Platform_Get_Type(lua_State* L)
402 {
403 platform_data* platform = get_platform_data(Lua_Platform::Index(L, 1));
404 Lua_PlatformType::Push(L, platform->type);
405 return 1;
406 }
407
408 extern bool set_platform_state(short, bool, short);
409
Lua_Platform_Set_Active(lua_State * L)410 static int Lua_Platform_Set_Active(lua_State *L)
411 {
412 if (!lua_isboolean(L, 2))
413 return luaL_error(L, "active: incorrect argument type");
414
415 short platform_index = Lua_Platform::Index(L, 1);
416 set_platform_state(platform_index, lua_toboolean(L, 2), NONE);
417 return 0;
418 }
419
Lua_Platform_Set_Ceiling_Height(lua_State * L)420 static int Lua_Platform_Set_Ceiling_Height(lua_State *L)
421 {
422 if (!lua_isnumber(L, 2))
423 return luaL_error(L, "ceiling_height: incorrect argument type");
424
425 short platform_index = Lua_Platform::Index(L, 1);
426 platform_data *platform = get_platform_data(platform_index);
427
428 platform->ceiling_height = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
429 adjust_platform_endpoint_and_line_heights(platform_index);
430 adjust_platform_for_media(platform_index, false);
431
432 return 0;
433 }
434
Lua_Platform_Set_Contracting(lua_State * L)435 static int Lua_Platform_Set_Contracting(lua_State *L)
436 {
437 if (!lua_isboolean(L, 2))
438 return luaL_error(L, "contracting: incorrect argument type");
439
440 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
441 bool contracting = lua_toboolean(L, 2);
442 if (contracting)
443 SET_PLATFORM_IS_CONTRACTING(platform);
444 else
445 SET_PLATFORM_IS_EXTENDING(platform);
446 return 0;
447 }
448
Lua_Platform_Set_Extending(lua_State * L)449 static int Lua_Platform_Set_Extending(lua_State *L)
450 {
451 if (!lua_isboolean(L, 2))
452 return luaL_error(L, "extending: incorrect argument type");
453
454 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
455 bool extending = lua_toboolean(L, 2);
456 if (extending)
457 SET_PLATFORM_IS_EXTENDING(platform);
458 else
459 SET_PLATFORM_IS_CONTRACTING(platform);
460 return 0;
461 }
462
Lua_Platform_Set_Floor_Height(lua_State * L)463 static int Lua_Platform_Set_Floor_Height(lua_State *L)
464 {
465 if (!lua_isnumber(L, 2))
466 return luaL_error(L, "ceiling_height: incorrect argument type");
467
468 short platform_index = Lua_Platform::Index(L, 1);
469 platform_data *platform = get_platform_data(platform_index);
470
471 platform->floor_height = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
472 adjust_platform_endpoint_and_line_heights(platform_index);
473 adjust_platform_for_media(platform_index, false);
474
475 return 0;
476 }
477
Lua_Platform_Set_Speed(lua_State * L)478 static int Lua_Platform_Set_Speed(lua_State *L)
479 {
480 if (!lua_isnumber(L, 2))
481 return luaL_error(L, "speed: incorrect argument type");
482
483 platform_data *platform = get_platform_data(Lua_Platform::Index(L, 1));
484 platform->speed = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
485 return 0;
486 }
487
Lua_Platform_Set_Type(lua_State * L)488 static int Lua_Platform_Set_Type(lua_State* L)
489 {
490 platform_data* platform = get_platform_data(Lua_Platform::Index(L, 1));
491 platform->type = Lua_PlatformType::ToIndex(L, 2);
492 return 0;
493 }
494
495
496 const luaL_Reg Lua_Platform_Get[] = {
497 {"active", Lua_Platform_Get_Active},
498 {"ceiling_height", Lua_Platform_Get_Ceiling_Height},
499 {"contracting", Lua_Platform_Get_Contracting},
500 {"door", Lua_Platform_Get_Static_Flag<_platform_is_door>},
501 {"extending", Lua_Platform_Get_Extending},
502 {"floor_height", Lua_Platform_Get_Floor_Height},
503 {"locked", Lua_Platform_Get_Static_Flag<_platform_is_locked>},
504 {"monster_controllable", Lua_Platform_Get_Static_Flag<_platform_is_monster_controllable>},
505 {"player_controllable", Lua_Platform_Get_Static_Flag<_platform_is_player_controllable>},
506 {"polygon", Lua_Platform_Get_Polygon},
507 {"secret", Lua_Platform_Get_Static_Flag<_platform_is_secret>},
508 {"speed", Lua_Platform_Get_Speed},
509 {"type", Lua_Platform_Get_Type},
510 {0, 0}
511 };
512
513 const luaL_Reg Lua_Platform_Set[] = {
514 {"active", Lua_Platform_Set_Active},
515 {"ceiling_height", Lua_Platform_Set_Ceiling_Height},
516 {"contracting", Lua_Platform_Set_Contracting},
517 {"door", Lua_Platform_Set_Static_Flag<_platform_is_door>},
518 {"extending", Lua_Platform_Set_Extending},
519 {"floor_height", Lua_Platform_Set_Floor_Height},
520 {"locked", Lua_Platform_Set_Static_Flag<_platform_is_locked>},
521 {"monster_controllable", Lua_Platform_Set_Static_Flag<_platform_is_monster_controllable>},
522 {"player_controllable", Lua_Platform_Set_Static_Flag<_platform_is_player_controllable>},
523 {"secret", Lua_Platform_Set_Static_Flag<_platform_is_secret>},
524 {"speed", Lua_Platform_Set_Speed},
525 {"type", Lua_Platform_Set_Type},
526 {0, 0}
527 };
528
529 char Lua_Platforms_Name[] = "Platforms";
Lua_Platforms_Length()530 int16 Lua_Platforms_Length() {
531 return dynamic_world->platform_count;
532 }
533
534 char Lua_Polygon_Floor_Name[] = "polygon_floor";
535
Lua_Polygon_Floor_Get_Collection(lua_State * L)536 static int Lua_Polygon_Floor_Get_Collection(lua_State *L)
537 {
538 Lua_Collection::Push(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_texture)));
539 return 1;
540 }
541
Lua_Polygon_Floor_Get_Height(lua_State * L)542 static int Lua_Polygon_Floor_Get_Height(lua_State *L)
543 {
544 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_height) / WORLD_ONE);
545 return 1;
546 }
547
Lua_Polygon_Floor_Get_Light(lua_State * L)548 static int Lua_Polygon_Floor_Get_Light(lua_State *L)
549 {
550 Lua_Light::Push(L, get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_lightsource_index);
551 return 1;
552 }
553
Lua_Polygon_Floor_Get_Texture_Index(lua_State * L)554 static int Lua_Polygon_Floor_Get_Texture_Index(lua_State *L)
555 {
556 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_texture));
557 return 1;
558 }
559
Lua_Polygon_Floor_Get_Texture_X(lua_State * L)560 static int Lua_Polygon_Floor_Get_Texture_X(lua_State *L)
561 {
562 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_origin.x) / WORLD_ONE);
563 return 1;
564 }
565
Lua_Polygon_Floor_Get_Texture_Y(lua_State * L)566 static int Lua_Polygon_Floor_Get_Texture_Y(lua_State *L)
567 {
568 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_origin.y) / WORLD_ONE);
569 return 1;
570 }
571
Lua_Polygon_Floor_Get_Transfer_Mode(lua_State * L)572 static int Lua_Polygon_Floor_Get_Transfer_Mode(lua_State *L)
573 {
574 Lua_TransferMode::Push(L, get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_transfer_mode);
575 return 1;
576 }
577
Lua_Polygon_Floor_Set_Collection(lua_State * L)578 static int Lua_Polygon_Floor_Set_Collection(lua_State *L)
579 {
580 short polygon_index = Lua_Polygon_Floor::Index(L, 1);
581 short collection_index = Lua_Collection::ToIndex(L, 2);
582
583 polygon_data *polygon = get_polygon_data(polygon_index);
584 polygon->floor_texture = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(polygon->floor_texture));
585 return 0;
586 }
587
Lua_Polygon_Floor_Set_Height(lua_State * L)588 static int Lua_Polygon_Floor_Set_Height(lua_State *L)
589 {
590 if (!lua_isnumber(L, 2))
591 {
592 luaL_error(L, "height: incorrect argument type");
593 }
594
595 struct polygon_data *polygon = get_polygon_data(Lua_Polygon_Floor::Index(L, 1));
596 polygon->floor_height = static_cast<world_distance>(lua_tonumber(L,2)*WORLD_ONE);
597 for (short i = 0; i < polygon->vertex_count; ++i)
598 {
599 recalculate_redundant_endpoint_data(polygon->endpoint_indexes[i]);
600 recalculate_redundant_line_data(polygon->line_indexes[i]);
601 }
602 return 0;
603 }
604
Lua_Polygon_Floor_Set_Light(lua_State * L)605 static int Lua_Polygon_Floor_Set_Light(lua_State *L)
606 {
607 short light_index;
608 if (lua_isnumber(L, 2))
609 {
610 light_index = static_cast<short>(lua_tonumber(L, 2));
611 if (light_index < 0 || light_index >= MAXIMUM_LIGHTS_PER_MAP)
612 return luaL_error(L, "light: invalid light index");
613 }
614 else
615 {
616 light_index = Lua_Light::Index(L, 2);
617 }
618
619 get_polygon_data(Lua_Polygon_Floor::Index(L, 1))->floor_lightsource_index = light_index;
620 return 0;
621 }
622
Lua_Polygon_Floor_Set_Texture_Index(lua_State * L)623 static int Lua_Polygon_Floor_Set_Texture_Index(lua_State *L)
624 {
625 polygon_data *polygon = get_polygon_data(Lua_Polygon_Floor::Index(L, 1));
626 if (!lua_isnumber(L, 2))
627 return luaL_error(L, "texture_index: incorrect argument type");
628
629 short shape_index = static_cast<short>(lua_tonumber(L, 2));
630 if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
631 return luaL_error(L, "texture_index: invalid texture index");
632
633 polygon->floor_texture = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(polygon->floor_texture), shape_index);
634 return 0;
635 }
636
Lua_Polygon_Floor_Set_Texture_X(lua_State * L)637 static int Lua_Polygon_Floor_Set_Texture_X(lua_State *L)
638 {
639 polygon_data *polygon = get_polygon_data(Lua_Polygon_Floor::Index(L, 1));
640 if (!lua_isnumber(L, 2))
641 return luaL_error(L, "texture_x: incorrect argument type");
642
643 polygon->floor_origin.x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
644 return 0;
645 }
646
Lua_Polygon_Floor_Set_Texture_Y(lua_State * L)647 static int Lua_Polygon_Floor_Set_Texture_Y(lua_State *L)
648 {
649 polygon_data *polygon = get_polygon_data(Lua_Polygon_Floor::Index(L, 1));
650 if (!lua_isnumber(L, 2))
651 return luaL_error(L, "texture_y: incorrect argument type");
652
653 polygon->floor_origin.y = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
654 return 0;
655 }
656
Lua_Polygon_Floor_Set_Transfer_Mode(lua_State * L)657 static int Lua_Polygon_Floor_Set_Transfer_Mode(lua_State *L)
658 {
659 polygon_data *polygon = get_polygon_data(Lua_Polygon_Floor::Index(L, 1));
660 polygon->floor_transfer_mode = Lua_TransferMode::ToIndex(L, 2);
661 return 0;
662 }
663
664 const luaL_Reg Lua_Polygon_Floor_Get[] = {
665 {"collection", Lua_Polygon_Floor_Get_Collection},
666 {"height", Lua_Polygon_Floor_Get_Height},
667 {"light", Lua_Polygon_Floor_Get_Light},
668 {"texture_index", Lua_Polygon_Floor_Get_Texture_Index},
669 {"texture_x", Lua_Polygon_Floor_Get_Texture_X},
670 {"texture_y", Lua_Polygon_Floor_Get_Texture_Y},
671 {"transfer_mode", Lua_Polygon_Floor_Get_Transfer_Mode},
672 {"z", Lua_Polygon_Floor_Get_Height},
673 {0, 0}
674 };
675
676 const luaL_Reg Lua_Polygon_Floor_Set[] = {
677 {"collection", Lua_Polygon_Floor_Set_Collection},
678 {"height", Lua_Polygon_Floor_Set_Height},
679 {"light", Lua_Polygon_Floor_Set_Light},
680 {"texture_index", Lua_Polygon_Floor_Set_Texture_Index},
681 {"texture_x", Lua_Polygon_Floor_Set_Texture_X},
682 {"texture_y", Lua_Polygon_Floor_Set_Texture_Y},
683 {"transfer_mode", Lua_Polygon_Floor_Set_Transfer_Mode},
684 {"z", Lua_Polygon_Floor_Set_Height},
685 {0, 0}
686 };
687
688 char Lua_Polygon_Ceiling_Name[] = "polygon_ceiling";
689
Lua_Polygon_Ceiling_Get_Collection(lua_State * L)690 static int Lua_Polygon_Ceiling_Get_Collection(lua_State *L)
691 {
692 Lua_Collection::Push(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_texture)));
693 return 1;
694 }
695
Lua_Polygon_Ceiling_Get_Height(lua_State * L)696 static int Lua_Polygon_Ceiling_Get_Height(lua_State *L)
697 {
698 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_height) / WORLD_ONE);
699 return 1;
700 }
701
Lua_Polygon_Ceiling_Get_Light(lua_State * L)702 static int Lua_Polygon_Ceiling_Get_Light(lua_State *L)
703 {
704 Lua_Light::Push(L, get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_lightsource_index);
705 return 1;
706 }
707
Lua_Polygon_Ceiling_Get_Texture_Index(lua_State * L)708 static int Lua_Polygon_Ceiling_Get_Texture_Index(lua_State *L)
709 {
710 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_texture));
711 return 1;
712 }
713
Lua_Polygon_Ceiling_Get_Texture_X(lua_State * L)714 static int Lua_Polygon_Ceiling_Get_Texture_X(lua_State *L)
715 {
716 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_origin.x) / WORLD_ONE);
717 return 1;
718 }
719
Lua_Polygon_Ceiling_Get_Texture_Y(lua_State * L)720 static int Lua_Polygon_Ceiling_Get_Texture_Y(lua_State *L)
721 {
722 lua_pushnumber(L, (double) (get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_origin.y) / WORLD_ONE);
723 return 1;
724 }
725
Lua_Polygon_Ceiling_Get_Transfer_Mode(lua_State * L)726 static int Lua_Polygon_Ceiling_Get_Transfer_Mode(lua_State *L)
727 {
728 Lua_TransferMode::Push(L, get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_transfer_mode);
729 return 1;
730 }
731
Lua_Polygon_Ceiling_Set_Collection(lua_State * L)732 static int Lua_Polygon_Ceiling_Set_Collection(lua_State *L)
733 {
734 short polygon_index = Lua_Polygon_Ceiling::Index(L, 1);
735 short collection_index = Lua_Collection::ToIndex(L, 2);
736
737 polygon_data *polygon = get_polygon_data(polygon_index);
738 polygon->ceiling_texture = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(polygon->ceiling_texture));
739 return 0;
740 }
741
Lua_Polygon_Ceiling_Set_Height(lua_State * L)742 static int Lua_Polygon_Ceiling_Set_Height(lua_State *L)
743 {
744 if (!lua_isnumber(L, 2))
745 {
746 luaL_error(L, "height: incorrect argument type");
747 }
748
749 struct polygon_data *polygon = get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1));
750 polygon->ceiling_height = static_cast<world_distance>(lua_tonumber(L,2)*WORLD_ONE);
751 for (short i = 0; i < polygon->vertex_count; ++i)
752 {
753 recalculate_redundant_endpoint_data(polygon->endpoint_indexes[i]);
754 recalculate_redundant_line_data(polygon->line_indexes[i]);
755 }
756 return 0;
757 }
758
Lua_Polygon_Ceiling_Set_Light(lua_State * L)759 static int Lua_Polygon_Ceiling_Set_Light(lua_State *L)
760 {
761 short light_index;
762 if (lua_isnumber(L, 2))
763 {
764 light_index = static_cast<short>(lua_tonumber(L, 2));
765 if (light_index < 0 || light_index >= MAXIMUM_LIGHTS_PER_MAP)
766 return luaL_error(L, "light: invalid light index");
767 }
768 else
769 {
770 light_index = Lua_Light::Index(L, 2);
771 }
772
773 get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1))->ceiling_lightsource_index = light_index;
774 return 0;
775 }
776
Lua_Polygon_Ceiling_Set_Texture_Index(lua_State * L)777 static int Lua_Polygon_Ceiling_Set_Texture_Index(lua_State *L)
778 {
779 polygon_data *polygon = get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1));
780 if (!lua_isnumber(L, 2))
781 return luaL_error(L, "texture_index: incorrect argument type");
782
783 short shape_index = static_cast<short>(lua_tonumber(L, 2));
784 if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
785 return luaL_error(L, "texture_index: invalid texture index");
786
787 polygon->ceiling_texture = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(polygon->ceiling_texture), shape_index);
788 return 0;
789 }
790
Lua_Polygon_Ceiling_Set_Texture_X(lua_State * L)791 static int Lua_Polygon_Ceiling_Set_Texture_X(lua_State *L)
792 {
793 polygon_data *polygon = get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1));
794 if (!lua_isnumber(L, 2))
795 return luaL_error(L, "texture_x: incorrect argument type");
796
797 polygon->ceiling_origin.x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
798 return 0;
799 }
800
Lua_Polygon_Ceiling_Set_Texture_Y(lua_State * L)801 static int Lua_Polygon_Ceiling_Set_Texture_Y(lua_State *L)
802 {
803 polygon_data *polygon = get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1));
804 if (!lua_isnumber(L, 2))
805 return luaL_error(L, "texture_y: incorrect argument type");
806
807 polygon->ceiling_origin.y = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
808 return 0;
809 }
810
Lua_Polygon_Ceiling_Set_Transfer_Mode(lua_State * L)811 static int Lua_Polygon_Ceiling_Set_Transfer_Mode(lua_State *L)
812 {
813 polygon_data *polygon = get_polygon_data(Lua_Polygon_Ceiling::Index(L, 1));
814 polygon->ceiling_transfer_mode = Lua_TransferMode::ToIndex(L, 2);
815 return 0;
816 }
817
818 const luaL_Reg Lua_Polygon_Ceiling_Get[] = {
819 {"collection", Lua_Polygon_Ceiling_Get_Collection},
820 {"height", Lua_Polygon_Ceiling_Get_Height},
821 {"light", Lua_Polygon_Ceiling_Get_Light},
822 {"texture_index", Lua_Polygon_Ceiling_Get_Texture_Index},
823 {"texture_x", Lua_Polygon_Ceiling_Get_Texture_X},
824 {"texture_y", Lua_Polygon_Ceiling_Get_Texture_Y},
825 {"transfer_mode", Lua_Polygon_Ceiling_Get_Transfer_Mode},
826 {"z", Lua_Polygon_Ceiling_Get_Height},
827 {0, 0}
828 };
829
830 const luaL_Reg Lua_Polygon_Ceiling_Set[] = {
831 {"collection", Lua_Polygon_Ceiling_Set_Collection},
832 {"height", Lua_Polygon_Ceiling_Set_Height},
833 {"light", Lua_Polygon_Ceiling_Set_Light},
834 {"texture_index", Lua_Polygon_Ceiling_Set_Texture_Index},
835 {"texture_x", Lua_Polygon_Ceiling_Set_Texture_X},
836 {"texture_y", Lua_Polygon_Ceiling_Set_Texture_Y},
837 {"transfer_mode", Lua_Polygon_Ceiling_Set_Transfer_Mode},
838 {"z", Lua_Polygon_Ceiling_Set_Height},
839 {0, 0}
840 };
841
842 char Lua_PolygonType_Name[] = "polygon_type";
843 typedef L_Enum<Lua_PolygonType_Name> Lua_PolygonType;
844
845 char Lua_PolygonTypes_Name[] = "PolygonTypes";
846 typedef L_EnumContainer<Lua_PolygonTypes_Name, Lua_PolygonType> Lua_PolygonTypes;
847
848 char Lua_Polygon_Name[] = "polygon";
849
850 char Lua_Adjacent_Polygons_Name[] = "adjacent_polygons";
851 typedef L_Class<Lua_Adjacent_Polygons_Name> Lua_Adjacent_Polygons;
852
Lua_Adjacent_Polygons_Iterator(lua_State * L)853 static int Lua_Adjacent_Polygons_Iterator(lua_State *L)
854 {
855 int index = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
856 short polygon_index = Lua_Adjacent_Polygons::Index(L, lua_upvalueindex(2));
857 polygon_data *polygon = get_polygon_data(polygon_index);
858
859 while (index < polygon->vertex_count)
860 {
861 if (polygon->adjacent_polygon_indexes[index] != NONE)
862 {
863 Lua_Polygon::Push(L, polygon->adjacent_polygon_indexes[index]);
864 lua_pushnumber(L, ++index);
865 lua_replace(L, lua_upvalueindex(1));
866 return 1;
867 }
868 else
869 {
870 index++;
871 }
872 }
873
874 lua_pushnil(L);
875 return 1;
876 }
877
Lua_Adjacent_Polygons_Call(lua_State * L)878 static int Lua_Adjacent_Polygons_Call(lua_State *L)
879 {
880 lua_pushnumber(L, 0);
881 lua_pushvalue(L, 1);
882 lua_pushcclosure(L, Lua_Adjacent_Polygons_Iterator, 2);
883 return 1;
884 }
885
Lua_Adjacent_Polygons_Get(lua_State * L)886 static int Lua_Adjacent_Polygons_Get(lua_State *L)
887 {
888 if (lua_isnumber(L, 2))
889 {
890 short polygon_index = Lua_Adjacent_Polygons::Index(L, 1);
891 polygon_data *polygon = get_polygon_data(polygon_index);
892 int adjacent_polygon_index = static_cast<int>(lua_tonumber(L, 2));
893 if (adjacent_polygon_index >= 0 && adjacent_polygon_index < polygon->vertex_count)
894 {
895 Lua_Polygon::Push(L, polygon->adjacent_polygon_indexes[adjacent_polygon_index]);
896 }
897 else
898 {
899 lua_pushnil(L);
900 }
901 }
902 else
903 {
904 lua_pushnil(L);
905 }
906
907 return 1;
908 }
909
Lua_Adjacent_Polygons_Length(lua_State * L)910 static int Lua_Adjacent_Polygons_Length(lua_State *L)
911 {
912 lua_pushnumber(L, get_polygon_data(Lua_Adjacent_Polygons::Index(L, 1))->vertex_count);
913 return 1;
914 }
915
916 const luaL_Reg Lua_Adjacent_Polygons_Metatable[] = {
917 {"__index", Lua_Adjacent_Polygons_Get},
918 {"__call", Lua_Adjacent_Polygons_Call},
919 {"__len", Lua_Adjacent_Polygons_Length},
920 {0, 0}
921 };
922
923 char Lua_Polygon_Endpoints_Name[] = "polygon_endpoints";
924 typedef L_Class<Lua_Polygon_Endpoints_Name> Lua_Polygon_Endpoints;
925
Lua_Polygon_Endpoints_Iterator(lua_State * L)926 static int Lua_Polygon_Endpoints_Iterator(lua_State *L)
927 {
928 int index = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
929 short polygon_index = Lua_Polygon_Endpoints::Index(L, lua_upvalueindex(2));
930 polygon_data *polygon = get_polygon_data(polygon_index);
931
932 while (index < polygon->vertex_count)
933 {
934 if (polygon->endpoint_indexes[index] != NONE)
935 {
936 Lua_Endpoint::Push(L, polygon->endpoint_indexes[index]);
937 lua_pushnumber(L, ++index);
938 lua_replace(L, lua_upvalueindex(1));
939 return 1;
940 }
941 else
942 {
943 index++;
944 }
945 }
946
947 lua_pushnil(L);
948 return 1;
949 }
950
Lua_Polygon_Endpoints_Call(lua_State * L)951 static int Lua_Polygon_Endpoints_Call(lua_State *L)
952 {
953 lua_pushnumber(L, 0);
954 lua_pushvalue(L, 1);
955 lua_pushcclosure(L, Lua_Polygon_Endpoints_Iterator, 2);
956 return 1;
957 }
958
Lua_Polygon_Endpoints_Get(lua_State * L)959 static int Lua_Polygon_Endpoints_Get(lua_State *L)
960 {
961 if (lua_isnumber(L, 2))
962 {
963 short polygon_index = Lua_Polygon_Endpoints::Index(L, 1);
964 polygon_data *polygon = get_polygon_data(polygon_index);
965 int endpoint_index = static_cast<int>(lua_tonumber(L, 2));
966 if (endpoint_index >= 0 && endpoint_index < polygon->vertex_count)
967 {
968 Lua_Endpoint::Push(L, polygon->endpoint_indexes[endpoint_index]);
969 }
970 else
971 {
972 lua_pushnil(L);
973 }
974 }
975
976 return 1;
977 }
978
Lua_Polygon_Endpoints_Length(lua_State * L)979 static int Lua_Polygon_Endpoints_Length(lua_State *L)
980 {
981 lua_pushnumber(L, get_polygon_data(Lua_Polygon_Endpoints::Index(L, 1))->vertex_count);
982 return 1;
983 }
984
985 const luaL_Reg Lua_Polygon_Endpoints_Metatable[] = {
986 {"__index", Lua_Polygon_Endpoints_Get},
987 {"__call", Lua_Polygon_Endpoints_Call},
988 {"__len", Lua_Polygon_Endpoints_Length},
989 {0, 0}
990 };
991
992 char Lua_Polygon_Lines_Name[] = "polygon_lines";
993 typedef L_Class<Lua_Polygon_Lines_Name> Lua_Polygon_Lines;
994
Lua_Polygon_Lines_Iterator(lua_State * L)995 static int Lua_Polygon_Lines_Iterator(lua_State *L)
996 {
997 int index = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
998 short polygon_index = Lua_Polygon_Lines::Index(L, lua_upvalueindex(2));
999 polygon_data *polygon = get_polygon_data(polygon_index);
1000
1001 while (index < polygon->vertex_count)
1002 {
1003 if (polygon->line_indexes[index] != NONE)
1004 {
1005 Lua_Line::Push(L, polygon->line_indexes[index]);
1006 lua_pushnumber(L, ++index);
1007 lua_replace(L, lua_upvalueindex(1));
1008 return 1;
1009 }
1010 else
1011 {
1012 index++;
1013 }
1014 }
1015
1016 lua_pushnil(L);
1017 return 1;
1018 }
1019
Lua_Polygon_Lines_Call(lua_State * L)1020 static int Lua_Polygon_Lines_Call(lua_State *L)
1021 {
1022 lua_pushnumber(L, 0);
1023 lua_pushvalue(L, 1);
1024 lua_pushcclosure(L, Lua_Polygon_Lines_Iterator, 2);
1025 return 1;
1026 }
1027
Lua_Polygon_Lines_Get(lua_State * L)1028 static int Lua_Polygon_Lines_Get(lua_State *L)
1029 {
1030 if (lua_isnumber(L, 2))
1031 {
1032 short polygon_index = Lua_Polygon_Lines::Index(L, 1);
1033 polygon_data *polygon = get_polygon_data(polygon_index);
1034 int line_index = static_cast<int>(lua_tonumber(L, 2));
1035 if (line_index >= 0 && line_index < polygon->vertex_count)
1036 {
1037 Lua_Line::Push(L, polygon->line_indexes[line_index]);
1038 }
1039 else
1040 {
1041 lua_pushnil(L);
1042 }
1043 }
1044
1045 return 1;
1046 }
1047
Lua_Polygon_Lines_Length(lua_State * L)1048 static int Lua_Polygon_Lines_Length(lua_State *L)
1049 {
1050 lua_pushnumber(L, get_polygon_data(Lua_Polygon_Lines::Index(L, 1))->vertex_count);
1051 return 1;
1052 }
1053
1054 const luaL_Reg Lua_Polygon_Lines_Metatable[] = {
1055 {"__index", Lua_Polygon_Lines_Get},
1056 {"__call", Lua_Polygon_Lines_Call},
1057 {"__len", Lua_Polygon_Lines_Length},
1058 {0, 0}
1059 };
1060
1061 char Lua_Polygon_Sides_Name[] = "polygon_sides";
1062 typedef L_Class<Lua_Polygon_Sides_Name> Lua_Polygon_Sides;
1063
Lua_Polygon_Sides_Iterator(lua_State * L)1064 static int Lua_Polygon_Sides_Iterator(lua_State *L)
1065 {
1066 int index = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
1067 short polygon_index = Lua_Polygon_Sides::Index(L, lua_upvalueindex(2));
1068 polygon_data *polygon = get_polygon_data(polygon_index);
1069
1070 while (index < polygon->vertex_count)
1071 {
1072 if (polygon->side_indexes[index] != NONE)
1073 {
1074 Lua_Side::Push(L, polygon->side_indexes[index]);
1075 lua_pushnumber(L, ++index);
1076 lua_replace(L, lua_upvalueindex(1));
1077 return 1;
1078 }
1079 else
1080 {
1081 index++;
1082 }
1083 }
1084
1085 lua_pushnil(L);
1086 return 1;
1087 }
1088
Lua_Polygon_Sides_Call(lua_State * L)1089 static int Lua_Polygon_Sides_Call(lua_State *L)
1090 {
1091 lua_pushnumber(L, 0);
1092 lua_pushvalue(L, 1);
1093 lua_pushcclosure(L, Lua_Polygon_Sides_Iterator, 2);
1094 return 1;
1095 }
1096
Lua_Polygon_Sides_Get(lua_State * L)1097 static int Lua_Polygon_Sides_Get(lua_State *L)
1098 {
1099 if (lua_isnumber(L, 2))
1100 {
1101 short polygon_index = Lua_Polygon_Sides::Index(L, 1);
1102 polygon_data *polygon = get_polygon_data(polygon_index);
1103 int side_index = static_cast<int>(lua_tonumber(L, 2));
1104 if (side_index >= 0 && side_index < polygon->vertex_count)
1105 {
1106 Lua_Side::Push(L, polygon->side_indexes[side_index]);
1107 }
1108 else
1109 {
1110 lua_pushnil(L);
1111 }
1112 }
1113
1114 return 1;
1115 }
1116
Lua_Polygon_Sides_Length(lua_State * L)1117 static int Lua_Polygon_Sides_Length(lua_State *L)
1118 {
1119 lua_pushnumber(L, get_polygon_data(Lua_Polygon_Sides::Index(L, 1))->vertex_count);
1120 return 1;
1121 }
1122
1123 const luaL_Reg Lua_Polygon_Sides_Metatable[] = {
1124 {"__index", Lua_Polygon_Sides_Get},
1125 {"__call", Lua_Polygon_Sides_Call},
1126 {"__len", Lua_Polygon_Sides_Length},
1127 {0, 0}
1128 };
1129
1130 // contains(x, y, z)
Lua_Polygon_Contains(lua_State * L)1131 int Lua_Polygon_Contains(lua_State *L)
1132 {
1133 if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3))
1134 return luaL_error(L, ("contains: incorrect argument type"));
1135
1136 short polygon_index = Lua_Polygon::Index(L, 1);
1137 polygon_data *polygon = get_polygon_data(polygon_index);
1138
1139 world_point2d p;
1140 p.x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1141 p.y = static_cast<world_distance>(lua_tonumber(L, 3) * WORLD_ONE);
1142
1143 world_distance z;
1144 if (lua_gettop(L) == 4)
1145 {
1146 if (lua_isnumber(L, 4))
1147 z = static_cast<world_distance>(lua_tonumber(L, 4) * WORLD_ONE);
1148 else
1149 return luaL_error(L, "contains: incorrect argument type");
1150 }
1151 else
1152 {
1153 z = polygon->floor_height;
1154 }
1155
1156 lua_pushboolean(L, point_in_polygon(polygon_index, &p) && z >= polygon->floor_height && z <= polygon->ceiling_height);
1157 return 1;
1158 }
1159
1160 // line_crossed_leaving(x1, y1, x2, y2)
Lua_Polygon_Find_Line_Crossed_Leaving(lua_State * L)1161 int Lua_Polygon_Find_Line_Crossed_Leaving(lua_State *L)
1162 {
1163 if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4) || !lua_isnumber(L, 5))
1164 return luaL_error(L, ("find_line_crossed_leaving: incorrect argument type"));
1165
1166 world_point2d origin;
1167 origin.x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1168 origin.y = static_cast<world_distance>(lua_tonumber(L, 3) * WORLD_ONE);
1169
1170 world_point2d destination;
1171 destination.x = static_cast<world_distance>(lua_tonumber(L, 4) * WORLD_ONE);
1172 destination.y = static_cast<world_distance>(lua_tonumber(L, 5) * WORLD_ONE);
1173
1174 short line_index = find_line_crossed_leaving_polygon(Lua_Polygon::Index(L, 1), &origin, &destination);
1175 if (line_index != NONE)
1176 {
1177 Lua_Line::Push(L, line_index);
1178 }
1179 else
1180 {
1181 lua_pushnil(L);
1182 }
1183
1184 return 1;
1185 }
1186
Lua_Polygon_Monsters_Iterator(lua_State * L)1187 static int Lua_Polygon_Monsters_Iterator(lua_State *L)
1188 {
1189 int index = static_cast<int>(lua_tonumber(L, lua_upvalueindex(1)));
1190 lua_pushvalue(L, lua_upvalueindex(2));
1191 lua_pushnumber(L, index);
1192 lua_gettable(L, -2);
1193 lua_remove(L, -2);
1194
1195 lua_pushnumber(L, ++index);
1196 lua_replace(L, lua_upvalueindex(1));
1197
1198 return 1;
1199 }
1200
Lua_Polygon_Monsters(lua_State * L)1201 int Lua_Polygon_Monsters(lua_State *L)
1202 {
1203 polygon_data *polygon = get_polygon_data(Lua_Polygon::Index(L, 1));
1204
1205 int table_index = 1;
1206 short object_index = polygon->first_object;
1207
1208 lua_pushnumber(L, 1);
1209 lua_newtable(L);
1210 while (object_index != NONE)
1211 {
1212 object_data *object = get_object_data(object_index);
1213 if (GET_OBJECT_OWNER(object) == _object_is_monster)
1214 {
1215 lua_pushnumber(L, table_index++);
1216 Lua_Monster::Push(L, object->permutation);
1217 lua_settable(L, -3);
1218 }
1219
1220 object_index = object->next_object;
1221 }
1222
1223 lua_pushcclosure(L, Lua_Polygon_Monsters_Iterator, 2);
1224 return 1;
1225 }
1226
1227 // play_sound(sound) or play_sound(x, y, z, sound, [pitch])
Lua_Polygon_Play_Sound(lua_State * L)1228 int Lua_Polygon_Play_Sound(lua_State *L)
1229 {
1230 if (lua_gettop(L) == 2)
1231 {
1232 short sound_code = Lua_Sound::ToIndex(L, 2);
1233 play_polygon_sound(Lua_Polygon::Index(L, 1), sound_code);
1234 }
1235 else
1236 {
1237 if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
1238 return luaL_error(L, "play_sound: incorrect argument type");
1239 world_location3d source;
1240 source.point.x = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1241 source.point.y = static_cast<world_distance>(lua_tonumber(L, 3) * WORLD_ONE);
1242 source.point.z = static_cast<world_distance>(lua_tonumber(L, 4) * WORLD_ONE);
1243 source.polygon_index = Lua_Polygon::Index(L, 1);
1244 short sound_code = Lua_Sound::ToIndex(L, 5);
1245 _fixed pitch = FIXED_ONE;
1246 if (lua_gettop(L) == 6)
1247 {
1248 if (!lua_isnumber(L, 6))
1249 return luaL_error(L, "play_sound: incorrect argument type");
1250 pitch = static_cast<_fixed>(lua_tonumber(L, 6) * FIXED_ONE);
1251 }
1252
1253 SoundManager::instance()->PlaySound(sound_code, &source, NONE, pitch);
1254 }
1255
1256 return 0;
1257 }
1258
Lua_Polygon_Get_Adjacent(lua_State * L)1259 static int Lua_Polygon_Get_Adjacent(lua_State *L)
1260 {
1261 Lua_Adjacent_Polygons::Push(L, Lua_Polygon::Index(L, 1));
1262 return 1;
1263 }
1264
Lua_Polygon_Get_Area(lua_State * L)1265 static int Lua_Polygon_Get_Area(lua_State *L)
1266 {
1267 lua_pushnumber(L, (double) get_polygon_data(Lua_Polygon::Index(L, 1))->area / WORLD_ONE / WORLD_ONE);
1268 return 1;
1269 }
1270
Lua_Polygon_Get_Ceiling(lua_State * L)1271 static int Lua_Polygon_Get_Ceiling(lua_State *L)
1272 {
1273 Lua_Polygon_Ceiling::Push(L, Lua_Polygon::Index(L, 1));
1274 return 1;
1275 }
1276
Lua_Polygon_Get_Endpoints(lua_State * L)1277 static int Lua_Polygon_Get_Endpoints(lua_State *L)
1278 {
1279 Lua_Polygon_Endpoints::Push(L, Lua_Polygon::Index(L, 1));
1280 return 1;
1281 }
1282
Lua_Polygon_Get_Floor(lua_State * L)1283 static int Lua_Polygon_Get_Floor(lua_State *L)
1284 {
1285 Lua_Polygon_Floor::Push(L, Lua_Polygon::Index(L, 1));
1286 return 1;
1287 }
1288
Lua_Polygon_Get_Lines(lua_State * L)1289 static int Lua_Polygon_Get_Lines(lua_State *L)
1290 {
1291 Lua_Polygon_Lines::Push(L, Lua_Polygon::Index(L, 1));
1292 return 1;
1293 }
1294
Lua_Polygon_Get_Media(lua_State * L)1295 static int Lua_Polygon_Get_Media(lua_State *L)
1296 {
1297 polygon_data *polygon = get_polygon_data(Lua_Polygon::Index(L, 1));
1298 if (polygon->media_index != NONE)
1299 {
1300 Lua_Media::Push(L, polygon->media_index);
1301 }
1302 else
1303 {
1304 lua_pushnil(L);
1305 }
1306
1307 return 1;
1308 }
1309
Lua_Polygon_Get_Permutation(lua_State * L)1310 static int Lua_Polygon_Get_Permutation(lua_State *L)
1311 {
1312 polygon_data *polygon = get_polygon_data(Lua_Polygon::Index(L, 1));
1313 lua_pushnumber(L, polygon->permutation);
1314 return 1;
1315 }
1316
Lua_Polygon_Get_Sides(lua_State * L)1317 static int Lua_Polygon_Get_Sides(lua_State *L)
1318 {
1319 Lua_Polygon_Sides::Push(L, Lua_Polygon::Index(L, 1));
1320 return 1;
1321 }
1322
Lua_Polygon_Get_Type(lua_State * L)1323 static int Lua_Polygon_Get_Type(lua_State *L)
1324 {
1325 Lua_PolygonType::Push(L, get_polygon_data(Lua_Polygon::Index(L, 1))->type);
1326 return 1;
1327 }
1328
Lua_Polygon_Get_Platform(lua_State * L)1329 static int Lua_Polygon_Get_Platform(lua_State *L)
1330 {
1331 polygon_data *polygon = get_polygon_data(Lua_Polygon::Index(L, 1));
1332 if (polygon->type == _polygon_is_platform)
1333 {
1334 Lua_Platform::Push(L, polygon->permutation);
1335 }
1336 else
1337 {
1338 lua_pushnil(L);
1339 }
1340
1341 return 1;
1342 }
1343
Lua_Polygon_Get_X(lua_State * L)1344 static int Lua_Polygon_Get_X(lua_State *L)
1345 {
1346 lua_pushnumber(L, (double) get_polygon_data(Lua_Polygon::Index(L, 1))->center.x / WORLD_ONE);
1347 return 1;
1348 }
1349
Lua_Polygon_Get_Y(lua_State * L)1350 static int Lua_Polygon_Get_Y(lua_State *L)
1351 {
1352 lua_pushnumber(L, (double) get_polygon_data(Lua_Polygon::Index(L, 1))->center.y / WORLD_ONE);
1353 return 1;
1354 }
1355
Lua_Polygon_Get_Z(lua_State * L)1356 static int Lua_Polygon_Get_Z(lua_State *L)
1357 {
1358 lua_pushnumber(L, (double) get_polygon_data(Lua_Polygon::Index(L, 1))->floor_height / WORLD_ONE);
1359 return 1;
1360 }
1361
Lua_Polygon_Get_Visible_On_Automap(lua_State * L)1362 static int Lua_Polygon_Get_Visible_On_Automap(lua_State *L)
1363 {
1364 lua_pushboolean(L, POLYGON_IS_IN_AUTOMAP(Lua_Polygon::Index(L, 1)));
1365 return 1;
1366 }
1367
Lua_Polygon_Set_Media(lua_State * L)1368 static int Lua_Polygon_Set_Media(lua_State *L)
1369 {
1370 polygon_data *polygon = get_polygon_data(Lua_Polygon::Index(L, 1));
1371 short media_index = NONE;
1372 if (lua_isnumber(L, 2))
1373 {
1374 media_index = static_cast<short>(lua_tonumber(L, 2));
1375 if (media_index < 0 || media_index > MAXIMUM_MEDIAS_PER_MAP)
1376 return luaL_error(L, "media: invalid media index");
1377
1378 }
1379 else if (Lua_Media::Is(L, 2))
1380 {
1381 media_index = Lua_Media::Index(L, 2);
1382 }
1383 else if (!lua_isnil(L, 2))
1384 {
1385 return luaL_error(L, "media: incorrect argument type");
1386 }
1387
1388 polygon->media_index = media_index;
1389 return 0;
1390 }
1391
Lua_Polygon_Set_Permutation(lua_State * L)1392 static int Lua_Polygon_Set_Permutation(lua_State *L)
1393 {
1394 if (!lua_isnumber(L, 2))
1395 return luaL_error(L, ("type: incorrect argument type"));
1396
1397 int permutation = static_cast<int>(lua_tonumber(L, 2));
1398 get_polygon_data(Lua_Polygon::Index(L, 1))->permutation = permutation;
1399 return 0;
1400 }
1401
Lua_Polygon_Set_Type(lua_State * L)1402 static int Lua_Polygon_Set_Type(lua_State *L)
1403 {
1404 short type = NONE;
1405 if (lua_isnumber(L, 2))
1406 {
1407 type = static_cast<short>(lua_tonumber(L, 2));
1408 if (type < 0 || type > _polygon_is_superglue) {
1409 luaL_error(L, "type: invalid polygon type index");
1410 }
1411 }
1412 else if (Lua_PolygonType::Is(L, 2)) {
1413 type = Lua_PolygonType::Index(L, 2);
1414 }
1415 else
1416 {
1417 return luaL_error(L, "type: incorrect argument type");
1418 }
1419
1420 get_polygon_data(Lua_Polygon::Index(L, 1))->type = type;
1421 return 0;
1422 }
1423
Lua_Polygon_Set_Visible_On_Automap(lua_State * L)1424 static int Lua_Polygon_Set_Visible_On_Automap(lua_State *L)
1425 {
1426 if (!lua_isboolean(L, 2))
1427 return luaL_error(L, ("visible_on_automap: incorrect argument type"));
1428
1429 if (lua_toboolean(L, 2))
1430 ADD_POLYGON_TO_AUTOMAP(Lua_Polygon::Index(L, 1));
1431 else
1432 CLEAR_POLYGON_FROM_AUTOMAP(Lua_Polygon::Index(L, 1));
1433 return 0;
1434 }
1435
Lua_Polygon_Valid(int16 index)1436 static bool Lua_Polygon_Valid(int16 index)
1437 {
1438 return index >= 0 && index < dynamic_world->polygon_count;
1439 }
1440
1441 const luaL_Reg Lua_Polygon_Get[] = {
1442 {"adjacent_polygons", Lua_Polygon_Get_Adjacent},
1443 {"area", Lua_Polygon_Get_Area},
1444 {"ceiling", Lua_Polygon_Get_Ceiling},
1445 {"contains", L_TableFunction<Lua_Polygon_Contains>},
1446 {"endpoints", Lua_Polygon_Get_Endpoints},
1447 {"find_line_crossed_leaving", L_TableFunction<Lua_Polygon_Find_Line_Crossed_Leaving>},
1448 {"floor", Lua_Polygon_Get_Floor},
1449 {"lines", Lua_Polygon_Get_Lines},
1450 {"media", Lua_Polygon_Get_Media},
1451 {"monsters", L_TableFunction<Lua_Polygon_Monsters>},
1452 {"permutation", Lua_Polygon_Get_Permutation},
1453 {"platform", Lua_Polygon_Get_Platform},
1454 {"play_sound", L_TableFunction<Lua_Polygon_Play_Sound>},
1455 {"sides", Lua_Polygon_Get_Sides},
1456 {"type", Lua_Polygon_Get_Type},
1457 {"visible_on_automap", Lua_Polygon_Get_Visible_On_Automap},
1458 {"x", Lua_Polygon_Get_X},
1459 {"y", Lua_Polygon_Get_Y},
1460 {"z", Lua_Polygon_Get_Z},
1461 {0, 0}
1462 };
1463
1464 const luaL_Reg Lua_Polygon_Set[] = {
1465 {"media", Lua_Polygon_Set_Media},
1466 {"permutation", Lua_Polygon_Set_Permutation},
1467 {"type", Lua_Polygon_Set_Type},
1468 {"visible_on_automap", Lua_Polygon_Set_Visible_On_Automap},
1469 {0, 0}
1470 };
1471
1472 char Lua_Polygons_Name[] = "Polygons";
1473
Lua_Polygons_Length()1474 int16 Lua_Polygons_Length() {
1475 return dynamic_world->polygon_count;
1476 }
1477
1478 char Lua_Side_ControlPanel_Name[] = "side_control_panel";
1479 typedef L_Class<Lua_Side_ControlPanel_Name> Lua_Side_ControlPanel;
1480
1481 template<int16 flag>
Lua_Side_ControlPanel_Get_Flag(lua_State * L)1482 static int Lua_Side_ControlPanel_Get_Flag(lua_State *L)
1483 {
1484 side_data *side = get_side_data(Lua_Side_ControlPanel::Index(L, 1));
1485 lua_pushboolean(L, side->flags & flag);
1486 return 1;
1487 }
1488
1489 template<int16 flag>
Lua_Side_ControlPanel_Set_Flag(lua_State * L)1490 static int Lua_Side_ControlPanel_Set_Flag(lua_State *L)
1491 {
1492 if (!lua_isboolean(L, 2))
1493 return luaL_error(L, "control_panel: incorrect argument type");
1494
1495 side_data *side = get_side_data(Lua_Side_ControlPanel::Index(L, 1));
1496 if (lua_toboolean(L, 2))
1497 side->flags |= flag;
1498 else
1499 side->flags &= ~flag;
1500 return 0;
1501 }
1502
Lua_Side_ControlPanel_Get_Type(lua_State * L)1503 static int Lua_Side_ControlPanel_Get_Type(lua_State *L)
1504 {
1505 Lua_ControlPanelType::Push(L, get_side_data(Lua_Side_ControlPanel::Index(L, 1))->control_panel_type);
1506 return 1;
1507 }
1508
Lua_Side_ControlPanel_Get_Permutation(lua_State * L)1509 static int Lua_Side_ControlPanel_Get_Permutation(lua_State *L)
1510 {
1511 lua_pushnumber(L, get_side_data(Lua_Side_ControlPanel::Index(L, 1))->control_panel_permutation);
1512 return 1;
1513 }
1514
Lua_Side_ControlPanel_Get_UsesItem(lua_State * L)1515 static int Lua_Side_ControlPanel_Get_UsesItem(lua_State* L)
1516 {
1517 control_panel_definition* definition = get_control_panel_definition(get_side_data(Lua_Side_ControlPanel::Index(L, 1))->control_panel_type);
1518 lua_pushboolean(L, definition->item != NONE);
1519 return 1;
1520 }
1521
1522 const luaL_Reg Lua_Side_ControlPanel_Get[] = {
1523 {"can_be_destroyed", Lua_Side_ControlPanel_Get_Flag<_side_switch_can_be_destroyed>},
1524 {"light_dependent", Lua_Side_ControlPanel_Get_Flag<_side_is_lighted_switch>},
1525 {"only_toggled_by_weapons", Lua_Side_ControlPanel_Get_Flag<_side_switch_can_only_be_hit_by_projectiles>},
1526 {"repair", Lua_Side_ControlPanel_Get_Flag<_side_is_repair_switch>},
1527 {"status", Lua_Side_ControlPanel_Get_Flag<_control_panel_status>},
1528 {"type", Lua_Side_ControlPanel_Get_Type},
1529 {"permutation", Lua_Side_ControlPanel_Get_Permutation},
1530 {"uses_item", Lua_Side_ControlPanel_Get_UsesItem},
1531 {0, 0}
1532 };
1533
Lua_Side_ControlPanel_Set_Permutation(lua_State * L)1534 static int Lua_Side_ControlPanel_Set_Permutation(lua_State *L)
1535 {
1536 if (!lua_isnumber(L, 2))
1537 return luaL_error(L, "permutation: incorrect argument type");
1538
1539 side_data *side = get_side_data(Lua_Side_ControlPanel::Index(L, 1));
1540 side->control_panel_permutation = static_cast<int16>(lua_tonumber(L, 2));
1541 return 0;
1542 }
1543
1544 extern void set_control_panel_texture(side_data *);
1545
Lua_Side_ControlPanel_Set_Type(lua_State * L)1546 static int Lua_Side_ControlPanel_Set_Type(lua_State *L)
1547 {
1548 side_data *side = get_side_data(Lua_Side_ControlPanel::Index(L, 1));
1549 side->control_panel_type = Lua_ControlPanelType::ToIndex(L, 2);
1550 set_control_panel_texture(side);
1551 return 0;
1552 }
1553
1554 // the old version set a useless flag; instead, do nothing
Lua_Side_ControlPanel_Set_UsesItem(lua_State *)1555 static int Lua_Side_ControlPanel_Set_UsesItem(lua_State*)
1556 {
1557 return 0;
1558 }
1559
1560 const luaL_Reg Lua_Side_ControlPanel_Set[] = {
1561 {"can_be_destroyed", Lua_Side_ControlPanel_Set_Flag<_side_switch_can_be_destroyed>},
1562 {"light_dependent", Lua_Side_ControlPanel_Set_Flag<_side_is_lighted_switch>},
1563 {"only_toggled_by_weapons", Lua_Side_ControlPanel_Set_Flag<_side_switch_can_only_be_hit_by_projectiles>},
1564 {"permutation", Lua_Side_ControlPanel_Set_Permutation},
1565 {"repair", Lua_Side_ControlPanel_Set_Flag<_side_is_repair_switch>},
1566 {"status", Lua_Side_ControlPanel_Set_Flag<_control_panel_status>},
1567 {"type", Lua_Side_ControlPanel_Set_Type},
1568 {"uses_item", Lua_Side_ControlPanel_Set_UsesItem},
1569 {0, 0}
1570 };
1571
1572 char Lua_Primary_Side_Name[] = "primary_side";
1573 typedef L_Class<Lua_Primary_Side_Name> Lua_Primary_Side;
1574
Lua_Primary_Side_Get_Collection(lua_State * L)1575 static int Lua_Primary_Side_Get_Collection(lua_State *L)
1576 {
1577 Lua_Collection::Push(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(get_side_data(Lua_Primary_Side::Index(L, 1))->primary_texture.texture)));
1578 return 1;
1579 }
1580
Lua_Primary_Side_Get_Light(lua_State * L)1581 static int Lua_Primary_Side_Get_Light(lua_State *L)
1582 {
1583 Lua_Light::Push(L, get_side_data(Lua_Primary_Side::Index(L, 1))->primary_lightsource_index);
1584 return 1;
1585 }
1586
Lua_Primary_Side_Get_Texture_Index(lua_State * L)1587 static int Lua_Primary_Side_Get_Texture_Index(lua_State *L)
1588 {
1589 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(get_side_data(Lua_Primary_Side::Index(L, 1))->primary_texture.texture));
1590 return 1;
1591 }
1592
Lua_Primary_Side_Get_Texture_X(lua_State * L)1593 static int Lua_Primary_Side_Get_Texture_X(lua_State *L)
1594 {
1595 lua_pushnumber(L, (double) (get_side_data(Lua_Primary_Side::Index(L, 1))->primary_texture.x0) / WORLD_ONE);
1596 return 1;
1597 }
1598
Lua_Primary_Side_Get_Texture_Y(lua_State * L)1599 static int Lua_Primary_Side_Get_Texture_Y(lua_State *L)
1600 {
1601 lua_pushnumber(L, (double) (get_side_data(Lua_Primary_Side::Index(L, 1))->primary_texture.y0) / WORLD_ONE);
1602 return 1;
1603 }
1604
Lua_Primary_Side_Get_Transfer_Mode(lua_State * L)1605 static int Lua_Primary_Side_Get_Transfer_Mode(lua_State *L)
1606 {
1607 Lua_TransferMode::Push(L, get_side_data(Lua_Primary_Side::Index(L, 1))->primary_transfer_mode);
1608 return 1;
1609 }
1610
update_line_redundancy(short line_index)1611 static void update_line_redundancy(short line_index)
1612 {
1613 line_data *line= get_line_data(line_index);
1614 side_data *clockwise_side= NULL, *counterclockwise_side= NULL;
1615
1616 bool landscaped= false;
1617 bool transparent_texture= false;
1618
1619 if (line->clockwise_polygon_side_index!=NONE)
1620 {
1621 clockwise_side= get_side_data(line->clockwise_polygon_side_index);
1622 }
1623 if (line->counterclockwise_polygon_side_index!=NONE)
1624 {
1625 counterclockwise_side= get_side_data(line->counterclockwise_polygon_side_index);
1626 }
1627
1628 if ((clockwise_side&&clockwise_side->primary_transfer_mode==_xfer_landscape) ||
1629 (counterclockwise_side&&counterclockwise_side->primary_transfer_mode==_xfer_landscape))
1630 {
1631 landscaped= true;
1632 }
1633
1634 if ((clockwise_side && clockwise_side->transparent_texture.texture!=UNONE) ||
1635 (counterclockwise_side && counterclockwise_side->transparent_texture.texture!=UNONE))
1636 {
1637 transparent_texture= true;
1638 }
1639
1640 SET_LINE_LANDSCAPE_STATUS(line, landscaped);
1641 SET_LINE_HAS_TRANSPARENT_SIDE(line, transparent_texture);
1642 }
1643
Lua_Primary_Side_Set_Collection(lua_State * L)1644 static int Lua_Primary_Side_Set_Collection(lua_State *L)
1645 {
1646 short side_index = Lua_Primary_Side::Index(L, 1);
1647 short collection_index = Lua_Collection::ToIndex(L, 2);
1648
1649 side_data *side = get_side_data(side_index);
1650 side->primary_texture.texture = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(side->primary_texture.texture));
1651 update_line_redundancy(side->line_index);
1652 return 0;
1653 }
1654
Lua_Primary_Side_Set_Light(lua_State * L)1655 static int Lua_Primary_Side_Set_Light(lua_State *L)
1656 {
1657 short light_index;
1658 if (lua_isnumber(L, 2))
1659 {
1660 light_index = static_cast<short>(lua_tonumber(L, 2));
1661 if (light_index < 0 || light_index >= MAXIMUM_LIGHTS_PER_MAP)
1662 return luaL_error(L, "light: invalid light index");
1663 }
1664 else
1665 {
1666 light_index = Lua_Light::Index(L, 2);
1667 }
1668
1669 get_side_data(Lua_Polygon_Floor::Index(L, 1))->primary_lightsource_index = light_index;
1670 return 0;
1671 }
Lua_Primary_Side_Set_Texture_Index(lua_State * L)1672 static int Lua_Primary_Side_Set_Texture_Index(lua_State *L)
1673 {
1674 side_data *side = get_side_data(Lua_Primary_Side::Index(L, 1));
1675 if (!lua_isnumber(L, 2))
1676 return luaL_error(L, "texture_index: incorrect argument type");
1677
1678 short shape_index = static_cast<short>(lua_tonumber(L, 2));
1679 if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
1680 return luaL_error(L, "texture_index: invalid texture index");
1681
1682 side->primary_texture.texture = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(side->primary_texture.texture), shape_index);
1683 update_line_redundancy(side->line_index);
1684 return 0;
1685 }
1686
Lua_Primary_Side_Set_Texture_X(lua_State * L)1687 static int Lua_Primary_Side_Set_Texture_X(lua_State *L)
1688 {
1689 side_data *side = get_side_data(Lua_Primary_Side::Index(L, 1));
1690 if (!lua_isnumber(L, 2))
1691 return luaL_error(L, "texture_x: incorrect argument type");
1692
1693 side->primary_texture.x0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1694 return 0;
1695 }
1696
Lua_Primary_Side_Set_Texture_Y(lua_State * L)1697 static int Lua_Primary_Side_Set_Texture_Y(lua_State *L)
1698 {
1699 side_data *side = get_side_data(Lua_Primary_Side::Index(L, 1));
1700 if (!lua_isnumber(L, 2))
1701 return luaL_error(L, "texture_y: incorrect argument type");
1702
1703 side->primary_texture.y0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1704 return 0;
1705 }
1706
Lua_Primary_Side_Set_Transfer_Mode(lua_State * L)1707 static int Lua_Primary_Side_Set_Transfer_Mode(lua_State *L)
1708 {
1709 side_data *side = get_side_data(Lua_Primary_Side::Index(L, 1));
1710 side->primary_transfer_mode = Lua_TransferMode::ToIndex(L, 2);
1711 return 0;
1712 }
1713 const luaL_Reg Lua_Primary_Side_Get[] = {
1714 {"collection", Lua_Primary_Side_Get_Collection},
1715 {"light", Lua_Primary_Side_Get_Light},
1716 {"texture_index", Lua_Primary_Side_Get_Texture_Index},
1717 {"texture_x", Lua_Primary_Side_Get_Texture_X},
1718 {"texture_y", Lua_Primary_Side_Get_Texture_Y},
1719 {"transfer_mode", Lua_Primary_Side_Get_Transfer_Mode},
1720 {0, 0}
1721 };
1722
1723 const luaL_Reg Lua_Primary_Side_Set[] = {
1724 {"collection", Lua_Primary_Side_Set_Collection},
1725 {"light", Lua_Primary_Side_Set_Light},
1726 {"texture_index", Lua_Primary_Side_Set_Texture_Index},
1727 {"texture_x", Lua_Primary_Side_Set_Texture_X},
1728 {"texture_y", Lua_Primary_Side_Set_Texture_Y},
1729 {"transfer_mode", Lua_Primary_Side_Set_Transfer_Mode},
1730 {0, 0}
1731 };
1732
1733 char Lua_Secondary_Side_Name[] = "secondary_side";
1734 typedef L_Class<Lua_Secondary_Side_Name> Lua_Secondary_Side;
1735
Lua_Secondary_Side_Get_Collection(lua_State * L)1736 static int Lua_Secondary_Side_Get_Collection(lua_State *L)
1737 {
1738 Lua_Collection::Push(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_texture.texture)));
1739 return 1;
1740 }
1741
Lua_Secondary_Side_Get_Light(lua_State * L)1742 static int Lua_Secondary_Side_Get_Light(lua_State *L)
1743 {
1744 Lua_Light::Push(L, get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_lightsource_index);
1745 return 1;
1746 }
1747
Lua_Secondary_Side_Get_Texture_Index(lua_State * L)1748 static int Lua_Secondary_Side_Get_Texture_Index(lua_State *L)
1749 {
1750 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_texture.texture));
1751 return 1;
1752 }
1753
Lua_Secondary_Side_Get_Texture_X(lua_State * L)1754 static int Lua_Secondary_Side_Get_Texture_X(lua_State *L)
1755 {
1756 lua_pushnumber(L, (double) (get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_texture.x0) / WORLD_ONE);
1757 return 1;
1758 }
1759
Lua_Secondary_Side_Get_Texture_Y(lua_State * L)1760 static int Lua_Secondary_Side_Get_Texture_Y(lua_State *L)
1761 {
1762 lua_pushnumber(L, (double) (get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_texture.y0) / WORLD_ONE);
1763 return 1;
1764 }
1765
Lua_Secondary_Side_Get_Transfer_Mode(lua_State * L)1766 static int Lua_Secondary_Side_Get_Transfer_Mode(lua_State *L)
1767 {
1768 Lua_TransferMode::Push(L, get_side_data(Lua_Secondary_Side::Index(L, 1))->secondary_transfer_mode);
1769 return 1;
1770 }
1771
Lua_Secondary_Side_Set_Collection(lua_State * L)1772 static int Lua_Secondary_Side_Set_Collection(lua_State *L)
1773 {
1774 short side_index = Lua_Secondary_Side::Index(L, 1);
1775 short collection_index = Lua_Collection::ToIndex(L, 2);
1776
1777 side_data *side = get_side_data(side_index);
1778 side->secondary_texture.texture = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(side->secondary_texture.texture));
1779 update_line_redundancy(side->line_index);
1780 return 0;
1781 }
1782
Lua_Secondary_Side_Set_Light(lua_State * L)1783 static int Lua_Secondary_Side_Set_Light(lua_State *L)
1784 {
1785 short light_index;
1786 if (lua_isnumber(L, 2))
1787 {
1788 light_index = static_cast<short>(lua_tonumber(L, 2));
1789 if (light_index < 0 || light_index >= MAXIMUM_LIGHTS_PER_MAP)
1790 return luaL_error(L, "light: invalid light index");
1791 }
1792 else
1793 {
1794 light_index = Lua_Light::Index(L, 2);
1795 }
1796
1797 get_side_data(Lua_Polygon_Floor::Index(L, 1))->secondary_lightsource_index = light_index;
1798 return 0;
1799 }
Lua_Secondary_Side_Set_Texture_Index(lua_State * L)1800 static int Lua_Secondary_Side_Set_Texture_Index(lua_State *L)
1801 {
1802 side_data *side = get_side_data(Lua_Secondary_Side::Index(L, 1));
1803 if (!lua_isnumber(L, 2))
1804 return luaL_error(L, "texture_index: incorrect argument type");
1805
1806 short shape_index = static_cast<short>(lua_tonumber(L, 2));
1807 if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
1808 return luaL_error(L, "texture_index: invalid texture index");
1809
1810 side->secondary_texture.texture = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(side->secondary_texture.texture), shape_index);
1811 update_line_redundancy(side->line_index);
1812 return 0;
1813 }
1814
Lua_Secondary_Side_Set_Texture_X(lua_State * L)1815 static int Lua_Secondary_Side_Set_Texture_X(lua_State *L)
1816 {
1817 side_data *side = get_side_data(Lua_Secondary_Side::Index(L, 1));
1818 if (!lua_isnumber(L, 2))
1819 return luaL_error(L, "texture_x: incorrect argument type");
1820
1821 side->secondary_texture.x0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1822 return 0;
1823 }
1824
Lua_Secondary_Side_Set_Texture_Y(lua_State * L)1825 static int Lua_Secondary_Side_Set_Texture_Y(lua_State *L)
1826 {
1827 side_data *side = get_side_data(Lua_Secondary_Side::Index(L, 1));
1828 if (!lua_isnumber(L, 2))
1829 return luaL_error(L, "texture_y: incorrect argument type");
1830
1831 side->secondary_texture.y0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1832 return 0;
1833 }
1834
Lua_Secondary_Side_Set_Transfer_Mode(lua_State * L)1835 static int Lua_Secondary_Side_Set_Transfer_Mode(lua_State *L)
1836 {
1837 side_data *side = get_side_data(Lua_Secondary_Side::Index(L, 1));
1838 side->secondary_transfer_mode = Lua_TransferMode::ToIndex(L, 2);
1839 return 0;
1840 }
1841 const luaL_Reg Lua_Secondary_Side_Get[] = {
1842 {"collection", Lua_Secondary_Side_Get_Collection},
1843 {"light", Lua_Secondary_Side_Get_Light},
1844 {"texture_index", Lua_Secondary_Side_Get_Texture_Index},
1845 {"texture_x", Lua_Secondary_Side_Get_Texture_X},
1846 {"texture_y", Lua_Secondary_Side_Get_Texture_Y},
1847 {"transfer_mode", Lua_Secondary_Side_Get_Transfer_Mode},
1848 {0, 0}
1849 };
1850
1851 const luaL_Reg Lua_Secondary_Side_Set[] = {
1852 {"collection", Lua_Secondary_Side_Set_Collection},
1853 {"light", Lua_Secondary_Side_Set_Light},
1854 {"texture_index", Lua_Secondary_Side_Set_Texture_Index},
1855 {"texture_x", Lua_Secondary_Side_Set_Texture_X},
1856 {"texture_y", Lua_Secondary_Side_Set_Texture_Y},
1857 {"transfer_mode", Lua_Secondary_Side_Set_Transfer_Mode},
1858 {0, 0}
1859 };
1860
1861 char Lua_Transparent_Side_Name[] = "transparent_side";
1862 typedef L_Class<Lua_Transparent_Side_Name> Lua_Transparent_Side;
1863
Lua_Transparent_Side_Get_Collection(lua_State * L)1864 static int Lua_Transparent_Side_Get_Collection(lua_State *L)
1865 {
1866 Lua_Collection::Push(L, GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_texture.texture)));
1867 return 1;
1868 }
1869
Lua_Transparent_Side_Get_Empty(lua_State * L)1870 static int Lua_Transparent_Side_Get_Empty(lua_State *L)
1871 {
1872 lua_pushboolean(L, get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_texture.texture == UNONE);
1873 return 1;
1874 }
1875
Lua_Transparent_Side_Get_Light(lua_State * L)1876 static int Lua_Transparent_Side_Get_Light(lua_State *L)
1877 {
1878 Lua_Light::Push(L, get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_lightsource_index);
1879 return 1;
1880 }
1881
Lua_Transparent_Side_Get_Texture_Index(lua_State * L)1882 static int Lua_Transparent_Side_Get_Texture_Index(lua_State *L)
1883 {
1884 lua_pushnumber(L, GET_DESCRIPTOR_SHAPE(get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_texture.texture));
1885 return 1;
1886 }
1887
Lua_Transparent_Side_Get_Texture_X(lua_State * L)1888 static int Lua_Transparent_Side_Get_Texture_X(lua_State *L)
1889 {
1890 lua_pushnumber(L, (double) (get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_texture.x0) / WORLD_ONE);
1891 return 1;
1892 }
1893
Lua_Transparent_Side_Get_Texture_Y(lua_State * L)1894 static int Lua_Transparent_Side_Get_Texture_Y(lua_State *L)
1895 {
1896 lua_pushnumber(L, (double) (get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_texture.y0) / WORLD_ONE);
1897 return 1;
1898 }
1899
Lua_Transparent_Side_Get_Transfer_Mode(lua_State * L)1900 static int Lua_Transparent_Side_Get_Transfer_Mode(lua_State *L)
1901 {
1902 Lua_TransferMode::Push(L, get_side_data(Lua_Transparent_Side::Index(L, 1))->transparent_transfer_mode);
1903 return 1;
1904 }
1905
Lua_Transparent_Side_Set_Collection(lua_State * L)1906 static int Lua_Transparent_Side_Set_Collection(lua_State *L)
1907 {
1908 short side_index = Lua_Transparent_Side::Index(L, 1);
1909 short collection_index = Lua_Collection::ToIndex(L, 2);
1910
1911 side_data *side = get_side_data(side_index);
1912 side->transparent_texture.texture = BUILD_DESCRIPTOR(collection_index, GET_DESCRIPTOR_SHAPE(side->transparent_texture.texture));
1913 update_line_redundancy(side->line_index);
1914 return 0;
1915 }
1916
Lua_Transparent_Side_Set_Empty(lua_State * L)1917 static int Lua_Transparent_Side_Set_Empty(lua_State *L)
1918 {
1919 short side_index = Lua_Transparent_Side::Index(L, 1);
1920 if (!lua_isboolean(L, 2))
1921 return luaL_error(L, "empty: incorrect argument type");
1922
1923 if (lua_toboolean(L, 2))
1924 {
1925 side_data *side = get_side_data(side_index);
1926 side->transparent_texture.texture = UNONE;
1927 update_line_redundancy(side->line_index);
1928 }
1929 return 0;
1930 }
1931
Lua_Transparent_Side_Set_Light(lua_State * L)1932 static int Lua_Transparent_Side_Set_Light(lua_State *L)
1933 {
1934 short light_index;
1935 if (lua_isnumber(L, 2))
1936 {
1937 light_index = static_cast<short>(lua_tonumber(L, 2));
1938 if (light_index < 0 || light_index >= MAXIMUM_LIGHTS_PER_MAP)
1939 return luaL_error(L, "light: invalid light index");
1940 }
1941 else
1942 {
1943 light_index = Lua_Light::Index(L, 2);
1944 }
1945
1946 get_side_data(Lua_Polygon_Floor::Index(L, 1))->transparent_lightsource_index = light_index;
1947 return 0;
1948 }
1949
Lua_Transparent_Side_Set_Texture_Index(lua_State * L)1950 static int Lua_Transparent_Side_Set_Texture_Index(lua_State *L)
1951 {
1952 side_data *side = get_side_data(Lua_Transparent_Side::Index(L, 1));
1953 if (!lua_isnumber(L, 2))
1954 return luaL_error(L, "texture_index: incorrect argument type");
1955
1956 short shape_index = static_cast<short>(lua_tonumber(L, 2));
1957 if (shape_index < 0 || shape_index >= MAXIMUM_SHAPES_PER_COLLECTION)
1958 return luaL_error(L, "texture_index: invalid texture index");
1959
1960 side->transparent_texture.texture = BUILD_DESCRIPTOR(GET_DESCRIPTOR_COLLECTION(side->transparent_texture.texture), shape_index);
1961 update_line_redundancy(side->line_index);
1962 return 0;
1963 }
1964
Lua_Transparent_Side_Set_Texture_X(lua_State * L)1965 static int Lua_Transparent_Side_Set_Texture_X(lua_State *L)
1966 {
1967 side_data *side = get_side_data(Lua_Transparent_Side::Index(L, 1));
1968 if (!lua_isnumber(L, 2))
1969 return luaL_error(L, "texture_x: incorrect argument type");
1970
1971 side->transparent_texture.x0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1972 return 0;
1973 }
1974
Lua_Transparent_Side_Set_Texture_Y(lua_State * L)1975 static int Lua_Transparent_Side_Set_Texture_Y(lua_State *L)
1976 {
1977 side_data *side = get_side_data(Lua_Transparent_Side::Index(L, 1));
1978 if (!lua_isnumber(L, 2))
1979 return luaL_error(L, "texture_y: incorrect argument type");
1980
1981 side->transparent_texture.y0 = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
1982 return 0;
1983 }
1984
Lua_Transparent_Side_Set_Transfer_Mode(lua_State * L)1985 static int Lua_Transparent_Side_Set_Transfer_Mode(lua_State *L)
1986 {
1987 side_data *side = get_side_data(Lua_Transparent_Side::Index(L, 1));
1988 side->transparent_transfer_mode = Lua_TransferMode::ToIndex(L, 2);
1989 return 0;
1990 }
1991 const luaL_Reg Lua_Transparent_Side_Get[] = {
1992 {"collection", Lua_Transparent_Side_Get_Collection},
1993 {"empty", Lua_Transparent_Side_Get_Empty},
1994 {"light", Lua_Transparent_Side_Get_Light},
1995 {"texture_index", Lua_Transparent_Side_Get_Texture_Index},
1996 {"texture_x", Lua_Transparent_Side_Get_Texture_X},
1997 {"texture_y", Lua_Transparent_Side_Get_Texture_Y},
1998 {"transfer_mode", Lua_Transparent_Side_Get_Transfer_Mode},
1999 {0, 0}
2000 };
2001
2002 const luaL_Reg Lua_Transparent_Side_Set[] = {
2003 {"collection", Lua_Transparent_Side_Set_Collection},
2004 {"empty", Lua_Transparent_Side_Set_Empty},
2005 {"light", Lua_Transparent_Side_Set_Light},
2006 {"texture_index", Lua_Transparent_Side_Set_Texture_Index},
2007 {"texture_x", Lua_Transparent_Side_Set_Texture_X},
2008 {"texture_y", Lua_Transparent_Side_Set_Texture_Y},
2009 {"transfer_mode", Lua_Transparent_Side_Set_Transfer_Mode},
2010 {0, 0}
2011 };
2012
2013 char Lua_SideType_Name[] = "side_type";
2014 char Lua_SideTypes_Name[] = "SideTypes";
2015
2016 char Lua_Side_Name[] = "side";
2017
Lua_Side_Play_Sound(lua_State * L)2018 int Lua_Side_Play_Sound(lua_State *L)
2019 {
2020 short sound_code = Lua_Sound::ToIndex(L, 2);
2021 _fixed pitch = FIXED_ONE;
2022 if (lua_gettop(L) == 3)
2023 {
2024 if (!lua_isnumber(L, 3))
2025 return luaL_error(L, "play_sound: incorrect argument type");
2026 pitch = static_cast<_fixed>(lua_tonumber(L, 3) * FIXED_ONE);
2027 }
2028
2029 _play_side_sound(Lua_Side::Index(L, 1), sound_code, pitch);
2030 return 0;
2031 }
2032
Lua_Side_Recalculate_Type(lua_State * L)2033 int Lua_Side_Recalculate_Type(lua_State *L)
2034 {
2035 recalculate_side_type(Lua_Side::Index(L, 1));
2036 return 0;
2037 }
2038
Lua_Side_Get_Control_Panel(lua_State * L)2039 static int Lua_Side_Get_Control_Panel(lua_State *L)
2040 {
2041 int16 side_index = Lua_Side::Index(L, 1);
2042 side_data *side = get_side_data(side_index);
2043 if (SIDE_IS_CONTROL_PANEL(side))
2044 {
2045 Lua_Side_ControlPanel::Push(L, side_index);
2046 }
2047 else
2048 {
2049 lua_pushnil(L);
2050 }
2051
2052 return 1;
2053 }
2054
Lua_Side_Get_Line(lua_State * L)2055 static int Lua_Side_Get_Line(lua_State *L)
2056 {
2057 Lua_Line::Push(L, get_side_data(Lua_Side::Index(L, 1))->line_index);
2058 return 1;
2059 }
2060
Lua_Side_Get_Polygon(lua_State * L)2061 static int Lua_Side_Get_Polygon(lua_State *L)
2062 {
2063 Lua_Polygon::Push(L, get_side_data(Lua_Side::Index(L, 1))->polygon_index);
2064 return 1;
2065 }
2066
Lua_Side_Get_Primary(lua_State * L)2067 static int Lua_Side_Get_Primary(lua_State *L)
2068 {
2069 Lua_Primary_Side::Push(L, Lua_Side::Index(L, 1));
2070 return 1;
2071 }
2072
Lua_Side_Get_Secondary(lua_State * L)2073 static int Lua_Side_Get_Secondary(lua_State *L)
2074 {
2075 Lua_Secondary_Side::Push(L, Lua_Side::Index(L, 1));
2076 return 1;
2077 }
2078
Lua_Side_Get_Transparent(lua_State * L)2079 static int Lua_Side_Get_Transparent(lua_State *L)
2080 {
2081 Lua_Transparent_Side::Push(L, Lua_Side::Index(L, 1));
2082 return 1;
2083 }
2084
Lua_Side_Get_Type(lua_State * L)2085 static int Lua_Side_Get_Type(lua_State *L)
2086 {
2087 Lua_SideType::Push(L, get_side_data(Lua_Side::Index(L, 1))->type);
2088 return 1;
2089 }
2090
2091 const luaL_Reg Lua_Side_Get[] = {
2092 {"control_panel", Lua_Side_Get_Control_Panel},
2093 {"line", Lua_Side_Get_Line},
2094 {"play_sound", L_TableFunction<Lua_Side_Play_Sound>},
2095 {"polygon", Lua_Side_Get_Polygon},
2096 {"primary", Lua_Side_Get_Primary},
2097 {"recalculate_type", L_TableFunction<Lua_Side_Recalculate_Type>},
2098 {"secondary", Lua_Side_Get_Secondary},
2099 {"transparent", Lua_Side_Get_Transparent},
2100 {"type", Lua_Side_Get_Type},
2101 {0, 0}
2102 };
2103
Lua_Side_Set_Control_Panel(lua_State * L)2104 static int Lua_Side_Set_Control_Panel(lua_State *L)
2105 {
2106 if (!lua_isboolean(L, 2))
2107 return luaL_error(L, "control_panel: incorrect argument type");
2108
2109 side_data *side = get_side_data(Lua_Side::Index(L, 1));
2110
2111 if (lua_toboolean(L, 2) != (side->flags & _side_is_control_panel))
2112 {
2113 // new control panel, or deleting old; clear either way
2114 side->control_panel_type = NONE;
2115 side->flags &= ~(_control_panel_status | _side_is_control_panel | _side_is_repair_switch | _side_is_destructive_switch | _side_is_lighted_switch | _side_switch_can_be_destroyed | _side_switch_can_only_be_hit_by_projectiles);
2116
2117 if (lua_toboolean(L, 2))
2118 side->flags |= _side_is_control_panel;
2119 }
2120
2121 return 0;
2122 }
2123
2124 const luaL_Reg Lua_Side_Set[] = {
2125 {"control_panel", Lua_Side_Set_Control_Panel},
2126 {0, 0}
2127 };
2128
2129
Lua_Side_Valid(int16 index)2130 static bool Lua_Side_Valid(int16 index)
2131 {
2132 return index >= 0 && index < SideList.size();
2133 }
2134
2135 char Lua_Sides_Name[] = "Sides";
Lua_Sides_Length()2136 static int16 Lua_Sides_Length() { return SideList.size(); }
2137
2138 // Sides.new(polygon, line)
Lua_Sides_New(lua_State * L)2139 int Lua_Sides_New(lua_State *L)
2140 {
2141 short polygon_index;
2142 if (lua_isnumber(L, 1))
2143 {
2144 polygon_index = static_cast<short>(lua_tonumber(L, 1));
2145 if (!Lua_Polygon::Valid(polygon_index))
2146 return luaL_error(L, "new: invalid polygon index");
2147 }
2148 else if (Lua_Polygon::Is(L, 1))
2149 polygon_index = Lua_Polygon::Index(L, 1);
2150 else
2151 return luaL_error(L, "new: incorrect argument type");
2152
2153 short line_index;
2154 if (lua_isnumber(L, 2))
2155 {
2156 line_index = static_cast<short>(lua_tonumber(L, 2));
2157 if (!Lua_Line::Valid(line_index))
2158 return luaL_error(L, "new: invalid line index");
2159 }
2160 else if (Lua_Line::Is(L, 2))
2161 line_index = Lua_Line::Index(L, 2);
2162 else
2163 return luaL_error(L, "new: incorrect argument type");
2164
2165 // make sure we don't assert
2166 line_data *line = get_line_data(line_index);
2167 if (!(line->clockwise_polygon_owner == polygon_index || line->counterclockwise_polygon_owner == polygon_index))
2168 return luaL_error(L, "new: line does not belong to polygon");
2169
2170 if ((line->clockwise_polygon_owner == polygon_index && line->clockwise_polygon_side_index != NONE) || (line->counterclockwise_polygon_owner == polygon_index && line->counterclockwise_polygon_side_index != NONE))
2171 return luaL_error(L, "new: side already exists");
2172
2173 Lua_Side::Push(L, new_side(polygon_index, line_index));
2174 return 1;
2175 }
2176
2177 const luaL_Reg Lua_Sides_Methods[] = {
2178 {"new", L_TableFunction<Lua_Sides_New>},
2179 {0, 0}
2180 };
2181
2182 char Lua_LightFunction_Name[] = "light_function";
2183 typedef L_Enum<Lua_LightFunction_Name> Lua_LightFunction;
2184
2185 char Lua_LightFunctions_Name[] = "LightFunctions";
2186 typedef L_EnumContainer<Lua_LightFunctions_Name, Lua_LightFunction> Lua_LightFunctions;
2187
2188 char Lua_LightPreset_Name[] = "light_preset";
2189 typedef L_Enum<Lua_LightPreset_Name> Lua_LightPreset;
2190
2191 char Lua_LightPresets_Name[] = "LightPresets";
2192 typedef L_EnumContainer<Lua_LightPresets_Name, Lua_LightPreset> Lua_LightPresets;
2193
2194 char Lua_LightState_Name[] = "light_state";
2195 typedef L_Enum<Lua_LightState_Name> Lua_LightState;
2196
2197 char Lua_LightStates_Name[] = "LightStates";
2198 typedef L_EnumContainer<Lua_LightStates_Name, Lua_LightState> Lua_LightStates;
2199
2200 char Lua_Light_State_Name[] = "light_state_subtable";
2201
2202 class Lua_Light_State : public L_Class<Lua_Light_State_Name>
2203 {
2204 public:
2205 int16 m_light_index;
2206 static Lua_Light_State* Push(lua_State* L, int16 light_index, int16 index);
2207 static int16 LightIndex(lua_State* L, int index);
2208 };
2209
Push(lua_State * L,int16 light_index,int16 index)2210 Lua_Light_State* Lua_Light_State::Push(lua_State* L, int16 light_index, int16 index)
2211 {
2212 Lua_Light_State* t = 0;
2213
2214 if (!Lua_Light_State::Valid(index) || !Lua_Light::Valid(light_index))
2215 {
2216 lua_pushnil(L);
2217 return 0;
2218 }
2219
2220 t = NewInstance<Lua_Light_State>(L, index);
2221 t->m_light_index = light_index;
2222
2223 return t;
2224 }
2225
LightIndex(lua_State * L,int index)2226 int16 Lua_Light_State::LightIndex(lua_State* L, int index)
2227 {
2228 Lua_Light_State* t = static_cast<Lua_Light_State*>(Instance(L, index));
2229 if (!t) luaL_typerror(L, index, Lua_Light_State_Name);
2230 return t->m_light_index;
2231 }
2232
get_light_function_spec(int light_index,int state)2233 static lighting_function_specification* get_light_function_spec(int light_index, int state)
2234 {
2235 light_data* light = get_light_data(light_index);
2236 switch (state)
2237 {
2238 case _light_becoming_active:
2239 return &light->static_data.becoming_active;
2240 case _light_primary_active:
2241 return &light->static_data.primary_active;
2242 case _light_secondary_active:
2243 return &light->static_data.secondary_active;
2244 case _light_becoming_inactive:
2245 return &light->static_data.becoming_inactive;
2246 case _light_primary_inactive:
2247 return &light->static_data.primary_inactive;
2248 case _light_secondary_inactive:
2249 return &light->static_data.secondary_inactive;
2250 default:
2251 assert(false);
2252 }
2253
2254 return 0;
2255 }
2256
Lua_Light_State_Get_Delta_Intensity(lua_State * L)2257 static int Lua_Light_State_Get_Delta_Intensity(lua_State* L)
2258 {
2259 int light_index = Lua_Light_State::LightIndex(L, 1);
2260 lighting_function_specification* spec = get_light_function_spec(light_index, Lua_Light_State::Index(L, 1));
2261 lua_pushnumber(L, static_cast<double>(spec->delta_intensity) / FIXED_ONE);
2262 return 1;
2263 }
2264
Lua_Light_State_Get_Delta_Period(lua_State * L)2265 static int Lua_Light_State_Get_Delta_Period(lua_State* L)
2266 {
2267 int light_index = Lua_Light_State::LightIndex(L, 1);
2268 lighting_function_specification* spec = get_light_function_spec(light_index, Lua_Light_State::Index(L, 1));
2269 lua_pushnumber(L, static_cast<double>(spec->delta_period));
2270 return 1;
2271 }
2272
Lua_Light_State_Get_Function(lua_State * L)2273 static int Lua_Light_State_Get_Function(lua_State* L)
2274 {
2275 int light_index = Lua_Light_State::LightIndex(L, 1);
2276 lighting_function_specification* spec = get_light_function_spec(light_index, Lua_Light_State::Index(L, 1));
2277 Lua_LightFunction::Push(L, spec->function);
2278 return 1;
2279 }
2280
Lua_Light_State_Get_Intensity(lua_State * L)2281 static int Lua_Light_State_Get_Intensity(lua_State* L)
2282 {
2283 int light_index = Lua_Light_State::LightIndex(L, 1);
2284 lighting_function_specification* spec = get_light_function_spec(light_index, Lua_Light_State::Index(L, 1));
2285 lua_pushnumber(L, static_cast<double>(spec->intensity) / FIXED_ONE);
2286 return 1;
2287 }
2288
Lua_Light_State_Get_Period(lua_State * L)2289 static int Lua_Light_State_Get_Period(lua_State* L)
2290 {
2291 int light_index = Lua_Light_State::LightIndex(L, 1);
2292 lighting_function_specification* spec = get_light_function_spec(light_index, Lua_Light_State::Index(L, 1));
2293 lua_pushnumber(L, static_cast<double>(spec->period));
2294 return 1;
2295 }
2296
2297
2298 const luaL_Reg Lua_Light_State_Get[] = {
2299 {"delta_intensity", Lua_Light_State_Get_Delta_Intensity},
2300 {"delta_period", Lua_Light_State_Get_Delta_Period},
2301 {"intensity", Lua_Light_State_Get_Intensity},
2302 {"light_function", Lua_Light_State_Get_Function},
2303 {"period", Lua_Light_State_Get_Period},
2304 {0, 0}
2305 };
2306
Lua_Light_State_Set_Delta_Intensity(lua_State * L)2307 static int Lua_Light_State_Set_Delta_Intensity(lua_State* L)
2308 {
2309 if (!lua_isnumber(L, 2))
2310 return luaL_error(L, "delta_intensity: incorrect argument type");
2311
2312 lighting_function_specification* spec = get_light_function_spec(Lua_Light_State::LightIndex(L, 1), Lua_Light_State::Index(L, 1));
2313 spec->delta_intensity = static_cast<int32>(lua_tonumber(L, 2) * FIXED_ONE);
2314 return 1;
2315 }
2316
Lua_Light_State_Set_Delta_Period(lua_State * L)2317 static int Lua_Light_State_Set_Delta_Period(lua_State* L)
2318 {
2319 if (!lua_isnumber(L, 2))
2320 return luaL_error(L, "delta_period: incorrect argument type");
2321
2322 int16 period = lua_tonumber(L, 2);
2323 if (period < 0)
2324 return luaL_error(L, "delta_period: must be nonnegative");
2325
2326 lighting_function_specification* spec = get_light_function_spec(Lua_Light_State::LightIndex(L, 1), Lua_Light_State::Index(L, 1));
2327 spec->delta_period = period;
2328 return 1;
2329 }
2330
Lua_Light_State_Set_Function(lua_State * L)2331 static int Lua_Light_State_Set_Function(lua_State* L)
2332 {
2333 int16 function = Lua_LightFunction::ToIndex(L, 2);
2334 lighting_function_specification* spec = get_light_function_spec(Lua_Light_State::LightIndex(L, 1), Lua_Light_State::Index(L, 1));
2335 spec->function = function;
2336 return 1;
2337 }
2338
Lua_Light_State_Set_Intensity(lua_State * L)2339 static int Lua_Light_State_Set_Intensity(lua_State* L)
2340 {
2341 if (!lua_isnumber(L, 2))
2342 return luaL_error(L, "intensity: incorrect argument type");
2343
2344 lighting_function_specification* spec = get_light_function_spec(Lua_Light_State::LightIndex(L, 1), Lua_Light_State::Index(L, 1));
2345 spec->intensity = static_cast<int32>(lua_tonumber(L, 2) * FIXED_ONE);
2346 return 1;
2347 }
2348
Lua_Light_State_Set_Period(lua_State * L)2349 static int Lua_Light_State_Set_Period(lua_State* L)
2350 {
2351 if (!lua_isnumber(L, 2))
2352 return luaL_error(L, "period: incorrect argument type");
2353
2354 int16 period = lua_tonumber(L, 2);
2355 if (period < 0)
2356 return luaL_error(L, "period: must be nonnegative");
2357
2358 lighting_function_specification* spec = get_light_function_spec(Lua_Light_State::LightIndex(L, 1), Lua_Light_State::Index(L, 1));
2359 spec->period = period;
2360 return 1;
2361 }
2362
2363 const luaL_Reg Lua_Light_State_Set[] = {
2364 {"delta_intensity", Lua_Light_State_Set_Delta_Intensity},
2365 {"delta_period", Lua_Light_State_Set_Delta_Period},
2366 {"intensity", Lua_Light_State_Set_Intensity},
2367 {"light_function", Lua_Light_State_Set_Function},
2368 {"period", Lua_Light_State_Set_Period},
2369 {0, 0}
2370 };
2371
2372 char Lua_Light_States_Name[] = "light_states";
2373 typedef L_Class<Lua_Light_States_Name> Lua_Light_States;
2374
Lua_Light_States_Get(lua_State * L)2375 static int Lua_Light_States_Get(lua_State* L)
2376 {
2377 int light_index = Lua_Light_States::Index(L, 1);
2378 int state_index = Lua_LightState::ToIndex(L, 2);
2379 Lua_Light_State::Push(L, light_index, state_index);
2380 return 1;
2381 }
2382
Lua_Light_States_Length(lua_State * L)2383 static int Lua_Light_States_Length(lua_State* L)
2384 {
2385 lua_pushnumber(L, static_cast<int16>(_light_secondary_inactive) + 1);
2386 return 1;
2387 }
2388
2389 const luaL_Reg Lua_Light_States_Metatable[] = {
2390 {"__index", Lua_Light_States_Get},
2391 {"__len", Lua_Light_States_Length},
2392 {0, 0}
2393 };
2394
2395 char Lua_Light_Name[] = "light";
2396
Lua_Light_Get_Active(lua_State * L)2397 static int Lua_Light_Get_Active(lua_State *L)
2398 {
2399 lua_pushboolean(L, get_light_status(Lua_Light::Index(L, 1)));
2400 return 1;
2401 }
2402
Lua_Light_Get_Intensity(lua_State * L)2403 static int Lua_Light_Get_Intensity(lua_State* L)
2404 {
2405 lua_pushnumber(L, static_cast<double>(get_light_intensity(Lua_Light::Index(L, 1))) / FIXED_ONE);
2406 return 1;
2407 }
2408
Lua_Light_Get_Initial_Phase(lua_State * L)2409 static int Lua_Light_Get_Initial_Phase(lua_State* L)
2410 {
2411 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2412 lua_pushnumber(L, static_cast<double>(data->static_data.phase));
2413 return 1;
2414 }
2415
Lua_Light_Get_Initially_Active(lua_State * L)2416 static int Lua_Light_Get_Initially_Active(lua_State* L)
2417 {
2418 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2419 lua_pushboolean(L, data->static_data.flags & _light_is_initially_active);
2420 return 1;
2421 }
2422
Lua_Light_Get_States(lua_State * L)2423 static int Lua_Light_Get_States(lua_State *L)
2424 {
2425 Lua_Light_States::Push(L, Lua_Light::Index(L, 1));
2426 return 1;
2427 }
2428
Lua_Light_Get_Tag(lua_State * L)2429 static int Lua_Light_Get_Tag(lua_State* L)
2430 {
2431 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2432 Lua_Tag::Push(L, data->static_data.tag);
2433 return 1;
2434 }
2435
2436 const luaL_Reg Lua_Light_Get[] = {
2437 {"active", Lua_Light_Get_Active},
2438 {"initial_phase", Lua_Light_Get_Initial_Phase},
2439 {"initially_active", Lua_Light_Get_Initially_Active},
2440 {"intensity", Lua_Light_Get_Intensity},
2441 {"states", Lua_Light_Get_States},
2442 {"tag", Lua_Light_Get_Tag},
2443 {0, 0}
2444 };
2445
Lua_Light_Set_Active(lua_State * L)2446 static int Lua_Light_Set_Active(lua_State *L)
2447 {
2448 if (!lua_isboolean(L, 2))
2449 return luaL_error(L, "active: incorrect argument type");
2450
2451 size_t light_index = Lua_Light::Index(L, 1);
2452 bool active = lua_toboolean(L, 2);
2453
2454 set_light_status(light_index, active);
2455 assume_correct_switch_position(_panel_is_light_switch, static_cast<short>(light_index), active);
2456 return 0;
2457 }
2458
Lua_Light_Set_Initially_Active(lua_State * L)2459 static int Lua_Light_Set_Initially_Active(lua_State* L)
2460 {
2461 if (!lua_isboolean(L, 2))
2462 return luaL_error(L, "initially_active: incorrect argument type");
2463
2464 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2465 bool active = lua_toboolean(L, 2);
2466 if (active)
2467 {
2468 data->static_data.flags |= _light_is_initially_active;
2469 }
2470 else
2471 {
2472 data->static_data.flags &= ~_light_is_initially_active;
2473 }
2474
2475 return 0;
2476 }
2477
Lua_Light_Set_Phase(lua_State * L)2478 static int Lua_Light_Set_Phase(lua_State* L)
2479 {
2480 if (!lua_isnumber(L, 2))
2481 return luaL_error(L, "phase: incorrect argument type");
2482
2483 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2484 data->static_data.phase = static_cast<int16>(lua_tonumber(L, 2));
2485 return 0;
2486 }
2487
Lua_Light_Set_Tag(lua_State * L)2488 static int Lua_Light_Set_Tag(lua_State* L)
2489 {
2490 int16 tag = NONE;
2491 if (lua_isnumber(L, 2))
2492 {
2493 tag = static_cast<int16>(lua_tonumber(L, 2));
2494 if (!Lua_Tag::Valid(tag))
2495 return luaL_error(L, "tag: invalid tag index");
2496 }
2497 else if (Lua_Tag::Is(L, 2))
2498 {
2499 tag = Lua_Tag::Index(L, 2);
2500 }
2501 else return luaL_error(L, "tag: incorrect argument type");
2502
2503 light_data* data = get_light_data(Lua_Light::Index(L, 1));
2504 data->static_data.tag = tag;
2505 return 0;
2506 }
2507
2508 const luaL_Reg Lua_Light_Set[] = {
2509 {"active", Lua_Light_Set_Active},
2510 {"initial_phase", Lua_Light_Set_Phase},
2511 {"initially_active", Lua_Light_Set_Initially_Active},
2512 {"tag", Lua_Light_Set_Tag},
2513 {0, 0}
2514 };
2515
Lua_Light_Valid(int16 index)2516 bool Lua_Light_Valid(int16 index)
2517 {
2518 return index >= 0 && index < MAXIMUM_LIGHTS_PER_MAP;
2519 }
2520
2521 char Lua_Lights_Name[] = "Lights";
Lua_Lights_Length()2522 static int16 Lua_Lights_Length() { return LightList.size(); }
2523
Lua_Lights_New(lua_State * L)2524 int Lua_Lights_New(lua_State* L)
2525 {
2526 if (LightList.size() == INT16_MAX)
2527 return 0;
2528
2529 short type;
2530 if (lua_isnil(L, 1))
2531 {
2532 type = _normal_light;
2533 }
2534 else
2535 {
2536 type = Lua_LightPreset::ToIndex(L, 1);
2537 }
2538
2539 LightList.resize(LightList.size() + 1);
2540 short index = new_light(get_defaults_for_light_type(type));
2541 Lua_Light::Push(L, index);
2542 return 1;
2543 }
2544
2545 const luaL_Reg Lua_Lights_Methods[] = {
2546 {"new", L_TableFunction<Lua_Lights_New>},
2547 {0, 0}
2548 };
2549
2550 char Lua_Tag_Name[] = "tag";
2551
Lua_Tag_Get_Active(lua_State * L)2552 static int Lua_Tag_Get_Active(lua_State *L)
2553 {
2554 int tag = Lua_Tag::Index(L, 1);
2555 bool changed = false;
2556
2557 size_t light_index;
2558 light_data *light;
2559
2560 for (light_index= 0, light= lights; light_index<MAXIMUM_LIGHTS_PER_MAP && !changed; ++light_index, ++light)
2561 {
2562 if (light->static_data.tag==tag)
2563 {
2564 if (get_light_status(light_index))
2565 {
2566 changed= true;
2567 }
2568 }
2569 }
2570
2571 short platform_index;
2572 platform_data *platform;
2573
2574 for (platform_index= 0, platform= platforms; platform_index<dynamic_world->platform_count && !changed; ++platform_index, ++platform)
2575 {
2576 if (platform->tag==tag)
2577 {
2578 if (PLATFORM_IS_ACTIVE(platform))
2579 {
2580 changed= true;
2581 }
2582 }
2583 }
2584
2585 lua_pushboolean(L, changed);
2586 return 1;
2587 }
2588
Lua_Tag_Set_Active(lua_State * L)2589 static int Lua_Tag_Set_Active(lua_State *L)
2590 {
2591 if (!lua_isboolean(L, 2))
2592 return luaL_error(L, "active: incorrect argument type");
2593
2594 int16 tag = Lua_Tag::Index(L, 1);
2595 bool active = lua_toboolean(L, 2);
2596
2597 set_tagged_light_statuses(tag, active);
2598 try_and_change_tagged_platform_states(tag, active);
2599 assume_correct_switch_position(_panel_is_tag_switch, tag, active);
2600
2601 return 0;
2602 }
2603
2604 const luaL_Reg Lua_Tag_Get[] = {
2605 {"active", Lua_Tag_Get_Active},
2606 {0, 0}
2607 };
2608
2609 const luaL_Reg Lua_Tag_Set[] = {
2610 {"active", Lua_Tag_Set_Active},
2611 {0, 0}
2612 };
2613
Lua_Tag_Valid(int16 index)2614 bool Lua_Tag_Valid(int16 index) { return index >= 0; }
2615
2616 char Lua_Tags_Name[] = "Tags";
2617
2618 char Lua_Terminal_Name[] = "terminal";
2619
2620 extern short number_of_terminal_texts();
2621
Lua_Terminal_Valid(int16 index)2622 static bool Lua_Terminal_Valid(int16 index)
2623 {
2624 return index >= 0 && index < number_of_terminal_texts();
2625 }
2626
2627 char Lua_Terminals_Name[] = "Terminals";
2628
Lua_Terminals_Length()2629 static int16 Lua_Terminals_Length() {
2630 return number_of_terminal_texts();
2631 }
2632
2633 char Lua_MediaType_Name[] = "media_type";
2634 typedef L_Enum<Lua_MediaType_Name> Lua_MediaType;
2635
2636 char Lua_MediaTypes_Name[] = "MediaTypes";
2637 typedef L_EnumContainer<Lua_MediaTypes_Name, Lua_MediaType> Lua_MediaTypes;
2638
2639 char Lua_Media_Name[] = "media";
2640
2641 const float AngleConvert = 360/float(FULL_CIRCLE);
2642
Lua_Media_Get_Direction(lua_State * L)2643 static int Lua_Media_Get_Direction(lua_State* L)
2644 {
2645 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2646 lua_pushnumber(L, static_cast<double>(media->current_direction) * AngleConvert);
2647 return 1;
2648 }
2649
Lua_Media_Get_Height(lua_State * L)2650 static int Lua_Media_Get_Height(lua_State* L)
2651 {
2652 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2653 lua_pushnumber(L, static_cast<double>(media->height) / WORLD_ONE);
2654 return 1;
2655 }
2656
Lua_Media_Get_High(lua_State * L)2657 static int Lua_Media_Get_High(lua_State* L)
2658 {
2659 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2660 lua_pushnumber(L, static_cast<double>(media->high) / WORLD_ONE);
2661 return 1;
2662 }
2663
Lua_Media_Get_Light(lua_State * L)2664 static int Lua_Media_Get_Light(lua_State* L)
2665 {
2666 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2667 Lua_Light::Push(L, media->light_index);
2668 return 1;
2669 }
2670
Lua_Media_Get_Low(lua_State * L)2671 static int Lua_Media_Get_Low(lua_State* L)
2672 {
2673 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2674 lua_pushnumber(L, static_cast<double>(media->low) / WORLD_ONE);
2675 return 1;
2676 }
2677
Lua_Media_Get_Speed(lua_State * L)2678 static int Lua_Media_Get_Speed(lua_State* L)
2679 {
2680 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2681 lua_pushnumber(L, static_cast<double>(media->current_magnitude) / WORLD_ONE);
2682 return 1;
2683 }
2684
Lua_Media_Get_Type(lua_State * L)2685 static int Lua_Media_Get_Type(lua_State *L)
2686 {
2687 media_data *media = get_media_data(Lua_Media::Index(L, 1));
2688 Lua_MediaType::Push(L, media->type);
2689 return 1;
2690 }
2691
2692 const luaL_Reg Lua_Media_Get[] = {
2693 {"direction", Lua_Media_Get_Direction},
2694 {"height", Lua_Media_Get_Height},
2695 {"high", Lua_Media_Get_High},
2696 {"light", Lua_Media_Get_Light},
2697 {"low", Lua_Media_Get_Low},
2698 {"speed", Lua_Media_Get_Speed},
2699 {"type", Lua_Media_Get_Type},
2700 {0, 0}
2701 };
2702
2703 extern void update_one_media(size_t, bool);
2704
Lua_Media_Set_Direction(lua_State * L)2705 static int Lua_Media_Set_Direction(lua_State* L)
2706 {
2707 if (!lua_isnumber(L, 2))
2708 return luaL_error(L, "direction: incorrect argument type");
2709
2710 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2711 media->current_direction = static_cast<angle>(lua_tonumber(L, 2) / AngleConvert);
2712 return 0;
2713 }
2714
Lua_Media_Set_High(lua_State * L)2715 static int Lua_Media_Set_High(lua_State* L)
2716 {
2717 if (!lua_isnumber(L, 2))
2718 return luaL_error(L, "high: incorrect argument type");
2719
2720 int media_index = Lua_Media::Index(L, 1);
2721 media_data* media = get_media_data(media_index);
2722 media->high = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
2723 update_one_media(media_index, true);
2724 return 0;
2725 }
2726
Lua_Media_Set_Light(lua_State * L)2727 static int Lua_Media_Set_Light(lua_State* L)
2728 {
2729 int light_index;
2730 if (lua_isnumber(L, 2))
2731 {
2732 light_index = static_cast<int>(lua_tonumber(L, 2));
2733 if (!Lua_Light::Valid(light_index))
2734 return luaL_error(L, "light: invalid light index");
2735 }
2736 else if (Lua_Light::Is(L, 2))
2737 {
2738 light_index = Lua_Light::Index(L, 2);
2739 }
2740 else
2741 {
2742 return luaL_error(L, "light: incorrect argument type");
2743 }
2744
2745 int media_index = Lua_Media::Index(L, 1);
2746 media_data* media = get_media_data(media_index);
2747 media->light_index = light_index;
2748 update_one_media(media_index, true);
2749 return 0;
2750 }
2751
Lua_Media_Set_Low(lua_State * L)2752 static int Lua_Media_Set_Low(lua_State* L)
2753 {
2754 if (!lua_isnumber(L, 2))
2755 return luaL_error(L, "high: incorrect argument type");
2756
2757 int media_index = Lua_Media::Index(L, 1);
2758 media_data* media = get_media_data(media_index);
2759 media->low = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
2760 update_one_media(media_index, true);
2761 return 0;
2762 }
2763
Lua_Media_Set_Speed(lua_State * L)2764 static int Lua_Media_Set_Speed(lua_State* L)
2765 {
2766 if (!lua_isnumber(L, 2))
2767 return luaL_error(L, "speed: incorrect argument type");
2768
2769 media_data* media = get_media_data(Lua_Media::Index(L, 1));
2770 media->current_magnitude = static_cast<world_distance>(lua_tonumber(L, 2) * WORLD_ONE);
2771 return 0;
2772 }
2773
Lua_Media_Set_Type(lua_State * L)2774 static int Lua_Media_Set_Type(lua_State* L)
2775 {
2776 int media_index = Lua_Media::Index(L, 1);
2777 media_data* media = get_media_data(media_index);
2778 media->type = Lua_MediaType::ToIndex(L, 2);
2779 update_one_media(media_index, true);
2780 return 0;
2781 }
2782
2783 const luaL_Reg Lua_Media_Set[] = {
2784 {"direction", Lua_Media_Set_Direction},
2785 {"high", Lua_Media_Set_High},
2786 {"light", Lua_Media_Set_Light},
2787 {"low", Lua_Media_Set_Low},
2788 {"speed", Lua_Media_Set_Speed},
2789 {"type", Lua_Media_Set_Type},
2790 {0, 0}
2791 };
2792
Lua_Media_Valid(int16 index)2793 static bool Lua_Media_Valid(int16 index)
2794 {
2795 return index >= 0 && index< MAXIMUM_MEDIAS_PER_MAP;
2796 }
2797
2798 char Lua_Medias_Name[] = "Media";
Lua_Medias_Length()2799 static int16 Lua_Medias_Length() { return MediaList.size(); }
2800
2801 char Lua_Annotation_Name[] = "annotation";
2802 typedef L_Class<Lua_Annotation_Name> Lua_Annotation;
2803
Lua_Annotation_Get_Polygon(lua_State * L)2804 static int Lua_Annotation_Get_Polygon(lua_State *L)
2805 {
2806 Lua_Polygon::Push(L, MapAnnotationList[Lua_Annotation::Index(L, 1)].polygon_index);
2807 return 1;
2808 }
2809
Lua_Annotation_Get_Text(lua_State * L)2810 static int Lua_Annotation_Get_Text(lua_State *L)
2811 {
2812 lua_pushstring(L, MapAnnotationList[Lua_Annotation::Index(L, 1)].text);
2813 return 1;
2814 }
2815
Lua_Annotation_Get_X(lua_State * L)2816 static int Lua_Annotation_Get_X(lua_State *L)
2817 {
2818 lua_pushnumber(L, (double) MapAnnotationList[Lua_Annotation::Index(L, 1)].location.x / WORLD_ONE);
2819 return 1;
2820 }
2821
Lua_Annotation_Get_Y(lua_State * L)2822 static int Lua_Annotation_Get_Y(lua_State *L)
2823 {
2824 lua_pushnumber(L, (double) MapAnnotationList[Lua_Annotation::Index(L, 1)].location.y / WORLD_ONE);
2825 return 1;
2826 }
2827
2828 const luaL_Reg Lua_Annotation_Get[] = {
2829 {"polygon", Lua_Annotation_Get_Polygon},
2830 {"text", Lua_Annotation_Get_Text},
2831 {"x", Lua_Annotation_Get_X},
2832 {"y", Lua_Annotation_Get_Y},
2833 {0, 0}
2834 };
2835
Lua_Annotation_Set_Polygon(lua_State * L)2836 static int Lua_Annotation_Set_Polygon(lua_State *L)
2837 {
2838 int polygon_index = NONE;
2839 if (lua_isnil(L, 2))
2840 {
2841 polygon_index = NONE;
2842 }
2843 else
2844 {
2845 polygon_index = Lua_Polygon::Index(L, 2);
2846 }
2847
2848 MapAnnotationList[Lua_Annotation::Index(L, 1)].polygon_index = polygon_index;
2849 return 0;
2850 }
2851
Lua_Annotation_Set_Text(lua_State * L)2852 static int Lua_Annotation_Set_Text(lua_State *L)
2853 {
2854 if (!lua_isstring(L, 2))
2855 return luaL_error(L, "text: incorrect argument type");
2856
2857 int annotation_index = Lua_Annotation::Index(L, 1);
2858 strncpy(MapAnnotationList[annotation_index].text, lua_tostring(L, 2), MAXIMUM_ANNOTATION_TEXT_LENGTH);
2859 MapAnnotationList[annotation_index].text[MAXIMUM_ANNOTATION_TEXT_LENGTH-1] = '\0';
2860 return 0;
2861 }
2862
Lua_Annotation_Set_X(lua_State * L)2863 static int Lua_Annotation_Set_X(lua_State *L)
2864 {
2865 if (!lua_isnumber(L, 2))
2866 return luaL_error(L, "x: incorrect argument type");
2867
2868 MapAnnotationList[Lua_Annotation::Index(L, 1)].location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
2869 return 0;
2870 }
2871
Lua_Annotation_Set_Y(lua_State * L)2872 static int Lua_Annotation_Set_Y(lua_State *L)
2873 {
2874 if (!lua_isnumber(L, 2))
2875 return luaL_error(L, "y: incorrect argument type");
2876
2877 MapAnnotationList[Lua_Annotation::Index(L, 1)].location.y = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
2878 return 0;
2879 }
2880
2881 const luaL_Reg Lua_Annotation_Set[] = {
2882 {"polygon", Lua_Annotation_Set_Polygon},
2883 {"text", Lua_Annotation_Set_Text},
2884 {"x", Lua_Annotation_Set_X},
2885 {"y", Lua_Annotation_Set_Y},
2886 {0, 0}
2887 };
2888
Lua_Annotation_Valid(int16 index)2889 bool Lua_Annotation_Valid(int16 index)
2890 {
2891 return index >= 0 && index < MapAnnotationList.size();
2892 }
2893
2894 char Lua_Annotations_Name[] = "Annotations";
2895 typedef L_Container<Lua_Annotations_Name, Lua_Annotation> Lua_Annotations;
2896
2897 // Annotations.new(polygon, text, [x, y])
Lua_Annotations_New(lua_State * L)2898 int Lua_Annotations_New(lua_State *L)
2899 {
2900 if (dynamic_world->default_annotation_count == INT16_MAX)
2901 return luaL_error(L, "new: annotation limit reached");
2902
2903 if (!lua_isstring(L, 2))
2904 return luaL_error(L, "new: incorrect argument type");
2905
2906 map_annotation annotation;
2907 annotation.type = 0;
2908
2909 if (lua_isnil(L, 1))
2910 {
2911 annotation.polygon_index = NONE;
2912 }
2913 else
2914 {
2915 annotation.polygon_index = Lua_Polygon::Index(L, 1);
2916 }
2917
2918 int x = 0, y = 0;
2919 if (annotation.polygon_index != NONE)
2920 {
2921 polygon_data *polygon = get_polygon_data(annotation.polygon_index);
2922 x = polygon->center.x;
2923 y = polygon->center.y;
2924 }
2925
2926 annotation.location.x = luaL_optint(L, 3, x);
2927 annotation.location.y = luaL_optint(L, 4, y);
2928
2929 strncpy(annotation.text, lua_tostring(L, 2), MAXIMUM_ANNOTATION_TEXT_LENGTH);
2930 annotation.text[MAXIMUM_ANNOTATION_TEXT_LENGTH-1] = '\0';
2931
2932 MapAnnotationList.push_back(annotation);
2933 dynamic_world->default_annotation_count++;
2934 Lua_Annotation::Push(L, MapAnnotationList.size() - 1);
2935 return 1;
2936 }
2937
2938 const luaL_Reg Lua_Annotations_Methods[] = {
2939 {"new", L_TableFunction<Lua_Annotations_New>},
2940 {0, 0}
2941 };
2942
Lua_Annotations_Length()2943 int16 Lua_Annotations_Length() {
2944 return MapAnnotationList.size();
2945 }
2946
2947 char Lua_Fog_Color_Name[] = "fog_color";
2948 typedef L_Class<Lua_Fog_Color_Name> Lua_Fog_Color;
2949
Lua_Fog_Color_Get_R(lua_State * L)2950 static int Lua_Fog_Color_Get_R(lua_State *L)
2951 {
2952 lua_pushnumber(L, (float) (OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.red) / 65535);
2953 return 1;
2954 }
2955
Lua_Fog_Color_Get_G(lua_State * L)2956 static int Lua_Fog_Color_Get_G(lua_State *L)
2957 {
2958 lua_pushnumber(L, (float) (OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.green) / 65535);
2959 return 1;
2960 }
2961
Lua_Fog_Color_Get_B(lua_State * L)2962 static int Lua_Fog_Color_Get_B(lua_State *L)
2963 {
2964 lua_pushnumber(L, (float) (OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.blue) / 65535);
2965 return 1;
2966 }
2967
Lua_Fog_Color_Set_R(lua_State * L)2968 static int Lua_Fog_Color_Set_R(lua_State *L)
2969 {
2970 if (!lua_isnumber(L, 2))
2971 luaL_error(L, "r: incorrect argument type");
2972
2973 float color = static_cast<float>(lua_tonumber(L, 2));
2974 OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.red = PIN(int(65535 * color + 0.5), 0, 65535);
2975 return 0;
2976 }
2977
Lua_Fog_Color_Set_G(lua_State * L)2978 static int Lua_Fog_Color_Set_G(lua_State *L)
2979 {
2980 if (!lua_isnumber(L, 2))
2981 luaL_error(L, "g: incorrect argument type");
2982
2983 float color = static_cast<float>(lua_tonumber(L, 2));
2984 OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.green = PIN(int(65535 * color + 0.5), 0, 65535);
2985 return 0;
2986 }
2987
Lua_Fog_Color_Set_B(lua_State * L)2988 static int Lua_Fog_Color_Set_B(lua_State *L)
2989 {
2990 if (!lua_isnumber(L, 2))
2991 luaL_error(L, "b: incorrect argument type");
2992
2993 float color = static_cast<float>(lua_tonumber(L, 2));
2994 OGL_GetFogData(Lua_Fog_Color::Index(L, 1))->Color.blue = PIN(int(65535 * color + 0.5), 0, 65535);
2995 return 0;
2996 }
2997
2998 const luaL_Reg Lua_Fog_Color_Get[] = {
2999 {"r", Lua_Fog_Color_Get_R},
3000 {"g", Lua_Fog_Color_Get_G},
3001 {"b", Lua_Fog_Color_Get_B},
3002 {0, 0}
3003 };
3004
3005 const luaL_Reg Lua_Fog_Color_Set[] = {
3006 {"r", Lua_Fog_Color_Set_R},
3007 {"g", Lua_Fog_Color_Set_G},
3008 {"b", Lua_Fog_Color_Set_B},
3009 {0, 0}
3010 };
3011
3012 char Lua_Fog_Name[] = "fog";
3013 typedef L_Class<Lua_Fog_Name> Lua_Fog;
3014
Lua_Fog_Get_Active(lua_State * L)3015 static int Lua_Fog_Get_Active(lua_State *L)
3016 {
3017 lua_pushboolean(L, OGL_GetFogData(Lua_Fog::Index(L, 1))->IsPresent);
3018 return 1;
3019 }
3020
Lua_Fog_Get_Affects_Landscapes(lua_State * L)3021 static int Lua_Fog_Get_Affects_Landscapes(lua_State *L)
3022 {
3023 lua_pushboolean(L, OGL_GetFogData(Lua_Fog::Index(L, 1))->AffectsLandscapes);
3024 return 1;
3025 }
3026
Lua_Fog_Get_Color(lua_State * L)3027 static int Lua_Fog_Get_Color(lua_State *L)
3028 {
3029 Lua_Fog_Color::Push(L, Lua_Fog::Index(L, 1));
3030 return 1;
3031 }
3032
Lua_Fog_Get_Depth(lua_State * L)3033 static int Lua_Fog_Get_Depth(lua_State *L)
3034 {
3035 lua_pushnumber(L, OGL_GetFogData(Lua_Fog::Index(L, 1))->Depth);
3036 return 1;
3037 }
3038
3039 const luaL_Reg Lua_Fog_Get[] = {
3040 {"active", Lua_Fog_Get_Active},
3041 {"affects_landscapes", Lua_Fog_Get_Affects_Landscapes},
3042 {"color", Lua_Fog_Get_Color},
3043 {"depth", Lua_Fog_Get_Depth},
3044 {"present", Lua_Fog_Get_Active},
3045 {0, 0}
3046 };
3047
Lua_Fog_Set_Active(lua_State * L)3048 static int Lua_Fog_Set_Active(lua_State *L)
3049 {
3050 if (!lua_isboolean(L, 2))
3051 return luaL_error(L, "active: incorrect argument type");
3052
3053 OGL_GetFogData(Lua_Fog::Index(L, 1))->IsPresent = static_cast<bool>(lua_toboolean(L, 2));
3054 return 0;
3055 }
3056
Lua_Fog_Set_Affects_Landscapes(lua_State * L)3057 static int Lua_Fog_Set_Affects_Landscapes(lua_State *L)
3058 {
3059 if (!lua_isboolean(L, 2))
3060 return luaL_error(L, "affects_landscapes: incorrect argument type");
3061
3062 OGL_GetFogData(Lua_Fog::Index(L, 1))->AffectsLandscapes = static_cast<bool>(lua_toboolean(L, 2));
3063 return 0;
3064 }
3065
Lua_Fog_Set_Depth(lua_State * L)3066 static int Lua_Fog_Set_Depth(lua_State *L)
3067 {
3068 if (!lua_isnumber(L, 2))
3069 return luaL_error(L, "depth: incorrect argument type");
3070
3071 OGL_GetFogData(Lua_Fog::Index(L, 1))->Depth = static_cast<float>(lua_tonumber(L, 2));
3072 return 0;
3073 }
3074
3075 const luaL_Reg Lua_Fog_Set[] = {
3076 {"active", Lua_Fog_Set_Active},
3077 {"affects_landscapes", Lua_Fog_Set_Affects_Landscapes},
3078 {"depth", Lua_Fog_Set_Depth},
3079 {"present", Lua_Fog_Set_Active},
3080 {0, 0}
3081 };
3082
3083
3084 char Lua_Level_Stash_Name[] = "LevelStash";
3085 typedef L_Class<Lua_Level_Stash_Name> Lua_Level_Stash;
3086
3087 extern std::unordered_map<std::string, std::string> lua_stash;
3088
Lua_Level_Stash_Get(lua_State * L)3089 static int Lua_Level_Stash_Get(lua_State* L)
3090 {
3091 if (!lua_isstring(L, 2))
3092 return luaL_error(L, "stash: incorrect argument type");
3093
3094 auto it = lua_stash.find(lua_tostring(L, 2));
3095 if (it != lua_stash.end())
3096 {
3097 lua_pushlstring(L, it->second.data(), it->second.size());
3098 }
3099 else
3100 {
3101 lua_pushnil(L);
3102 }
3103
3104 return 1;
3105 }
3106
Lua_Level_Stash_Set(lua_State * L)3107 static int Lua_Level_Stash_Set(lua_State* L)
3108 {
3109 if (!lua_isstring(L, 3) && !lua_isnil(L, 3))
3110 return luaL_error(L, "stash: incorrect argument type");
3111
3112 auto key = lua_tostring(L, 2);
3113 if (lua_isstring(L, 3))
3114 {
3115 size_t len;
3116 auto s = lua_tolstring(L, 3, &len);
3117 lua_stash[key] = std::string{s, len};
3118 }
3119 else
3120 {
3121 lua_stash.erase(key);
3122 }
3123
3124 return 0;
3125 }
3126
3127 const luaL_Reg Lua_Level_Stash_Metatable[] = {
3128 {"__index", Lua_Level_Stash_Get},
3129 {"__newindex", Lua_Level_Stash_Set},
3130 {0, 0}
3131 };
3132
3133 char Lua_Level_Name[] = "Level";
3134 typedef L_Class<Lua_Level_Name> Lua_Level;
3135
3136 char Lua_CompletionState_Name[] = "completion_state";
3137 typedef L_Enum<Lua_CompletionState_Name> Lua_CompletionState;
3138
3139 char Lua_CompletionStates_Name[] = "CompletionStates";
3140 typedef L_EnumContainer<Lua_CompletionStates_Name, Lua_CompletionState> Lua_CompletionStates;
3141
Lua_Level_Calculate_Completion_State(lua_State * L)3142 int Lua_Level_Calculate_Completion_State(lua_State *L)
3143 {
3144 Lua_CompletionState::Push(L, calculate_level_completion_state());
3145 return 1;
3146 }
3147
Lua_Level_Get_Completed(lua_State * L)3148 int Lua_Level_Get_Completed(lua_State* L)
3149 {
3150 lua_pushboolean(L, get_game_state() == _change_level);
3151 return 1;
3152 }
3153
3154 template<int16 flag>
Lua_Level_Get_Environment_Flag(lua_State * L)3155 static int Lua_Level_Get_Environment_Flag(lua_State *L)
3156 {
3157 lua_pushboolean(L, static_world->environment_flags & flag);
3158 return 1;
3159 }
3160
3161 template<int16 flag>
Lua_Level_Get_Mission_Flag(lua_State * L)3162 static int Lua_Level_Get_Mission_Flag(lua_State *L)
3163 {
3164 lua_pushboolean(L, static_world->mission_flags & flag);
3165 return 1;
3166 }
3167
Lua_Level_Get_Fog(lua_State * L)3168 static int Lua_Level_Get_Fog(lua_State *L)
3169 {
3170 Lua_Fog::Push(L, OGL_Fog_AboveLiquid);
3171 return 1;
3172 }
3173
Lua_Level_Get_Name(lua_State * L)3174 static int Lua_Level_Get_Name(lua_State *L)
3175 {
3176 lua_pushstring(L, static_world->level_name);
3177 return 1;
3178 }
3179
Lua_Level_Get_Index(lua_State * L)3180 static int Lua_Level_Get_Index(lua_State *L)
3181 {
3182 lua_pushinteger(L, dynamic_world->current_level_number);
3183 return 1;
3184 }
3185
Lua_Level_Get_Map_Checksum(lua_State * L)3186 static int Lua_Level_Get_Map_Checksum(lua_State *L)
3187 {
3188 #if !defined(DISABLE_NETWORKING)
3189 if (game_is_networked)
3190 lua_pushinteger(L, ((game_info *) NetGetGameData())->parent_checksum);
3191 else
3192 #endif
3193 lua_pushinteger(L, get_current_map_checksum());
3194 return 1;
3195 }
3196
Lua_Level_Get_Stash(lua_State * L)3197 static int Lua_Level_Get_Stash(lua_State* L)
3198 {
3199 Lua_Level_Stash::Push(L, 0);
3200 return 1;
3201 }
3202
Lua_Level_Get_Underwater_Fog(lua_State * L)3203 static int Lua_Level_Get_Underwater_Fog(lua_State *L)
3204 {
3205 Lua_Fog::Push(L, OGL_Fog_BelowLiquid);
3206 return 1;
3207 }
3208
3209 const luaL_Reg Lua_Level_Get[] = {
3210 {"calculate_completion_state", L_TableFunction<Lua_Level_Calculate_Completion_State>},
3211 {"completed", Lua_Level_Get_Completed},
3212 {"extermination", Lua_Level_Get_Mission_Flag<_mission_extermination>},
3213 {"exploration", Lua_Level_Get_Mission_Flag<_mission_exploration>},
3214 {"fog", Lua_Level_Get_Fog},
3215 {"low_gravity", Lua_Level_Get_Environment_Flag<_environment_low_gravity>},
3216 {"magnetic", Lua_Level_Get_Environment_Flag<_environment_magnetic>},
3217 {"name", Lua_Level_Get_Name},
3218 {"index", Lua_Level_Get_Index},
3219 {"map_checksum", Lua_Level_Get_Map_Checksum},
3220 {"rebellion", Lua_Level_Get_Environment_Flag<_environment_rebellion>},
3221 {"retrieval", Lua_Level_Get_Mission_Flag<_mission_retrieval>},
3222 {"repair", Lua_Level_Get_Mission_Flag<_mission_repair>},
3223 {"rescue", Lua_Level_Get_Mission_Flag<_mission_rescue>},
3224 {"stash", Lua_Level_Get_Stash},
3225 {"underwater_fog", Lua_Level_Get_Underwater_Fog},
3226 {"vacuum", Lua_Level_Get_Environment_Flag<_environment_vacuum>},
3227 {0, 0}
3228 };
3229
3230 char Lua_TransferMode_Name[] = "transfer_mode";
3231 char Lua_TransferModes_Name[] = "TransferModes";
3232
3233 static void compatibility(lua_State *L);
3234 #define NUMBER_OF_CONTROL_PANEL_DEFINITIONS 54
3235
3236 extern bool collection_loaded(short);
3237
Lua_Map_register(lua_State * L)3238 int Lua_Map_register(lua_State *L)
3239 {
3240 Lua_AmbientSound::Register(L, 0, 0, 0, Lua_AmbientSound_Mnemonics);
3241 Lua_AmbientSound::Valid = Lua_AmbientSound::ValidRange(NUMBER_OF_AMBIENT_SOUND_DEFINITIONS);
3242 Lua_AmbientSounds::Register(L);
3243 Lua_AmbientSounds::Length = Lua_AmbientSounds::ConstantLength(NUMBER_OF_AMBIENT_SOUND_DEFINITIONS);
3244
3245 Lua_Collection::Register(L, Lua_Collection_Get, 0, 0, Lua_Collection_Mnemonics);
3246 Lua_Collection::Valid = collection_loaded;
3247 Lua_Collections::Register(L);
3248 Lua_Collections::Length = Lua_Collections::ConstantLength(MAXIMUM_COLLECTIONS);
3249
3250 Lua_CompletionState::Register(L, 0, 0, 0, Lua_CompletionState_Mnemonics);
3251 Lua_CompletionState::Valid = Lua_CompletionState::ValidRange(static_cast<int16>(_level_failed) + 1);
3252 Lua_CompletionStates::Register(L);
3253 Lua_CompletionStates::Length = Lua_CompletionStates::ConstantLength(static_cast<int16>(_level_failed) + 1);
3254
3255 Lua_ControlPanelClass::Register(L, 0, 0, 0, Lua_ControlPanelClass_Mnemonics);
3256 Lua_ControlPanelClass::Valid = Lua_ControlPanelClass::ValidRange(NUMBER_OF_CONTROL_PANELS);
3257
3258 Lua_ControlPanelClasses::Register(L);
3259 Lua_ControlPanelClasses::Length = Lua_ControlPanelClasses::ConstantLength(NUMBER_OF_CONTROL_PANELS);
3260
3261 Lua_ControlPanelType::Register(L, Lua_ControlPanelType_Get);
3262 Lua_ControlPanelType::Valid = Lua_ControlPanelType::ValidRange(NUMBER_OF_CONTROL_PANEL_DEFINITIONS);
3263
3264 Lua_ControlPanelTypes::Register(L);
3265 Lua_ControlPanelTypes::Length = Lua_ControlPanelTypes::ConstantLength(NUMBER_OF_CONTROL_PANEL_DEFINITIONS);
3266
3267 Lua_DamageType::Register(L, 0, 0, 0, Lua_DamageType_Mnemonics);
3268 Lua_DamageType::Valid = Lua_DamageType::ValidRange(NUMBER_OF_DAMAGE_TYPES);
3269 Lua_DamageTypes::Register(L);
3270 Lua_DamageTypes::Length = Lua_DamageTypes::ConstantLength(NUMBER_OF_DAMAGE_TYPES);
3271
3272 Lua_Endpoint::Register(L, Lua_Endpoint_Get);
3273 Lua_Endpoint::Valid = Lua_Endpoint_Valid;
3274
3275 Lua_Endpoints::Register(L);
3276 // CodeWarrior doesn't let me do this:
3277 // Lua_Endpoints::Length = boost::bind(&std::vector<endpoint_data>::size, &EndpointList);
3278 Lua_Endpoints::Length = Lua_Endpoints_Length;
3279
3280 Lua_Line_Endpoints::Register(L, 0, 0, Lua_Line_Endpoints_Metatable);
3281
3282 Lua_Line::Register(L, Lua_Line_Get, Lua_Line_Set);
3283 Lua_Line::Valid = Lua_Line_Valid;
3284
3285 Lua_Lines::Register(L);
3286 Lua_Lines::Length = Lua_Lines_Length;
3287
3288 Lua_Platform::Register(L, Lua_Platform_Get, Lua_Platform_Set);
3289 Lua_Platform::Valid = Lua_Platform_Valid;
3290
3291 Lua_Platforms::Register(L);
3292 Lua_Platforms::Length = Lua_Platforms_Length;
3293
3294 Lua_PlatformType::Register(L, 0, 0, 0, Lua_PlatformType_Mnemonics);
3295 Lua_PlatformType::Valid = Lua_PlatformType::ValidRange(NUMBER_OF_PLATFORM_TYPES);
3296
3297 Lua_PlatformTypes::Register(L);
3298 Lua_PlatformTypes::Length = Lua_PlatformTypes::ConstantLength(NUMBER_OF_PLATFORM_TYPES);
3299
3300 Lua_Polygon_Floor::Register(L, Lua_Polygon_Floor_Get, Lua_Polygon_Floor_Set);
3301 Lua_Polygon_Floor::Valid = Lua_Polygon_Valid;
3302
3303 Lua_Polygon_Ceiling::Register(L, Lua_Polygon_Ceiling_Get, Lua_Polygon_Ceiling_Set);
3304 Lua_Polygon_Ceiling::Valid = Lua_Polygon_Valid;
3305
3306 Lua_PolygonType::Register(L, 0, 0, 0, Lua_PolygonType_Mnemonics);
3307 Lua_PolygonType::Valid = Lua_PolygonType::ValidRange(static_cast<int16>(_polygon_is_superglue) + 1);
3308
3309 Lua_PolygonTypes::Register(L);
3310 Lua_PolygonTypes::Length = Lua_PolygonTypes::ConstantLength(static_cast<int16>(_polygon_is_superglue) + 1);
3311
3312 Lua_Adjacent_Polygons::Register(L, 0, 0, Lua_Adjacent_Polygons_Metatable);
3313 Lua_Polygon_Endpoints::Register(L, 0, 0, Lua_Polygon_Endpoints_Metatable);
3314 Lua_Polygon_Lines::Register(L, 0, 0, Lua_Polygon_Lines_Metatable);
3315 Lua_Polygon_Sides::Register(L, 0, 0, Lua_Polygon_Sides_Metatable);
3316
3317 Lua_Polygon::Register(L, Lua_Polygon_Get, Lua_Polygon_Set);
3318 Lua_Polygon::Valid = Lua_Polygon_Valid;
3319
3320 Lua_Polygons::Register(L);
3321 Lua_Polygons::Length = Lua_Polygons_Length;
3322
3323 Lua_Side_ControlPanel::Register(L, Lua_Side_ControlPanel_Get, Lua_Side_ControlPanel_Set);
3324
3325 Lua_Primary_Side::Register(L, Lua_Primary_Side_Get, Lua_Primary_Side_Set);
3326 Lua_Secondary_Side::Register(L, Lua_Secondary_Side_Get, Lua_Secondary_Side_Set);
3327 Lua_Transparent_Side::Register(L, Lua_Transparent_Side_Get, Lua_Transparent_Side_Set);
3328
3329 Lua_Side::Register(L, Lua_Side_Get, Lua_Side_Set);
3330 Lua_Side::Valid = Lua_Side_Valid;
3331
3332 Lua_Sides::Register(L, Lua_Sides_Methods);
3333 Lua_Sides::Length = Lua_Sides_Length;
3334
3335 Lua_SideType::Register(L, 0, 0, 0, Lua_SideType_Mnemonics);
3336 Lua_SideType::Valid = Lua_SideType::ValidRange(static_cast<int16>(_split_side) + 1);
3337 Lua_SideTypes::Register(L);
3338 Lua_SideTypes::Length = Lua_SideTypes::ConstantLength(static_cast<int16>(_split_side) + 1);
3339
3340 Lua_Light_State::Register(L, Lua_Light_State_Get, Lua_Light_State_Set);
3341 Lua_Light_State::Valid = Lua_Light_State::ValidRange(static_cast<int16>(_light_secondary_inactive) + 1);
3342
3343 Lua_Light_States::Register(L, 0, 0, Lua_Light_States_Metatable);
3344 Lua_Light_States::Valid = Lua_Light_Valid;
3345
3346 Lua_LightPreset::Register(L, 0, 0, 0, Lua_LightPreset_Mnemonics);
3347 Lua_LightPreset::Valid = Lua_LightPreset::ValidRange(NUMBER_OF_LIGHT_TYPES);
3348
3349 Lua_LightPresets::Register(L);
3350 Lua_LightPresets::Length = Lua_LightPresets::ConstantLength(NUMBER_OF_LIGHT_TYPES);
3351
3352 Lua_LightFunction::Register(L, 0, 0, 0, Lua_LightFunction_Mnenonics);
3353 Lua_LightFunction::Valid = Lua_LightFunction::ValidRange(NUMBER_OF_LIGHTING_FUNCTIONS);
3354
3355 Lua_LightFunctions::Register(L);
3356 Lua_LightFunctions::Length = Lua_LightFunctions::ConstantLength(NUMBER_OF_LIGHTING_FUNCTIONS);
3357
3358 Lua_LightState::Register(L, 0, 0, 0, Lua_LightState_Mnemonics);
3359 Lua_LightState::Valid = Lua_LightState::ValidRange(static_cast<int16>(_light_secondary_inactive) + 1);
3360
3361 Lua_LightStates::Register(L);
3362 Lua_LightStates::Length = Lua_LightStates::ConstantLength(static_cast<int16>(_light_secondary_inactive) + 1);
3363
3364 Lua_Light::Register(L, Lua_Light_Get, Lua_Light_Set);
3365 Lua_Light::Valid = Lua_Light_Valid;
3366
3367 Lua_Lights::Register(L, Lua_Lights_Methods);
3368 Lua_Lights::Length = Lua_Lights_Length;
3369
3370 Lua_Tag::Register(L, Lua_Tag_Get, Lua_Tag_Set);
3371 Lua_Tag::Valid = Lua_Tag_Valid;
3372
3373 Lua_Tags::Register(L);
3374 Lua_Tags::Length = Lua_Tags::ConstantLength(INT16_MAX);
3375
3376 Lua_Terminal::Register(L);
3377 Lua_Terminal::Valid = Lua_Terminal_Valid;
3378
3379 Lua_Terminals::Register(L);
3380 Lua_Terminals::Length = Lua_Terminals_Length;
3381
3382 Lua_TransferMode::Register(L, 0, 0, 0, Lua_TransferMode_Mnemonics);
3383 Lua_TransferMode::Valid = Lua_TransferMode::ValidRange(NUMBER_OF_TRANSFER_MODES);
3384
3385 Lua_TransferModes::Register(L);
3386 Lua_TransferModes::Length = Lua_TransferModes::ConstantLength(NUMBER_OF_TRANSFER_MODES);
3387
3388 Lua_MediaType::Register(L, 0, 0, 0, Lua_MediaType_Mnemonics);
3389 Lua_MediaType::Valid = Lua_MediaType::ValidRange(NUMBER_OF_MEDIA_TYPES);
3390
3391 Lua_MediaTypes::Register(L);
3392 Lua_MediaTypes::Length = Lua_MediaTypes::ConstantLength(NUMBER_OF_MEDIA_TYPES);
3393
3394 Lua_Media::Register(L, Lua_Media_Get, Lua_Media_Set);
3395 Lua_Media::Valid = Lua_Media_Valid;
3396
3397 Lua_Medias::Register(L);
3398 Lua_Medias::Length = Lua_Medias_Length;
3399
3400 Lua_Level_Stash::Register(L, 0, 0, Lua_Level_Stash_Metatable);
3401
3402 Lua_Level::Register(L, Lua_Level_Get);
3403
3404 Lua_Annotation::Register(L, Lua_Annotation_Get, Lua_Annotation_Set);
3405 Lua_Annotation::Valid = Lua_Annotation_Valid;
3406
3407 Lua_Annotations::Register(L, Lua_Annotations_Methods);
3408 Lua_Annotations::Length = Lua_Annotations_Length;
3409
3410 Lua_Fog::Register(L, Lua_Fog_Get, Lua_Fog_Set);
3411
3412 Lua_Fog_Color::Register(L, Lua_Fog_Color_Get, Lua_Fog_Color_Set);
3413
3414 // register one Level userdatum globally
3415 Lua_Level::Push(L, 0);
3416 lua_setglobal(L, Lua_Level_Name);
3417
3418 compatibility(L);
3419 return 0;
3420 }
3421
3422 static const char* compatibility_script = ""
3423 "function annotations() local i = 0 local n = # Annotations return function() if i < n then a = Annotations[i] i = i + 1 if a.polygon then p = a.polygon.index else p = -1 end return a.text, p, a.x, a.y else return nil end end end\n"
3424 "function get_all_fog_attributes() local attributes = { OGL_Fog_AboveLiquid = { Depth = Level.fog.depth, Color = { red = Level.fog.color.r, blue = Level.fog.color.b, green = Level.fog.color.g }, IsPresent = Level.fog.present, AffectsLandscapes = Level.fog.affects_landscapes }, OGL_Fog_BelowLiquid = { Depth = Level.underwater_fog.depth, Color = { red = Level.underwater_fog.color.r, green = Level.underwater_fog.color.g, blue = Level.underwater_fog.color.b, }, IsPresent = Level.underwater_fog.present, AffectsLandscapes = Level.underwater_fog.affects_landscapes } } return attributes end\n"
3425 "function get_fog_affects_landscapes() return Level.fog.affects_landscapes end\n"
3426 "function get_fog_color() return Level.fog.color.r, Level.fog.color.g, Level.fog.color.b end\n"
3427 "function get_fog_depth() return Level.fog.depth end\n"
3428 "function get_fog_present() return Level.fog.active end\n"
3429 "function get_level_name() return Level.name end\n"
3430 "function get_light_state(light) return Lights[light].active end\n"
3431 "function get_map_environment() return Level.vacuum, Level.magnetic, Level.rebellion, Level.low_gravity end\n"
3432 "function get_platform_ceiling_height(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.ceiling_height end end\n"
3433 "function get_platform_floor_height(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.floor_height end end\n"
3434 "function get_platform_index(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.index else return -1 end end\n"
3435 "function get_polygon_media(polygon) if Polygons[polygon].media then return Polygons[polygon].media.index else return -1 end end\n"
3436 "function get_platform_monster_control(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.monster_controllable end end\n"
3437 "function get_platform_movement(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.extending end end\n"
3438 "function get_platform_player_control(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.player_controllable end end\n"
3439 "function get_platform_speed(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.speed * 1024 end end\n"
3440 "function get_platform_state(polygon) if Polygons[polygon].platform then return Polygons[polygon].platform.active end end\n"
3441 "function get_polygon_ceiling_height(polygon) return Polygons[polygon].ceiling.height end\n"
3442 "function get_polygon_center(polygon) return Polygons[polygon].x * 1024, Polygons[polygon].y * 1024 end\n"
3443 "function get_polygon_floor_height(polygon) return Polygons[polygon].floor.height end\n"
3444 "function get_polygon_target(polygon) return Polygons[polygon].permutation end\n"
3445 "function get_polygon_type(polygon) return Polygons[polygon].type.index end\n"
3446 "function get_tag_state(tag) return Tags[tag].active end\n"
3447 "function get_terminal_text_number(poly, line) if Lines[line].ccw_polygon == Polygons[poly] then s = Lines[line].ccw_side elseif Lines[line].cw_polygon == Polygons[poly] then s = Lines[line].cw_side else return line end if s.control_panel and s.control_panel.type.class == 8 then return s.control_panel.permutation else return line end end\n"
3448 "function get_underwater_fog_affects_landscapes() return Level.underwater_fog.affects_landscapes end\n"
3449 "function get_underwater_fog_color() return Level.underwater_fog.color.r, Level.underwater_fog.color.g, Level.underwater_fog.color.b end\n"
3450 "function get_underwater_fog_depth() return Level.underwater_fog.depth end\n"
3451 "function get_underwater_fog_present() return Level.underwater_fog.active end\n"
3452
3453 "function number_of_polygons() return # Polygons end\n"
3454 "function select_monster(type, poly) for m in Polygons[poly]:monsters() do if m.type == type and m.visible and (m.action < 6 or m.action > 9) then return m.index end end return nil end\n"
3455 "function set_all_fog_attributes(t) Level.fog.depth = t.OGL_Fog_AboveLiquid.Depth Level.fog.present = t.OGL_Fog_AboveLiquid.IsPresent Level.fog.affects_landscapes = t.OGL_Fog_AboveLiquid.AffectsLandscapes Level.fog.color.r = t.OGL_Fog_AboveLiquid.Color.red Level.fog.color.g = t.OGL_Fog_AboveLiquid.Color.green Level.fog.color.b = t.OGL_Fog_AboveLiquid.Color.blue Level.underwater_fog.depth = t.OGL_Fog_BelowLiquid.Depth Level.underwater_fog.present = t.OGL_Fog_BelowLiquid.IsPresent Level.underwater_fog.affects_landscapes = t.OGL_Fog_BelowLiquid.AffectsLandscapes Level.underwater_fog.color.r = t.OGL_Fog_BelowLiquid.Color.red Level.underwater_fog.color.g = t.OGL_Fog_BelowLiquid.Color.green Level.underwater_fog.color.b = t.OGL_Fog_BelowLiquid.Color.blue end\n"
3456 "function set_fog_affects_landscapes(affects_landscapes) Level.fog.affects_landscapes = affects_landscapes end\n"
3457 "function set_fog_color(r, g, b) Level.fog.color.r = r Level.fog.color.g = g Level.fog.color.b = b end\n"
3458 "function set_fog_depth(depth) Level.fog.depth = depth end\n"
3459 "function set_fog_present(present) Level.fog.active = present end\n"
3460 "function set_light_state(light, state) Lights[light].active = state end\n"
3461 "function set_platform_ceiling_height(polygon, height) if Polygons[polygon].platform then Polygons[polygon].platform.ceiling_height = height end end\n"
3462 "function set_platform_floor_height(polygon, height) if Polygons[polygon].platform then Polygons[polygon].platform.floor_height = height end end\n"
3463 "function set_platform_monster_control(polygon, control) if Polygons[polygon].platform then Polygons[polygon].platform.monster_controllable = control end end\n"
3464 "function set_platform_movement(polygon, movement) if Polygons[polygon].platform then Polygons[polygon].platform.extending = movement end end\n"
3465 "function set_platform_player_control(polygon, control) if Polygons[polygon].platform then Polygons[polygon].platform.player_controllable = control end end\n"
3466 "function set_platform_speed(polygon, speed) if Polygons[polygon].platform then Polygons[polygon].platform.speed = speed / 1024 end end\n"
3467 "function set_platform_state(polygon, state) if Polygons[polygon].platform then Polygons[polygon].platform.active = state end end\n"
3468 "function set_polygon_ceiling_height(polygon, height) Polygons[polygon].ceiling.height = height end\n"
3469 "function set_polygon_floor_height(polygon, height) Polygons[polygon].floor.height = height end\n"
3470 "function set_polygon_media(polygon, media) if media == -1 then Polygons[polygon].media = nil else Polygons[polygon].media = media end end\n"
3471 "function set_polygon_target(polygon, target) Polygons[polygon].permutation = target end\n"
3472 "function set_polygon_type(polygon, type) Polygons[polygon].type = type end\n"
3473 "function set_tag_state(tag, state) Tags[tag].active = state end\n"
3474 "function set_terminal_text_number(poly, line, id) if Lines[line].ccw_polygon == Polygons[poly] then s = Lines[line].ccw_side elseif Lines[line].cw_polygon == Polygons[poly] then s = Lines[line].cw_side else return end if s.control_panel and s.control_panel.type.class == 8 then s.control_panel.permutation = id end end\n"
3475 "function set_underwater_fog_affects_landscapes(affects_landscapes) Level.underwater_fog.affects_landscapes = affects_landscapes end\n"
3476 "function set_underwater_fog_color(r, g, b) Level.underwater_fog.color.r = r Level.underwater_fog.color.g = g Level.underwater_fog.color.b = b end\n"
3477 "function set_underwater_fog_depth(depth) Level.underwater_fog.depth = depth end\n"
3478 "function set_underwater_fog_present(present) Level.underwater_fog.active = present end\n"
3479 ;
3480
compatibility(lua_State * L)3481 static void compatibility(lua_State *L)
3482 {
3483 luaL_loadbuffer(L, compatibility_script, strlen(compatibility_script), "map_compatibility");
3484 lua_pcall(L, 0, 0, 0);
3485 }
3486
3487 #endif
3488
3489