1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/file.h"
24 #include "common/lua/lua.h"
25 #include "common/lua/lauxlib.h"
26 #include "common/lua/lualib.h"
27
28 #include "hdb/hdb.h"
29 #include "hdb/ai.h"
30 #include "hdb/file-manager.h"
31 #include "hdb/lua-script.h"
32 #include "hdb/gfx.h"
33 #include "hdb/map.h"
34 #include "hdb/mpc.h"
35 #include "hdb/sound.h"
36 #include "hdb/window.h"
37
38 namespace HDB {
39
40 struct ScriptPatch {
41 const char *scriptName;
42 const char *search;
43 const char *replace;
44 } scriptPatches[] = {
45 {"GLOBAL", "return gsub( s, \"\\n\", \"\\\\\\n\" )", "return string.gsub( s, \"\\n\", \"\\\\\\n\" )"}, // line 10
46 {"GLOBAL", "strsub(", "string.sub("}, // line 15
47 {"GLOBAL", "function save( i,v, nest )", "function func_namelookup(func)\nfor i,v in pairs(_G) do\nif type(v) == 'function' and v == func then\nreturn i\nend\nend\nend\nfunction save( i,v, nest )"}, // line 13
48 {"GLOBAL", "if type(v) == 'userdata' or type(v) == 'function' then return end", "if type(v) == 'userdata' or i == 'package' or i == 'os' or i == 'io' or i == 'string' or i == 'table' or i == 'debug' or i == 'math' or i == 'coroutine' then return end" }, // Line 16
49 {"GLOBAL", "local t=type(v)", "local t=type(v)\nif (t == 'function' and nest == 0) then return end"}, // line 18
50 {"GLOBAL", "then write_record(v, nest + 1)", "then write_record(v, nest + 1)\nelseif t=='function' then write(savefile, func_namelookup(v)) if nest > 0 then write(savefile, ',' ) end"}, // line 32
51 {"GLOBAL", "for i,v in t do", "for i,v in pairs(t) do"}, // line 43
52 {"GLOBAL", "for i,v in globals() do", "for i,v in pairs(_G) do"}, // line 52
53 {"GLOBAL", "for npcname,npcdata in npcs do", "for npcname,npcdata in pairs(npcs) do"}, // Line 66
54 {"GLOBAL", "for dlgname,dlgdata in npcdata.dialog do", "for dlgname,dlgdata in pairs(npcdata.dialog) do"}, // Line 67
55 {"GLOBAL", "s = format( \"npcs.%s.dialog.%s.counter", "s = string.format( \"npcs.%s.dialog.%s.counter"}, // Line 68
56 {"GLOBAL", "s = format( \"npcs.%s.dialog.%s.finished = ", "s = string.format( \"npcs.%s.dialog.%s.finished = "}, // line 70
57 {"GLOBAL", "if( getglobal( \"map\"..tostring(v1)..\"_complete\" ) ) then", "if( _G[\"map\"..tostring(v1)..\"_complete\"] ) then"}, // line 219
58 {"GLOBAL", "local mapname = format( \"MAP", "local mapname = string.format( \"MAP"}, // line 225
59 {"GLOBAL", "if( dtable.counter < getn(dtable) ) then", "if( dtable.counter < #dtable ) then"}, // line 254
60 {"GLOBAL", "closefunc = getglobal( npcdef.codename..\"_use\" )", "closefunc = _G[npcdef.codename..\"_use\"]"}, // line 272
61 {"GLOBAL", "setglobal( npcdef.codename..\"_init\", function() return NPC_Init( %npcdef ) end )", "_G[npcdef.codename .. \"_init\"] = function() return NPC_Init( npcdef ) end"}, // line 317
62 {"GLOBA", "setglobal( npcdef.codename..\"_use\", function(x, y, v1, v2) return NPC_Use( %npcdef, x, y, v1, v2 ) end )", "_G[npcdef.codename .. \"_use\"] = function(x, y, v1, v2) return NPC_Use( npcdef, x, y, v1, v2 ) end"}, // line 318
63 {"GLOBAL", "for i,npc in npcs do", "for i,npc in pairs(npcs) do"}, // 323
64
65 {"MAP00", "if( getn( beds ) == 0 ) then", "if( #beds == 0 ) then"}, // line 924
66 {"MAP00", "tempfunc = function() emptybed_use( %x, %y, %v1, %v2 ) end", "tempfunc = function() emptybed_use(x, y, v1, v2) end"}, // line 926
67
68 {"MAP01", "strsub(", "string.sub("}, // line 23
69 {"MAP01", "if( covert_index < getn(covert_dialog) ) then", "if( covert_index < #covert_dialog ) then"}, // line 766
70 {"MAP01", "if( chiste_index < getn( chiste_dialog ) )then", "if( chiste_index < #chiste_dialog ) then"}, // 845
71
72 {"MAP10", "if( getn( beds ) == 0 ) then", "if( #beds == 0 ) then"}, // line 119
73 {"MAP10", "emptybed_use( %x, %y, %v1, %v2 )", "emptybed_use( x, y, v1, v2 )"}, // line 121
74
75 {"MAP15", "function cop5_5b()", "function cop5_4b()"}, // line 112
76 {"MAP15", "function cop5_5c()", "function cop5_4c()"}, // line 115
77 {"MAP15", "function cop5_5d()", "function cop5_4d()"}, // line 118
78 {"MAP15", "function cop5_5e()", "function cop5_4e()"}, // line 121
79 {"MAP15", "function cop5_5f()", "function cop5_4f()"}, // line 124
80
81 {"MAP19", "func = getglobal( \"frustrato_nice\"..tostring(frustrato_stage) )", "func = _G[ \"frustrato_nice\"..tostring(frustrato_stage) ]"}, // line 296
82 {"MAP19", "func = getglobal( \"frustrato_choice\"..tostring(frustrato_stage + 1) )", "func = _G[ \"frustrato_choice\"..tostring(frustrato_stage + 1) ]"}, // line 298
83
84 {"MAP11", "mapstring = strsub( LASTMAP, 1, 5 )", "mapstring = string.sub( LASTMAP, 1, 5 )"}, // line 51
85
86 {"MAP21", "mapstring = strsub( LASTMAP, 1, 5 )", "mapstring = string.sub( LASTMAP, 1, 5 )"}, // line 105
87
88 {"MAP29", "Message( format( \"", "Message( string.format( \""}, // line 195
89
90 {"MAP30", "rots = 19 + random( 6 )", "rots = 19 + math.random( 6 )"}, // line 208
91 {"MAP30", "if i1 > getn(tiles)", "if i1 > #tiles"}, // line 211
92 {"MAP30", "if i2 > getn(tiles)", "if i2 > #tiles"}, // line 212
93 {"MAP30", "if i3 > getn(tiles)", "if i3 > #tiles"}, // line 213
94 {"MAP30", "rots = 13 + random( 4 )", "rots = 13 + math.random( 4 )"}, // line 234
95 {"MAP30", "if i2 > getn(tiles)", "if i2 > #tiles"}, // line 237
96 {"MAP30", "if i3 > getn(tiles)", "if i3 > #tiles"}, // line 238
97 {"MAP30", "rots = 13 + random( 4 )", "rots = 13 + math.random( 4 )"}, // line 258
98 {"MAP30", "if i3 > getn(tiles)", "if i3 > #tiles"}, // line 261
99
100 // Jump straight to credits
101 //{"CINE_OUTRO", "-- delegate", "-- delegate\nCine_FadeOutBlack( 40 )\nCredits()"},
102
103 {nullptr, nullptr, nullptr}
104 };
105
LuaScript()106 LuaScript::LuaScript() {
107
108 if (g_hdb->isPPC()) {
109 _cameraXOff = 0;
110 _cameraYOff = 0;
111 } else {
112 _cameraXOff = (32 * 3 + 24); // 3.75 Tiles Extra
113 _cameraYOff = (32 * 2 + 16); // 2.50 Tiles Extra
114 }
115
116 _state = nullptr;
117 _systemInit = false;
118
119
120 _pcallErrorhandlerRegistryIndex = 0;
121 _globalLuaStream = nullptr;
122 _globalLuaLength = 0;
123 }
124
~LuaScript()125 LuaScript::~LuaScript() {
126 if (_state)
127 lua_close(_state);
128
129 if (_globalLuaStream)
130 delete _globalLuaStream;
131 }
132
init()133 void LuaScript::init() {
134 // Load Global Lua Code
135 _globalLuaStream = g_hdb->_fileMan->findFirstData("GLOBAL.LUA", TYPE_BINARY);
136 _globalLuaLength = g_hdb->_fileMan->getLength("GLOBAL.LUA", TYPE_BINARY);
137 if (_globalLuaStream == nullptr || _globalLuaLength == 0) {
138 error("LuaScript::initScript: 'global code' failed to load");
139 }
140 }
141
loadLua(const char * name)142 bool LuaScript::loadLua(const char *name) {
143 Common::SeekableReadStream *luaStream = g_hdb->_fileMan->findFirstData(name, TYPE_BINARY);
144 int32 luaLength = g_hdb->_fileMan->getLength(name, TYPE_BINARY);
145 if (luaStream == nullptr) {
146 warning("The %s MPC entry can't be found", name);
147
148 _systemInit = false;
149
150 delete luaStream;
151 return false;
152 }
153
154 _systemInit = initScript(luaStream, name, luaLength);
155 delete luaStream;
156
157 return true;
158 }
159
saveGlobalNumber(const char * global,double value)160 void LuaScript::saveGlobalNumber(const char *global, double value) {
161 // see if global already exists; if so, overwrite it.
162 for (uint i = 0; i < _globals.size(); i++) {
163 if (!scumm_stricmp(global, _globals[i]->global)) {
164 _globals[i]->valueOrString = 0;
165 _globals[i]->value = value;
166 return;
167 }
168 }
169
170 Global *g = new Global;
171 Common::strlcpy(g->global, global, 32);
172 g->valueOrString = 0;
173 g->value = value;
174
175 _globals.push_back(g);
176 }
177
saveGlobalString(const char * global,const char * string)178 void LuaScript::saveGlobalString(const char *global, const char *string) {
179 if (!string)
180 return;
181
182 // see if global already exists; if so, overwrite it.
183 for (uint i = 0; i < _globals.size(); i++) {
184 if (!scumm_stricmp(global, _globals[i]->global)) {
185 _globals[i]->valueOrString = 1;
186 Common::strlcpy(_globals[i]->string, string, 32);
187 return;
188 }
189 }
190
191 Global *g = new Global;
192 Common::strlcpy(g->global, global, 32);
193 g->valueOrString = 1;
194 Common::strlcpy(g->string, string, 32);
195
196 _globals.push_back(g);
197 }
198
loadGlobal(const char * global)199 void LuaScript::loadGlobal(const char *global) {
200 for (uint i = 0; i < _globals.size(); i++) {
201 if (!scumm_stricmp(global, _globals[i]->global)) {
202 if (_globals[i]->valueOrString) {
203 lua_pushstring(_state, _globals[i]->string);
204 lua_setglobal(_state, _globals[i]->global);
205 } else {
206 lua_pushnumber(_state, _globals[i]->value);
207 lua_setglobal(_state, _globals[i]->global);
208 }
209 return;
210 }
211 }
212 }
213
purgeGlobals()214 void LuaScript::purgeGlobals() {
215 _globals.clear();
216 }
217
save(Common::OutSaveFile * out)218 void LuaScript::save(Common::OutSaveFile *out) {
219 out->writeUint32LE(_globals.size());
220
221 // Save Globals
222 for (uint i = 0; i < _globals.size(); i++) {
223 out->write(_globals[i]->global, 32);
224 out->writeSint32LE(_globals[i]->valueOrString);
225 out->writeDoubleLE(_globals[i]->value);
226 out->write(_globals[i]->string, 32);
227 }
228
229 g_hdb->_currentOutSaveFile = out;
230
231 lua_printstack(_state);
232 lua_getglobal(_state, "SaveState");
233
234 // the save file will be ignored
235 lua_pushstring(_state, "tempSave");
236 lua_call(_state, 1, 0);
237
238 g_hdb->_currentOutSaveFile = nullptr;
239 }
240
loadSaveFile(Common::InSaveFile * in)241 void LuaScript::loadSaveFile(Common::InSaveFile *in) {
242 // Clear out all globals
243 _globals.clear();
244
245 // Start reading globals
246 uint32 globalsSize = in->readUint32LE();
247 for (uint i = 0; i < globalsSize; i++) {
248 Global *g = new Global;
249
250 in->read(g->global, 32);
251 g->valueOrString = in->readSint32LE();
252 g->value = in->readDoubleLE();
253 in->read(g->string, 32);
254
255 _globals.push_back(g);
256 }
257
258 g_hdb->_currentInSaveFile = in;
259
260 lua_getglobal(_state, "LoadState");
261 // it will be ignored
262 lua_pushstring(_state, "tempSave");
263
264 lua_call(_state, 1, 0);
265
266 g_hdb->_currentInSaveFile = nullptr;
267 }
268
setLuaGlobalValue(const char * name,int value)269 void LuaScript::setLuaGlobalValue(const char *name, int value) {
270 if (!_state)
271 return;
272
273 lua_pushnumber(_state, value);
274 lua_setglobal(_state, name);
275 }
276
277 /*
278 Called from Lua, this will pop into the menu
279 */
280
cineStart(lua_State * L)281 static int cineStart(lua_State *L) {
282 double abortable = lua_tonumber(L, 1);
283 const char *abortFunc = lua_tostring(L, 2);
284
285 g_hdb->_lua->checkParameters("cineStart", 2);
286
287 lua_pop(L, 2);
288
289 g_hdb->_ai->cineStart((bool)abortable, abortFunc);
290
291 return 0;
292 }
293
cineStop(lua_State * L)294 static int cineStop(lua_State *L) {
295 const char *funcNext = nullptr;
296
297 int stackTop = lua_gettop(L);
298 if (stackTop) {
299 funcNext = lua_tostring(L, 1);
300 lua_pop(L, 1);
301 }
302
303 g_hdb->_ai->cineStop(funcNext);
304 return 0;
305 }
306
cineFadeInBlack(lua_State * L)307 static int cineFadeInBlack(lua_State *L) {
308 double steps = lua_tonumber(L, 1);
309
310 g_hdb->_lua->checkParameters("cineFadeInBlack", 1);
311
312 lua_pop(L, 1);
313
314 g_hdb->_ai->cineFadeIn(false, (int) steps);
315
316 return 0;
317 }
318
cineFadeOutBlack(lua_State * L)319 static int cineFadeOutBlack(lua_State *L) {
320 double steps = lua_tonumber(L, 1);
321
322 g_hdb->_lua->checkParameters("cineFadeOutBlack", 1);
323
324 lua_pop(L, 1);
325
326 g_hdb->_ai->cineFadeOut(false, (int)steps);
327
328 return 0;
329 }
330
cineFadeInWhite(lua_State * L)331 static int cineFadeInWhite(lua_State *L) {
332 double steps = lua_tonumber(L, 1);
333
334 g_hdb->_lua->checkParameters("cineFadeInWhite", 1);
335
336 lua_pop(L, 1);
337
338 g_hdb->_ai->cineFadeIn(true, (int)steps);
339
340 return 0;
341 }
342
cineFadeOutWhite(lua_State * L)343 static int cineFadeOutWhite(lua_State *L) {
344 double steps = lua_tonumber(L, 1);
345
346 g_hdb->_lua->checkParameters("cineFadeOutWhite", 1);
347
348 lua_pop(L, 1);
349
350 g_hdb->_ai->cineFadeOut(true, (int)steps);
351
352 return 0;
353 }
354
cineStartMap(lua_State * L)355 static int cineStartMap(lua_State *L) {
356 const char *mapName = lua_tostring(L, 1);
357
358 g_hdb->_lua->checkParameters("cineStartMap", 1);
359
360 lua_pop(L, 1);
361
362 g_hdb->_ai->cineStartMap(mapName);
363
364 return 0;
365 }
366
cineLockPlayer(lua_State * L)367 static int cineLockPlayer(lua_State *L) {
368 g_hdb->_ai->cineLockPlayer();
369 return 0;
370 }
371
cineUnlockPlayer(lua_State * L)372 static int cineUnlockPlayer(lua_State *L) {
373 g_hdb->_ai->cineUnlockPlayer();
374 return 0;
375 }
376
cineSetCamera(lua_State * L)377 static int cineSetCamera(lua_State *L) {
378 double x = lua_tonumber(L, 1);
379 double y = lua_tonumber(L, 2);
380
381 g_hdb->_lua->checkParameters("cineSetCamera", 2);
382
383 lua_pop(L, 2);
384
385 g_hdb->_ai->cineSetCamera((int) x, (int) y);
386
387 return 0;
388 }
389
cineResetCamera(lua_State * L)390 static int cineResetCamera(lua_State *L) {
391 g_hdb->_ai->cineResetCamera();
392 return 0;
393 }
394
cineMoveCamera(lua_State * L)395 static int cineMoveCamera(lua_State *L) {
396 double x = lua_tonumber(L, 1);
397 double y = lua_tonumber(L, 2);
398 double speed = lua_tonumber(L, 3);
399
400 g_hdb->_lua->checkParameters("cineMoveCamera", 3);
401
402 lua_pop(L, 3);
403 g_hdb->_ai->cineMoveCamera((int) x, (int) y, (int) speed);
404
405 return 0;
406 }
407
cineWait(lua_State * L)408 static int cineWait(lua_State *L) {
409 double seconds = lua_tonumber(L, 1);
410
411 g_hdb->_lua->checkParameters("cineWait", 1);
412
413 lua_pop(L, 1);
414 g_hdb->_ai->cineWait((int) seconds);
415 return 0;
416 }
417
cineWaitUntilDone(lua_State * L)418 static int cineWaitUntilDone(lua_State *L) {
419 g_hdb->_ai->cineWaitUntilDone();
420 return 0;
421 }
422
cinePlaySound(lua_State * L)423 static int cinePlaySound(lua_State *L) {
424 double index = lua_tonumber(L, 1);
425
426 g_hdb->_lua->checkParameters("cinePlaySound", 1);
427
428 lua_pop(L, 1);
429
430 g_hdb->_ai->cinePlaySound((int)index);
431 return 0;
432 }
433
cinePlayVoice(lua_State * L)434 static int cinePlayVoice(lua_State *L) {
435 double index = lua_tonumber(L, 1);
436 double actor = lua_tonumber(L, 2);
437
438 g_hdb->_lua->checkParameters("cinePlayVoice", 2);
439
440 lua_pop(L, 2);
441
442 g_hdb->_ai->cinePlayVoice((int)index, (int)actor);
443 return 0;
444 }
445
cineUseEntity(lua_State * L)446 static int cineUseEntity(lua_State *L) {
447 const char *string = lua_tostring(L, 1);
448
449 g_hdb->_lua->checkParameters("cineUseEntity", 1);
450
451 lua_pop(L, 1);
452 g_hdb->_ai->cineUse(string);
453 return 0;
454 }
455
cineSetEntity(lua_State * L)456 static int cineSetEntity(lua_State *L) {
457 const char *entName = lua_tostring(L, 1);
458 double x = lua_tonumber(L, 2);
459 double y = lua_tonumber(L, 3);
460 double level = lua_tonumber(L, 4);
461
462 g_hdb->_lua->checkParameters("cineSetEntity", 4);
463
464 lua_pop(L, 4);
465 g_hdb->_ai->cineSetEntity(entName, (int)x, (int)y, (int)level);
466 return 0;
467 }
468
cineRemoveEntity(lua_State * L)469 static int cineRemoveEntity(lua_State *L) {
470 const char *entName = lua_tostring(L, 1);
471
472 g_hdb->_lua->checkParameters("cineRemoveEntity", 1);
473
474 lua_pop(L, 1);
475
476 g_hdb->_ai->cineRemoveEntity(entName);
477 return 0;
478 }
479
cineMoveEntity(lua_State * L)480 static int cineMoveEntity(lua_State *L) {
481 const char *entName = lua_tostring(L, 1);
482 double x = lua_tonumber(L, 2);
483 double y = lua_tonumber(L, 3);
484 double level = lua_tonumber(L, 4);
485 double speed = lua_tonumber(L, 5);
486
487 g_hdb->_lua->checkParameters("cineMoveEntity", 5);
488
489 lua_pop(L, 5);
490 g_hdb->_ai->cineMoveEntity(entName, (int)x, (int)y, (int)level, (int)speed);
491 return 0;
492 }
493
cineAnimEntity(lua_State * L)494 static int cineAnimEntity(lua_State *L) {
495 const char *entName = lua_tostring(L, 1);
496 double state = lua_tonumber(L, 2);
497 double loop = lua_tonumber(L, 3);
498
499 g_hdb->_lua->checkParameters("cineAnimEntity", 3);
500
501 lua_pop(L, 3);
502 int s = (int)state;
503 g_hdb->_ai->cineAnimEntity(entName, (AIState)s, (int)loop);
504 return 0;
505 }
506
cineSetAnimFrame(lua_State * L)507 static int cineSetAnimFrame(lua_State *L) {
508 const char *entName = lua_tostring(L, 1);
509 double state = lua_tonumber(L, 2);
510 double frame = lua_tonumber(L, 3);
511
512 g_hdb->_lua->checkParameters("cineSetAnimFrame", 3);
513
514 lua_pop(L, 3);
515 int s = (int)state;
516 g_hdb->_ai->cineSetAnimFrame(entName, (AIState)s, (int)frame);
517 return 0;
518 }
519
cineDialog(lua_State * L)520 static int cineDialog(lua_State *L) {
521 const char *title = lua_tostring(L, 1);
522 const char *string = lua_tostring(L, 2);
523 double seconds = lua_tonumber(L, 3);
524
525 g_hdb->_lua->checkParameters("cineDialog", 3);
526
527 lua_pop(L, 3);
528 g_hdb->_ai->cineDialog(title, string, (int)seconds);
529 return 0;
530 }
531
cineDrawPic(lua_State * L)532 static int cineDrawPic(lua_State *L) {
533 const char *id = lua_tostring(L, 1);
534 const char *pic = lua_tostring(L, 2);
535 double x = lua_tonumber(L, 3);
536 double y = lua_tonumber(L, 4);
537
538 g_hdb->_lua->checkParameters("cineDrawPic", 4);
539
540 x += g_hdb->_lua->_cameraXOff;
541 y += g_hdb->_lua->_cameraYOff;
542
543 lua_pop(L, 4);
544 g_hdb->_ai->cineDrawPic(id, pic, (int)x, (int)y);
545
546 return 0;
547 }
548
cineDrawMaskedPic(lua_State * L)549 static int cineDrawMaskedPic(lua_State *L) {
550 const char *id = lua_tostring(L, 1);
551 const char *pic = lua_tostring(L, 2);
552 double x = lua_tonumber(L, 3);
553 double y = lua_tonumber(L, 4);
554
555 g_hdb->_lua->checkParameters("cineDrawMaskedPic", 4);
556
557 x += g_hdb->_lua->_cameraXOff;
558 y += g_hdb->_lua->_cameraYOff;
559
560 lua_pop(L, 4);
561 g_hdb->_ai->cineDrawMaskedPic(id, pic, (int)x, (int)y);
562
563 return 0;
564 }
565
cineMovePic(lua_State * L)566 static int cineMovePic(lua_State *L) {
567 const char *id = lua_tostring(L, 1);
568 const char *pic = lua_tostring(L, 2);
569 double x1 = lua_tonumber(L, 3);
570 double y1 = lua_tonumber(L, 4);
571 double x2 = lua_tonumber(L, 5);
572 double y2 = lua_tonumber(L, 6);
573 double speed = lua_tonumber(L, 7);
574
575 g_hdb->_lua->checkParameters("cineMovePic", 7);
576
577 x1 += g_hdb->_lua->_cameraXOff;
578 y1 += g_hdb->_lua->_cameraYOff;
579 x2 += g_hdb->_lua->_cameraXOff;
580 y2 += g_hdb->_lua->_cameraYOff;
581
582 lua_pop(L, 7);
583
584 g_hdb->_ai->cineMovePic(id, pic, (int)x1, (int)y1, (int)x2, (int)y2, (int)speed);
585
586 return 0;
587 }
588
cineMoveMaskedPic(lua_State * L)589 static int cineMoveMaskedPic(lua_State *L) {
590 const char *id = lua_tostring(L, 1);
591 const char *pic = lua_tostring(L, 2);
592 double x1 = lua_tonumber(L, 3);
593 double y1 = lua_tonumber(L, 4);
594 double x2 = lua_tonumber(L, 5);
595 double y2 = lua_tonumber(L, 6);
596 double speed = lua_tonumber(L, 7);
597
598 g_hdb->_lua->checkParameters("cineMoveMaskedPic", 7);
599
600 x1 += g_hdb->_lua->_cameraXOff;
601 y1 += g_hdb->_lua->_cameraYOff;
602 x2 += g_hdb->_lua->_cameraXOff;
603 y2 += g_hdb->_lua->_cameraYOff;
604
605 lua_pop(L, 7);
606
607 g_hdb->_ai->cineMoveMaskedPic(id, pic, (int)x1, (int)y1, (int)x2, (int)y2, (int)speed);
608
609 return 0;
610 }
611
cineSpawnEntity(lua_State * L)612 static int cineSpawnEntity(lua_State *L) {
613 double type = lua_tonumber( L, 1 );
614 double dir = lua_tonumber( L, 2 );
615 double x = lua_tonumber( L, 3 );
616 double y = lua_tonumber( L, 4 );
617 const char *func_init = lua_tostring( L, 5 );
618 const char *func_action = lua_tostring( L, 6 );
619 const char *func_use = lua_tostring( L, 7 );
620 double dir2 = lua_tonumber( L, 8 );
621 double level = lua_tonumber( L, 9 );
622 double value1 = lua_tonumber( L, 10 );
623 double value2 = lua_tonumber( L, 11 );
624
625 int t = (int) type;
626 int d = (int) dir;
627 int d2 = (int) dir2;
628
629 g_hdb->_lua->checkParameters("Cine_SpawnEntity", 11);
630
631 lua_pop(L, 11);
632 g_hdb->_ai->cineSpawnEntity((AIType)t, (AIDir)d, (int)x, (int)y, func_init, func_action, func_use,
633 (AIDir)d2, (int)level, (int)value1, (int)value2);
634 return 0;
635 }
636
cineClearForeground(lua_State * L)637 static int cineClearForeground(lua_State *L) {
638 double x = lua_tonumber(L, 1);
639 double y = lua_tonumber(L, 2);
640
641 g_hdb->_lua->checkParameters("cineClearForeground", 2);
642
643 lua_pop(L, 2);
644 g_hdb->_ai->cineClearForeground((int)x, (int)y);
645 return 0;
646 }
647
cineSetForeground(lua_State * L)648 static int cineSetForeground(lua_State *L) {
649 double x = lua_tonumber(L, 1);
650 double y = lua_tonumber(L, 2);
651 const char *tileName = lua_tostring(L, 3);
652
653 g_hdb->_lua->checkParameters("cineSetForeground", 3);
654
655 lua_pop(L, 3);
656 int index = g_hdb->_gfx->getTileIndex(tileName);
657 g_hdb->_gfx->getTile(index);
658 g_hdb->_ai->cineSetForeground((int)x, (int)y, index);
659 return 0;
660 }
661
cineSetBackground(lua_State * L)662 static int cineSetBackground(lua_State *L) {
663 double x = lua_tonumber(L, 1);
664 double y = lua_tonumber(L, 2);
665 const char *tileName = lua_tostring(L, 3);
666
667 g_hdb->_lua->checkParameters("cineSetBackground", 3);
668
669 lua_pop(L, 3);
670 int index = g_hdb->_gfx->getTileIndex(tileName);
671 g_hdb->_gfx->getTile(index);
672 g_hdb->_ai->cineSetBackground((int)x, (int)y, index);
673 return 0;
674 }
675
cineFunction(lua_State * L)676 static int cineFunction(lua_State *L) {
677 const char *func = lua_tostring(L, 1);
678
679 g_hdb->_lua->checkParameters("cineFunction", 1);
680
681 lua_pop(L, 1);
682
683 g_hdb->_ai->cineFunction(func);
684
685 return 0;
686 }
687
cineEntityFace(lua_State * L)688 static int cineEntityFace(lua_State *L) {
689 const char *luaName = lua_tostring(L, 1);
690 double dir = lua_tonumber(L, 2);
691
692 g_hdb->_lua->checkParameters("CineEntityFace", 2);
693
694 lua_pop(L, 2);
695 g_hdb->_ai->cineEntityFace(luaName, dir);
696 return 0;
697 }
698
cineTextOut(lua_State * L)699 static int cineTextOut(lua_State *L) {
700 const char *string = lua_tostring(L, 1);
701 double x = lua_tonumber(L, 2);
702 double y = lua_tonumber(L, 3);
703 double timer = lua_tonumber(L, 4);
704
705 g_hdb->_lua->checkParameters("cineTextOut", 4);
706
707 x += g_hdb->_lua->_cameraXOff;
708 y += g_hdb->_lua->_cameraYOff;
709
710 lua_pop(L, 4);
711 g_hdb->_ai->cineTextOut(string, (int)x, (int)y, (int)timer);
712 return 0;
713 }
714
cineCenterTextOut(lua_State * L)715 static int cineCenterTextOut(lua_State *L) {
716 const char *string = lua_tostring(L, 1);
717 double y = lua_tonumber(L, 2);
718 double timer = lua_tonumber(L, 3);
719
720 g_hdb->_lua->checkParameters("cineCenterTextOut", 3);
721
722 y += g_hdb->_lua->_cameraYOff;
723
724 lua_pop(L, 3);
725 g_hdb->_ai->cineCenterTextOut(string, (int)y, (int)timer);
726 return 0;
727 }
728
newDelivery(lua_State * L)729 static int newDelivery(lua_State *L) {
730 const char *itemTextName = lua_tostring(L, 1);
731 const char *itemGfxName = lua_tostring(L, 2);
732 const char *destTextName = lua_tostring(L, 3);
733 const char *destGfxName = lua_tostring(L, 4);
734 const char *id = lua_tostring(L, 5);
735
736 g_hdb->_lua->checkParameters("newDelivery", 5);
737
738 lua_pop(L, 5);
739
740 g_hdb->_ai->newDelivery(itemTextName, itemGfxName, destTextName, destGfxName, id);
741
742 return 0;
743 }
744
completeDelivery(lua_State * L)745 static int completeDelivery(lua_State *L) {
746 const char *id = lua_tostring(L, 1);
747 double rtn = g_hdb->_ai->completeDelivery(id);
748
749 g_hdb->_lua->checkParameters("completeDelivery", 1);
750
751 lua_pop(L, 1);
752 lua_pushnumber(L, rtn);
753 return 1;
754 }
755
deliveriesLeft(lua_State * L)756 static int deliveriesLeft(lua_State *L) {
757 double value = (double)g_hdb->_ai->getDeliveriesAmount();
758 lua_pushnumber(L, value);
759 return 1;
760 }
761
getEntityXY(lua_State * L)762 static int getEntityXY(lua_State *L) {
763 const char *initName = lua_tostring(L, 1);
764
765 g_hdb->_lua->checkParameters("getEntityXY", 1);
766
767 lua_pop(L, 1);
768
769 int x, y;
770 g_hdb->_ai->getEntityXY(initName, &x, &y);
771
772 lua_pushnumber(L, x);
773 lua_pushnumber(L, y);
774 return 2;
775 }
776
setEntity(lua_State * L)777 static int setEntity(lua_State *L) {
778 const char *entName = lua_tostring(L, 1);
779 double x = lua_tonumber(L, 2);
780 double y = lua_tonumber(L, 3);
781 double level = lua_tonumber(L, 4);
782
783 g_hdb->_lua->checkParameters("setEntity", 4);
784
785 lua_pop(L, 4);
786 AIEntity *e = g_hdb->_ai->locateEntity(entName);
787 if (e) {
788 e->x = (int)x * kTileWidth;
789 e->tileX = (int)x;
790 e->y = (int)y * kTileHeight;
791 e->tileY = (int)y;
792 e->level = (int)level;
793 e->goalX = e->goalY = e->xVel = e->yVel = 0;
794 e->state = STATE_STANDDOWN;
795 } else {
796 warning("Couldn't SetEntity on '%s'", entName);
797 }
798 return 0;
799 }
800
setEntDir(lua_State * L)801 static int setEntDir(lua_State *L) {
802 const char *entName = lua_tostring(L, 1);
803 double d = lua_tonumber(L, 2);
804
805 g_hdb->_lua->checkParameters("setEntDir", 2);
806
807 lua_pop(L, 2);
808 AIEntity *e = g_hdb->_ai->locateEntity(entName);
809
810 if (e) {
811 int dd = (int)d;
812 e->dir = (AIDir)dd;
813 } else {
814 Common::String entMessageString = Common::String::format("Could not SetEntDir on '%s'", entName);
815 g_hdb->_window->openMessageBar(entMessageString.c_str(), 10);
816 }
817
818 return 0;
819 }
820
removeEntity(lua_State * L)821 static int removeEntity(lua_State *L) {
822 const char *entName = lua_tostring(L, 1);
823
824 g_hdb->_lua->checkParameters("removeEntity", 1);
825
826 lua_pop(L, 1);
827
828 g_hdb->_ai->removeLuaEntity(entName);
829
830 return 0;
831 }
832
animEntity(lua_State * L)833 static int animEntity(lua_State *L) {
834 const char *entName = lua_tostring(L, 1);
835 double state = lua_tonumber(L, 2);
836
837 g_hdb->_lua->checkParameters("animEntity", 2);
838
839 lua_pop(L, 2);
840 int s = (int)state;
841 g_hdb->_ai->animLuaEntity(entName, (AIState)s);
842 return 0;
843 }
844
setAnimFrame(lua_State * L)845 static int setAnimFrame(lua_State *L) {
846 const char *entName = lua_tostring(L, 1);
847 double state = lua_tonumber(L, 2);
848 double frame = lua_tonumber(L, 3);
849
850 g_hdb->_lua->checkParameters("setAnimFrame", 3);
851
852 lua_pop(L, 3);
853
854 int s = (int)state;
855 g_hdb->_ai->setLuaAnimFrame(entName, (AIState)s, (int)frame);
856
857 return 0;
858 }
859
useEntity(lua_State * L)860 static int useEntity(lua_State *L) {
861 const char *initName = lua_tostring(L, 1);
862
863 g_hdb->_lua->checkParameters("useEntity", 1);
864
865 lua_pop(L, 1);
866
867 g_hdb->_ai->useLuaEntity(initName);
868
869 return 0;
870 }
871
entityFace(lua_State * L)872 static int entityFace(lua_State *L) {
873 const char *initName = lua_tostring(L, 1);
874 double dir = lua_tonumber(L, 2);
875
876 g_hdb->_lua->checkParameters("entityFace", 2);
877
878 lua_pop(L, 2);
879
880 g_hdb->_ai->entityFace(initName, (int)dir);
881
882 return 0;
883 }
884
clearForeground(lua_State * L)885 static int clearForeground(lua_State *L) {
886 double x = lua_tonumber(L, 1);
887 double y = lua_tonumber(L, 2);
888
889 g_hdb->_lua->checkParameters("clearForegnd", 2);
890
891 lua_pop(L, 2);
892
893 g_hdb->_map->setMapFGTileIndex((int)x, (int)y, -1);
894 g_hdb->_map->removeFGTileAnimation((int)x, (int)y);
895
896 return 0;
897 }
898
setForeground(lua_State * L)899 static int setForeground(lua_State *L) {
900 double x = lua_tonumber(L, 1);
901 double y = lua_tonumber(L, 2);
902 const char *tileName = lua_tostring(L, 3);
903
904 g_hdb->_lua->checkParameters("setForeground", 3);
905
906 lua_pop(L, 3);
907 int index = g_hdb->_gfx->getTileIndex(tileName);
908 g_hdb->_gfx->getTile(index);
909 g_hdb->_map->setMapFGTileIndex((int)x, (int)y, index);
910 g_hdb->_map->addFGTileAnimation((int)x, (int)y);
911 return 0;
912 }
913
setBackground(lua_State * L)914 static int setBackground(lua_State *L) {
915 double x = lua_tonumber(L, 1);
916 double y = lua_tonumber(L, 2);
917 const char *tileName = lua_tostring(L, 3);
918
919 g_hdb->_lua->checkParameters("setBackground", 3);
920
921 lua_pop(L, 3);
922 int index = g_hdb->_gfx->getTileIndex(tileName);
923 g_hdb->_gfx->getTile(index);
924 g_hdb->_map->setMapBGTileIndex((int)x, (int)y, index);
925 g_hdb->_map->addBGTileAnimation((int)x, (int)y);
926 return 0;
927 }
928
dialog(lua_State * L)929 static int dialog(lua_State *L) {
930 const char *title = lua_tostring(L, 1);
931 double tileIndex = lua_tonumber(L, 2);
932 const char *string = lua_tostring(L, 3);
933 const char *more = lua_tostring(L, 4);
934
935 if (!more || more[0] == '0')
936 more = nullptr;
937
938 g_hdb->_lua->checkParameters("dialog", 4);
939
940 lua_pop(L, 4);
941 if (string)
942 g_hdb->_window->openDialog(title, (int)tileIndex, string, more ? 1 : 0, more);
943 return 0;
944 }
945
dialogChoice(lua_State * L)946 static int dialogChoice(lua_State *L) {
947 const char *title = lua_tostring(L, 1);
948 const char *text = lua_tostring(L, 2);
949 const char *func = lua_tostring(L, 3);
950 const char *choice[10] = {0,0,0,0,0,0,0,0,0,0};
951
952 int amount = lua_gettop(L) - 3;
953 if (amount > 9)
954 amount = 9;
955
956 for (int i = 0; i < amount; i++)
957 choice[i] = lua_tostring(L, 4 + i);
958
959 lua_pop(L, amount + 3);
960
961 g_hdb->_window->openDialogChoice(title, text, func, amount, &choice[0]);
962 return 0;
963 }
964
message(lua_State * L)965 static int message(lua_State *L) {
966 const char *title = lua_tostring(L, 1);
967 double delay = lua_tonumber(L, 2);
968
969 g_hdb->_lua->checkParameters("message", 2);
970
971 lua_pop(L, 2);
972
973 g_hdb->_window->openMessageBar(title, (int)delay);
974 return 0;
975 }
976
animation(lua_State * L)977 static int animation(lua_State *L) {
978 double x = lua_tonumber(L, 1);
979 double y = lua_tonumber(L, 2);
980 double which = lua_tonumber(L, 3);
981 double playsnd = lua_tonumber(L, 4);
982
983 g_hdb->_lua->checkParameters("animation", 4);
984
985 x *= kTileWidth;
986 y *= kTileHeight;
987
988 switch ((int)which) {
989 case 0:
990 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 3, ANIM_NORMAL, false, false, GROUP_WATER_SPLASH_SIT);
991 if (playsnd)
992 g_hdb->_sound->playSound(SND_SPLASH);
993 break;
994 case 1:
995 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
996 if (!g_hdb->isDemo())
997 if (playsnd)
998 g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
999 break;
1000 case 2:
1001 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 3, ANIM_FAST, false, false, GROUP_STEAM_PUFF_SIT);
1002 if (!g_hdb->isDemo())
1003 if (playsnd)
1004 g_hdb->_sound->playSound(SND_BARREL_MELTING);
1005 break;
1006 case 3:
1007 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 7, ANIM_NORMAL, false, false, TELEPORT_FLASH);
1008 if (playsnd)
1009 g_hdb->_sound->playSound(SND_TELEPORT);
1010 break;
1011 case 4:
1012 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
1013 if (playsnd)
1014 g_hdb->_sound->playSound(SND_GET_GEM);
1015 break;
1016 case 5:
1017 g_hdb->_ai->addAnimateTarget((int)x, (int)y, 0, 2, ANIM_NORMAL, false, false, GROUP_ENT_CHICKEN_DIE);
1018 if (playsnd)
1019 g_hdb->_sound->playSound(SND_CHICKEN_DEATH);
1020 break;
1021 default:
1022 break;
1023 }
1024
1025 lua_pop(L, 3);
1026 return 0;
1027 }
1028
spawnEntity(lua_State * L)1029 static int spawnEntity(lua_State *L) {
1030 double type = lua_tonumber(L, 1);
1031 double dir = lua_tonumber(L, 2);
1032 double x = lua_tonumber(L, 3);
1033 double y = lua_tonumber(L, 4);
1034 const char *funcInit = lua_tostring(L, 5);
1035 const char *funcAction = lua_tostring(L, 6);
1036 const char *funcUse = lua_tostring(L, 7);
1037 double dir2 = lua_tonumber(L, 8);
1038 double level = lua_tonumber(L, 9);
1039 double value1 = lua_tonumber(L, 10);
1040 double value2 = lua_tonumber(L, 11);
1041
1042 int t = (int)type;
1043 int d = (int)dir;
1044 int d2 = (int)dir2;
1045
1046 g_hdb->_lua->checkParameters("spawnEntity", 11);
1047
1048 lua_pop(L, 11);
1049
1050 g_hdb->_ai->spawn((AIType)t, (AIDir)d, (int)x, (int)y, funcInit, funcAction, funcUse, (AIDir)d2, (int)level, (int)value1, (int)value2, 1);
1051 return 0;
1052 }
1053
addInvItem(lua_State * L)1054 static int addInvItem(lua_State *L) {
1055 double type = lua_tonumber(L, 1);
1056 double amount = lua_tonumber(L, 2);
1057 const char *funcInit = lua_tostring(L, 3);
1058 const char *funcAction = lua_tostring(L, 4);
1059 const char *funcUse = lua_tostring(L, 5);
1060
1061 int t = (int)type;
1062
1063 g_hdb->_lua->checkParameters("addInvItem", 5);
1064
1065 lua_pop(L, 5);
1066
1067 bool rtn = g_hdb->_ai->addItemToInventory((AIType)t, (int)amount, funcInit, funcAction, funcUse);
1068
1069 lua_pushnumber(L, rtn);
1070 return 1;
1071 }
1072
keepInvItem(lua_State * L)1073 static int keepInvItem(lua_State *L) {
1074 double type = lua_tonumber(L, 1);
1075 int t = (int)type;
1076
1077 g_hdb->_lua->checkParameters("keepInvItem", 1);
1078
1079 lua_pop(L, 1);
1080
1081 g_hdb->_ai->keepInvItem((AIType)t);
1082 return 0;
1083 }
1084
queryInv(lua_State * L)1085 static int queryInv(lua_State *L) {
1086 // get the passed-in search string
1087 const char *search = lua_tostring(L, 1);
1088
1089 g_hdb->_lua->checkParameters("queryInv", 1);
1090
1091 lua_pop(L, 1);
1092
1093 // call the function & get return value
1094 int result = g_hdb->_ai->queryInventory(search);
1095 // send the return value back to Lua
1096 lua_pushnumber(L, result);
1097 return 1;
1098 }
1099
purgeInv(lua_State * L)1100 static int purgeInv(lua_State *L) {
1101 g_hdb->_ai->purgeInventory();
1102 return 0;
1103 }
1104
queryInvItem(lua_State * L)1105 static int queryInvItem(lua_State *L) {
1106 // get the passed-in search string
1107 double search = lua_tonumber(L, 1);
1108 int s1 = (int)search;
1109
1110 g_hdb->_lua->checkParameters("queryInvItem", 1);
1111
1112 lua_pop(L, 1);
1113
1114 // call the function & get return value
1115 int result = g_hdb->_ai->queryInventoryType((AIType)s1);
1116 // send the return value back to Lua
1117 lua_pushnumber(L, result);
1118 return 1;
1119 }
1120
removeInv(lua_State * L)1121 static int removeInv(lua_State *L) {
1122 // get the passed-in search string
1123 const char *search = lua_tostring(L, 1);
1124 double number = lua_tonumber(L, 2);
1125
1126 g_hdb->_lua->checkParameters("removeInv", 2);
1127
1128 lua_pop(L, 2);
1129
1130 // call the function & get return value
1131 int result = (int)g_hdb->_ai->removeInvItem(search, (int)number);
1132 // send the return value back to Lua
1133 lua_pushnumber(L, result);
1134 return 1;
1135 }
1136
removeInvItem(lua_State * L)1137 static int removeInvItem(lua_State *L) {
1138 // get the passed-in type value
1139 double search = lua_tonumber(L, 1);
1140 double number = lua_tonumber(L, 2);
1141
1142 g_hdb->_lua->checkParameters("removeInvItem", 2);
1143
1144 lua_pop(L, 2);
1145
1146 int s = (int)search;
1147 // call the function & get return value
1148 int result = (int)g_hdb->_ai->removeInvItemType((AIType)s, (int)number);
1149 // send the return value back to Lua
1150 lua_pushnumber(L, result);
1151 return 1;
1152 }
1153
killTrigger(lua_State * L)1154 static int killTrigger(lua_State *L) {
1155 const char *id = lua_tostring(L, 1);
1156
1157 g_hdb->_lua->checkParameters("killTrigger", 1);
1158
1159 lua_pop(L, 1);
1160 g_hdb->_ai->killTrigger(id);
1161 return 0;
1162 }
1163
startMusic(lua_State * L)1164 static int startMusic(lua_State *L) {
1165 double song = lua_tonumber(L, 1);
1166 int s1 = (int)song;
1167
1168 g_hdb->_lua->checkParameters("startMusic", 1);
1169
1170 lua_pop(L, 1);
1171 g_hdb->_sound->startMusic((SoundType)s1);
1172
1173 return 0;
1174 }
1175
fadeInMusic(lua_State * L)1176 static int fadeInMusic(lua_State *L) {
1177 double song = lua_tonumber(L, 1);
1178 int s1 = (int)song;
1179 int ramp = (int)lua_tonumber(L, 2);
1180 if (!ramp)
1181 ramp = 1;
1182
1183 g_hdb->_lua->checkParameters("fadeInMusic", 2);
1184
1185 lua_pop(L, 2);
1186 g_hdb->_sound->fadeInMusic((SoundType)s1, ramp);
1187
1188 return 0;
1189 }
1190
stopMusic(lua_State * L)1191 static int stopMusic(lua_State *L) {
1192 g_hdb->_sound->stopMusic();
1193 return 0;
1194 }
1195
fadeOutMusic(lua_State * L)1196 static int fadeOutMusic(lua_State *L) {
1197 int ramp = (int)lua_tonumber(L, 1);
1198 if (!ramp)
1199 ramp = 1;
1200
1201 g_hdb->_lua->checkParameters("fadeOutMusic", 1);
1202
1203 lua_pop(L, 1);
1204 g_hdb->_sound->fadeOutMusic(ramp);
1205
1206 return 0;
1207 }
1208
registerSound(lua_State * L)1209 static int registerSound(lua_State *L) {
1210 const char *name = lua_tostring(L, 1);
1211
1212 g_hdb->_lua->checkParameters("registerSound", 1);
1213
1214 lua_pop(L, 1);
1215 int index = g_hdb->_sound->registerSound(name);
1216 lua_pushnumber(L, index);
1217
1218 return 1;
1219 }
1220
playSound(lua_State * L)1221 static int playSound(lua_State *L) {
1222 int index = (int)lua_tonumber(L, 1);
1223
1224 g_hdb->_lua->checkParameters("playSound", 1);
1225
1226 lua_pop(L, 1);
1227 g_hdb->_sound->playSound(index);
1228
1229 return 0;
1230 }
1231
freeSound(lua_State * L)1232 static int freeSound(lua_State *L) {
1233 int index = (int)lua_tonumber(L, 1);
1234
1235 g_hdb->_lua->checkParameters("freeSound", 1);
1236
1237 lua_pop(L, 1);
1238 g_hdb->_sound->freeSound(index);
1239
1240 return 0;
1241 }
1242
startMap(lua_State * L)1243 static int startMap(lua_State *L) {
1244 const char *string = lua_tostring(L, 1);
1245
1246 g_hdb->_lua->checkParameters("startMap", 1);
1247
1248 lua_pop(L, 1);
1249 g_hdb->changeLevel(string);
1250
1251 return 0;
1252 }
1253
saveGlobal(lua_State * L)1254 static int saveGlobal(lua_State *L) {
1255 const char *global = lua_tostring(L, 1);
1256
1257 g_hdb->_lua->checkParameters("saveGlobal", 1);
1258
1259 lua_pop(L, 1);
1260
1261 lua_getglobal(L, global);
1262 int type = lua_type(L, 1);
1263 if (type == LUA_TNUMBER) {
1264 double value = lua_tonumber(L, 1);
1265 g_hdb->_lua->saveGlobalNumber(global, value);
1266 } else if (type == LUA_TSTRING) {
1267 const char *string = lua_tostring(L, 1);
1268 g_hdb->_lua->saveGlobalString(global, string);
1269 }
1270
1271 return 0;
1272 }
1273
loadGlobal(lua_State * L)1274 static int loadGlobal(lua_State *L) {
1275 const char *global = lua_tostring(L, 1);
1276
1277 g_hdb->_lua->checkParameters("loadGlobal", 1);
1278
1279 lua_pop(L, 1);
1280
1281 g_hdb->_lua->loadGlobal(global);
1282
1283 return 0;
1284 }
1285
purgeGlobals(lua_State * L)1286 static int purgeGlobals(lua_State *L) {
1287 g_hdb->_lua->purgeGlobals();
1288 return 0;
1289 }
1290
textOut(lua_State * L)1291 static int textOut(lua_State *L) {
1292 const char *string = lua_tostring(L, 1);
1293 double x = lua_tonumber(L, 2);
1294 double y = lua_tonumber(L, 3);
1295 double timer = lua_tonumber(L, 4);
1296
1297 g_hdb->_lua->checkParameters("textOut", 4);
1298
1299 lua_pop(L, 4);
1300 g_hdb->_window->textOut(string, (int)x, (int)y, (int)timer);
1301 return 0;
1302 }
1303
centerTextOut(lua_State * L)1304 static int centerTextOut(lua_State *L) {
1305 const char *string = lua_tostring(L, 1);
1306 double y = lua_tonumber(L, 2);
1307 double timer = lua_tonumber(L, 3);
1308
1309 g_hdb->_lua->checkParameters("centerTextOut", 3);
1310
1311 lua_pop(L, 3);
1312 g_hdb->_window->centerTextOut(string, (int)y, (int)timer);
1313 return 0;
1314 }
1315
turnOnSnow(lua_State * L)1316 static int turnOnSnow(lua_State *L) {
1317 g_hdb->_gfx->turnOnSnow();
1318 return 0;
1319 }
1320
turnOffSnow(lua_State * L)1321 static int turnOffSnow(lua_State *L) {
1322 g_hdb->_gfx->turnOffSnow();
1323 return 0;
1324 }
1325
gotoMenu(lua_State * L)1326 static int gotoMenu(lua_State *L) {
1327 g_hdb->changeGameState();
1328 return 0;
1329 }
1330
setInfobarDark(lua_State * L)1331 static int setInfobarDark(lua_State *L) {
1332 double value = lua_tonumber(L, 1);
1333
1334 g_hdb->_lua->checkParameters("setInfobarDark", 1);
1335
1336 lua_pop(L, 1);
1337
1338 g_hdb->_window->setInfobarDark((int)value);
1339
1340 return 0;
1341 }
1342
setPointerState(lua_State * L)1343 static int setPointerState(lua_State *L) {
1344 double value = lua_tonumber(L, 1);
1345
1346 g_hdb->_lua->checkParameters("setPointerState", 1);
1347
1348 lua_pop(L, 1);
1349
1350 g_hdb->_gfx->setPointerState((int)value);
1351 return 0;
1352 }
1353
playVoice(lua_State * L)1354 static int playVoice(lua_State *L) {
1355 double index = lua_tonumber(L, 1);
1356 double actor = lua_tonumber(L, 2);
1357
1358 g_hdb->_lua->checkParameters("playVoice", 2);
1359
1360 lua_pop(L, 2);
1361
1362 g_hdb->_sound->playVoice((int)index, (int)actor);
1363 return 0;
1364 }
1365
openFile(lua_State * L)1366 static int openFile(lua_State *L) {
1367 g_hdb->_lua->checkParameters("openFile", 2);
1368
1369 lua_pop(L, 2); // drop 2 parameters
1370
1371 lua_pushlightuserdata(L, 0);
1372
1373 return 1;
1374 }
1375
writeto(lua_State * L)1376 static int writeto(lua_State *L) {
1377 g_hdb->_lua->checkParameters("writeto", 1);
1378
1379 lua_pop(L, 1);
1380
1381 return 1;
1382 }
1383
write(lua_State * L)1384 static int write(lua_State *L) {
1385 Common::OutSaveFile *out = g_hdb->_currentOutSaveFile;
1386 const char *data;
1387
1388 if (g_hdb->isDemo() && g_hdb->isPPC()) {
1389 data = lua_tostring(L, 1);
1390
1391 g_hdb->_lua->checkParameters("write", 1);
1392
1393 lua_pop(L, 1);
1394 } else {
1395 data = lua_tostring(L, 2);
1396
1397 g_hdb->_lua->checkParameters("write", 2);
1398
1399 lua_pop(L, 2);
1400 }
1401
1402 out->write(data, strlen(data));
1403
1404 return 0;
1405 }
1406
closeFile(lua_State * L)1407 static int closeFile(lua_State *L) {
1408 g_hdb->_lua->checkParameters("closeFile", 1);
1409
1410 lua_pop(L, 1);
1411
1412 // No op
1413
1414 return 0;
1415 }
1416
dofile(lua_State * L)1417 static int dofile(lua_State *L) {
1418 g_hdb->_lua->checkParameters("dofile", 1);
1419
1420 lua_pop(L, 1);
1421
1422 Common::InSaveFile *in = g_hdb->_currentInSaveFile;
1423
1424 int length = in->size() - in->pos();
1425 char *chunk = new char[length + 1];
1426 in->read((void *)chunk, length);
1427
1428 chunk[length] = '\0'; // be on the safe side
1429
1430 Common::String chunkString(chunk);
1431 delete[] chunk;
1432
1433 if (!g_hdb->_lua->executeChunk(chunkString, "saveState")) {
1434 return 0;
1435 }
1436
1437 return 0;
1438 }
1439
1440 /*
1441 Lua Initialization Code
1442 */
1443
1444 struct VarInit {
1445 const char *realName;
1446 const char *luaName;
1447 } luaGlobalStrings[] = {
1448 { "Map00", "MAP00"},
1449 { TILE_TELEPORT1, "TILE_TELEPORT1" },
1450 { TILE_SKY_STARS, "TILE_SKY_STARS" },
1451 { TILE_HOLDER1, "TILE_HOLDER1" },
1452 { TILE_HOLDERFULL, "TILE_HOLDERFULL" },
1453 { TILE_SWITCH1, "TILE_SWITCH1" },
1454 { TILE_1SWITCH1, "TILE_1SWITCH1" },
1455 { TILE_DOOR_N, "TILE_DOOR_N" },
1456 { TILE_DOOR_P, "TILE_DOOR_P" },
1457 { TILE_DOOR_S, "TILE_DOOR_S" },
1458 { TILE_ASKCOMP1, "TILE_ASKCOMP1" },
1459 { TILE_SWITCH_ON, "TILE_SWITCH_ON" },
1460 { TILE_1SWITCH_ON, "TILE_1SWITCH_ON" },
1461 { TILE_FLOORSHOCK, "TILE_FLOORSHOCK" },
1462 { TILE_DOOR_NV, "TILE_DOOR_NV" },
1463 { TILE_DOOR_PV, "TILE_DOOR_PV" },
1464 { TILE_DOOR_SV, "TILE_DOOR_SV" },
1465 { TILE_MAILSORT, "TILE_MAILSORT" },
1466 { TILE_BEDR_OPEN, "TILE_BEDR_OPEN" },
1467 { TILE_BEDL_OPEN, "TILE_BEDL_OPEN" },
1468 { TILE_BEDR_CLOSED, "TILE_BEDR_CLOSED" },
1469 { TILE_BEDL_CLOSED, "TILE_BEDL_CLOSED" },
1470 { TILE_FERRET, "TILE_FERRET" },
1471 { TILE_CABOPEN_T, "TILE_CABOPEN_T" },
1472 { TILE_CABOPEN_B, "TILE_CABOPEN_B" },
1473 { GROUP_ENT_ENVELOPE_WHITE_SIT"01", "TILE_ENV_WHITE" },
1474 { GROUP_ENT_ENVELOPE_BLUE_SIT"01", "TILE_ENV_BLUE" },
1475 { GROUP_ENT_ENVELOPE_RED_SIT"01", "TILE_ENV_RED" },
1476 { GROUP_ENT_ENVELOPE_GREEN_SIT"01", "TILE_ENV_GREEN" },
1477 { GROUP_ENT_TRANSCEIVER_SIT"01", "TILE_TRANSCEIVER" },
1478 { TILE_HEAD_SCIENTIST, "TILE_HEAD_SCIENTIST" },
1479 { TILE_HEAD_SPACEDUDE, "TILE_HEAD_SPACEDUDE" },
1480 { TILE_HEAD_WORKER, "TILE_HEAD_WORKER" },
1481 { TILE_HEAD_ACCOUNTANT, "TILE_HEAD_ACCOUNTANT" },
1482 { TILE_HEAD_DOLLY, "TILE_HEAD_DOLLY" },
1483 { TILE_HEAD_SARGE, "TILE_HEAD_SARGE" },
1484 { TILE_BTUNNEL_BLOCK_B, "TILE_BTUNNEL_BLOCK_B" },
1485 { TILE_BTUNNEL_BLOCK_L, "TILE_BTUNNEL_BLOCK_L" },
1486 { TILE_BTUNNEL_BLOCK_R, "TILE_BTUNNEL_BLOCK_R" },
1487 { TILE_BTUNNEL_BLOCK_T, "TILE_BTUNNEL_BLOCK_T" },
1488 { TILE_BTUNNEL_DONE_B, "TILE_BTUNNEL_DONE_B" },
1489 { TILE_BTUNNEL_DONE_L, "TILE_BTUNNEL_DONE_L" },
1490 { TILE_BTUNNEL_DONE_R, "TILE_BTUNNEL_DONE_R" },
1491 { TILE_BTUNNEL_DONE_T, "TILE_BTUNNEL_DONE_T" },
1492 { GROUP_ENT_ROUTER_SIT"01", "TILE_ROUTER" },
1493 { GROUP_ENT_NOTE_SIT"01", "TILE_NOTE" },
1494 { TILE_INBOX, "TILE_INBOX" },
1495 { TILE_MEMOS, "TILE_MEMOS" },
1496 { TILE_A, "TILE_A" },
1497 { TILE_B, "TILE_B" },
1498 { TILE_C, "TILE_C" },
1499 { TILE_D, "TILE_D" },
1500 { TILE_E, "TILE_E" },
1501 { TILE_F, "TILE_F" },
1502 { TILE_G, "TILE_G" },
1503 { TILE_H, "TILE_H" },
1504 { TILE_I, "TILE_I" },
1505 { TILE_J, "TILE_J" },
1506 { TILE_K, "TILE_K" },
1507 { TILE_L, "TILE_L" },
1508 { TILE_M, "TILE_M" },
1509 { TILE_N, "TILE_N" },
1510 { TILE_O, "TILE_O" },
1511 { TILE_P, "TILE_P" },
1512 { TILE_Q, "TILE_Q" },
1513 { TILE_R, "TILE_R" },
1514 { TILE_S, "TILE_S" },
1515 { TILE_T, "TILE_T" },
1516 { TILE_U, "TILE_U" },
1517 { TILE_V, "TILE_V" },
1518 { TILE_W, "TILE_W" },
1519 { TILE_X, "TILE_X" },
1520 { TILE_Y, "TILE_Y" },
1521 { TILE_Z, "TILE_Z" },
1522 { TILE_SNOWDOOR_B, "TILE_SNOWDOOR_B" },
1523 { TILE_PACKAGE, "TILE_PACKAGE" },
1524 { TILE_TYRANIUM, "TILE_TYRANIUM" },
1525 { TILE_CHAIR, "TILE_CHAIR" },
1526 { TILE_ROUTER_HOLDER, "TILE_ROUTER_HOLDER" },
1527 { TILE_PHAR_CARPET, "TILE_PHAR_CARPET" },
1528 { TILE_WASTEBASKET, "TILE_WASTEBASKET" },
1529 { TILE_PIZZA, "TILE_PIZZA" },
1530 { TILE_HEADSTATUE, "TILE_HEADSTATUE" },
1531 { TILE_SLOT_GOOD1, "TILE_SLOT_GOOD1" },
1532 { TILE_SLOT_GOOD2, "TILE_SLOT_GOOD2" },
1533 { TILE_SLOT_GOOD3, "TILE_SLOT_GOOD3" },
1534 { TILE_SLOT_GOOD4, "TILE_SLOT_GOOD4" },
1535 { TILE_SLOT_GOOD5, "TILE_SLOT_GOOD5" },
1536 { TILE_SLOT_GOOD6, "TILE_SLOT_GOOD6" },
1537 { TILE_SLOT_BAD, "TILE_SLOT_BAD" },
1538 { GEM_BLUE_GFX, "TILE_GEM_BLUE" },
1539 { GEM_RED_GFX, "TILE_GEM_RED" },
1540 { GEM_GREEN_GFX, "TILE_GEM_GREEN" },
1541 { TITLE_EPISODE1, "PIC_TITLE_EPISODE1" },
1542 { TITLE_EPISODE2, "PIC_TITLE_EPISODE2" },
1543 { TITLE_EPISODE3, "PIC_TITLE_EPISODE3" },
1544 { PIC_FROG_STATUE, "PIC_FROG_STATUE" },
1545 { PIC_JENKINS, "PIC_JENKINS" },
1546 { GEM_WHITE, "TILE_GEM_WHITE" },
1547
1548 { CINE_INTROSHIP, "PIC_CINE_INTROSHIP" },
1549 { CINE_LITTLE_MBOT, "PIC_CINE_LITTLE_MBOT" },
1550 { CINE_CLOCK, "PIC_CINE_CLOCK" },
1551 { MONKEYLOGOSCREEN, "PIC_MONKEYLOGOSCREEN" },
1552 { MONKEYLOGO_OOHOOH, "PIC_MONKEYLOGO_OOHOOH" },
1553 { MONKEYLOGO_SMILE, "PIC_MONKEYLOGO_SMILE" },
1554 { PIC_DEMOSCREEN, "PIC_DEMOSCREEN" },
1555 { PIC_DEMOSCREEN2, "PIC_DEMOSCREEN2" },
1556 { PIC_ENV_WHITE, "PIC_ENV_WHITE" },
1557 { PIC_TEAM_BRIAN, "PIC_TEAM_BRIAN" },
1558 { PIC_TEAM_STEVIE, "PIC_TEAM_STEVIE" },
1559 { PIC_TEAM_JOSH, "PIC_TEAM_JOSH" },
1560 { PIC_TEAM_TOM, "PIC_TEAM_TOM" },
1561 { PIC_TEAM_JOHN, "PIC_TEAM_JOHN" },
1562 { PIC_TEAM_LUCAS, "PIC_TEAM_LUCAS" },
1563
1564 { PIC_RANK1, "PIC_RANK1" },
1565 { PIC_RANK2, "PIC_RANK2" },
1566 { PIC_RANK3, "PIC_RANK3" },
1567 { PIC_RANK4, "PIC_RANK4" },
1568 { PIC_RANK5, "PIC_RANK5" },
1569 {nullptr, nullptr}
1570 };
1571
1572 // For AI States, to be implemented
1573 struct NumberInit {
1574 int value;
1575 const char *luaName;
1576 } luaGlobalValues[] = {
1577 { DIR_NONE, "DIR_NONE" },
1578 { DIR_DOWN, "DIR_DOWN" },
1579 { DIR_UP, "DIR_UP" },
1580 { DIR_LEFT, "DIR_LEFT" },
1581 { DIR_RIGHT, "DIR_RIGHT" },
1582
1583 { STATE_NONE, "STATE_NONE" },
1584 { STATE_STANDDOWN, "STATE_STANDDOWN" },
1585 { STATE_STANDUP, "STATE_STANDUP" },
1586 { STATE_STANDLEFT, "STATE_STANDLEFT" },
1587 { STATE_STANDRIGHT, "STATE_STANDRIGHT" },
1588 { STATE_BLINK, "STATE_BLINK" },
1589 { STATE_MOVEUP, "STATE_MOVEUP" },
1590 { STATE_MOVEDOWN, "STATE_MOVEDOWN" },
1591 { STATE_MOVELEFT, "STATE_MOVELEFT" },
1592 { STATE_MOVERIGHT, "STATE_MOVERIGHT" },
1593 { STATE_DYING, "STATE_DYING" },
1594 { STATE_DEAD, "STATE_DEAD" },
1595 { STATE_GOODJOB, "STATE_GOODJOB" },
1596 { STATE_HORRIBLE1, "STATE_HORRIBLE1" },
1597 { STATE_HORRIBLE2, "STATE_HORRIBLE2" },
1598 { STATE_HORRIBLE3, "STATE_HORRIBLE3" },
1599 { STATE_HORRIBLE4, "STATE_HORRIBLE4" },
1600 { STATE_PUSHUP, "STATE_PUSHUP" },
1601 { STATE_PUSHDOWN, "STATE_PUSHDOWN" },
1602 { STATE_PUSHLEFT, "STATE_PUSHLEFT" },
1603 { STATE_PUSHRIGHT, "STATE_PUSHRIGHT" },
1604 { STATE_GRABUP, "STATE_GRABUP" },
1605 { STATE_GRABDOWN, "STATE_GRABDOWN" },
1606 { STATE_GRABLEFT, "STATE_GRABLEFT" },
1607 { STATE_GRABRIGHT, "STATE_GRABRIGHT" },
1608 { STATE_ATK_CLUB_UP, "STATE_ATK_CLUB_UP" },
1609 { STATE_ATK_CLUB_DOWN, "STATE_ATK_CLUB_DOWN" },
1610 { STATE_ATK_CLUB_LEFT, "STATE_ATK_CLUB_LEFT" },
1611 { STATE_ATK_CLUB_RIGHT, "STATE_ATK_CLUB_RIGHT" },
1612 { STATE_ATK_STUN_DOWN, "STATE_ATK_STUN_DOWN" },
1613 { STATE_ATK_STUN_UP, "STATE_ATK_STUN_UP" },
1614 { STATE_ATK_STUN_LEFT, "STATE_ATK_STUN_LEFT" },
1615 { STATE_ATK_STUN_RIGHT, "STATE_ATK_STUN_RIGHT" },
1616 { STATE_ATK_SLUG_DOWN, "STATE_ATK_SLUG_DOWN" },
1617 { STATE_ATK_SLUG_UP, "STATE_ATK_SLUG_UP" },
1618 { STATE_ATK_SLUG_LEFT, "STATE_ATK_SLUG_LEFT" },
1619 { STATE_ATK_SLUG_RIGHT, "STATE_ATK_SLUG_RIGHT" },
1620 { STATE_FLOATING, "STATE_FLOATING" },
1621 { STATE_FLOATDOWN, "STATE_FLOATDOWN" },
1622 { STATE_FLOATUP, "STATE_FLOATUP" },
1623 { STATE_FLOATLEFT, "STATE_FLOATLEFT" },
1624 { STATE_FLOATRIGHT, "STATE_FLOATRIGHT" },
1625 { STATE_MELTED, "STATE_MELTED" },
1626 { STATE_SLIDING, "STATE_SLIDING" },
1627 { STATE_SHOCKING, "STATE_SHOCKING" },
1628 { STATE_EXPLODING, "STATE_EXPLODING" },
1629 { STATE_USEDOWN, "STATE_USEDOWN" },
1630 { STATE_USEUP, "STATE_USEUP" },
1631 { STATE_USELEFT, "STATE_USELEFT" },
1632 { STATE_USERIGHT, "STATE_USERIGHT" },
1633 { STATE_MEER_MOVE, "STATE_MEER_MOVE" },
1634 { STATE_MEER_APPEAR, "STATE_MEER_APPEAR" },
1635 { STATE_MEER_BITE, "STATE_MEER_BITE" },
1636 { STATE_MEER_DISAPPEAR, "STATE_MEER_DISAPPEAR" },
1637 { STATE_MEER_LOOK, "STATE_MEER_LOOK" },
1638 { STATE_ICEP_PEEK, "STATE_ICEP_PEEK" },
1639 { STATE_ICEP_APPEAR, "STATE_ICEP_APPEAR" },
1640 { STATE_ICEP_THROWDOWN, "STATE_ICEP_THROWDOWN" },
1641 { STATE_ICEP_THROWRIGHT,"STATE_ICEP_THROWRIGHT" },
1642 { STATE_ICEP_THROWLEFT, "STATE_ICEP_THROWLEFT" },
1643 { STATE_ICEP_DISAPPEAR, "STATE_ICEP_DISAPPEAR" },
1644 { STATE_ANGRY, "STATE_ANGRY" },
1645 { STATE_PANIC, "STATE_PANIC" },
1646 { STATE_LAUGH, "STATE_LAUGH" },
1647 { STATE_KISSLEFT, "STATE_KISSLEFT" },
1648 { STATE_KISSRIGHT, "STATE_KISSRIGHT" },
1649 { STATE_DOLLYUSERIGHT, "STATE_DOLLYUSERIGHT" },
1650 { STATE_YELL, "STATE_YELL" },
1651
1652 { STATE_NONE, nullptr }
1653 };
1654
1655 struct FuncInit {
1656 const char *luaName;
1657 int (*function) (lua_State *L);
1658 } luaFuncs[] = {
1659 { "Dialog", dialog },
1660 { "DialogChoice", dialogChoice },
1661 { "Message", message },
1662 { "QueryInv", queryInv },
1663 { "QueryInvItem", queryInvItem },
1664 { "RemoveInv", removeInv },
1665 { "RemoveInvItem", removeInvItem },
1666 { "AddInvItem", addInvItem },
1667 { "KeepInvItem", keepInvItem },
1668 { "PurgeInv", purgeInv },
1669 { "StartMusic", startMusic },
1670 { "StopMusic", stopMusic },
1671 { "FadeInMusic", fadeInMusic },
1672 { "FadeOutMusic", fadeOutMusic },
1673 { "RegisterSound", registerSound },
1674 { "PlaySound", playSound },
1675 { "FreeSound", freeSound },
1676 { "StartMap", startMap },
1677 { "Tile_ClearFG", clearForeground },
1678 { "Tile_SetFG", setForeground },
1679 { "Tile_SetBG", setBackground },
1680 { "GetEntityXY", getEntityXY },
1681 { "UseEntity", useEntity },
1682 { "SetEntity", setEntity },
1683 { "SetEntDir", setEntDir },
1684 { "RemoveEntity", removeEntity },
1685 { "AnimEntity", animEntity },
1686 { "SetAnimFrame", setAnimFrame },
1687 { "EntityFace", entityFace },
1688 { "KillTrigger", killTrigger },
1689 { "SpawnEntity", spawnEntity },
1690 { "Animation", animation },
1691 { "NewDelivery", newDelivery },
1692 { "CompleteDelivery", completeDelivery },
1693 { "DeliveriesLeft", deliveriesLeft },
1694 { "SaveGlobal", saveGlobal },
1695 { "LoadGlobal", loadGlobal },
1696 { "PurgeGlobals", purgeGlobals },
1697 { "TextOut", textOut },
1698 { "CenterTextOut", centerTextOut },
1699 { "SnowOn", turnOnSnow },
1700 { "SnowOff", turnOffSnow },
1701 { "GotoMenu", gotoMenu },
1702 { "SetInfobarDark", setInfobarDark },
1703 { "SetPointerState", setPointerState },
1704 { "PlayVoice", playVoice },
1705
1706 { "Cine_StartCine", cineStart },
1707 { "Cine_StopCine", cineStop },
1708 { "Cine_StartMap", cineStartMap },
1709 { "Cine_LockPlayer", cineLockPlayer },
1710 { "Cine_UnlockPlayer", cineUnlockPlayer },
1711 { "Cine_SetCamera", cineSetCamera },
1712 { "Cine_ResetCamera", cineResetCamera },
1713 { "Cine_MoveCamera", cineMoveCamera },
1714 { "Cine_Wait", cineWait },
1715 { "Cine_WaitUntilDone", cineWaitUntilDone },
1716 { "Cine_UseEntity", cineUseEntity },
1717 { "Cine_SetEntity", cineSetEntity },
1718 { "Cine_RemoveEntity", cineRemoveEntity },
1719 { "Cine_EntityFace", cineEntityFace },
1720 { "Cine_MoveEntity", cineMoveEntity },
1721 { "Cine_AnimEntity", cineAnimEntity },
1722 { "Cine_SetAnimFrame", cineSetAnimFrame },
1723 { "Cine_Dialog", cineDialog },
1724 { "Cine_DrawPic", cineDrawPic },
1725 { "Cine_DrawMaskedPic", cineDrawMaskedPic },
1726 { "Cine_MovePic", cineMovePic },
1727 { "Cine_MoveMaskedPic", cineMoveMaskedPic },
1728 { "Cine_FadeOutBlack", cineFadeOutBlack },
1729 { "Cine_FadeInBlack", cineFadeInBlack },
1730 { "Cine_FadeOutWhite", cineFadeOutWhite },
1731 { "Cine_FadeInWhite", cineFadeInWhite },
1732 { "Cine_SpawnEntity", cineSpawnEntity },
1733 { "Cine_PlaySound", cinePlaySound },
1734 { "Cine_Tile_ClearFG", cineClearForeground },
1735 { "Cine_Tile_SetFG", cineSetForeground },
1736 { "Cine_Tile_SetBG", cineSetBackground },
1737 { "Cine_Function", cineFunction },
1738 { "Cine_TextOut", cineTextOut },
1739 { "Cine_CenterTextOut", cineCenterTextOut },
1740 { "Cine_PlayVoice", cinePlayVoice },
1741
1742 { "openfile", openFile, },
1743 { "write", write, },
1744 { "closefile", closeFile, },
1745 { "dofile", dofile, },
1746 { "writeto", writeto, },
1747 { nullptr, nullptr }
1748 };
1749
1750 namespace {
panicCB(lua_State * L)1751 int panicCB(lua_State *L) {
1752 error("Lua panic. Error message: %s", lua_isnil(L, -1) ? "" : lua_tostring(L, -1));
1753 return 0;
1754 }
1755
debugHook(lua_State * L,lua_Debug * ar)1756 void debugHook(lua_State *L, lua_Debug *ar) {
1757 if (!lua_getinfo(L, "Sn", ar))
1758 return;
1759
1760 debug("LUA: %s %s: %s %d", ar->namewhat, ar->name, ar->short_src, ar->currentline);
1761 }
1762 }
1763
initScript(Common::SeekableReadStream * stream,const char * scriptName,int32 length)1764 bool LuaScript::initScript(Common::SeekableReadStream *stream, const char *scriptName, int32 length) {
1765 if (_state != nullptr) {
1766 lua_close(_state);
1767 }
1768
1769 // Initialize Lua Environment
1770 _state = lua_open();
1771 if (_state == nullptr) {
1772 error("Couldn't initialize Lua script.");
1773 return false;
1774 }
1775 luaL_openlibs(_state);
1776
1777 // Register Extensions
1778 for (int i = 0; luaFuncs[i].luaName; i++) {
1779 lua_register(_state, luaFuncs[i].luaName, luaFuncs[i].function);
1780 }
1781
1782 // Register Lua Globals
1783
1784 for (int i = 0; luaGlobalStrings[i].realName; i++) {
1785 lua_pushstring(_state, luaGlobalStrings[i].realName);
1786 lua_setglobal(_state, luaGlobalStrings[i].luaName);
1787 }
1788
1789 for (int j = 0; luaGlobalValues[j].luaName; j++) {
1790 lua_pushnumber(_state, luaGlobalValues[j].value);
1791 lua_setglobal(_state, luaGlobalValues[j].luaName);
1792 }
1793
1794 // set the last mapname as a global
1795 lua_pushstring(_state, g_hdb->lastMapName());
1796 lua_setglobal(_state, "LASTMAP");
1797
1798 // Set the lowest printable line
1799 lua_pushnumber(_state, 480 - 14);
1800 lua_setglobal(_state, "BOTTOM_Y");
1801
1802 for (int j = 0; j < g_hdb->_sound->getNumSounds(); j++) {
1803 const char *name = g_hdb->_sound->getSNDLuaName(j);
1804 lua_pushnumber(_state, j);
1805 lua_setglobal(_state, name);
1806 }
1807
1808 // Set the Entity Spawn Names in Lua
1809 int j = 0;
1810 while (aiEntList[j].luaName) {
1811 lua_pushnumber(_state, aiEntList[j].type);
1812 lua_setglobal(_state, aiEntList[j].luaName);
1813 j++;
1814 }
1815
1816 // Register panic callback function
1817 lua_atpanic(_state, panicCB);
1818
1819 // Error handler for lua_pcall calls
1820 // The code below contains a local error handler function
1821 const char errorHandlerCode[] =
1822 "local function ErrorHandler(message) "
1823 " return message .. '\\n' .. debug.traceback('', 2) "
1824 "end "
1825 "return ErrorHandler";
1826
1827 // Compile the code
1828 if (luaL_loadbuffer(_state, errorHandlerCode, strlen(errorHandlerCode), "PCALL ERRORHANDLER") != 0) {
1829 // An error occurred, so dislay the reason and exit
1830 error("Couldn't compile luaL_pcall errorhandler:\n%s", lua_tostring(_state, -1));
1831 lua_pop(_state, 1);
1832
1833 return false;
1834 }
1835
1836 // Running the code, the error handler function sets the top of the stack
1837 if (lua_pcall(_state, 0, 1, 0) != 0) {
1838 // An error occurred, so display the reason and exit
1839 error("Couldn't prepare luaL_pcall errorhandler:\n%s", lua_tostring(_state, -1));
1840 lua_pop(_state, 1);
1841
1842 return false;
1843 }
1844
1845 // Place the error handler function in the Lua registry, and remember the index
1846 _pcallErrorhandlerRegistryIndex = luaL_ref(_state, LUA_REGISTRYINDEX);
1847
1848 if (gDebugLevel >= 8) {
1849 // Initialize debugging callback
1850 lua_sethook(_state, debugHook, LUA_MASKCALL | LUA_MASKLINE, 0);
1851 }
1852
1853 // Load GLOBAL.LUA and execute it
1854
1855 // Make sure we start from the beginning
1856 _globalLuaStream->seek(0);
1857 if (!executeMPC(_globalLuaStream, "GLOBAL.LUA", "GLOBAL.LUA", _globalLuaLength)) {
1858 error("LuaScript::initScript: 'global code' failed to execute");
1859 return false;
1860 }
1861
1862 // Load script and execute it
1863
1864 if (!executeMPC(stream, scriptName, scriptName, length)) {
1865 error("LuaScript::initScript: %s failed to execute", scriptName);
1866 return false;
1867 }
1868
1869 lua_getglobal(_state, "level_init");
1870
1871 // Error handling function to be executed after the function is put on the stack
1872 lua_rawgeti(_state, LUA_REGISTRYINDEX, _pcallErrorhandlerRegistryIndex);
1873 lua_insert(_state, -2);
1874
1875 if (lua_pcall(_state, 0, 0, -2)) {
1876 error("LuaScript::initScript: An error occured while executing \"%s\": %s.", "level_init", lua_tostring(_state, -1));
1877 lua_pop(_state, -1);
1878
1879 return false;
1880 }
1881
1882 // Remove the error handler function from the stack
1883 lua_pop(_state, 1);
1884
1885 return true;
1886 }
1887
pushInt(int value)1888 void LuaScript::pushInt(int value) {
1889 if (!_systemInit)
1890 return;
1891 lua_pushnumber(_state, (double)value);
1892 }
1893
pushString(char * string)1894 void LuaScript::pushString(char *string) {
1895 if (!_systemInit)
1896 return;
1897 lua_pushstring(_state, string);
1898 }
1899
pushFunction(char * func)1900 void LuaScript::pushFunction(char *func) {
1901 if (!_systemInit)
1902 return;
1903
1904 lua_getglobal(_state, func);
1905 int type = lua_type(_state, 1);
1906 if (type != LUA_TFUNCTION && type != LUA_TNUMBER) {
1907 warning("pushFunction: Function '%s' doesn't exists", func);
1908 }
1909 }
1910
call(int args,int returns)1911 void LuaScript::call(int args, int returns) {
1912 if (!_systemInit)
1913 return;
1914
1915 if (lua_pcall(_state, args, returns, -2)) {
1916 error("LuaScript::call: An error occured while executing: %s.", lua_tostring(_state, -1));
1917 lua_pop(_state, -1);
1918 }
1919 }
1920
callFunction(const char * name,int returns)1921 bool LuaScript::callFunction(const char *name, int returns) {
1922 if (!_systemInit) {
1923 return false;
1924 }
1925
1926 lua_getglobal(_state, name);
1927
1928 if (lua_pcall(_state, 0, returns, -2)) {
1929 error("LuaScript::callFunction: An error occured while executing \"%s\": %s.", name, lua_tostring(_state, -1));
1930 lua_pop(_state, -1);
1931
1932 return false;
1933 }
1934
1935 return true;
1936 }
1937
invokeLuaFunction(char * luaFunc,int x,int y,int value1,int value2)1938 void LuaScript::invokeLuaFunction(char *luaFunc, int x, int y, int value1, int value2) {
1939 if (!_systemInit)
1940 return;
1941
1942 lua_getglobal(_state, luaFunc);
1943 int type = lua_type(_state, 1);
1944
1945 #if 0
1946 if (!strcmp(luaFunc, "ferretbed_use")) {
1947 const char *t = lua_typename(_state, type);
1948 warning("type: %s", t);
1949 Common::String a("print(ferretbed_init(50, 30, 0, 0))");
1950
1951 executeChunk(a, "debug");
1952
1953 // a = "print('woo') for i,v in pairs(_G) do if type(v) == 'function' then print(i) end end";
1954 // a = "print(ferretbed_use())";
1955
1956 executeChunk(a, "debug");
1957
1958 lua_printstack(_state);
1959 }
1960 #endif
1961
1962 if (type != LUA_TFUNCTION) {
1963 warning("Function '%s' doesn't exist (%d)", luaFunc, type);
1964 } else {
1965 lua_pushnumber(_state, x);
1966 lua_pushnumber(_state, y);
1967 lua_pushnumber(_state, value1);
1968 lua_pushnumber(_state, value2);
1969 lua_call(_state, 4, 0);
1970 }
1971 }
1972
executeMPC(Common::SeekableReadStream * stream,const char * name,const char * scriptName,int32 length)1973 bool LuaScript::executeMPC(Common::SeekableReadStream *stream, const char *name, const char *scriptName, int32 length) {
1974 char *chunk = new char[length + 1];
1975 stream->read((void *)chunk, length);
1976 chunk[length] = '\0'; // be on the safe side
1977
1978 stripComments(chunk);
1979
1980 /*
1981 Remove C-style comments from the script
1982 and update the upvalue syntax for Lua 5.1.3
1983 */
1984 Common::String chunkString(chunk, length);
1985
1986 addPatches(chunkString, scriptName);
1987
1988 if (!executeChunk(chunkString, name)) {
1989 delete[] chunk;
1990
1991 return false;
1992 }
1993
1994 delete[] chunk;
1995
1996 return true;
1997 }
1998
executeFile(const Common::String & filename)1999 bool LuaScript::executeFile(const Common::String &filename) {
2000 Common::File *file = new Common::File;
2001
2002 if (!file->open(filename)) {
2003 error("Cannot find \"%s\"", filename.c_str());
2004 }
2005
2006 uint fileSize = file->size();
2007 char *fileData = new char[fileSize + 1];
2008 file->read((void *)fileData, fileSize);
2009 fileData[fileSize] = '\0'; // be on the safe side
2010
2011 stripComments(fileData);
2012
2013 Common::String fileDataString(fileData);
2014
2015 addPatches(fileDataString, filename.c_str());
2016
2017 if (!executeChunk(fileDataString, filename)) {
2018 delete[] fileData;
2019 delete file;
2020
2021 return false;
2022 }
2023
2024 delete[] fileData;
2025 delete file;
2026
2027 return true;
2028 }
2029
executeChunk(Common::String & chunk,const Common::String & chunkName) const2030 bool LuaScript::executeChunk(Common::String &chunk, const Common::String &chunkName) const {
2031 // Compile Chunk
2032 if (luaL_loadbuffer(_state, chunk.c_str(), chunk.size(), chunkName.c_str())) {
2033 error("Couldn't compile \"%s\": %s", chunkName.c_str(), lua_tostring(_state, -1));
2034 lua_pop(_state, -1);
2035
2036 return false;
2037 }
2038
2039 // Error handling function to be executed after the function is put on the stack
2040 lua_rawgeti(_state, LUA_REGISTRYINDEX, _pcallErrorhandlerRegistryIndex);
2041 lua_insert(_state, -2);
2042
2043 // Execute Chunk
2044 if (lua_pcall(_state, 0, 0, -2)) {
2045 error("LuaScript::executeChunk: An error occured while executing \"%s\": %s.", chunkName.c_str(), lua_tostring(_state, -1));
2046 lua_pop(_state, -1);
2047
2048 return false;
2049 }
2050
2051 // Remove the error handler function from the stack
2052 lua_pop(_state, 1);
2053
2054 return true;
2055 }
2056
stripComments(char * chunk)2057 void LuaScript::stripComments(char *chunk) {
2058 uint32 offset = 0;
2059
2060 while (chunk[offset]) {
2061 // Strip C-Style comments
2062 if (chunk[offset] == '/' && chunk[offset + 1] == '/') {
2063 while (chunk[offset] != 0x0d) {
2064 chunk[offset++] = ' ';
2065 }
2066 }
2067 offset++;
2068 }
2069 }
2070
addPatches(Common::String & chunk,const char * scriptName)2071 void LuaScript::addPatches(Common::String &chunk, const char *scriptName) {
2072 ScriptPatch *patch = scriptPatches;
2073 int applied = 0;
2074
2075 while (patch->scriptName) {
2076 if (!scumm_strnicmp(scriptName, patch->scriptName, strlen(patch->scriptName))) {
2077 Common::String searchString(patch->search);
2078 Common::String replaceString(patch->replace);
2079 Common::replace(chunk, searchString, replaceString);
2080 applied++;
2081 }
2082 patch++;
2083 }
2084
2085 if (applied)
2086 debug(1, "Applied %d patches to %s", applied, scriptName);
2087
2088 if (gDebugLevel > 3) {
2089 warning(">>>>>>>>>>> SCRIPT: %s", scriptName);
2090 chunk += "\nfor i,v in pairs(_G) do if type(v) == 'function' then print(i) end end";
2091 }
2092 }
2093
checkParameters(const char * func,int params)2094 void LuaScript::checkParameters(const char *func, int params) {
2095 int stackTop = lua_gettop(_state);
2096 if (stackTop < params) {
2097 warning("%s: Not Enough Parameters", func);
2098 } else if (stackTop > params) {
2099 warning("%s: Too Many Parameters", func);
2100 }
2101 }
2102
lua_printstack(lua_State * L)2103 void lua_printstack(lua_State *L) {
2104 int n = lua_gettop(L);
2105 for (int i = 1; i <= n; i++) {
2106 debug(1, "STACK %d %s %s", i, lua_tostring(L, i), luaL_typename(L, i));
2107 }
2108 }
2109
getStringOffStack()2110 const char *LuaScript::getStringOffStack() {
2111 if (!_systemInit) {
2112 return nullptr;
2113 }
2114
2115 const char *string = lua_tostring(_state, 1);
2116 lua_remove(_state, 1);
2117 return string;
2118 }
2119
2120 }
2121