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 
14 #include "../core/system.h"
15 #include "../core/console.h"
16 #include "../audio/audio.h"
17 
18 #include "../gameflow.h"
19 #include "../engine.h"
20 #include "../world.h"
21 
22 
Script_ParseAudio(lua_State * lua,struct audio_settings_s * as)23 int Script_ParseAudio(lua_State *lua, struct audio_settings_s *as)
24 {
25     if(lua)
26     {
27         int top = lua_gettop(lua);
28 
29         lua_getglobal(lua, "audio");
30         lua_getfield(lua, -1, "music_volume");
31         as->music_volume = lua_tonumber(lua, -1);
32         lua_pop(lua, 1);
33 
34         lua_getfield(lua, -1, "sound_volume");
35         as->sound_volume = lua_tonumber(lua, -1);
36         lua_pop(lua, 1);
37 
38         lua_getfield(lua, -1, "use_effects");
39         as->use_effects  = lua_tointeger(lua, -1);
40         lua_pop(lua, 1);
41 
42         lua_getfield(lua, -1, "listener_is_player");
43         as->listener_is_player = lua_tointeger(lua, -1);
44         lua_pop(lua, 1);
45 
46         lua_settop(lua, top);
47         return 1;
48     }
49 
50     return -1;
51 }
52 
53 /*
54  *   Specific functions to get specific parameters from script.
55  */
Script_GetGlobalSound(lua_State * lua,int global_sound_id)56  int Script_GetGlobalSound(lua_State *lua, int global_sound_id)
57 {
58     int sound_id = 0;
59 
60     if(lua)
61     {
62         int top = lua_gettop(lua);
63         lua_getglobal(lua, "getGlobalSound");
64 
65         if(lua_isfunction(lua, -1))
66         {
67             lua_pushinteger(lua, World_GetVersion());
68             lua_pushinteger(lua, global_sound_id);
69             if(lua_CallAndLog(lua, 2, 1, 0))
70             {
71                 sound_id = lua_tointeger(lua, -1);
72             }
73         }
74         lua_settop(lua, top);
75     }
76 
77     return sound_id;
78 }
79 
80 
Script_GetSecretTrackNumber(lua_State * lua)81 int Script_GetSecretTrackNumber(lua_State *lua)
82 {
83     lua_Integer track_number = 0;
84 
85     if(lua)
86     {
87         int top = lua_gettop(lua);
88         lua_getglobal(lua, "getSecretTrackNumber");
89 
90         if(lua_isfunction(lua, -1))
91         {
92             lua_pushinteger(lua, World_GetVersion());
93             if(lua_CallAndLog(lua, 1, 1, 0))
94             {
95                 track_number = lua_tointeger(lua, -1);
96             }
97         }
98         lua_settop(lua, top);
99     }
100 
101     return (int)track_number;
102 }
103 
104 
Script_GetNumTracks(lua_State * lua)105 int Script_GetNumTracks(lua_State *lua)
106 {
107     lua_Integer num_tracks = 0;
108 
109     if(lua)
110     {
111         int top = lua_gettop(lua);
112         lua_getglobal(lua, "getNumTracks");
113 
114         if(lua_isfunction(lua, -1))
115         {
116             lua_pushinteger(lua, World_GetVersion());
117             if(lua_CallAndLog(lua, 1, 1, 0))
118             {
119                 num_tracks = lua_tointeger(lua, -1);
120             }
121         }
122         lua_settop(lua, top);
123     }
124 
125     return (int)num_tracks;
126 }
127 
128 
Script_GetOverridedSamplesInfo(lua_State * lua,int * num_samples,int * num_sounds,char * sample_name_mask)129 bool Script_GetOverridedSamplesInfo(lua_State *lua, int *num_samples, int *num_sounds, char *sample_name_mask)
130 {
131     bool result = false;
132 
133     if(lua)
134     {
135         int top = lua_gettop(lua);
136         lua_getglobal(lua, "getOverridedSamplesInfo");
137         const char *real_path;
138 
139         if(lua_isfunction(lua, -1))
140         {
141             lua_pushinteger(lua, World_GetVersion());
142             if(lua_CallAndLog(lua, 1, 3, 0))
143             {
144                 size_t string_length = 0;
145                 real_path   = lua_tolstring(lua, -1, &string_length);
146                *num_sounds  = lua_tointeger(lua, -2);
147                *num_samples = lua_tointeger(lua, -3);
148                 strncpy(sample_name_mask, real_path, string_length);
149                 result = ((*num_sounds != -1) && (*num_samples != -1) && (strcmp(real_path, "NONE") != 0));
150             }
151         }
152         lua_settop(lua, top);
153     }
154 
155     // If Lua environment doesn't exist or script function returned -1 in one of the
156     // fields, it means that corresponding sample override table is missing or not
157     // valid - hence, return false.
158 
159     return result;
160 }
161 
162 
Script_GetOverridedSample(lua_State * lua,int sound_id,int * first_sample_number,int * samples_count)163 bool Script_GetOverridedSample(lua_State *lua, int sound_id, int *first_sample_number, int *samples_count)
164 {
165     bool result = false;
166 
167     if(lua)
168     {
169         int top = lua_gettop(lua);
170         lua_getglobal(lua, "getOverridedSample");
171 
172         if(lua_isfunction(lua, -1))
173         {
174             lua_pushinteger(lua, World_GetVersion());
175             lua_pushinteger(lua, Gameflow_GetCurrentLevelID());
176             lua_pushinteger(lua, sound_id);
177             if(lua_CallAndLog(lua, 3, 2, 0))
178             {
179                 *first_sample_number = (int)lua_tointeger(lua, -2);
180                 *samples_count       = (int)lua_tointeger(lua, -1);
181                 result = ((*first_sample_number != -1) && (*samples_count != -1));
182             }
183         }
184         lua_settop(lua, top);
185     }
186 
187     return result;
188 }
189 
190 
Script_GetSoundtrack(lua_State * lua,int track_index,char * file_path,int file_path_len,int * load_method,int * stream_type)191 bool Script_GetSoundtrack(lua_State *lua, int track_index, char *file_path, int file_path_len, int *load_method, int *stream_type)
192 {
193     bool result = false;
194 
195     if(lua)
196     {
197         int top = lua_gettop(lua);
198         const char *real_path;
199 
200         lua_getglobal(lua, "getTrackInfo");
201 
202         if(lua_isfunction(lua, -1))
203         {
204             lua_pushinteger(lua, World_GetVersion());
205             lua_pushinteger(lua, track_index);
206             if(lua_CallAndLog(lua, 2, 3, 0))
207             {
208                 size_t string_length  = 0;
209                 real_path   = lua_tolstring(lua, -3, &string_length);
210                *stream_type = (int)lua_tointeger(lua, -2);
211                *load_method = (int)lua_tointeger(lua, -1);
212 
213                 // Lua returns constant string pointer, which we can't assign to
214                 // provided argument; so we need to straightly copy it.
215 
216                 strncpy(file_path, Engine_GetBasePath(), file_path_len);
217                 strncat(file_path, real_path, file_path_len);
218                 result = (*stream_type != -1);
219             }
220         }
221         lua_settop(lua, top);
222     }
223 
224     // If Lua wasn't able to extract file path from the script, most likely it means
225     // that entry is broken or missing, or wrong track ID was specified. So we return
226     // FALSE in such cases.
227 
228     return result;
229 }
230 
231 
232 /*
233  * General gameplay functions
234  */
lua_PlayStream(lua_State * lua)235 int lua_PlayStream(lua_State *lua)
236 {
237     int top = lua_gettop(lua);
238 
239     if(top >= 1)
240     {
241         int id = lua_tointeger(lua, 1);
242         if(id >= 0)
243         {
244             uint8_t mask = (top >= 2) ? (lua_tointeger(lua, 2)) : (0);
245             Audio_StreamPlay(id, mask);
246         }
247         else
248         {
249             Con_Warning("wrong stream id");
250         }
251     }
252     else
253     {
254         Con_Warning("playStream: expecting arguments (stream_id, (mask))");
255     }
256 
257     return 0;
258 }
259 
260 
lua_PlaySound(lua_State * lua)261 int lua_PlaySound(lua_State *lua)
262 {
263     int top = lua_gettop(lua);
264 
265     if(top >= 1)
266     {
267         uint32_t id  = lua_tointeger(lua, 1);           // uint_t can't been less zero, reduce number of comparations
268         int ent_id = -1;
269         if((top >= 2) && World_GetEntityByID(ent_id = lua_tointeger(lua, 2)) == NULL)
270         {
271             ent_id = -1;
272         }
273 
274         int result;
275 
276         if(ent_id >= 0)
277         {
278             result = Audio_Send(id, TR_AUDIO_EMITTER_ENTITY, ent_id);
279         }
280         else
281         {
282             result = Audio_Send(id, TR_AUDIO_EMITTER_GLOBAL);
283         }
284 
285         if(result < 0)
286         {
287             switch(result)
288             {
289                 case TR_AUDIO_SEND_NOCHANNEL:
290                     Con_Warning("send ignored: no free channels");
291                     break;
292 
293                 case TR_AUDIO_SEND_NOSAMPLE:
294                     Con_Warning("send ignored: no sample");
295                     break;
296             }
297         }
298     }
299     else
300     {
301         Con_Warning("playSound: expecting arguments (sound_id, (entity_id))");
302     }
303 
304     return 0;
305 }
306 
307 
lua_StopSound(lua_State * lua)308 int lua_StopSound(lua_State *lua)
309 {
310     int top = lua_gettop(lua);
311 
312     if(top >= 1)
313     {
314         uint32_t id  = lua_tointeger(lua, 1);
315         int ent_id = -1;
316         if((top >= 2) && World_GetEntityByID(ent_id = lua_tointeger(lua, 2)) == NULL)
317         {
318             ent_id = -1;
319         }
320 
321         int result;
322 
323         if(ent_id == -1)
324         {
325             result = Audio_Kill(id, TR_AUDIO_EMITTER_GLOBAL);
326         }
327         else
328         {
329             result = Audio_Kill(id, TR_AUDIO_EMITTER_ENTITY, ent_id);
330         }
331 
332         if(result < 0)
333         {
334             Con_Warning("audio with id = %d not played", id);
335         }
336     }
337     else
338     {
339         Con_Warning("stopSound: expecting arguments (sound_id, (entity_id))");
340     }
341 
342     return 0;
343 }
344 
345 
Script_LuaRegisterAudioFuncs(lua_State * lua)346 void Script_LuaRegisterAudioFuncs(lua_State *lua)
347 {
348     lua_register(lua, "playSound", lua_PlaySound);
349     lua_register(lua, "stopSound", lua_StopSound);
350     lua_register(lua, "playStream", lua_PlayStream);
351 }
352