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