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