1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 extern "C" {
7 #include <lua.h>
8 #include <lualib.h>
9 #include <lauxlib.h>
10 }
11
12 #include "script.h"
13 #include "../core/system.h"
14 #include "../core/gl_text.h"
15 #include "../core/console.h"
16 #include "../core/vmath.h"
17 #include "../render/camera.h"
18 #include "../render/render.h"
19 #include "../state_control/state_control.h"
20 #include "../vt/tr_versions.h"
21 #include "../skeletal_model.h"
22 #include "../trigger.h"
23 #include "../room.h"
24 #include "../entity.h"
25 #include "../engine.h"
26 #include "../inventory.h"
27 #include "../controls.h"
28 #include "../game.h"
29 #include "../gameflow.h"
30 #include "../character_controller.h"
31
32
33 #define LUA_EXPOSE(lua, x) do { lua_pushinteger(lua, x); lua_setglobal(lua, #x); } while(false)
34
35
36 /*
37 * MISK
38 */
SC_ParseToken(char * data,char * token,size_t token_size)39 char *SC_ParseToken(char *data, char *token, size_t token_size)
40 {
41 int c;
42 int len = 0;
43
44 if(!data || token_size < 2)
45 {
46 return NULL;
47 }
48 token[0] = 0;
49
50 // skip whitespace
51 skipwhite:
52 while((c = *data) <= ' ')
53 {
54 if(c == 0)
55 {
56 return NULL;
57 }
58 data++;
59 }
60
61 // skip // comments
62 if(data[0] == '/' && data[1] == '/')
63 {
64 while(*data && *data != '\n')
65 {
66 data++;
67 }
68 goto skipwhite;
69 }
70
71 // handle quoted strings specially
72 if(c == '\"')
73 {
74 data++;
75 while(len + 1 < token_size)
76 {
77 c = *data++;
78 if (c == '\"' || !c)
79 {
80 token[len] = 0;
81 return data;
82 }
83 token[len] = c;
84 len++;
85 }
86 }
87
88 // parse single characters
89 if(c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
90 {
91 token[len] = c;
92 len++;
93 token[len] = 0;
94 return data+1;
95 }
96
97 // parse a regular word
98 do
99 {
100 token[len] = c;
101 data++;
102 len++;
103 c = *data;
104 if(c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == '\"' || c == ':')
105 {
106 break;
107 }
108 }
109 while((c > ' ') && (len + 1 < token_size));
110
111 token[len] = 0;
112 return data;
113 }
114
SC_ParseFloat(char ** ch)115 float SC_ParseFloat(char **ch)
116 {
117 char token[64];
118 (*ch) = SC_ParseToken(*ch, token, sizeof(token));
119 if(token[0])
120 {
121 return atof(token);
122 }
123 return 0.0;
124 }
125
SC_ParseInt(char ** ch)126 int SC_ParseInt(char **ch)
127 {
128 char token[64];
129 (*ch) = SC_ParseToken(*ch, token, sizeof(token));
130 if(token[0])
131 {
132 return atoi(token);
133 }
134 return 0;
135 }
136
137
Script_GetString(lua_State * lua,int string_index,size_t string_size,char * buffer)138 bool Script_GetString(lua_State *lua, int string_index, size_t string_size, char *buffer)
139 {
140 bool result = false;
141
142 if(lua)
143 {
144 int top = lua_gettop(lua);
145
146 lua_getglobal(lua, "getString");
147
148 if(lua_isfunction(lua, -1))
149 {
150 size_t *string_length = NULL;
151
152 lua_pushinteger(lua, string_index);
153 if (lua_CallAndLog(lua, 1, 1, 0))
154 {
155 const char* lua_str = lua_tolstring(lua, -1, string_length);
156 strncpy(buffer, lua_str, string_size);
157 result = true;
158 }
159 }
160 lua_settop(lua, top);
161 }
162
163 return result;
164 }
165
166
167 /*
168 * Gameplay functions
169 */
170
Script_UseItem(lua_State * lua,int item_id,int activator_id)171 int Script_UseItem(lua_State *lua, int item_id, int activator_id)
172 {
173 int top = lua_gettop(lua);
174 int ret = -1;
175
176 lua_getglobal(lua, "items_funcs");
177 if(!lua_istable(lua, -1))
178 {
179 lua_settop(lua, top);
180 return -1;
181 }
182
183 lua_rawgeti(lua, -1, item_id);
184 if(!lua_istable(lua, -1))
185 {
186 lua_settop(lua, top);
187 return -1;
188 }
189
190 lua_pushstring(lua, "onUse");
191 lua_rawget(lua, -2);
192 if(!lua_isfunction(lua, -1))
193 {
194 lua_settop(lua, top);
195 return -1;
196 }
197
198 lua_pushinteger(lua, activator_id);
199 if(lua_pcall(lua, 1, 1, 0) == LUA_OK)
200 {
201 ret = lua_tointeger(lua, -1);
202 }
203 lua_settop(lua, top);
204
205 return ret;
206 }
207
208
Script_DoTasks(lua_State * lua,float time)209 int Script_DoTasks(lua_State *lua, float time)
210 {
211 lua_pushnumber(lua, time);
212 lua_setglobal(lua, "frame_time");
213
214 Script_CallVoidFunc(lua, "doTasks");
215 Script_CallVoidFunc(lua, "clearKeys");
216
217 return 0;
218 }
219
Script_AddKey(lua_State * lua,int keycode,int state)220 void Script_AddKey(lua_State *lua, int keycode, int state)
221 {
222 int top = lua_gettop(lua);
223
224 lua_getglobal(lua, "addKey");
225
226 if(!lua_isfunction(lua, -1))
227 {
228 lua_settop(lua, top);
229 return;
230 }
231
232 lua_pushinteger(lua, keycode);
233 lua_pushinteger(lua, state);
234 lua_CallAndLog(lua, 2, 0, 0);
235
236 lua_settop(lua, top);
237 }
238
Script_CallVoidFunc(lua_State * lua,const char * func_name,bool destroy_after_call)239 bool Script_CallVoidFunc(lua_State *lua, const char* func_name, bool destroy_after_call)
240 {
241 int top = lua_gettop(lua);
242
243 lua_getglobal(lua, func_name);
244
245 if(!lua_isfunction(lua, -1))
246 {
247 lua_settop(lua, top);
248 return false;
249 }
250
251 lua_CallAndLog(lua, 0, 0, 0);
252
253 if(destroy_after_call)
254 {
255 lua_pushnil(engine_lua);
256 lua_setglobal(lua, func_name);
257 }
258
259 lua_settop(lua, top);
260 return true;
261 }
262
263
264 /*
265 * Game structures parse
266 */
Script_ParseControls(lua_State * lua,struct control_settings_s * cs)267 int Script_ParseControls(lua_State *lua, struct control_settings_s *cs)
268 {
269 if(lua)
270 {
271 int top = lua_gettop(lua);
272
273 lua_getglobal(lua, "controls");
274
275 lua_getfield(lua, -1, "mouse_sensitivity_x");
276 cs->mouse_sensitivity_x = lua_tonumber(lua, -1);
277 lua_pop(lua, 1);
278
279 lua_getfield(lua, -1, "mouse_sensitivity_y");
280 cs->mouse_sensitivity_y = lua_tonumber(lua, -1);
281 lua_pop(lua, 1);
282
283 lua_getfield(lua, -1, "use_joy");
284 cs->use_joy = lua_tonumber(lua, -1);
285 lua_pop(lua, 1);
286
287 lua_getfield(lua, -1, "joy_number");
288 cs->joy_number = lua_tonumber(lua, -1);
289 lua_pop(lua, 1);
290
291 lua_getfield(lua, -1, "joy_rumble");
292 cs->joy_rumble = lua_tonumber(lua, -1);
293 lua_pop(lua, 1);
294
295 lua_getfield(lua, -1, "joy_look_axis_x");
296 cs->joy_axis_map[AXIS_LOOK_X] = lua_tonumber(lua, -1);
297 lua_pop(lua, 1);
298
299 lua_getfield(lua, -1, "joy_look_axis_y");
300 cs->joy_axis_map[AXIS_LOOK_Y] = lua_tonumber(lua, -1);
301 lua_pop(lua, 1);
302
303 lua_getfield(lua, -1, "joy_look_invert_x");
304 cs->joy_look_invert_x = lua_tonumber(lua, -1);
305 lua_pop(lua, 1);
306
307 lua_getfield(lua, -1, "joy_look_invert_y");
308 cs->joy_look_invert_y = lua_tonumber(lua, -1);
309 lua_pop(lua, 1);
310
311 lua_getfield(lua, -1, "joy_look_sensitivity");
312 cs->joy_look_sensitivity = lua_tonumber(lua, -1);
313 lua_pop(lua, 1);
314
315 lua_getfield(lua, -1, "joy_look_deadzone");
316 cs->joy_look_deadzone = lua_tonumber(lua, -1);
317 lua_pop(lua, 1);
318
319 lua_getfield(lua, -1, "joy_move_axis_x");
320 cs->joy_axis_map[AXIS_MOVE_X] = lua_tonumber(lua, -1);
321 lua_pop(lua, 1);
322
323 lua_getfield(lua, -1, "joy_move_axis_y");
324 cs->joy_axis_map[AXIS_MOVE_Y] = lua_tonumber(lua, -1);
325 lua_pop(lua, 1);
326
327 lua_getfield(lua, -1, "joy_move_invert_x");
328 cs->joy_move_invert_x = lua_tonumber(lua, -1);
329 lua_pop(lua, 1);
330
331 lua_getfield(lua, -1, "joy_move_invert_y");
332 cs->joy_move_invert_y = lua_tonumber(lua, -1);
333 lua_pop(lua, 1);
334
335 lua_getfield(lua, -1, "joy_move_sensitivity");
336 cs->joy_move_sensitivity = lua_tonumber(lua, -1);
337 lua_pop(lua, 1);
338
339 lua_getfield(lua, -1, "joy_move_deadzone");
340 cs->joy_move_deadzone = lua_tonumber(lua, -1);
341 lua_pop(lua, 1);
342
343
344 lua_settop(lua, top);
345 return 1;
346 }
347
348 return -1;
349 }
350
Script_ParseScreen(lua_State * lua,struct screen_info_s * sc)351 int Script_ParseScreen(lua_State *lua, struct screen_info_s *sc)
352 {
353 if(lua)
354 {
355 int top = lua_gettop(lua);
356
357 lua_getglobal(lua, "screen");
358 lua_getfield(lua, -1, "x");
359 sc->x = (int16_t)lua_tonumber(lua, -1);
360 lua_pop(lua, 1);
361
362 lua_getfield(lua, -1, "y");
363 sc->y = (int16_t)lua_tonumber(lua, -1);
364 lua_pop(lua, 1);
365
366 lua_getfield(lua, -1, "width");
367 sc->w = (int16_t)lua_tonumber(lua, -1);
368 lua_pop(lua, 1);
369
370 lua_getfield(lua, -1, "height");
371 sc->h = (int16_t)lua_tonumber(lua, -1);
372 lua_pop(lua, 1);
373
374 lua_getfield(lua, -1, "fullscreen");
375 sc->fullscreen = (int8_t)lua_tonumber(lua, -1);
376 lua_pop(lua, 1);
377
378 lua_getfield(lua, -1, "debug_view_state");
379 sc->debug_view_state = (int8_t)lua_tonumber(lua, -1);
380 lua_pop(lua, 1);
381
382 lua_getfield(lua, -1, "crosshair");
383 sc->crosshair = (int8_t)lua_tonumber(lua, -1);
384 lua_pop(lua, 1);
385
386 lua_getfield(lua, -1, "fov");
387 sc->fov = (float)lua_tonumber(lua, -1);
388 lua_pop(lua, 1);
389
390 lua_settop(lua, top);
391 return 1;
392 }
393
394 return -1;
395 }
396
Script_ParseRender(lua_State * lua,struct render_settings_s * rs)397 int Script_ParseRender(lua_State *lua, struct render_settings_s *rs)
398 {
399 if(lua)
400 {
401 int top = lua_gettop(lua);
402
403 lua_getglobal(lua, "render");
404 lua_getfield(lua, -1, "mipmap_mode");
405 rs->mipmap_mode = lua_tonumber(lua, -1);
406 lua_pop(lua, 1);
407
408 lua_getfield(lua, -1, "mipmaps");
409 rs->mipmaps = lua_tonumber(lua, -1);
410 lua_pop(lua, 1);
411
412 lua_getfield(lua, -1, "lod_bias");
413 rs->lod_bias = lua_tonumber(lua, -1);
414 lua_pop(lua, 1);
415
416 lua_getfield(lua, -1, "anisotropy");
417 rs->anisotropy = lua_tonumber(lua, -1);
418 lua_pop(lua, 1);
419
420 lua_getfield(lua, -1, "antialias");
421 rs->antialias = lua_tonumber(lua, -1);
422 lua_pop(lua, 1);
423
424 lua_getfield(lua, -1, "antialias_samples");
425 rs->antialias_samples = lua_tonumber(lua, -1);
426 lua_pop(lua, 1);
427
428 lua_getfield(lua, -1, "texture_border");
429 rs->texture_border = lua_tonumber(lua, -1);
430 lua_pop(lua, 1);
431
432 lua_getfield(lua, -1, "z_depth");
433 rs->z_depth = lua_tonumber(lua, -1);
434 lua_pop(lua, 1);
435
436 lua_getfield(lua, -1, "fog_enabled");
437 rs->fog_enabled = lua_tonumber(lua, -1);
438 lua_pop(lua, 1);
439
440 lua_getfield(lua, -1, "fog_start_depth");
441 rs->fog_start_depth = lua_tonumber(lua, -1);
442 lua_pop(lua, 1);
443
444 lua_getfield(lua, -1, "fog_end_depth");
445 rs->fog_end_depth = lua_tonumber(lua, -1);
446 lua_pop(lua, 1);
447
448
449 lua_getfield(lua, -1, "fog_color");
450 if(lua_istable(lua, -1))
451 {
452 lua_getfield(lua, -1, "r");
453 rs->fog_color[0] = (GLfloat)lua_tonumber(lua, -1) / 255.0;
454 lua_pop(lua, 1);
455
456 lua_getfield(lua, -1, "g");
457 rs->fog_color[1] = (GLfloat)lua_tonumber(lua, -1) / 255.0;
458 lua_pop(lua, 1);
459
460 lua_getfield(lua, -1, "b");
461 rs->fog_color[2] = (GLfloat)lua_tonumber(lua, -1) / 255.0;
462 lua_pop(lua, 1);
463
464 rs->fog_color[3] = 1.0; // Not sure if we need this at all...
465 }
466
467 if(rs->z_depth != 8 && rs->z_depth != 16 && rs->z_depth != 24)
468 {
469 rs->z_depth = 24;
470 }
471
472 lua_settop(lua, top);
473 return 1;
474 }
475
476 return -1;
477 }
478
479
Script_ParseConsole(lua_State * lua)480 int Script_ParseConsole(lua_State *lua)
481 {
482 if(lua)
483 {
484 int top = lua_gettop(lua);
485
486 lua_getglobal(lua, "console");
487 lua_getfield(lua, -1, "background_color");
488 if(lua_istable(lua, -1))
489 {
490 float color[4];
491 lua_getfield(lua, -1, "r");
492 color[0] = lua_tonumber(lua, -1) / 255.0;
493 lua_pop(lua, 1);
494
495 lua_getfield(lua, -1, "g");
496 color[1] = lua_tonumber(lua, -1) / 255.0;
497 lua_pop(lua, 1);
498
499 lua_getfield(lua, -1, "b");
500 color[2] = lua_tonumber(lua, -1) / 255.0;
501 lua_pop(lua, 1);
502
503 lua_getfield(lua, -1, "a");
504 color[3] = lua_tonumber(lua, -1) / 255.0;
505 lua_pop(lua, 1);
506 Con_SetBackgroundColor(color);
507 }
508 lua_pop(lua, 1);
509
510 lua_getfield(lua, -1, "spacing");
511 Con_SetLineInterval(lua_tonumber(lua, -1));
512 lua_pop(lua, 1);
513
514 lua_getfield(lua, -1, "height");
515 Con_SetHeight(lua_tonumber(lua, -1));
516 lua_pop(lua, 1);
517
518 lua_getfield(lua, -1, "lines_count");
519 Con_SetLinesHistorySize(lua_tonumber(lua, -1));
520 lua_pop(lua, 1);
521
522 lua_getfield(lua, -1, "commands_count");
523 Con_SetCommandsHistorySize(lua_tonumber(lua, -1));
524 lua_pop(lua, 1);
525
526 lua_getfield(lua, -1, "show");
527 Con_SetShown(lua_tonumber(lua, -1));
528 lua_pop(lua, 1);
529
530 lua_getfield(lua, -1, "show_cursor_period");
531 Con_SetShowCursorPeriod(lua_tonumber(lua, -1));
532 lua_pop(lua, 1);
533
534 lua_settop(lua, top);
535 return 1;
536 }
537
538 return -1;
539 }
540
541
lua_CallWithError(lua_State * lua,int nargs,int nresults,int errfunc,const char * cfile,int cline)542 bool lua_CallWithError(lua_State *lua, int nargs, int nresults, int errfunc, const char *cfile, int cline)
543 {
544 if(lua_pcall(lua, nargs, nresults, errfunc) != LUA_OK)
545 {
546 if (lua_gettop(lua) > 0 && lua_isstring(lua, -1))
547 {
548 const char *luaErrorDescription = lua_tostring(lua, -1);
549 Con_Warning("Lua error: %s (called from %s:%d)", luaErrorDescription, cfile, cline);
550 lua_pop(lua, 1);
551 }
552 else
553 {
554 Con_Warning("Lua error without message (called from %s:%d)", cfile, cline);
555 }
556 return false;
557 }
558 return true;
559 }
560
561
562 /*
563 * debug functions
564 */
lua_print(lua_State * lua)565 int lua_print(lua_State * lua)
566 {
567 int top = lua_gettop(lua);
568
569 if(top == 0)
570 {
571 Con_AddLine("nil", FONTSTYLE_CONSOLE_EVENT);
572 }
573
574 for(int i = 1; i <= top; i++)
575 {
576 switch(lua_type(lua, i))
577 {
578 case LUA_TNUMBER:
579 case LUA_TSTRING:
580 Con_AddLine(lua_tostring(lua, i), FONTSTYLE_CONSOLE_EVENT);
581 break;
582
583 case LUA_TBOOLEAN:
584 Con_AddLine(lua_toboolean(lua, i) ? ("true") : ("false"), FONTSTYLE_CONSOLE_EVENT);
585 break;
586
587 case LUA_TFUNCTION:
588 Con_AddLine("function", FONTSTYLE_CONSOLE_EVENT);
589 break;
590
591 case LUA_TTABLE:
592 Con_AddLine("table", FONTSTYLE_CONSOLE_EVENT);
593 break;
594
595 case LUA_TTHREAD:
596 Con_AddLine("thread", FONTSTYLE_CONSOLE_EVENT);
597 break;
598
599 case LUA_TLIGHTUSERDATA:
600 Con_AddLine("light user data", FONTSTYLE_CONSOLE_EVENT);
601 break;
602
603 case LUA_TNIL:
604 Con_AddLine("nil", FONTSTYLE_CONSOLE_EVENT);
605 break;
606
607 case LUA_TNONE:
608 Con_AddLine("none", FONTSTYLE_CONSOLE_EVENT);
609 break;
610
611 default:
612 Con_AddLine("none or nil", FONTSTYLE_CONSOLE_EVENT);
613 break;
614 };
615 }
616
617 return 0;
618 }
619
620
lua_BindKey(lua_State * lua)621 int lua_BindKey(lua_State *lua)
622 {
623 int top = lua_gettop(lua);
624 int act = lua_tointeger(lua, 1);
625
626 if(top < 1 || act < 0 || act >= ACT_LASTINDEX)
627 {
628 Con_Warning("wrong action number");
629 }
630
631 else if(top == 2)
632 {
633 control_mapper.action_map[act].primary = lua_tointeger(lua, 2);
634 }
635 else if(top == 3)
636 {
637 control_mapper.action_map[act].primary = lua_tointeger(lua, 2);
638 control_mapper.action_map[act].secondary = lua_tointeger(lua, 3);
639 }
640 else
641 {
642 Con_Warning("bindKey: expecting arguments (action_id, key_id1, (key_id2))");
643 }
644
645 return 0;
646 }
647
648
lua_GetActionState(lua_State * lua)649 int lua_GetActionState(lua_State *lua)
650 {
651 if(lua_gettop(lua) >= 1)
652 {
653 int act = lua_tointeger(lua, 1);
654
655 if((act >= 0) && (act < ACT_LASTINDEX))
656 {
657 lua_pushinteger(lua, (int)(control_mapper.action_map[act].state));
658 return 1;
659 }
660
661 Con_Warning("wrong action number");
662 return 0;
663 }
664
665 Con_Warning("getActionState: expecting arguments (action_id)");
666 return 0;
667 }
668
669
lua_GetActionChange(lua_State * lua)670 int lua_GetActionChange(lua_State *lua)
671 {
672 if(lua_gettop(lua) >= 1)
673 {
674 int act = lua_tointeger(lua, 1);
675
676 if((act >= 0) && (act < ACT_LASTINDEX))
677 {
678 lua_pushinteger(lua, (int)(control_mapper.action_map[act].already_pressed));
679 return 1;
680 }
681
682 Con_Warning("wrong action number");
683 return 0;
684 }
685
686 Con_Warning("getActionChange: expecting arguments (action_id)");
687 return 0;
688 }
689
690
lua_AddFont(lua_State * lua)691 int lua_AddFont(lua_State *lua)
692 {
693 if(lua_gettop(lua) != 3)
694 {
695 Con_Warning("addFont: expecting arguments (font index, font path, font size)");
696 return 0;
697 }
698
699 if(!GLText_AddFont(lua_tointeger(lua, 1), lua_tointeger(lua, 3), lua_tostring(lua, 2)))
700 {
701 Con_Warning("can't create font with id = %d", lua_tointeger(lua, 1));
702 }
703
704 return 0;
705 }
706
707
lua_AddFontStyle(lua_State * lua)708 int lua_AddFontStyle(lua_State *lua)
709 {
710 if(lua_gettop(lua) < 12)
711 {
712 Con_Warning("addFontStyle: expecting arguments (index, R, G, B, A, shadow, fade, rect, border, bR, bG, bB, bA, hide)");
713 return 0;
714 }
715
716 font_Style style_index = (font_Style)lua_tointeger(lua, 1);
717 GLfloat color_R = (GLfloat)lua_tonumber(lua, 2);
718 GLfloat color_G = (GLfloat)lua_tonumber(lua, 3);
719 GLfloat color_B = (GLfloat)lua_tonumber(lua, 4);
720 GLfloat color_A = (GLfloat)lua_tonumber(lua, 5);
721 int shadowed = lua_toboolean(lua, 6);
722 int rect = lua_toboolean(lua, 7);
723 GLfloat rect_border = (GLfloat)lua_tonumber(lua, 8);
724 GLfloat rect_R = (GLfloat)lua_tonumber(lua, 9);
725 GLfloat rect_G = (GLfloat)lua_tonumber(lua, 10);
726 GLfloat rect_B = (GLfloat)lua_tonumber(lua, 11);
727 GLfloat rect_A = (GLfloat)lua_tonumber(lua, 12);
728
729 if(!GLText_AddFontStyle(style_index,
730 color_R, color_G, color_B, color_A,
731 shadowed, rect, rect_border,
732 rect_R, rect_G, rect_B, rect_A))
733 {
734 Con_Warning("can't create fontstyle with id = %d", style_index);
735 }
736
737 return 0;
738 }
739
740
lua_RemoveFont(lua_State * lua)741 int lua_RemoveFont(lua_State *lua)
742 {
743 if(lua_gettop(lua) != 1)
744 {
745 Con_Warning("removeFont: expecting arguments (font index)");
746 return 0;
747 }
748
749 if(!GLText_RemoveFont(lua_tointeger(lua, 1)))
750 {
751 Con_Warning("can't remove font");
752 }
753
754 return 0;
755 }
756
757
lua_RemoveFontStyle(lua_State * lua)758 int lua_RemoveFontStyle(lua_State *lua)
759 {
760 if(lua_gettop(lua) != 1)
761 {
762 Con_Warning("removeFontStyle: expecting arguments (style index)");
763 return 0;
764 }
765
766 if(!GLText_RemoveFontStyle(lua_tointeger(lua, 1)))
767 {
768 Con_Warning("can't remove font style");
769 }
770
771 return 0;
772 }
773
774
775 // Called when something goes absolutely horribly wrong in Lua, and tries
776 // to produce some debug output. Lua calls abort afterwards, so sending
777 // the output to the internal console is not an option.
lua_LuaPanic(lua_State * lua)778 static int lua_LuaPanic(lua_State *lua)
779 {
780 if(lua_gettop(lua) < 1)
781 {
782 fprintf(stderr, "Fatal lua error (no details provided).\n");
783 }
784 else
785 {
786 fprintf(stderr, "Fatal lua error: %s\n", lua_tostring(lua, 1));
787 }
788 fflush(stderr);
789 return 0;
790 }
791
792
Script_LoadConstants(lua_State * lua)793 void Script_LoadConstants(lua_State *lua)
794 {
795 if(lua)
796 {
797 int top = lua_gettop(lua);
798
799 LUA_EXPOSE(lua, TR_I);
800 LUA_EXPOSE(lua, TR_I_DEMO);
801 LUA_EXPOSE(lua, TR_I_UB);
802 LUA_EXPOSE(lua, TR_II);
803 LUA_EXPOSE(lua, TR_II_DEMO);
804 LUA_EXPOSE(lua, TR_III);
805 LUA_EXPOSE(lua, TR_IV);
806 LUA_EXPOSE(lua, TR_IV_DEMO);
807 LUA_EXPOSE(lua, TR_V);
808 LUA_EXPOSE(lua, TR_UNKNOWN);
809
810 LUA_EXPOSE(lua, GAME_1);
811 LUA_EXPOSE(lua, GAME_1_1);
812 LUA_EXPOSE(lua, GAME_1_5);
813 LUA_EXPOSE(lua, GAME_2);
814 LUA_EXPOSE(lua, GAME_2_1);
815 LUA_EXPOSE(lua, GAME_2_5);
816 LUA_EXPOSE(lua, GAME_3);
817 LUA_EXPOSE(lua, GAME_3_5);
818 LUA_EXPOSE(lua, GAME_4);
819 LUA_EXPOSE(lua, GAME_4_1);
820 LUA_EXPOSE(lua, GAME_5);
821
822 LUA_EXPOSE(lua, GF_OP_PICTURE);
823 LUA_EXPOSE(lua, GF_OP_LISTSTART);
824 LUA_EXPOSE(lua, GF_OP_LISTEND);
825 LUA_EXPOSE(lua, GF_OP_STARTFMV);
826 LUA_EXPOSE(lua, GF_OP_STARTLEVEL);
827 LUA_EXPOSE(lua, GF_OP_STARTCINE);
828 LUA_EXPOSE(lua, GF_OP_LEVELCOMPLETE);
829 LUA_EXPOSE(lua, GF_OP_STARTDEMO);
830 LUA_EXPOSE(lua, GF_OP_JUMPTOSEQUENCE);
831 LUA_EXPOSE(lua, GF_OP_ENDSEQUENCE);
832 LUA_EXPOSE(lua, GF_OP_SETTRACK);
833 LUA_EXPOSE(lua, GF_OP_ENABLESUNSET);
834 LUA_EXPOSE(lua, GF_OP_LOADINGPIC);
835 LUA_EXPOSE(lua, GF_OP_DEADLYWATER);
836 LUA_EXPOSE(lua, GF_OP_REMOVEWEAPONS);
837 LUA_EXPOSE(lua, GF_OP_GAMECOMPLETE);
838 LUA_EXPOSE(lua, GF_OP_CUTANGLE);
839 LUA_EXPOSE(lua, GF_OP_NOFLOOR);
840 LUA_EXPOSE(lua, GF_OP_ADDTOINVENTORY);
841 LUA_EXPOSE(lua, GF_OP_LARASTARTANIM);
842 LUA_EXPOSE(lua, GF_OP_NUMSECRETS);
843 LUA_EXPOSE(lua, GF_OP_KILLTOCOMPLETE);
844 LUA_EXPOSE(lua, GF_OP_REMOVEAMMO);
845
846 LUA_EXPOSE(lua, ITEM_TYPE_SYSTEM);
847 LUA_EXPOSE(lua, ITEM_TYPE_SUPPLY);
848 LUA_EXPOSE(lua, ITEM_TYPE_QUEST);
849
850 LUA_EXPOSE(lua, ITEM_COMPASS);
851 LUA_EXPOSE(lua, ITEM_PASSPORT);
852 LUA_EXPOSE(lua, ITEM_LARAHOME);
853 LUA_EXPOSE(lua, ITEM_VIDEO);
854 LUA_EXPOSE(lua, ITEM_AUDIO);
855 LUA_EXPOSE(lua, ITEM_CONTROLS);
856 LUA_EXPOSE(lua, ITEM_LOAD);
857 LUA_EXPOSE(lua, ITEM_SAVE);
858 LUA_EXPOSE(lua, ITEM_MAP);
859
860 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_TRIGGER);
861 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_PAD);
862 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_SWITCH);
863 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_KEY);
864 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_PICKUP);
865 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_HEAVY);
866 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_ANTIPAD);
867 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_COMBAT);
868 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_DUMMY);
869 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_ANTITRIGGER);
870 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_HEAVYSWITCH);
871 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_HEAVYANTITRIGGER);
872 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_MONKEY);
873 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_SKELETON);
874 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_TIGHTROPE);
875 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_CRAWLDUCK);
876 LUA_EXPOSE(lua, TR_FD_TRIGTYPE_CLIMB);
877
878 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_OBJECT);
879 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_SET_CAMERA);
880 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_UWCURRENT);
881 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_FLIPMAP);
882 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_FLIPON);
883 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_FLIPOFF);
884 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_SET_TARGET);
885 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_ENDLEVEL);
886 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_PLAYTRACK);
887 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_FLIPEFFECT);
888 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_SECRET);
889 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_CLEARBODIES);
890 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_FLYBY);
891 LUA_EXPOSE(lua, TR_FD_TRIGFUNC_CUTSCENE);
892
893 LUA_EXPOSE(lua, ENTITY_STATE_ENABLED);
894 LUA_EXPOSE(lua, ENTITY_STATE_ACTIVE);
895 LUA_EXPOSE(lua, ENTITY_STATE_VISIBLE);
896 LUA_EXPOSE(lua, ENTITY_STATE_COLLIDABLE);
897 LUA_EXPOSE(lua, ENTITY_STATE_DELETED);
898
899 LUA_EXPOSE(lua, ENTITY_TYPE_SPAWNED);
900 LUA_EXPOSE(lua, ENTITY_TYPE_GENERIC);
901 LUA_EXPOSE(lua, ENTITY_TYPE_INTERACTIVE);
902 LUA_EXPOSE(lua, ENTITY_TYPE_TRIGGER_ACTIVATOR);
903 LUA_EXPOSE(lua, ENTITY_TYPE_HEAVYTRIGGER_ACTIVATOR);
904 LUA_EXPOSE(lua, ENTITY_TYPE_PICKABLE);
905 LUA_EXPOSE(lua, ENTITY_TYPE_TRAVERSE);
906 LUA_EXPOSE(lua, ENTITY_TYPE_TRAVERSE_FLOOR);
907 LUA_EXPOSE(lua, ENTITY_TYPE_DYNAMIC);
908 LUA_EXPOSE(lua, ENTITY_TYPE_ACTOR);
909
910 LUA_EXPOSE(lua, ENTITY_CALLBACK_NONE);
911 LUA_EXPOSE(lua, ENTITY_CALLBACK_ACTIVATE);
912 LUA_EXPOSE(lua, ENTITY_CALLBACK_DEACTIVATE);
913 LUA_EXPOSE(lua, ENTITY_CALLBACK_COLLISION);
914 LUA_EXPOSE(lua, ENTITY_CALLBACK_STAND);
915 LUA_EXPOSE(lua, ENTITY_CALLBACK_HIT);
916 LUA_EXPOSE(lua, ENTITY_CALLBACK_ATTACK);
917 LUA_EXPOSE(lua, ENTITY_CALLBACK_SHOOT);
918
919 LUA_EXPOSE(lua, PARAM_HEALTH);
920 LUA_EXPOSE(lua, PARAM_AIR);
921 LUA_EXPOSE(lua, PARAM_STAMINA);
922 LUA_EXPOSE(lua, PARAM_WARMTH);
923 LUA_EXPOSE(lua, PARAM_HIT_DAMAGE);
924 LUA_EXPOSE(lua, PARAM_EXTRA1);
925 LUA_EXPOSE(lua, PARAM_EXTRA2);
926 LUA_EXPOSE(lua, PARAM_EXTRA3);
927 LUA_EXPOSE(lua, PARAM_EXTRA4);
928 LUA_EXPOSE(lua, PARAM_LASTINDEX);
929
930 LUA_EXPOSE(lua, ANIMATION_KEY_INIT);
931 LUA_EXPOSE(lua, ANIMATION_KEY_DEAD);
932
933 LUA_EXPOSE(lua, STATE_FUNCTIONS_LARA);
934 LUA_EXPOSE(lua, STATE_FUNCTIONS_BAT);
935 LUA_EXPOSE(lua, STATE_FUNCTIONS_WOLF);
936 LUA_EXPOSE(lua, STATE_FUNCTIONS_BEAR);
937 LUA_EXPOSE(lua, STATE_FUNCTIONS_RAPTOR);
938 LUA_EXPOSE(lua, STATE_FUNCTIONS_TREX);
939 LUA_EXPOSE(lua, STATE_FUNCTIONS_LARSON);
940 LUA_EXPOSE(lua, STATE_FUNCTIONS_PIERRE);
941 LUA_EXPOSE(lua, STATE_FUNCTIONS_LION);
942 LUA_EXPOSE(lua, STATE_FUNCTIONS_GORILLA);
943 LUA_EXPOSE(lua, STATE_FUNCTIONS_CROCODILE);
944 LUA_EXPOSE(lua, STATE_FUNCTIONS_RAT);
945 LUA_EXPOSE(lua, STATE_FUNCTIONS_CENTAUR);
946 LUA_EXPOSE(lua, STATE_FUNCTIONS_PUMA);
947 LUA_EXPOSE(lua, STATE_FUNCTIONS_WINGED_MUTANT);
948 LUA_EXPOSE(lua, STATE_FUNCTIONS_COWBOY);
949 LUA_EXPOSE(lua, STATE_FUNCTIONS_SKATEBOARDIST);
950 LUA_EXPOSE(lua, STATE_FUNCTIONS_MRT);
951 LUA_EXPOSE(lua, STATE_FUNCTIONS_TORSO_BOSS);
952 LUA_EXPOSE(lua, STATE_FUNCTIONS_NATLA);
953
954 LUA_EXPOSE(lua, ANIM_NORMAL_CONTROL);
955 LUA_EXPOSE(lua, ANIM_LOOP_LAST_FRAME);
956 LUA_EXPOSE(lua, ANIM_FRAME_LOCK);
957 LUA_EXPOSE(lua, ANIM_FRAME_REVERSE);
958
959 LUA_EXPOSE(lua, ANIM_TYPE_BASE);
960 LUA_EXPOSE(lua, ANIM_TYPE_WEAPON_LH);
961 LUA_EXPOSE(lua, ANIM_TYPE_WEAPON_RH);
962 LUA_EXPOSE(lua, ANIM_TYPE_WEAPON_TH);
963 LUA_EXPOSE(lua, ANIM_TYPE_MISK_1);
964 LUA_EXPOSE(lua, ANIM_TYPE_MISK_2);
965 LUA_EXPOSE(lua, ANIM_TYPE_MISK_3);
966 LUA_EXPOSE(lua, ANIM_TYPE_MISK_4);
967
968 LUA_EXPOSE(lua, ZONE_TYPE_ALL);
969 LUA_EXPOSE(lua, ZONE_TYPE_1);
970 LUA_EXPOSE(lua, ZONE_TYPE_2);
971 LUA_EXPOSE(lua, ZONE_TYPE_3);
972 LUA_EXPOSE(lua, ZONE_TYPE_4);
973 LUA_EXPOSE(lua, ZONE_TYPE_FLY);
974
975 LUA_EXPOSE(lua, MOVE_STATIC_POS);
976 LUA_EXPOSE(lua, MOVE_KINEMATIC);
977 LUA_EXPOSE(lua, MOVE_ON_FLOOR);
978 LUA_EXPOSE(lua, MOVE_WADE);
979 LUA_EXPOSE(lua, MOVE_QUICKSAND);
980 LUA_EXPOSE(lua, MOVE_ON_WATER);
981 LUA_EXPOSE(lua, MOVE_UNDERWATER);
982 LUA_EXPOSE(lua, MOVE_FREE_FALLING);
983 LUA_EXPOSE(lua, MOVE_CLIMBING);
984 LUA_EXPOSE(lua, MOVE_MONKEYSWING);
985 LUA_EXPOSE(lua, MOVE_WALLS_CLIMB);
986 LUA_EXPOSE(lua, MOVE_DOZY);
987 LUA_EXPOSE(lua, MOVE_FLY);
988
989 LUA_EXPOSE(lua, TRIGGER_OP_OR);
990 LUA_EXPOSE(lua, TRIGGER_OP_XOR);
991 LUA_EXPOSE(lua, TRIGGER_OP_AND_INV);
992
993 LUA_EXPOSE(lua, CHARACTER_STATE_DEAD);
994
995 LUA_EXPOSE(lua, TICK_IDLE);
996 LUA_EXPOSE(lua, TICK_STOPPED);
997 LUA_EXPOSE(lua, TICK_ACTIVE);
998
999 LUA_EXPOSE(lua, COLLISION_SHAPE_BOX);
1000 LUA_EXPOSE(lua, COLLISION_SHAPE_BOX_BASE);
1001 LUA_EXPOSE(lua, COLLISION_SHAPE_SPHERE);
1002 LUA_EXPOSE(lua, COLLISION_SHAPE_TRIMESH);
1003 LUA_EXPOSE(lua, COLLISION_SHAPE_TRIMESH_CONVEX);
1004 LUA_EXPOSE(lua, COLLISION_SHAPE_SINGLE_BOX);
1005 LUA_EXPOSE(lua, COLLISION_SHAPE_SINGLE_SPHERE);
1006
1007 LUA_EXPOSE(lua, COLLISION_NONE);
1008 LUA_EXPOSE(lua, COLLISION_GROUP_ALL);
1009 LUA_EXPOSE(lua, COLLISION_MASK_ALL);
1010 LUA_EXPOSE(lua, COLLISION_GROUP_STATIC_ROOM);
1011 LUA_EXPOSE(lua, COLLISION_GROUP_STATIC_OBLECT);
1012 LUA_EXPOSE(lua, COLLISION_GROUP_KINEMATIC);
1013 //LUA_EXPOSE(lua, COLLISION_GROUP_GHOST);
1014 LUA_EXPOSE(lua, COLLISION_GROUP_TRIGGERS);
1015 LUA_EXPOSE(lua, COLLISION_GROUP_CHARACTERS);
1016 LUA_EXPOSE(lua, COLLISION_GROUP_VEHICLE);
1017 LUA_EXPOSE(lua, COLLISION_GROUP_BULLETS);
1018 LUA_EXPOSE(lua, COLLISION_GROUP_DYNAMICS);
1019 LUA_EXPOSE(lua, COLLISION_GROUP_DYNAMICS_NI);
1020
1021 LUA_EXPOSE(lua, ENTITY_TRIGGERING_ACTIVATED);
1022 LUA_EXPOSE(lua, ENTITY_TRIGGERING_DEACTIVATED);
1023 LUA_EXPOSE(lua, ENTITY_TRIGGERING_NOT_READY);
1024
1025 lua_pushstring(lua, Engine_GetBasePath());
1026 lua_setglobal(lua, "base_path");
1027
1028 lua_settop(lua, top);
1029 }
1030 }
1031
1032
Script_LuaInit()1033 bool Script_LuaInit()
1034 {
1035 bool ret = false;
1036 engine_lua = luaL_newstate();
1037
1038 if(engine_lua)
1039 {
1040 luaL_openlibs(engine_lua);
1041 Script_LoadConstants(engine_lua);
1042 Script_LuaRegisterFuncs(engine_lua);
1043 lua_atpanic(engine_lua, lua_LuaPanic);
1044
1045 // Load script loading order (sic!)
1046 Script_DoLuaFile(engine_lua, "scripts/loadscript.lua");
1047 ret = true;
1048 }
1049
1050 return ret;
1051 }
1052
1053
Script_DoLuaFile(lua_State * lua,const char * local_path)1054 int Script_DoLuaFile(lua_State *lua, const char *local_path)
1055 {
1056 char script_path[1024];
1057 size_t script_path_base_len = sizeof(script_path) - 1;
1058 strncpy(script_path, Engine_GetBasePath(), script_path_base_len);
1059 script_path[script_path_base_len] = 0;
1060 strncat(script_path, local_path, script_path_base_len - 1);
1061 return luaL_dofile(lua, script_path);
1062 }
1063
1064
Script_LuaClearTasks()1065 void Script_LuaClearTasks()
1066 {
1067 if(engine_lua)
1068 {
1069 int top = lua_gettop(engine_lua);
1070
1071 Script_CallVoidFunc(engine_lua, "clearTasks");
1072
1073 lua_getglobal(engine_lua, "tlist_Clear");
1074 if(lua_isfunction(engine_lua, -1))
1075 {
1076 lua_CallAndLog(engine_lua, 0, 1, 0);
1077 }
1078
1079 lua_getglobal(engine_lua, "entfuncs_Clear");
1080 if(lua_isfunction(engine_lua, -1))
1081 {
1082 lua_CallAndLog(engine_lua, 0, 1, 0);
1083 }
1084
1085 lua_settop(engine_lua, top);
1086 }
1087 }
1088
1089
1090 void Script_LuaRegisterAnimFuncs(lua_State *lua);
1091 void Script_LuaRegisterEntityFuncs(lua_State *lua);
1092 void Script_LuaRegisterCharacterFuncs(lua_State *lua);
1093 void Script_LuaRegisterWorldFuncs(lua_State *lua);
1094 void Script_LuaRegisterAudioFuncs(lua_State *lua);
1095
1096
Script_LuaRegisterFuncs(lua_State * lua)1097 void Script_LuaRegisterFuncs(lua_State *lua)
1098 {
1099 luaL_dostring(lua, CVAR_LUA_TABLE_NAME " = {};");
1100
1101 lua_register(lua, "print", lua_print);
1102
1103 lua_register(lua, "getActionState", lua_GetActionState);
1104 lua_register(lua, "getActionChange", lua_GetActionChange);
1105
1106 lua_register(lua, "bind", lua_BindKey);
1107 lua_register(lua, "addFont", lua_AddFont);
1108 lua_register(lua, "removeFont", lua_RemoveFont);
1109 lua_register(lua, "addFontStyle", lua_AddFontStyle);
1110 lua_register(lua, "removeFontStyle", lua_RemoveFontStyle);
1111
1112 Game_RegisterLuaFunctions(lua);
1113
1114 Script_LuaRegisterAnimFuncs(lua);
1115 Script_LuaRegisterEntityFuncs(lua);
1116 Script_LuaRegisterCharacterFuncs(lua);
1117 Script_LuaRegisterWorldFuncs(lua);
1118 Script_LuaRegisterAudioFuncs(lua);
1119 }
1120