1 (*
2  * Hedgewars, a free turn based strategy game
3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; version 2 of the License
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *)
18 
19 {$INCLUDE "options.inc"}
20 
21 unit uScript;
22 (*
23  * This unit defines, implements and registers functions and
24  * variables/constants bindings for usage in Lua scripts.
25  *
26  * Please keep https://hedgewars.org/kb/LuaAPI up to date!
27  *
28  * Note: If you add a new function, make sure to test if _all_ parameters
29  *       work as intended! (Especially conversions errors can sneak in
30  *       unnoticed and render the parameter useless!)
31  *)
32 interface
33 
34 procedure ScriptPrintStack;
35 procedure ScriptClearStack;
36 
ScriptLoadnull37 function ScriptLoad(name : shortstring; mustExist : boolean): boolean;
38 procedure ScriptOnPreviewInit;
39 procedure ScriptOnGameInit;
40 procedure ScriptOnScreenResize;
41 procedure ScriptSetInteger(name : shortstring; value : LongInt);
42 procedure ScriptSetString(name : shortstring; value : shortstring);
43 procedure ScriptSetMapGlobals;
44 
45 procedure ScriptCall(fname : shortstring);
ScriptCallnull46 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
ScriptCallnull47 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
ScriptCallnull48 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
ScriptCallnull49 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
ScriptExistsnull50 function ScriptExists(fname : shortstring) : boolean;
51 
52 procedure LuaParseString(s: shortString);
53 
ParseCommandOverridenull54 //function ParseCommandOverride(key, value : shortstring) : shortstring;  This did not work out well
55 
56 procedure initModule;
57 procedure freeModule;
58 
59 implementation
60 
61 uses LuaPas,
62     uConsole,
63     uConsts,
64     uGears,
65     uGearsList,
66     uGearsUtils,
67     uFloat,
68     uWorld,
69     uAmmos,
70     uTeams,
71     uSound,
72     uChat,
73     uStats,
74     uStore,
75     uRandom,
76     uTypes,
77     uVariables,
78     uCommands,
79     uCaptions,
80     uDebug,
81     uCollisions,
82     uRenderUtils,
83     uTextures,
84     uLandGraphics,
85     uUtils,
86     uIO,
87     uVisualGearsList,
88     uGearsHandlersMess,
89     uPhysFSLayer,
90     uLocale,
91     SDLh
92 {$IFNDEF PAS2C}
93     , typinfo
94 {$ENDIF}
95     ;
96 
97 var luaState : Plua_State;
98     ScriptAmmoLoadout : shortstring;
99     ScriptAmmoProbability : shortstring;
100     ScriptAmmoDelay : shortstring;
101     ScriptAmmoReinforcement : shortstring;
102     ScriptLoaded : boolean;
103     PointsBuffer: shortstring;
104     PrevCursorX, PrevCursorY: LongInt;
105     PendingTurnTimeLeft, PendingReadyTimeLeft: LongWord;
106     isPendingTurnTimeLeft, isPendingReadyTimeLeft: boolean;
107 
108 {$IFDEF USE_LUA_SCRIPT}
109 procedure ScriptPrepareAmmoStore; forward;
110 procedure ScriptApplyAmmoStore; forward;
111 procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte); forward;
112 procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: LongWord); forward;
113 
114 var LuaDebugInfo: lua_Debug;
115 
116 procedure SetGlobals; forward;
117 procedure GetGlobals; forward;
118 procedure LuaParseString(s: shortString);
119 begin
120     SetGlobals;
121     AddFileLog('[Lua] input string: ' + s);
122     AddChatString(#3 + '[Lua] > ' + s);
123     if luaL_dostring(luaState, Str2PChar(s)) <> 0 then
124         begin
125         AddFileLog('[Lua] input string parsing error!');
126         AddChatString(#5 + '[Lua] Error while parsing!');
127         end
128     else
129         GetGlobals();
130 end;
131 
LuaUpdateDebugInfonull132 function LuaUpdateDebugInfo(): Boolean;
133 begin
134     FillChar(LuaDebugInfo, sizeof(LuaDebugInfo), 0);
135 
136     if lua_getstack(luaState, 1, @LuaDebugInfo) = 0 then
137         exit(false); // stack not deep enough
138 
139     // get source name and line count
140     lua_getinfo(luaState, PChar('Sl'), @LuaDebugInfo);
141     exit(true);
142 end;
143 
144 procedure LuaErrorOrWarning(s: shortstring; isWarning: boolean);
145 var src, intro: shortstring;
146 const
147     maxsrclen = 20;
148 begin
149     if isWarning then
150         intro:= 'LUA WARNING'
151     else
152         intro:= 'LUA ERROR';
153     if LuaUpdateDebugInfo() then
154         begin
155         src:= StrPas(LuaDebugInfo.source);
156         s:= intro + ': [ ... '
157             + copy(src, Length(src) - maxsrclen, maxsrclen - 3) + ':'
158             + inttostr(LuaDebugInfo.currentLine) + ']: ' + s;
159         end
160     else
161         s:= intro + ': ' + s;
162     WriteLnToConsole(s);
163     if isWarning then
164         AddChatString(#0 + s)
165     else
166         AddChatString(#5 + s);
167     if cTestLua and (not isWarning) then
168         halt(HaltTestLuaError);
169 end;
170 
171 procedure LuaError(s: shortstring);
172 begin
173     LuaErrorOrWarning(s, false);
174 end;
175 
176 procedure LuaWarning(s: shortstring);
177 begin
178     LuaErrorOrWarning(s, true);
179 end;
180 
181 procedure LuaCallError(error, call, paramsyntax: shortstring);
182 begin
183     LuaError(call + ': ' + error);
184     LuaError('-- SYNTAX: ' + call + ' ( ' + paramsyntax + ' )');
185 end;
186 
187 procedure LuaParameterCountError(expected, call, paramsyntax: shortstring; wrongcount: LongInt); inline;
188 begin
189     // TODO: i18n?
190     LuaCallError('Wrong number of parameters! (is: ' + inttostr(wrongcount) + ', should be: '+ expected + ')', call, paramsyntax);
191 end;
192 
193 // compare with allowed count
CheckLuaParamCountnull194 function CheckLuaParamCount(L : Plua_State; count: LongInt; call, paramsyntax: shortstring): boolean; inline;
195 var c: LongInt;
196 begin
197     c:= lua_gettop(L);
198     if c <> count then
199         begin
200         LuaParameterCountError('exactly ' + inttostr(count), call, paramsyntax, c);
201         exit(false);
202         end;
203 
204     CheckLuaParamCount:= true;
205 end;
206 
207 // check if is either count1 or count2
CheckAndFetchParamCountnull208 function CheckAndFetchParamCount(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
209 begin
210     actual:= lua_gettop(L);
211     if (actual <> count1) and (actual <> count2) then
212         begin
213         LuaParameterCountError('either ' + inttostr(count1) + ' or ' + inttostr(count2), call, paramsyntax, actual);
214         exit(false);
215         end;
216 
217     CheckAndFetchParamCount:= true;
218 end;
219 
220 // check if is in range of count1 and count2
CheckAndFetchParamCountRangenull221 function CheckAndFetchParamCountRange(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
222 begin
223     actual:= lua_gettop(L);
224     if (actual < count1) or (actual > count2) then
225         begin
226         LuaParameterCountError('at least ' + inttostr(count1) + ', but at most ' + inttostr(count2), call, paramsyntax, actual);
227         exit(false);
228         end;
229 
230     CheckAndFetchParamCountRange:= true;
231 end;
232 
233 // check if is same or higher as minCount
CheckAndFetchLuaParamMinCountnull234 function CheckAndFetchLuaParamMinCount(L : Plua_State; minCount: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
235 begin
236     actual:= lua_gettop(L);
237     if (actual < minCount) then
238         begin
239         LuaParameterCountError(inttostr(minCount) + ' or more', call, paramsyntax, actual);
240         exit(false);
241         end;
242 
243     CheckAndFetchLuaParamMinCount:= true;
244 end;
245 
LuaToGearTypeOrdnull246 function LuaToGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
247 begin
248     if lua_isnoneornil(L, i) then i:= -1
249     else i:= Trunc(lua_tonumber(L, i));
250     if (i < ord(Low(TGearType))) or (i > ord(High(TGearType))) then
251         begin
252         LuaCallError('Invalid gearType!', call, paramsyntax);
253         LuaToGearTypeOrd:= -1;
254         end
255     else
256         LuaToGearTypeOrd:= i;
257 end;
258 
LuaToVisualGearTypeOrdnull259 function LuaToVisualGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
260 begin
261     if lua_isnoneornil(L, i) then i:= -1
262     else i:= Trunc(lua_tonumber(L, i));
263     if (i < ord(Low(TVisualGearType))) or (i > ord(High(TVisualGearType))) then
264         begin
265         LuaCallError('Invalid visualGearType!', call, paramsyntax);
266         LuaToVisualGearTypeOrd:= -1;
267         end
268     else
269         LuaToVisualGearTypeOrd:= i;
270 end;
271 
LuaToAmmoTypeOrdnull272 function LuaToAmmoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
273 begin
274     if lua_isnoneornil(L, i) then i:= -1
275     else i:= Trunc(lua_tonumber(L, i));
276     if (i < ord(Low(TAmmoType))) or (i > ord(High(TAmmoType))) then
277         begin
278         LuaCallError('Invalid ammoType!', call, paramsyntax);
279         LuaToAmmoTypeOrd:= -1;
280         end
281     else
282         LuaToAmmoTypeOrd:= i;
283 end;
284 
LuaToStatInfoTypeOrdnull285 function LuaToStatInfoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
286 begin
287     if lua_isnoneornil(L, i) then i:= -1
288     else i:= Trunc(lua_tonumber(L, i));
289     if (i < ord(Low(TStatInfoType))) or (i > ord(High(TStatInfoType))) then
290         begin
291         LuaCallError('Invalid statInfoType!', call, paramsyntax);
292         LuaToStatInfoTypeOrd:= -1;
293         end
294     else
295         LuaToStatInfoTypeOrd:= i;
296 end;
297 
LuaToSoundOrdnull298 function LuaToSoundOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
299 begin
300     if lua_isnoneornil(L, i) then i:= -1
301     else i:= Trunc(lua_tonumber(L, i));
302     if (i < ord(Low(TSound))) or (i > ord(High(TSound))) then
303         begin
304         LuaCallError('Invalid soundId!', call, paramsyntax);
305         LuaToSoundOrd:= -1;
306         end
307     else
308         LuaToSoundOrd:= i;
309 end;
310 
LuaToHogEffectOrdnull311 function LuaToHogEffectOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
312 begin
313     if lua_isnoneornil(L, i) then i:= -1
314     else i:= Trunc(lua_tonumber(L, i));
315     if (i < ord(Low(THogEffect))) or (i > ord(High(THogEffect))) then
316         begin
317         LuaCallError('Invalid effect type!', call, paramsyntax);
318         LuaToHogEffectOrd:= -1;
319         end
320     else
321         LuaToHogEffectOrd:= i;
322 end;
323 
LuaToCapGroupOrdnull324 function LuaToCapGroupOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
325 begin
326     if lua_isnoneornil(L, i) then i:= -1
327     else i:= Trunc(lua_tonumber(L, i));
328     if (i < ord(Low(TCapGroup))) or (i > ord(High(TCapGroup))) then
329         begin
330         LuaCallError('Invalid capgroup type!', call, paramsyntax);
331         LuaToCapGroupOrd:= -1;
332         end
333     else
334         LuaToCapGroupOrd:= i;
335 end;
336 
LuaToSpriteOrdnull337 function LuaToSpriteOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
338 begin
339     if lua_isnoneornil(L, i) then i:= -1
340     else i:= Trunc(lua_tonumber(L, i));
341     if (i < ord(Low(TSprite))) or (i > ord(High(TSprite))) then
342         begin
343         LuaCallError('Invalid sprite id!', call, paramsyntax);
344         LuaToSpriteOrd:= -1;
345         end
346     else
347         LuaToSpriteOrd:= i;
348 end;
349 
LuaToMapGenOrdnull350 function LuaToMapGenOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
351 begin
352     if lua_isnoneornil(L, i) then i:= -1
353     else i:= Trunc(lua_tonumber(L, i));
354     if (i < ord(Low(TMapGen))) or (i > ord(High(TMapGen))) then
355         begin
356         LuaCallError('Invalid mapgen id!', call, paramsyntax);
357         LuaToMapGenOrd:= -1;
358         end
359     else
360         LuaToMapGenOrd:= i;
361 end;
362 
363 // wrapped calls
364 
365 // functions called from Lua:
366 // function(L : Plua_State) : LongInt; Cdecl;
367 // where L contains the state, returns the number of return values on the stack
368 // call CheckLuaParamCount or CheckAndFetchParamCount
369 // to validate/get the number of passed arguments (see their call definitions)
370 //
371 // use as return value the number of variables pushed back to the lua script
372 
lc_bandnull373 function lc_band(L: PLua_State): LongInt; Cdecl;
374 begin
375     if CheckLuaParamCount(L, 2, 'band', 'value1, value2') then
376         lua_pushnumber(L, Trunc(lua_tonumber(L, 2)) and Trunc(lua_tonumber(L, 1)))
377     else
378         lua_pushnil(L);
379     lc_band := 1;
380 end;
381 
lc_bornull382 function lc_bor(L: PLua_State): LongInt; Cdecl;
383 begin
384     if CheckLuaParamCount(L, 2, 'bor', 'value1, value2') then
385         lua_pushnumber(L, Trunc(lua_tonumber(L, 2)) or Trunc(lua_tonumber(L, 1)))
386     else
387         lua_pushnil(L);
388     lc_bor := 1;
389 end;
390 
lc_bnotnull391 function lc_bnot(L: PLua_State): LongInt; Cdecl;
392 begin
393     if CheckLuaParamCount(L, 1, 'bnot', 'value') then
394         lua_pushnumber(L, (not Trunc(lua_tonumber(L, 1))))
395     else
396         lua_pushnil(L);
397     lc_bnot := 1;
398 end;
399 
lc_divnull400 function lc_div(L: PLua_State): LongInt; Cdecl;
401 begin
402     if CheckLuaParamCount(L, 2, 'div', 'dividend, divisor') then
403         lua_pushnumber(L, Trunc(lua_tonumber(L, 1)) div Trunc(lua_tonumber(L, 2)))
404     else
405         lua_pushnil(L);
406     lc_div := 1;
407 end;
408 
lc_getinputmasknull409 function lc_getinputmask(L : Plua_State) : LongInt; Cdecl;
410 begin
411     if CheckLuaParamCount(L, 0, 'GetInputMask', '') then
412         lua_pushnumber(L, InputMask);
413     lc_getinputmask:= 1
414 end;
415 
lc_setinputmasknull416 function lc_setinputmask(L : Plua_State) : LongInt; Cdecl;
417 begin
418     if CheckLuaParamCount(L, 1, 'SetInputMask', 'mask') then
419         InputMask:= Trunc(lua_tonumber(L, 1));
420     lc_setinputmask:= 0
421 end;
422 
lc_writelntoconsolenull423 function lc_writelntoconsole(L : Plua_State) : LongInt; Cdecl;
424 begin
425     if CheckLuaParamCount(L, 1, 'WriteLnToConsole', 'string') then
426         WriteLnToConsole('Lua: ' + lua_tostring(L ,1));
427     lc_writelntoconsole:= 0;
428 end;
429 
lc_writelntochatnull430 function lc_writelntochat(L : Plua_State) : LongInt; Cdecl;
431 begin
432     if CheckLuaParamCount(L, 1, 'WriteLnToChat', 'string') then
433         AddChatString(#2 + lua_tostring(L, 1));
434     lc_writelntochat:= 0;
435 end;
436 
lc_parsecommandnull437 function lc_parsecommand(L : Plua_State) : LongInt; Cdecl;
438 var t: PChar;
439     i,c: LongWord;
440     s: shortstring;
441 begin
442     if CheckLuaParamCount(L, 1, 'ParseCommand', 'string') then
443         begin
444         t:= lua_tolstring(L, 1, Psize_t(@c));
445 
446         for i:= 1 to c do s[i]:= t[i-1];
447         s[0]:= char(c);
448 
449         ParseCommand(s, true, true);
450 
451         end;
452     lc_parsecommand:= 0;
453 end;
454 
455 // sets weapon to the desired ammo type
lc_setweaponnull456 function lc_setweapon(L : Plua_State) : LongInt; Cdecl;
457 var at: LongInt;
458 const
459     call = 'SetWeapon';
460     params = 'ammoType';
461 begin
462     // no point to run this without any CurrentHedgehog
463     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 1, call, params)) then
464         begin
465         at:= LuaToAmmoTypeOrd(L, 1, call, params);
466         if at >= 0 then
467             ParseCommand('setweap ' + char(at), true, true);
468         end;
469     lc_setweapon:= 0;
470 end;
471 
472 // enable/disable cinematic effects
lc_setcinematicmodenull473 function lc_setcinematicmode(L : Plua_State) : LongInt; Cdecl;
474 const
475     call = 'SetCinematicMode';
476     params = 'enable';
477 begin
478     if (CheckLuaParamCount(L, 1, call, params)) then
479         begin
480         CinematicScript:= lua_toboolean(L, 1);
481         end;
482     lc_setcinematicmode:= 0;
483 end;
484 
485 // no parameter means reset to default (and 0 means unlimited)
lc_setmaxbuilddistancenull486 function lc_setmaxbuilddistance(L : Plua_State) : LongInt; Cdecl;
487 var np: LongInt;
488 const
489     call = 'SetMaxBuildDistance';
490     params = '[ distInPx ]';
491 begin
492     if CheckAndFetchParamCountRange(L, 0, 1, call, params, np) then
493         begin
494         if np = 0 then
495             begin
496             // no args? reset
497             cBuildMaxDist:= cDefaultBuildMaxDist;
498             end
499         else
500             CBuildMaxDist:= Trunc(lua_tonumber(L, 1));
501         end;
502     lc_setmaxbuilddistance:= 0;
503 end;
504 
505 // sets weapon to whatever weapons is next (wraps around, amSkip is skipped)
lc_setnextweaponnull506 function lc_setnextweapon(L : Plua_State) : LongInt; Cdecl;
507 var at          : LongInt;
508     nextAmmo    : TAmmo;
509     s, a, cs, fa: LongInt;
510 const
511     call = 'SetNextWeapon';
512     params = '';
513 begin
514     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, call, params)) then
515         begin
516         at:= -1;
517         with CurrentHedgehog^ do
518             begin
519             cs:= 0; // current slot
520             fa:= 0; // first ammo item to check
521 
522             // if something is selected, find it is successor
523             if curAmmoType <> amNothing then
524                 begin
525                 // get current slot index
526                 cs:= Ammoz[CurAmmoType].Slot;
527                 // find current ammo index
528                 while (fa < cMaxSlotAmmoIndex)
529                     and (Ammo^[cs, fa].AmmoType <> CurAmmoType) do
530                         inc(fa);
531                 // increase once more because we will not successor
532                 inc(fa);
533                 end;
534 
535             // find first available ammo
536             // revisit current slot too (current item might not be first)
537             for s:= cs to cs + cMaxSlotIndex + 1 do
538                 begin
539                 for a:= fa to cMaxSlotAmmoIndex do
540                     begin
541                     // check if we went full circle
542                     if (a = fa) and (s = cs + cMaxSlotIndex + 1)  then
543                         exit(0);
544 
545                     // get ammo
546                     nextAmmo:= Ammo^[s mod (cMaxSlotIndex + 1), a];
547                     // only switch to ammos the hog actually has
548                     if (nextAmmo.AmmoType <> amNothing)
549                         and (nextAmmo.AmmoType <> amSkip) and (nextAmmo.Count > 0) then
550                             begin
551                             at:= ord(nextAmmo.AmmoType);
552                             break;
553                             end;
554                     end;
555                 // stop slot loop if something was found
556                 if at >= 0 then
557                     break;
558                 // check following slots starting with first item
559                 fa:= 0;
560                 end;
561             end;
562 
563         if at >= 0 then
564             ParseCommand('setweap ' + char(at), true, true);
565         end;
566     lc_setnextweapon:= 0;
567 end;
568 
lc_showmissionnull569 function lc_showmission(L : Plua_State) : LongInt; Cdecl;
570 var n: LongInt;
571 begin
572     if CheckAndFetchParamCount(L, 5, 6, 'ShowMission', 'caption, subcaption, text, icon, time [, forceDisplay]', n) then
573         if n = 5 then
574             ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), Trunc(lua_tonumber(L, 4)), Trunc(lua_tonumber(L, 5)))
575         else
576             ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), Trunc(lua_tonumber(L, 4)), Trunc(lua_tonumber(L, 5)), lua_toboolean(L, 6));
577     lc_showmission:= 0;
578 end;
579 
lc_hidemissionnull580 function lc_hidemission(L : Plua_State) : LongInt; Cdecl;
581 begin
582     L:= L; // avoid compiler hint
583     HideMission;
584     lc_hidemission:= 0;
585 end;
586 
lc_setammotextsnull587 function lc_setammotexts(L : Plua_State) : LongInt; Cdecl;
588 const
589     call = 'SetAmmoTexts';
590     params = 'ammoType, name, caption, description [, showExtra]';
591 var n: integer;
592     showExtra: boolean;
593 begin
594     if CheckAndFetchParamCount(L, 4, 5, call, params, n) then
595         begin
596         if n = 5 then
597             showExtra:= lua_toboolean(L, 5)
598         else
599             showExtra:= true;
600         SetAmmoTexts(TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params)), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tostringA(L, 4), showExtra);
601         end;
602     lc_setammotexts:= 0;
603 end;
604 
lc_setammodescriptionappendixnull605 function lc_setammodescriptionappendix(L : Plua_State) : LongInt; Cdecl;
606 const
607     call = 'SetAmmoDescriptionAppendix';
608     params = 'ammoType, descAppend';
609 var
610     ammoType: TAmmoType;
611     descAppend: ansistring;
612 begin
613     if CheckLuaParamCount(L, 2, call, params) then
614         begin
615         ammoType := TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params));
616         descAppend := lua_tostringA(L, 2);
617         trluaammoa[Ammoz[ammoType].NameId] := descAppend;
618         end;
619     lc_setammodescriptionappendix := 0;
620 end;
621 
lc_enablegameflagsnull622 function lc_enablegameflags(L : Plua_State) : LongInt; Cdecl;
623 var i, n : integer;
624 begin
625     // can have 1 or more arguments
626     if CheckAndFetchLuaParamMinCount(L, 1, 'EnableGameFlags', 'gameFlag, ... ', n) then
627         begin
628         for i:= 1 to n do
629             GameFlags := GameFlags or LongWord(Trunc(lua_tonumber(L, i)));
630         ScriptSetInteger('GameFlags', GameFlags);
631         end;
632     lc_enablegameflags:= 0;
633 end;
634 
lc_disablegameflagsnull635 function lc_disablegameflags(L : Plua_State) : LongInt; Cdecl;
636 var i , n: integer;
637 begin
638     // can have 1 or more arguments
639     if CheckAndFetchLuaParamMinCount(L, 1, 'DisableGameFlags', 'gameFlag, ... ', n) then
640         begin
641         for i:= 1 to n do
642             GameFlags := GameFlags and (not LongWord(Trunc(lua_tonumber(L, i))));
643         ScriptSetInteger('GameFlags', GameFlags);
644         end;
645     lc_disablegameflags:= 0;
646 end;
647 
lc_cleargameflagsnull648 function lc_cleargameflags(L : Plua_State) : LongInt; Cdecl;
649 begin
650     if CheckLuaParamCount(L, 0, 'ClearGameFlags', '') then
651         begin
652         GameFlags:= 0;
653         ScriptSetInteger('GameFlags', GameFlags);
654         end;
655     lc_cleargameflags:= 0;
656 end;
657 
lc_getgameflagnull658 function lc_getgameflag(L : Plua_State) : LongInt; Cdecl;
659 begin
660     if CheckLuaParamCount(L, 1, 'GetGameFlag', 'gameflag') then
661         lua_pushboolean(L, (GameFlags and LongWord(Trunc(lua_tonumber(L, 1))) <> 0))
662     else
663         lua_pushnil(L);
664     lc_getgameflag:= 1;
665 end;
666 
lc_addcaptionnull667 function lc_addcaption(L : Plua_State) : LongInt; Cdecl;
668 var cg: LongInt;
669 const
670     call = 'AddCaption';
671     params = 'text [, color, captiongroup]';
672 begin
673     if CheckAndFetchParamCount(L, 1, 3, call, params, cg) then
674         begin
675         if cg = 1 then
676             AddCaption(lua_tostringA(L, 1), capcolDefault, capgrpMessage)
677         else
678             begin
679             cg:= LuaToCapGroupOrd(L, 3, call, params);
680             if cg >= 0 then
681                 AddCaption(lua_tostringA(L, 1), Trunc(lua_tonumber(L, 2)) shr 8, TCapGroup(cg));
682             end
683         end;
684     lc_addcaption:= 0;
685 end;
686 
lc_spawnfakehealthcratenull687 function lc_spawnfakehealthcrate(L: Plua_State) : LongInt; Cdecl;
688 var gear: PGear;
689     explode, poison: boolean;
690     n: LongInt;
691 begin
692     if CheckAndFetchParamCountRange(L, 2, 4, 'SpawnFakeHealthCrate', 'x, y [, explode [, poison]]', n) then
693         begin
694         explode:= false;
695         poison:= false;
696         if (n >= 3) and (not lua_isnil(L, 3)) then
697             explode:= lua_toboolean(L, 3);
698         if (n = 4) and (not lua_isnil(L, 4)) then
699             poison:= lua_toboolean(L, 4);
700 
701         gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
702         HealthCrate, explode, poison);
703         if gear <> nil then
704              lua_pushnumber(L, gear^.uid)
705         else lua_pushnil(L)
706         end
707     else
708         lua_pushnil(L);
709     lc_spawnfakehealthcrate := 1;
710 end;
711 
lc_spawnfakeammocratenull712 function lc_spawnfakeammocrate(L: PLua_State): LongInt; Cdecl;
713 var gear: PGear;
714     explode, poison: boolean;
715     n: LongInt;
716 begin
717     if CheckAndFetchParamCountRange(L, 2, 4, 'SpawnFakeAmmoCrate', 'x, y [, explode [, poison]]', n) then
718         begin
719         explode:= false;
720         poison:= false;
721         if (n >= 3) and (not lua_isnil(L, 3)) then
722             explode:= lua_toboolean(L, 3);
723         if (n = 4) and (not lua_isnil(L, 4)) then
724             poison:= lua_toboolean(L, 4);
725 
726         gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
727         AmmoCrate, explode, poison);
728         if gear <> nil then
729              lua_pushnumber(L, gear^.uid)
730         else lua_pushnil(L)
731         end
732     else
733         lua_pushnil(L);
734     lc_spawnfakeammocrate := 1;
735 end;
736 
lc_spawnfakeutilitycratenull737 function lc_spawnfakeutilitycrate(L: PLua_State): LongInt; Cdecl;
738 var gear: PGear;
739     explode, poison: boolean;
740     n: LongInt;
741 begin
742     if CheckAndFetchParamCountRange(L, 2, 4, 'SpawnFakeUtilityCrate', 'x, y [, explode [, poison]]', n) then
743         begin
744         explode:= false;
745         poison:= false;
746         if (n >= 3) and (not lua_isnil(L, 3)) then
747             explode:= lua_toboolean(L, 3);
748         if (n = 4) and (not lua_isnil(L, 4)) then
749             poison:= lua_toboolean(L, 4);
750 
751         gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
752         UtilityCrate, explode, poison);
753         if gear <> nil then
754              lua_pushnumber(L, gear^.uid)
755         else lua_pushnil(L)
756         end
757     else
758         lua_pushnil(L);
759     lc_spawnfakeutilitycrate := 1;
760 end;
761 
lc_spawnhealthcratenull762 function lc_spawnhealthcrate(L: Plua_State) : LongInt; Cdecl;
763 var gear: PGear;
764 var health, n: LongInt;
765 begin
766     if CheckAndFetchParamCount(L, 2, 3, 'SpawnHealthCrate', 'x, y [, health]', n) then
767         begin
768         if n = 3 then
769             health:= Trunc(lua_tonumber(L, 3))
770         else
771             health:= cHealthCaseAmount;
772         gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), HealthCrate, health, 0);
773         if gear <> nil then
774              lua_pushnumber(L, gear^.uid)
775         else lua_pushnil(L);
776         end
777     else
778         lua_pushnil(L);
779     lc_spawnhealthcrate := 1;
780 end;
781 
lc_spawnammocratenull782 function lc_spawnammocrate(L: PLua_State): LongInt; Cdecl;
783 var gear: PGear;
784     n   : LongInt;
785 begin
786     if CheckAndFetchParamCount(L, 3, 4, 'SpawnAmmoCrate', 'x, y, content [, amount]', n) then
787         begin
788         if n = 3 then
789              gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), AmmoCrate, Trunc(lua_tonumber(L, 3)), 0)
790         else gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), AmmoCrate, Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)));
791         if gear <> nil then
792              lua_pushnumber(L, gear^.uid)
793         else lua_pushnil(L);
794         end
795     else
796         lua_pushnil(L);
797     lc_spawnammocrate := 1;
798 end;
799 
lc_spawnutilitycratenull800 function lc_spawnutilitycrate(L: PLua_State): LongInt; Cdecl;
801 var gear: PGear;
802     n   : LongInt;
803 begin
804     if CheckAndFetchParamCount(L, 3, 4, 'SpawnUtilityCrate', 'x, y, content [, amount]', n) then
805         begin
806         if n = 3 then
807              gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), UtilityCrate, Trunc(lua_tonumber(L, 3)), 0)
808         else gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), UtilityCrate, Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)));
809         if gear <> nil then
810              lua_pushnumber(L, gear^.uid)
811         else lua_pushnil(L);
812        end
813     else
814         lua_pushnil(L);
815     lc_spawnutilitycrate := 1;
816 end;
817 
lc_spawnsupplycratenull818 function lc_spawnsupplycrate(L: PLua_State): LongInt; Cdecl;
819 var gear: PGear;
820     n, at:LongInt;
821     t:    TCrateType;
822 begin
823     if CheckAndFetchParamCount(L, 3, 4, 'SpawnSupplyCrate', 'x, y, content [, amount]', n) then
824         begin
825         // Get crate type (ammo or utility)
826         at:= Trunc(lua_tonumber(L, 3));
827         if (Ammoz[TAmmoType(at)].Ammo.Propz and ammoprop_Utility) <> 0 then
828             t:= UtilityCrate
829         else
830             t:= AmmoCrate;
831         if n = 3 then
832              gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), t, at, 0)
833         else gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), t, at, Trunc(lua_tonumber(L, 4)));
834         if gear <> nil then
835              lua_pushnumber(L, gear^.uid)
836         else lua_pushnil(L);
837         end
838     else
839         lua_pushnil(L);
840     lc_spawnsupplycrate := 1;
841 end;
842 
lc_addgearnull843 function lc_addgear(L : Plua_State) : LongInt; Cdecl;
844 var gear : PGear;
845     x, y, s, t: LongInt;
846     dx, dy: hwFloat;
847     gt: TGearType;
848 const
849     call = 'AddGear';
850     params = 'x, y, gearType, state, dx, dy, timer';
851 begin
852     if CheckLuaParamCount(L, 7, call, params) then
853         begin
854         t:= LuaToGearTypeOrd(L, 3, call, params);
855         if t >= 0 then
856             begin
857             gt:= TGearType(t);
858             x:= Trunc(lua_tonumber(L, 1));
859             y:= Trunc(lua_tonumber(L, 2));
860             s:= Trunc(lua_tonumber(L, 4));
861             dx:= int2hwFloat(Trunc(lua_tonumber(L, 5))) / 1000000;
862             dy:= int2hwFloat(Trunc(lua_tonumber(L, 6))) / 1000000;
863             t:= Trunc(lua_tonumber(L, 7));
864 
865             gear:= AddGear(x, y, gt, s, dx, dy, t);
866             lastGearByUID:= gear;
867             lua_pushnumber(L, gear^.uid)
868             end
869         else
870             lua_pushnil(L);
871         end
872     else
873         lua_pushnil(L);
874     lc_addgear:= 1; // 1 return value
875 end;
876 
lc_deletegearnull877 function lc_deletegear(L : Plua_State) : LongInt; Cdecl;
878 var gear : PGear;
879 begin
880     if CheckLuaParamCount(L, 1, 'DeleteGear', 'gearUid') then
881         begin
882         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
883         if gear <> nil then
884             gear^.Message:= gear^.Message or gmDelete;
885         end;
886     lc_deletegear:= 0
887 end;
888 
lc_addvisualgearnull889 function lc_addvisualgear(L : Plua_State) : LongInt; Cdecl;
890 var vg : PVisualGear;
891     x, y, s, n, layer: LongInt;
892     c: Boolean;
893     vgt: TVisualGearType;
894     uid: Longword;
895 const
896     call = 'AddVisualGear';
897     params = 'x, y, visualGearType, state, critical [, layer]';
898 begin
899     uid:= 0;
900     if CheckAndFetchParamCount(L, 5, 6, call, params, n) then
901         begin
902         s:= LuaToVisualGearTypeOrd(L, 3, call, params);
903         if s >= 0 then
904             begin
905             vgt:= TVisualGearType(s);
906             x:= Trunc(lua_tonumber(L, 1));
907             y:= Trunc(lua_tonumber(L, 2));
908             s:= Trunc(lua_tonumber(L, 4));
909             c:= lua_toboolean(L, 5);
910 
911             if n = 6 then
912                 begin
913                 layer:= Trunc(lua_tonumber(L, 6));
914                 vg:= AddVisualGear(x, y, vgt, s, c, layer);
915                 end
916             else
917                 vg:= AddVisualGear(x, y, vgt, s, c);
918 
919             if vg <> nil then
920                 begin
921                 lastVisualGearByUID:= vg;
922                 uid:= vg^.uid;
923                 lua_pushnumber(L, uid);
924                 end;
925             end
926             else
927                 lua_pushnil(L);
928         end
929     else
930         lua_pushnil(L); // return value on stack (nil)
931     lc_addvisualgear:= 1; // 1 return value
932 end;
933 
lc_deletevisualgearnull934 function lc_deletevisualgear(L : Plua_State) : LongInt; Cdecl;
935 var vg : PVisualGear;
936 begin
937     vg:= nil;
938     if CheckLuaParamCount(L, 1, 'DeleteVisualGear', 'vgUid') then
939         begin
940         vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
941         if vg <> nil then
942             DeleteVisualGear(vg);
943         end;
944     // allow caller to know whether there was something to delete
945     lua_pushboolean(L, vg <> nil);
946     lc_deletevisualgear:= 1
947 end;
948 
lc_getvisualgeartypenull949 function lc_getvisualgeartype(L : Plua_State) : LongInt; Cdecl;
950 var vg : PVisualGear;
951 begin
952     if CheckLuaParamCount(L, 1, 'GetVisualGearType', 'vgUid') then
953         begin
954         vg := VisualGearByUID(Trunc(lua_tonumber(L, 1)));
955         if vg <> nil then
956             lua_pushnumber(L, ord(vg^.Kind))
957         else
958             lua_pushnil(L);
959         end
960     else
961         lua_pushnil(L); // return value on stack (nil)
962     lc_getvisualgeartype:= 1
963 end;
964 
965 
lc_getvisualgearvaluesnull966 function lc_getvisualgearvalues(L : Plua_State) : LongInt; Cdecl;
967 var vg: PVisualGear;
968 begin
969     if CheckLuaParamCount(L, 1, 'GetVisualGearValues', 'vgUid') then
970         begin
971         vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
972         if vg <> nil then
973             begin
974             lua_pushnumber(L, round(vg^.X));
975             lua_pushnumber(L, round(vg^.Y));
976             lua_pushnumber(L, vg^.dX);
977             lua_pushnumber(L, vg^.dY);
978             lua_pushnumber(L, vg^.Angle);
979             lua_pushnumber(L, vg^.Frame);
980             lua_pushnumber(L, vg^.FrameTicks);
981             lua_pushnumber(L, vg^.State);
982             lua_pushnumber(L, vg^.Timer);
983             lua_pushnumber(L, vg^.Tint);
984             lua_pushnumber(L, vg^.Scale);
985             end
986         else
987             begin
988             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
989             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
990             end
991         end
992     else
993         begin
994         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
995         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
996         end;
997     lc_getvisualgearvalues:= 10
998 end;
999 
lc_setvisualgearvaluesnull1000 function lc_setvisualgearvalues(L : Plua_State) : LongInt; Cdecl;
1001 var vg : PVisualGear;
1002 begin
1003 // Param count can be 1-11 at present
1004 //    if CheckLuaParamCount(L, 11, 'SetVisualGearValues', 'vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint, Scale') then
1005 //        begin
1006         vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
1007         if vg <> nil then
1008             begin
1009             if not lua_isnoneornil(L, 2) then
1010                 vg^.X:= Trunc(lua_tonumber(L, 2));
1011             if not lua_isnoneornil(L, 3) then
1012                 vg^.Y:= Trunc(lua_tonumber(L, 3));
1013             if not lua_isnoneornil(L, 4) then
1014                 vg^.dX:= lua_tonumber(L, 4);
1015             if not lua_isnoneornil(L, 5) then
1016                 vg^.dY:= lua_tonumber(L, 5);
1017             if not lua_isnoneornil(L, 6) then
1018                 vg^.Angle:= lua_tonumber(L, 6);
1019             if not lua_isnoneornil(L, 7) then
1020                 vg^.Frame:= Trunc(lua_tonumber(L, 7));
1021             if not lua_isnoneornil(L, 8) then
1022                 vg^.FrameTicks:= Trunc(lua_tonumber(L, 8));
1023             if not lua_isnoneornil(L, 9) then
1024                 vg^.State:= Trunc(lua_tonumber(L, 9));
1025             if not lua_isnoneornil(L, 10) then
1026                 vg^.Timer:= Trunc(lua_tonumber(L, 10));
1027             if not lua_isnoneornil(L, 11) then
1028                 vg^.Tint:= Trunc(lua_tonumber(L, 11));
1029             if not lua_isnoneornil(L, 12) then
1030                 vg^.Scale:= Trunc(lua_tonumber(L, 12))
1031             end;
1032 //        end
1033 //    else
1034 //        lua_pushnil(L); // return value on stack (nil)
1035     lc_setvisualgearvalues:= 0
1036 end;
1037 
1038 // so. going to use this to get/set some of the more obscure gear values which were not already exposed elsewhere
1039 // can keep adding things in the future. isnoneornil makes it safe
lc_getgearvaluesnull1040 function lc_getgearvalues(L : Plua_State) : LongInt; Cdecl;
1041 var gear: PGear;
1042 begin
1043     if CheckLuaParamCount(L, 1, 'GetGearValues', 'gearUid') then
1044         begin
1045         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1046         if gear <> nil then
1047             begin
1048             lua_pushnumber(L, gear^.Angle);
1049             lua_pushnumber(L, gear^.Power);
1050             lua_pushnumber(L, gear^.WDTimer);
1051             lua_pushnumber(L, gear^.Radius);
1052             lua_pushnumber(L, hwRound(gear^.Density * _10000));
1053             lua_pushnumber(L, gear^.Karma);
1054             lua_pushnumber(L,  gear^.DirAngle);
1055             lua_pushnumber(L, gear^.AdvBounce);
1056             lua_pushnumber(L, Integer(gear^.ImpactSound));
1057             lua_pushnumber(L, gear^.nImpactSounds);
1058             lua_pushnumber(L, gear^.Tint);
1059             lua_pushnumber(L, gear^.Damage);
1060             lua_pushnumber(L, gear^.Boom)
1061             end
1062         else
1063             begin
1064             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
1065             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
1066             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L)
1067             end
1068         end
1069     else
1070         begin
1071         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
1072         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
1073         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L)
1074         end;
1075     lc_getgearvalues:= 13
1076 end;
1077 
lc_setgearvaluesnull1078 function lc_setgearvalues(L : Plua_State) : LongInt; Cdecl;
1079 var gear : PGear;
1080 begin
1081 // Currently allows 1-14 params
1082 //    if CheckLuaParamCount(L, 14, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint, Damage, Boom') then
1083 //        begin
1084         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1085         if gear <> nil then
1086             begin
1087             if not lua_isnoneornil(L, 2) then
1088                 gear^.Angle := Trunc(lua_tonumber(L, 2));
1089             if not lua_isnoneornil(L, 3) then
1090                 gear^.Power := Trunc(lua_tonumber(L, 3));
1091             if not lua_isnoneornil(L, 4) then
1092                 gear^.WDTimer := Trunc(lua_tonumber(L, 4));
1093             if not lua_isnoneornil(L, 5) then
1094                 gear^.Radius := Trunc(lua_tonumber(L, 5));
1095             if not lua_isnoneornil(L, 6) then
1096                 gear^.Density:= int2hwFloat(Trunc(lua_tonumber(L, 6))) / 10000;
1097             if not lua_isnoneornil(L, 7) then
1098                 gear^.Karma := Trunc(lua_tonumber(L, 7));
1099             if not lua_isnoneornil(L, 8) then
1100                 gear^.DirAngle:= lua_tonumber(L, 8);
1101             if not lua_isnoneornil(L, 9) then
1102                 gear^.AdvBounce := Trunc(lua_tonumber(L, 9));
1103             if not lua_isnoneornil(L, 10) then
1104                 gear^.ImpactSound := TSound(Trunc(lua_tonumber(L, 10)));
1105             if not lua_isnoneornil(L, 11) then
1106                 gear^.nImpactSounds := Trunc(lua_tonumber(L, 11));
1107             if not lua_isnoneornil(L, 12) then
1108                 gear^.Tint := Trunc(lua_tonumber(L, 12));
1109             if not lua_isnoneornil(L, 13) then
1110                 gear^.Damage := Trunc(lua_tonumber(L, 13));
1111             if not lua_isnoneornil(L, 14) then
1112                 gear^.Boom := Trunc(lua_tonumber(L, 14));
1113             end;
1114 //        end
1115 //    else
1116 //        lua_pushnil(L); // return value on stack (nil)
1117     lc_setgearvalues:= 0
1118 end;
1119 
lc_getfollowgearnull1120 function lc_getfollowgear(L : Plua_State) : LongInt; Cdecl;
1121 begin
1122     if CheckLuaParamCount(L, 0, 'GetFollowGear', '') then
1123         begin
1124         if FollowGear = nil then
1125             lua_pushnil(L)
1126         else
1127             lua_pushnumber(L, FollowGear^.uid);
1128         end
1129     else
1130         lua_pushnil(L);
1131     lc_getfollowgear:= 1; // 1 return value
1132 end;
1133 
lc_getgeartypenull1134 function lc_getgeartype(L : Plua_State) : LongInt; Cdecl;
1135 var gear : PGear;
1136 begin
1137     if CheckLuaParamCount(L, 1, 'GetGearType', 'gearUid') then
1138         begin
1139         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1140         if gear <> nil then
1141             lua_pushnumber(L, ord(gear^.Kind))
1142         else
1143             lua_pushnil(L);
1144         end
1145     else
1146         lua_pushnil(L); // return value on stack (nil)
1147     lc_getgeartype:= 1
1148 end;
1149 
lc_getgearmessagenull1150 function lc_getgearmessage(L : Plua_State) : LongInt; Cdecl;
1151 var gear : PGear;
1152 begin
1153     if CheckLuaParamCount(L, 1, 'GetGearMessage', 'gearUid') then
1154         begin
1155         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1156         if gear <> nil then
1157             lua_pushnumber(L, gear^.message)
1158         else
1159             lua_pushnil(L);
1160         end
1161     else
1162         lua_pushnil(L); // return value on stack (nil)
1163     lc_getgearmessage:= 1
1164 end;
1165 
lc_getgearelasticitynull1166 function lc_getgearelasticity(L : Plua_State) : LongInt; Cdecl;
1167 var gear : PGear;
1168 begin
1169     if CheckLuaParamCount(L, 1, 'GetGearElasticity', 'gearUid') then
1170         begin
1171         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1172         if gear <> nil then
1173             lua_pushnumber(L, hwRound(gear^.elasticity * _10000))
1174         else
1175             lua_pushnil(L);
1176         end
1177     else
1178         lua_pushnil(L); // return value on stack (nil)
1179     lc_getgearelasticity:= 1
1180 end;
1181 
lc_setgearelasticitynull1182 function lc_setgearelasticity(L : Plua_State) : LongInt; Cdecl;
1183 var gear: PGear;
1184 begin
1185     if CheckLuaParamCount(L, 2, 'SetGearElasticity', 'gearUid, Elasticity') then
1186         begin
1187         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1188         if gear <> nil then
1189             gear^.Elasticity:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 10000
1190         end;
1191     lc_setgearelasticity:= 0
1192 end;
1193 
lc_getgearfrictionnull1194 function lc_getgearfriction(L : Plua_State) : LongInt; Cdecl;
1195 var gear : PGear;
1196 begin
1197     if CheckLuaParamCount(L, 1, 'GetGearFriction', 'gearUid') then
1198         begin
1199         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1200         if gear <> nil then
1201             lua_pushnumber(L, hwRound(gear^.friction * _10000))
1202         else
1203             lua_pushnil(L);
1204         end
1205     else
1206         lua_pushnil(L); // return value on stack (nil)
1207     lc_getgearfriction:= 1
1208 end;
1209 
lc_setgearfrictionnull1210 function lc_setgearfriction(L : Plua_State) : LongInt; Cdecl;
1211 var gear: PGear;
1212 begin
1213     if CheckLuaParamCount(L, 2, 'SetGearFriction', 'gearUid, Friction') then
1214         begin
1215         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1216         if gear <> nil then
1217             gear^.Friction:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 10000
1218         end;
1219     lc_setgearfriction:= 0
1220 end;
1221 
lc_setgearmessagenull1222 function lc_setgearmessage(L : Plua_State) : LongInt; Cdecl;
1223 var gear : PGear;
1224 begin
1225     if CheckLuaParamCount(L, 2, 'SetGearMessage', 'gearUid, message') then
1226         begin
1227         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1228         if gear <> nil then
1229             gear^.message:= Trunc(lua_tonumber(L, 2));
1230         end;
1231     lc_setgearmessage:= 0
1232 end;
1233 
lc_getgearposnull1234 function lc_getgearpos(L : Plua_State) : LongInt; Cdecl;
1235 var gear : PGear;
1236 begin
1237     if CheckLuaParamCount(L, 1, 'GetGearPos', 'gearUid') then
1238         begin
1239         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1240         if gear <> nil then
1241             lua_pushnumber(L, gear^.Pos)
1242         else
1243             lua_pushnil(L);
1244         end
1245     else
1246         lua_pushnil(L); // return value on stack (nil)
1247     lc_getgearpos:= 1
1248 end;
1249 
lc_setgearposnull1250 function lc_setgearpos(L : Plua_State) : LongInt; Cdecl;
1251 var gear : PGear;
1252 begin
1253     if CheckLuaParamCount(L, 2, 'SetGearPos', 'gearUid, value') then
1254         begin
1255         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1256         if gear <> nil then
1257             gear^.Pos:= Trunc(lua_tonumber(L, 2));
1258         end;
1259     lc_setgearpos:= 0
1260 end;
1261 
lc_getgearcollisionmasknull1262 function lc_getgearcollisionmask(L : Plua_State) : LongInt; Cdecl;
1263 var gear : PGear;
1264 begin
1265     if CheckLuaParamCount(L, 1, 'GetGearCollisionMask', 'gearUid') then
1266         begin
1267         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1268         if gear <> nil then
1269             lua_pushnumber(L, gear^.CollisionMask)
1270         else
1271             lua_pushnil(L);
1272         end
1273     else
1274         lua_pushnil(L); // return value on stack (nil)
1275     lc_getgearcollisionmask:= 1
1276 end;
1277 
lc_setgearcollisionmasknull1278 function lc_setgearcollisionmask(L : Plua_State) : LongInt; Cdecl;
1279 var gear : PGear;
1280 begin
1281     if CheckLuaParamCount(L, 2, 'SetGearCollisionMask', 'gearUid, mask') then
1282         begin
1283         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1284         if gear <> nil then
1285             gear^.CollisionMask:= Trunc(lua_tonumber(L, 2));
1286         end;
1287     lc_setgearcollisionmask:= 0
1288 end;
1289 
lc_gethoglevelnull1290 function lc_gethoglevel(L : Plua_State): LongInt; Cdecl;
1291 var gear : PGear;
1292 begin
1293     if CheckLuaParamCount(L, 1, 'GetHogLevel', 'gearUid') then
1294         begin
1295         gear := GearByUID(Trunc(lua_tonumber(L, 1)));
1296         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1297             lua_pushnumber(L, gear^.Hedgehog^.BotLevel)
1298         else
1299             lua_pushnil(L);
1300     end;
1301     lc_gethoglevel := 1;
1302 end;
1303 
lc_sethoglevelnull1304 function lc_sethoglevel(L : Plua_State) : LongInt; Cdecl;
1305 var gear : PGear;
1306 begin
1307     if CheckLuaParamCount(L, 2, 'SetHogLevel', 'gearUid, level') then
1308         begin
1309         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1310         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1311             gear^.Hedgehog^.BotLevel:= Trunc(lua_tonumber(L, 2));
1312         end;
1313     lc_sethoglevel:= 0
1314 end;
1315 
lc_gethogclannull1316 function lc_gethogclan(L : Plua_State) : LongInt; Cdecl;
1317 var gear : PGear;
1318 begin
1319     if CheckLuaParamCount(L, 1, 'GetHogClan', 'gearUid') then
1320         begin
1321         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1322         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1323             begin
1324             lua_pushnumber(L, gear^.Hedgehog^.Team^.Clan^.ClanIndex)
1325             end
1326         else
1327             lua_pushnil(L);
1328         end
1329     else
1330         lua_pushnil(L); // return value on stack (nil)
1331     lc_gethogclan:= 1
1332 end;
1333 
lc_getclancolornull1334 function lc_getclancolor(L : Plua_State) : LongInt; Cdecl;
1335 var idx: integer;
1336 begin
1337     if CheckLuaParamCount(L, 1, 'GetClanColor', 'clanIdx') then
1338         begin
1339         idx:= Trunc(lua_tonumber(L, 1));
1340         if (not lua_isnumber(L, 1)) then
1341             begin
1342             LuaError('Argument ''clanIdx'' must be a number!');
1343             lua_pushnil(L);
1344             end
1345         else if (idx < 0) or (idx >= ClansCount) then
1346             begin
1347             LuaError('Argument ''clanIdx'' out of range! (There are currently ' + IntToStr(ClansCount) + ' clans, so valid range is: 0-' + IntToStr(ClansCount-1) + ')');
1348             lua_pushnil(L);
1349             end
1350         else
1351             lua_pushnumber(L, ClansArray[idx]^.Color shl 8 or $FF);
1352         end
1353     else
1354         lua_pushnil(L); // return value on stack (nil)
1355     lc_getclancolor:= 1
1356 end;
1357 
lc_setclancolornull1358 function lc_setclancolor(L : Plua_State) : LongInt; Cdecl;
1359 var clan : PClan;
1360     team : PTeam;
1361     hh  : THedgehog;
1362     i, j : LongInt;
1363     colorArg: Int64;
1364     color: LongWord;
1365 begin
1366     if CheckLuaParamCount(L, 2, 'SetClanColor', 'clan, color') then
1367         begin
1368         i:= Trunc(lua_tonumber(L,1));
1369         if i >= ClansCount then exit(0);
1370         clan := ClansArray[i];
1371         colorArg:= Trunc(lua_tonumber(L, 2));
1372         if (colorArg < 0) and (abs(colorArg) <= cClanColors) then
1373             // Pick clan color from settings (recommended)
1374             color:= ClanColorArray[Pred(abs(colorArg))]
1375         else if (colorArg >= 0) and (colorArg <= $ffffffff) then
1376             // Specify color directly
1377             color:= colorArg shr 8
1378         else
1379             begin
1380             OutError('Lua error: SetClanColor: Invalid ''color'' argument, must be between '+IntToStr(-cClanColors)+' and 0xffffffff!', true);
1381             lc_setclancolor:= 0;
1382             exit;
1383             end;
1384 
1385         clan^.Color:= color;
1386 
1387         for i:= 0 to Pred(clan^.TeamsNumber) do
1388             begin
1389             team:= clan^.Teams[i];
1390             for j:= 0 to cMaxHHIndex do
1391                 begin
1392                 hh:= team^.Hedgehogs[j];
1393                 if (hh.Gear <> nil) or (hh.GearHidden <> nil) then
1394                     begin
1395                     FreeAndNilTexture(hh.NameTagTex);
1396                     hh.NameTagTex:= RenderStringTex(ansistring(hh.Name), clan^.Color, fnt16);
1397                     RenderHealth(hh);
1398                     team^.Hedgehogs[j]:= hh;
1399                     end;
1400                 end;
1401             FreeAndNilTexture(team^.NameTagTex);
1402             team^.NameTagTex:= RenderStringTex(ansistring(clan^.Teams[i]^.TeamName), clan^.Color, fnt16);
1403             end;
1404 
1405         FreeAndNilTexture(clan^.HealthTex);
1406         clan^.HealthTex:= makeHealthBarTexture(cTeamHealthWidth + 5, clan^.Teams[0]^.NameTagTex^.h, clan^.Color);
1407         end;
1408 
1409     lc_setclancolor:= 0
1410 end;
1411 
lc_gethogvoicepacknull1412 function lc_gethogvoicepack(L : Plua_State) : LongInt; Cdecl;
1413 var gear : PGear;
1414 begin
1415     if CheckLuaParamCount(L, 1, 'GetHogVoicepack', 'gearUid') then
1416         begin
1417         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1418         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1419             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Voicepack^.name))
1420         else
1421             lua_pushnil(L);
1422         end
1423     else
1424         lua_pushnil(L); // return value on stack (nil)
1425     lc_gethogvoicepack:= 1
1426 end;
1427 
lc_gethoggravenull1428 function lc_gethoggrave(L : Plua_State) : LongInt; Cdecl;
1429 var gear : PGear;
1430 begin
1431     if CheckLuaParamCount(L, 1, 'GetHogGrave', 'gearUid') then
1432         begin
1433         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1434         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1435             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.GraveName))
1436         else
1437             lua_pushnil(L);
1438         end
1439     else
1440         lua_pushnil(L); // return value on stack (nil)
1441     lc_gethoggrave:= 1
1442 end;
1443 
lc_gethogflagnull1444 function lc_gethogflag(L : Plua_State) : LongInt; Cdecl;
1445 var gear : PGear;
1446 begin
1447     if CheckLuaParamCount(L, 1, 'GetHogFlag', 'gearUid') then
1448         begin
1449         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1450         // TODO error messages
1451         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1452             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Flag))
1453         else
1454             lua_pushnil(L);
1455         end
1456     else
1457         lua_pushnil(L); // return value on stack (nil)
1458     lc_gethogflag:= 1
1459 end;
1460 
lc_gethogfortnull1461 function lc_gethogfort(L : Plua_State) : LongInt; Cdecl;
1462 var gear : PGear;
1463 begin
1464     if CheckLuaParamCount(L, 1, 'GetHogFort', 'gearUid') then
1465         begin
1466         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1467         // TODO error messages
1468         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1469             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.FortName))
1470         else
1471             lua_pushnil(L);
1472         end
1473     else
1474         lua_pushnil(L); // return value on stack (nil)
1475     lc_gethogfort:= 1
1476 end;
1477 
lc_ishogalivenull1478 function lc_ishogalive(L : Plua_State) : LongInt; Cdecl;
1479 var gear : PGear;
1480 begin
1481     if CheckLuaParamCount(L, 1, 'IsHogAlive', 'gearUid') then
1482         begin
1483         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1484         if gear <> nil then
1485             if gear^.Kind = gtHedgehog then
1486                 if (gear^.Health > 0) and (gear^.Health > gear^.Damage) and ((gear^.State and (gstDrowning or gstHHDeath)) = 0) and ((gear^.Message and gmDestroy) = 0) then
1487                     lua_pushboolean(L, true)
1488                 else
1489                     lua_pushboolean(L, false)
1490             else
1491                 lua_pushboolean(L, false)
1492         else
1493             lua_pushboolean(L, false);
1494         end
1495     else
1496         lua_pushnil(L); // return value on stack (nil)
1497     lc_ishogalive:= 1
1498 end;
1499 
lc_ishoglocalnull1500 function lc_ishoglocal(L : Plua_State) : LongInt; Cdecl;
1501 var gear : PGear;
1502 begin
1503     if CheckLuaParamCount(L, 1, 'IsHogLocal', 'gearUid') then
1504         begin
1505         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1506         // TODO error messages
1507         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1508             lua_pushboolean(L, IsHogLocal(gear^.Hedgehog))
1509         else
1510             lua_pushnil(L);
1511         end
1512     else
1513         lua_pushnil(L); // return value on stack (nil)
1514     lc_ishoglocal:= 1
1515 end;
1516 
lc_gethogteamnamenull1517 function lc_gethogteamname(L : Plua_State) : LongInt; Cdecl;
1518 var gear : PGear;
1519 begin
1520     if CheckLuaParamCount(L, 1, 'GetHogTeamName', 'gearUid') then
1521         begin
1522         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1523         // TODO error messages
1524         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1525             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.TeamName))
1526         else
1527             lua_pushnil(L);
1528         end
1529     else
1530         lua_pushnil(L); // return value on stack (nil)
1531     lc_gethogteamname:= 1
1532 end;
1533 
lc_sethogteamnamenull1534 function lc_sethogteamname(L : Plua_State) : LongInt; Cdecl;
1535 var gear : PGear;
1536 begin
1537     if CheckLuaParamCount(L, 2, 'SetHogTeamName', 'gearUid, name') then
1538         begin
1539         gear := GearByUID(Trunc(lua_tonumber(L, 1)));
1540         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1541             begin
1542             gear^.Hedgehog^.Team^.TeamName := lua_tostring(L, 2);
1543 
1544             FreeAndNilTexture(gear^.Hedgehog^.Team^.NameTagTex);
1545             gear^.Hedgehog^.Team^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Team^.TeamName), gear^.Hedgehog^.Team^.Clan^.Color, fnt16);
1546             end
1547         else
1548             lua_pushnil(L);
1549         end
1550     else
1551         lua_pushnil(L); // return value on stack (nil)
1552     lc_sethogteamname:= 1
1553 end;
1554 
lc_gethognamenull1555 function lc_gethogname(L : Plua_State) : LongInt; Cdecl;
1556 var gear : PGear;
1557 begin
1558     if CheckLuaParamCount(L, 1, 'GetHogName', 'gearUid') then
1559         begin
1560         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1561         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
1562             begin
1563             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Name))
1564             end
1565         else
1566             lua_pushnil(L);
1567         end
1568     else
1569         lua_pushnil(L); // return value on stack (nil)
1570     lc_gethogname:= 1
1571 end;
1572 
lc_sethognamenull1573 function lc_sethogname(L : Plua_State) : LongInt; Cdecl;
1574 var gear : PGear;
1575 begin
1576     if CheckLuaParamCount(L, 2, 'SetHogName', 'gearUid, name') then
1577         begin
1578         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1579         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1580             begin
1581             gear^.Hedgehog^.Name:= lua_tostring(L, 2);
1582 
1583             FreeAndNilTexture(gear^.Hedgehog^.NameTagTex);
1584             gear^.Hedgehog^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Name), gear^.Hedgehog^.Team^.Clan^.Color, fnt16)
1585             end
1586         end;
1587     lc_sethogname:= 0;
1588 end;
1589 
lc_gettimernull1590 function lc_gettimer(L : Plua_State) : LongInt; Cdecl;
1591 var gear : PGear;
1592 begin
1593     if CheckLuaParamCount(L, 1, 'GetTimer', 'gearUid') then
1594         begin
1595         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1596         if gear <> nil then
1597             lua_pushnumber(L, gear^.Timer)
1598         else
1599             lua_pushnil(L);
1600         end
1601     else
1602         lua_pushnil(L); // return value on stack (nil)
1603     lc_gettimer:= 1
1604 end;
1605 
lc_getflighttimenull1606 function lc_getflighttime(L : Plua_State) : LongInt; Cdecl;
1607 var gear : PGear;
1608 begin
1609     if CheckLuaParamCount(L, 1, 'GetFlightTime', 'gearUid') then
1610         begin
1611         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1612         if gear <> nil then
1613             lua_pushnumber(L, gear^.FlightTime)
1614         else
1615             lua_pushnil(L);
1616         end
1617     else
1618         lua_pushnil(L); // return value on stack (nil)
1619     lc_getflighttime:= 1
1620 end;
1621 
lc_gethealthnull1622 function lc_gethealth(L : Plua_State) : LongInt; Cdecl;
1623 var gear : PGear;
1624 begin
1625     if CheckLuaParamCount(L, 1, 'GetHealth', 'gearUid') then
1626         begin
1627         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1628         if gear <> nil then
1629             lua_pushnumber(L, gear^.Health)
1630         else
1631             lua_pushnil(L);
1632         end
1633     else
1634         lua_pushnil(L); // return value on stack (nil)
1635     lc_gethealth:= 1
1636 end;
1637 
lc_getxnull1638 function lc_getx(L : Plua_State) : LongInt; Cdecl;
1639 var gear : PGear;
1640 begin
1641     if CheckLuaParamCount(L, 1, 'GetX', 'gearUid') then
1642         begin
1643         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1644         if gear <> nil then
1645             lua_pushnumber(L, hwRound(gear^.X))
1646         else
1647             lua_pushnil(L);
1648         end
1649     else
1650         lua_pushnil(L); // return value on stack (nil)
1651     lc_getx:= 1
1652 end;
1653 
lc_getynull1654 function lc_gety(L : Plua_State) : LongInt; Cdecl;
1655 var gear : PGear;
1656 begin
1657     if CheckLuaParamCount(L, 1, 'GetY', 'gearUid') then
1658         begin
1659         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1660         if gear <> nil then
1661             lua_pushnumber(L, hwRound(gear^.Y))
1662         else
1663             lua_pushnil(L);
1664         end
1665     else
1666         lua_pushnil(L); // return value on stack (nil)
1667     lc_gety:= 1
1668 end;
1669 
lc_copypvnull1670 function lc_copypv(L : Plua_State) : LongInt; Cdecl;
1671 var gears, geard : PGear;
1672 begin
1673     if CheckLuaParamCount(L, 2, 'CopyPV', 'fromGearUid, toGearUid') then
1674         begin
1675         gears:= GearByUID(Trunc(lua_tonumber(L, 1)));
1676         geard:= GearByUID(Trunc(lua_tonumber(L, 2)));
1677         if (gears <> nil) and (geard <> nil) then
1678             begin
1679             geard^.X:= gears^.X;
1680             geard^.Y:= gears^.Y;
1681             geard^.dX:= gears^.dX;
1682             geard^.dY:= gears^.dY;
1683             end
1684         end;
1685     lc_copypv:= 0
1686 end;
1687 
lc_followgearnull1688 function lc_followgear(L : Plua_State) : LongInt; Cdecl;
1689 var gear : PGear;
1690 begin
1691     if CheckLuaParamCount(L, 1, 'FollowGear', 'gearUid') then
1692         begin
1693         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1694         if gear <> nil then FollowGear:= gear
1695         end;
1696     lc_followgear:= 0
1697 end;
1698 
lc_hogsaynull1699 function lc_hogsay(L : Plua_State) : LongInt; Cdecl;
1700 var gear : PGear;
1701    vgear : PVisualGear;
1702        s : LongWord;
1703        n : LongInt;
1704 begin
1705     if CheckAndFetchParamCount(L, 3, 4, 'HogSay', 'gearUid, text, manner [, vgState]', n) then
1706         begin
1707         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1708         if gear <> nil then
1709             begin
1710             // state defaults to 0 if state param is given
1711             if n = 4 then
1712                 s:= Trunc(lua_tonumber(L, 4))
1713             else
1714                 s:= 0;
1715             vgear:= AddVisualGear(0, 0, vgtSpeechBubble, s, true);
1716             if vgear <> nil then
1717                begin
1718                vgear^.Text:= lua_tostring(L, 2);
1719                if Gear^.Kind = gtHedgehog then
1720                    begin
1721                    AddChatString(#9+Format(shortstring(trmsg[sidChatHog]), gear^.Hedgehog^.Name, vgear^.text));
1722                    vgear^.Hedgehog:= gear^.Hedgehog
1723                    end
1724                else vgear^.Frame:= gear^.uid;
1725 
1726                vgear^.FrameTicks:= Trunc(lua_tonumber(L, 3));
1727                if (vgear^.FrameTicks < 1) or (vgear^.FrameTicks > 3) then
1728                    vgear^.FrameTicks:= 1;
1729                lua_pushnumber(L, vgear^.Uid);
1730                end
1731             end
1732         else
1733             lua_pushnil(L)
1734         end
1735     else
1736         lua_pushnil(L);
1737     lc_hogsay:= 1
1738 end;
1739 
lc_switchhognull1740 function lc_switchhog(L : Plua_State) : LongInt; Cdecl;
1741 var gear, prevgear : PGear;
1742 begin
1743     if CheckLuaParamCount(L, 1, 'SwitchHog', 'gearUid') then
1744         begin
1745         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1746 // should we allow this when there is no current hedgehog? might do some odd(er) things to turn sequence.
1747         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) and (CurrentHedgehog <> nil) then
1748             begin
1749             CurrentHedgehog^.MultiShootAttacks:= 0;
1750             prevgear := CurrentHedgehog^.Gear;
1751             if prevgear <> nil then
1752                 begin
1753                 prevgear^.Active := false;
1754                 prevgear^.State:= prevgear^.State and (not gstHHDriven);
1755                 prevgear^.Z := cHHZ;
1756                 prevgear^.Message:= prevgear^.Message or gmRemoveFromList or gmAddToList;
1757                 end;
1758 
1759             SwitchCurrentHedgehog(gear^.Hedgehog);
1760             AmmoMenuInvalidated:= true;
1761             CurrentTeam:= CurrentHedgehog^.Team;
1762 
1763             repeat
1764                 CurrentTeam^.CurrHedgehog := (CurrentTeam^.CurrHedgehog + 1) mod CurrentTeam^.HedgehogsNumber
1765             until
1766                 CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear = CurrentHedgehog^.Gear;
1767 
1768             gear^.State:= gear^.State or gstHHDriven;
1769             gear^.Active := true;
1770             gear^.Z := cCurrHHZ;
1771             gear^.Message:= gear^.Message or gmRemoveFromList or gmAddToList;
1772             end
1773         end;
1774     lc_switchhog:= 0
1775 end;
1776 
lc_enableswitchhognull1777 function lc_enableswitchhog(L : Plua_State) : LongInt; Cdecl;
1778 var gear, iterator: PGear;
1779     alreadySwitching: boolean;
1780 begin
1781     if CheckLuaParamCount(L, 0, 'EnableSwitchHog', '') then
1782         if ((CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)) then
1783             begin
1784             alreadySwitching:= false;
1785             iterator:= GearsList;
1786             // Check if there's already a switcher gear
1787             while (iterator <> nil) do
1788                 begin
1789                 if (iterator^.Kind = gtSwitcher) then
1790                     begin
1791                     alreadySwitching:= true;
1792                     lua_pushnumber(L, iterator^.Uid);
1793                     break;
1794                     end;
1795                 iterator:= iterator^.NextGear;
1796                 end;
1797             if (not alreadySwitching) then
1798                 begin
1799                 // Enable switching and return gear UID
1800                 gear:= AddGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), gtSwitcher, 0, _0, _0, 0);
1801                 CurAmmoGear:= gear;
1802                 lastGearByUID:= gear;
1803                 bShowFinger:= false;
1804                 lua_pushnumber(L, gear^.Uid);
1805                 end;
1806             end
1807     // Return nil on failure
1808         else
1809             lua_pushnil(L)
1810     else
1811         lua_pushnil(L);
1812     lc_enableswitchhog:= 1;
1813 end;
1814 
1815 function lc_addammo(L : Plua_State) : LongInt; Cdecl;
1816 var gear : PGear;
1817     at, n, c: LongInt;
1818 const
1819     call = 'AddAmmo';
1820     params = 'gearUid, ammoType [, ammoCount]';
1821 begin
1822     if CheckAndFetchParamCount(L, 2, 3, call, params, n) then
1823         begin
1824         at:= LuaToAmmoTypeOrd(L, 2, call, params);
1825         if (at >= 0) and (TAmmoType(at) <> amNothing) then
1826             begin
1827             gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1828             if (gear <> nil) and (gear^.Hedgehog <> nil) then
1829                 if n = 2 then
1830                     AddAmmo(gear^.Hedgehog^, TAmmoType(at))
1831                 else
1832                     begin
1833                     c:= Trunc(lua_tonumber(L, 3));
1834                     if (c = 0) and (CurrentHedgehog = gear^.Hedgehog) and (gear^.Hedgehog^.CurAmmoType = TAmmoType(at)) then
1835                         ParseCommand('setweap ' + char(0), true, true);
1836                     SetAmmo(gear^.Hedgehog^, TAmmoType(at), c);
1837                     end;
1838             end;
1839         end;
1840     lc_addammo:= 0
1841 end;
1842 
1843 function lc_getammocount(L : Plua_State) : LongInt; Cdecl;
1844 var gear : PGear;
1845     ammo : PAmmo;
1846     at   : LongInt;
1847 const
1848     call = 'GetAmmoCount';
1849     params = 'gearUid, ammoType';
1850 begin
1851     if CheckLuaParamCount(L, 2, call, params) then
1852         begin
1853         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1854         if (gear <> nil) and (gear^.Hedgehog <> nil) then
1855             begin
1856             at:= LuaToAmmoTypeOrd(L, 2, call, params);
1857             if at >= 0 then
1858                 begin
1859                 ammo:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(at));
1860                 if ammo^.AmmoType = amNothing then
1861                     lua_pushnumber(L, 0)
1862                 else
1863                     lua_pushnumber(L, ammo^.Count);
1864                 end;
1865             end
1866         else lua_pushnumber(L, 0);
1867         end
1868     else
1869         lua_pushnil(L);
1870     lc_getammocount:= 1
1871 end;
1872 
1873 function lc_sethealth(L : Plua_State) : LongInt; Cdecl;
1874 var gear : PGear;
1875 begin
1876     if CheckLuaParamCount(L, 2, 'SetHealth', 'gearUid, health') then
1877         begin
1878         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1879         if gear <> nil then
1880             begin
1881             gear^.Health:= Trunc(lua_tonumber(L, 2));
1882 
1883             if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
1884                 begin
1885                 if gear^.Health > cMaxHogHealth then
1886                     gear^.Health:= cMaxHogHealth;
1887                 if gear^.Health < 0 then
1888                     gear^.Health:= 0;
1889                 RenderHealth(gear^.Hedgehog^);
1890                 RecountTeamHealth(gear^.Hedgehog^.Team)
1891                 end
1892             else if (gear^.RenderHealth) and (gear^.Tex <> nil) then
1893                 FreeAndNilTexture(gear^.Tex);
1894             Gear^.Active:= true;
1895             AllInactive:= false
1896             end
1897         end;
1898     lc_sethealth:= 0
1899 end;
1900 
1901 function lc_healhog(L : Plua_State) : LongInt; Cdecl;
1902 var gear : PGear;
1903     healthBoost, n: LongInt;
1904 begin
1905     if CheckAndFetchParamCountRange(L, 2, 4, 'HealHog', 'gearUid, healthBoost [, showMessage [, tint]]', n) then
1906         begin
1907         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1908         healthBoost:= Trunc(lua_tonumber(L, 2));
1909         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) and (healthBoost >= 1) then
1910             begin
1911             healthBoost:= IncHogHealth(gear^.Hedgehog, healthBoost);
1912             RenderHealth(gear^.Hedgehog^);
1913             RecountTeamHealth(gear^.Hedgehog^.Team);
1914             if n = 4 then
1915                 HHHeal(gear^.Hedgehog, healthBoost, lua_toboolean(L, 3), Trunc(lua_tonumber(L, 4)))
1916             else if n = 3 then
1917                 HHHeal(gear^.Hedgehog, healthBoost, lua_toboolean(L, 3))
1918             else if n = 2 then
1919                 HHHeal(gear^.Hedgehog, healthBoost, true);
1920             Gear^.Active:= true;
1921             AllInactive:= false
1922             end
1923         end;
1924     lc_healhog:= 0
1925 end;
1926 
1927 function lc_settimer(L : Plua_State) : LongInt; Cdecl;
1928 var gear : PGear;
1929 begin
1930     if CheckLuaParamCount(L, 2, 'SetTimer', 'gearUid, timer') then
1931         begin
1932         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1933         if gear <> nil then
1934             begin
1935             gear^.Timer:= Trunc(lua_tonumber(L, 2));
1936             if gear^.RenderTimer and (gear^.Tex <> nil) then
1937                 FreeAndNilTexture(gear^.Tex);
1938             end;
1939         end;
1940     lc_settimer:= 0
1941 end;
1942 
1943 function lc_setflighttime(L : Plua_State) : LongInt; Cdecl;
1944 var gear : PGear;
1945 begin
1946     if CheckLuaParamCount(L, 2, 'SetFlightTime', 'gearUid, flighttime') then
1947         begin
1948         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1949         if gear <> nil then gear^.FlightTime:= Trunc(lua_tonumber(L, 2))
1950         end;
1951     lc_setflighttime:= 0
1952 end;
1953 
1954 function lc_seteffect(L : Plua_State) : LongInt; Cdecl;
1955 var gear: PGear;
1956     t   : LongInt;
1957 const
1958     call = 'SetEffect';
1959     params = 'gearUid, effect, effectState';
1960 begin
1961     if CheckLuaParamCount(L, 3, call, params) then
1962         begin
1963         t:= LuaToHogEffectOrd(L, 2, call, params);
1964         if t >= 0 then
1965             begin
1966             gear := GearByUID(Trunc(lua_tonumber(L, 1)));
1967             if (gear <> nil) and (gear^.Hedgehog <> nil) then
1968                 gear^.Hedgehog^.Effects[THogEffect(t)]:= Trunc(lua_tonumber(L, 3));
1969             end;
1970         end;
1971     lc_seteffect := 0;
1972 end;
1973 
1974 function lc_geteffect(L : Plua_State) : LongInt; Cdecl;
1975 var gear : PGear;
1976     t    : LongInt;
1977 const
1978     call = 'GetEffect';
1979     params = 'gearUid, effect';
1980 begin
1981     if CheckLuaParamCount(L, 2, call, params) then
1982         begin
1983         t:= LuaToHogEffectOrd(L, 2, call, params);
1984         if t >= 0 then
1985             begin
1986             gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
1987             if (gear <> nil) and (gear^.Hedgehog <> nil) then
1988                 lua_pushnumber(L, gear^.Hedgehog^.Effects[THogEffect(t)])
1989             else
1990                 lua_pushnumber(L, 0)
1991             end;
1992         end
1993     else
1994         lua_pushnumber(L, 0);
1995     lc_geteffect:= 1
1996 end;
1997 
1998 function lc_setstate(L : Plua_State) : LongInt; Cdecl;
1999 var gear : PGear;
2000 begin
2001     if CheckLuaParamCount(L, 2, 'SetState', 'gearUid, state') then
2002         begin
2003         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2004         if gear <> nil then
2005             begin
2006             gear^.State:= Trunc(lua_tonumber(L, 2));
2007             SetAllToActive;
2008             end
2009         end;
2010     lc_setstate:= 0
2011 end;
2012 
2013 function lc_getstate(L : Plua_State) : LongInt; Cdecl;
2014 var gear : PGear;
2015 begin
2016     if CheckLuaParamCount(L, 1, 'GetState', 'gearUid') then
2017         begin
2018         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2019         if gear <> nil then
2020             lua_pushnumber(L, gear^.State)
2021         else
2022             lua_pushnil(L)
2023         end
2024     else
2025         lua_pushnil(L); // return value on stack (nil)
2026     lc_getstate:= 1
2027 end;
2028 
2029 function lc_gettag(L : Plua_State) : LongInt; Cdecl;
2030 var gear : PGear;
2031 begin
2032     if CheckLuaParamCount(L, 1, 'GetTag', 'gearUid') then
2033         begin
2034         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2035         if gear <> nil then
2036             lua_pushnumber(L, gear^.Tag)
2037         else
2038             lua_pushnil(L);
2039         end
2040     else
2041         lua_pushnil(L); // return value on stack (nil)
2042     lc_gettag:= 1
2043 end;
2044 
2045 function lc_settag(L : Plua_State) : LongInt; Cdecl;
2046 var gear : PGear;
2047 begin
2048     if CheckLuaParamCount(L, 2, 'SetTag', 'gearUid, tag') then
2049         begin
2050         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2051         if gear <> nil then
2052             begin
2053             gear^.Tag:= Trunc(lua_tonumber(L, 2));
2054             SetAllToActive;
2055             end
2056         end;
2057     lc_settag:= 0
2058 end;
2059 
2060 function lc_endgame(L : Plua_State) : LongInt; Cdecl;
2061 begin
2062     L:= L; // avoid compiler hint
2063     GameOver:= true;
2064     AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000);
2065     lc_endgame:= 0
2066 end;
2067 
2068 function lc_endturn(L : Plua_State) : LongInt; Cdecl;
2069 var n: LongInt;
2070 const
2071     call = 'EndTurn';
2072     params = '[noTaunts]';
2073 begin
2074     if CheckAndFetchParamCount(L, 0, 1, call, params, n) then
2075         if n >= 1 then
2076             LuaNoEndTurnTaunts:= lua_toboolean(L, 1);
2077     LuaEndTurnRequested:= true;
2078     lc_endturn:= 0
2079 end;
2080 
2081 function lc_retreat(L : Plua_State) : LongInt; Cdecl;
2082 var n, time: LongInt;
2083     respectFactor: Boolean;
2084 const
2085     call = 'Retreat';
2086     params = 'time [, respectGetAwayTimeFactor]';
2087 begin
2088     if CheckAndFetchParamCount(L, 1, 2, call, params, n) then
2089         begin
2090         IsGetAwayTime:= true;
2091         AttackBar:= 0;
2092         time:= Trunc(lua_tonumber(L, 1));
2093         if n = 2 then
2094             respectFactor:= lua_toboolean(L, 2)
2095         else
2096             respectFactor:= True;
2097         if respectFactor then
2098             PendingTurnTimeLeft:= (time * cGetAwayTime) div 100
2099         else
2100             PendingTurnTimeLeft:= time;
2101         isPendingTurnTimeLeft:= true;
2102         if ((CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)) then
2103             begin
2104             CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstAttacked;
2105             CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State and (not gstAttacking);
2106             end;
2107         end;
2108     lc_retreat:= 0
2109 end;
2110 
2111 function lc_skipturn(L : Plua_State): LongInt; Cdecl;
2112 begin
2113     L:= L; // avoid compiler hint
2114     ParseCommand('skip', true, true);
2115     lc_skipturn:= 0;
2116 end;
2117 
2118 function lc_sendstat(L : Plua_State) : LongInt; Cdecl;
2119 var statInfo : TStatInfoType;
2120     i, n     : LongInt;
2121     color, tn: shortstring;
2122     needsTn  : boolean;
2123 const
2124     call = 'SendStat';
2125     params = 'statInfoType, color [, teamname]';
2126 begin
2127     if CheckAndFetchParamCount(L, 2, 3, call, params, n) then
2128         begin
2129         i:= LuaToStatInfoTypeOrd(L, 1, call, params);
2130         if i >= 0 then
2131             begin
2132             statInfo:= TStatInfoType(i);
2133             needsTn:= ((statInfo = siPlayerKills) or (statInfo = siClanHealth));
2134             // check if param count is correct for the used statInfo
2135             if (n = 3) <> needsTn then
2136                 begin
2137                 if n = 3 then
2138                     LuaCallError(EnumToStr(statInfo) + ' does not support the teamname parameter', call, params)
2139                 else
2140                     LuaCallError(EnumToStr(statInfo) + ' requires the teamname parameter', call, params);
2141                 end
2142             else // count is correct!
2143                 begin
2144                 if needsTn then
2145                     begin
2146                     // 3: team name
2147                     for i:= 0 to Pred(TeamsCount) do
2148                         begin
2149                         color:= _S'0';
2150                         tn:= lua_tostring(L, 3);
2151                         with TeamsArray[i]^ do
2152                             begin
2153                                 if TeamName = tn then
2154                                     begin
2155                                     color := uUtils.IntToStr(Clan^.Color);
2156                                     Break;
2157                                     end
2158                             end
2159                         end;
2160                     if (statInfo = siPlayerKills) then
2161                         begin
2162                             SendStat(siPlayerKills, color + ' ' +
2163                                 lua_tostring(L, 2) + ' ' + tn);
2164                         end
2165                     else if (statInfo = siClanHealth) then
2166                         begin
2167                             SendStat(siClanHealth, color + ' ' +
2168                                 lua_tostring(L, 2));
2169                         end
2170                     end
2171                 else
2172                     begin
2173                     SendStat(statInfo,lua_tostring(L, 2));
2174                     end;
2175                 end;
2176             end;
2177         end;
2178     lc_sendstat:= 0
2179 end;
2180 
2181 function lc_sendgameresultoff(L : Plua_State) : LongInt; Cdecl;
2182 begin
2183     L:= L; // avoid compiler hint
2184     uStats.SendGameResultOn := false;
2185     lc_sendgameresultoff:= 0
2186 end;
2187 
2188 function lc_sendrankingstatsoff(L : Plua_State) : LongInt; Cdecl;
2189 begin
2190     L:= L; // avoid compiler hint
2191     uStats.SendRankingStatsOn := false;
2192     lc_sendrankingstatsoff:= 0
2193 end;
2194 
2195 function lc_sendachievementsstatsoff(L : Plua_State) : LongInt; Cdecl;
2196 begin
2197     L:= L; // avoid compiler hint
2198     uStats.SendAchievementsStatsOn := false;
2199     lc_sendachievementsstatsoff:= 0
2200 end;
2201 
2202 function lc_sendhealthstatsoff(L : Plua_State) : LongInt; Cdecl;
2203 begin
2204     L:= L; // avoid compiler hint
2205     uStats.SendHealthStatsOn := false;
2206     lc_sendhealthstatsoff:= 0
2207 end;
2208 
2209 function lc_findplace(L : Plua_State) : LongInt; Cdecl;
2210 var gear: PGear;
2211     fall: boolean;
2212     tryhard: boolean;
2213     left, right, n: LongInt;
2214 begin
2215     if CheckAndFetchParamCount(L, 4, 5, 'FindPlace', 'gearUid, fall, left, right [, tryHarder]', n) then
2216         begin
2217         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2218         fall:= lua_toboolean(L, 2);
2219         left:= Trunc(lua_tonumber(L, 3));
2220         right:= Trunc(lua_tonumber(L, 4));
2221         if n = 5 then
2222             tryhard:= lua_toboolean(L, 5)
2223         else
2224             tryhard:= false;
2225         if gear <> nil then
2226             FindPlace(gear, fall, left, right, tryhard);
2227         if gear <> nil then
2228             lua_pushnumber(L, gear^.uid)
2229         else
2230             lua_pushnil(L);
2231         end
2232     else
2233         lua_pushnil(L); // return value on stack (nil)
2234     lc_findplace:= 1
2235 end;
2236 
2237 function lc_playsound(L : Plua_State) : LongInt; Cdecl;
2238 var gear: PGear;
2239     n, s: LongInt;
2240     instaVoice: boolean;
2241 const
2242     call = 'PlaySound';
2243     params = 'soundId [, hhGearUid [, instaVoice]]';
2244 begin
2245     if CheckAndFetchParamCountRange(L, 1, 3, call, params, n) then
2246         begin
2247         s:= LuaToSoundOrd(L, 1, call, params);
2248         if s >= 0 then
2249             begin
2250             // no gear specified
2251             if n = 1 then
2252                 PlaySound(TSound(s), false, true)
2253             else
2254                 begin
2255                 gear:= GearByUID(Trunc(lua_tonumber(L, 2)));
2256                 if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
2257                     begin
2258                     instaVoice:= false;
2259                     if n = 3 then
2260                         instaVoice:= lua_toboolean(L, 3);
2261                     if instaVoice then
2262                         PlaySoundV(TSound(s), gear^.Hedgehog^.Team^.Voicepack, false, true)
2263                     else
2264                         AddVoice(TSound(s), gear^.Hedgehog^.Team^.Voicepack, true, false);
2265                     end;
2266                 end;
2267             end;
2268         end;
2269     lc_playsound:= 0;
2270 end;
2271 
2272 function lc_playmusicsound(L : Plua_State) : LongInt; Cdecl;
2273 var s: LongInt;
2274 const
2275     call = 'PlayMusicSound';
2276     params = 'soundId';
2277 begin
2278     if CheckLuaParamCount(L, 1, call, params) then
2279         begin
2280         s:= LuaToSoundOrd(L, 1, call, params);
2281         if s >= 0 then
2282             PlayMusicSound(TSound(s))
2283         end;
2284     lc_playmusicsound:= 0;
2285 end;
2286 
2287 function lc_stopmusicsound(L : Plua_State) : LongInt; Cdecl;
2288 var s: LongInt;
2289 const
2290     call = 'StopMusicSound';
2291     params = 'soundId';
2292 begin
2293     if CheckLuaParamCount(L, 1, call, params) then
2294         begin
2295         s:= LuaToSoundOrd(L, 1, call, params);
2296         if s >= 0 then
2297             StopMusicSound(TSound(s))
2298         end;
2299     lc_stopmusicsound:= 0;
2300 end;
2301 
2302 
2303 function lc_setsoundmask(L : Plua_State) : LongInt; Cdecl;
2304 var s: LongInt;
2305     soundState: boolean;
2306 const
2307     call = 'SetSoundMask';
2308     params = 'soundId, isMasked';
2309 begin
2310     if CheckLuaParamCount(L, 2, call, params) then
2311         begin
2312         s:= LuaToSoundOrd(L, 1, call, params);
2313         if s <> Ord(sndNone) then
2314             begin
2315             soundState:= lua_toboolean(L, 2);
2316             MaskedSounds[TSound(s)]:= soundState;
2317             end;
2318         end;
2319     lc_setsoundmask:= 0;
2320 end;
2321 
2322 function lc_addteam(L : Plua_State) : LongInt; Cdecl;
2323 var np: LongInt;
2324     colorArg: Int64;
2325     colorStr: shortstring;
2326 begin
2327     if CheckAndFetchParamCount(L, 5, 6, 'AddTeam', 'teamname, color, grave, fort, voicepack [, flag]', np) then
2328         begin
2329         colorArg:= Trunc(lua_tonumber(L, 2));
2330         if (colorArg < 0) and (abs(colorArg) <= cClanColors) then
2331             // Pick clan color from settings (recommended)
2332             colorStr:= IntToStr(ClanColorArray[Pred(abs(colorArg))])
2333         else if (colorArg >= 0) and (colorArg <= $ffffffff) then
2334             // Specify color directly
2335             colorStr:= IntToStr(colorArg)
2336         else
2337             begin
2338             OutError('Lua error: AddTeam: Invalid ''color'' argument, must be between '+IntToStr(-cClanColors)+' and 0xffffffff!', true);
2339             lua_pushnil(L);
2340             lua_pushnil(L);
2341             lc_addteam:= 2;
2342             exit;
2343             end;
2344         ParseCommand('addteam x ' + colorStr + ' ' + lua_tostring(L, 1), true, true);
2345         ParseCommand('grave ' + lua_tostring(L, 3), true, true);
2346         ParseCommand('fort ' + lua_tostring(L, 4), true, true);
2347         ParseCommand('voicepack ' + lua_tostring(L, 5), true, true);
2348         if (np = 6) then ParseCommand('flag ' + lua_tostring(L, 6), true, true);
2349         // If there's a mission team, copy it's control scheme.
2350         // So in singleplayer missions, all teams use the player team's controls.
2351         if MissionTeam <> nil then
2352             CurrentTeam^.Binds:= MissionTeam^.Binds
2353         // Default keys otherwise
2354         else
2355             CurrentTeam^.Binds:= DefaultBinds;
2356         // push team name and index
2357         lua_pushstring(L, str2pchar(CurrentTeam^.TeamName));
2358         lua_pushnumber(L, TeamsCount - 1);
2359         end
2360     else
2361         begin
2362         lua_pushnil(L);
2363         lua_pushnil(L);
2364         end;
2365     lc_addteam:= 2;
2366 end;
2367 
lc_addmissionteamnull2368 function lc_addmissionteam(L : Plua_State) : LongInt; Cdecl;
2369 var colorArg: Int64;
2370     colorStr: shortstring;
2371 begin
2372     if CheckLuaParamCount(L, 1, 'AddMissionTeam', 'color') then
2373         begin
2374         if(MissionTeam = nil) then
2375             begin
2376             OutError('Lua error: AddMissionTeam: Could not add team. Note: This function only works in singleplayer missions!', true);
2377             lc_addmissionteam:= 0;
2378             exit;
2379             end;
2380 
2381         colorArg:= Trunc(lua_tonumber(L, 1));
2382         if (colorArg < 0) and (abs(colorArg) <= cClanColors) then
2383             // Pick clan color from settings (recommended)
2384             colorStr:= IntToStr(ClanColorArray[Pred(abs(colorArg))])
2385         else if (colorArg >= 0) and (colorArg <= $ffffffff) then
2386             // Specify color directly
2387             colorStr:= IntToStr(colorArg)
2388         else
2389             begin
2390             OutError('Lua error: AddMissionTeam: Invalid ''color'' argument, must be between '+IntToStr(-cClanColors)+' and 0xffffffff!', true);
2391             lua_pushnil(L);
2392             lua_pushnil(L);
2393             lc_addmissionteam:= 2;
2394             exit;
2395             end;
2396 
2397         ParseCommand('addteam x ' + colorStr + ' ' + MissionTeam^.TeamName, true, true);
2398         ParseCommand('grave ' + MissionTeam^.GraveName, true, true);
2399         ParseCommand('fort ' + MissionTeam^.FortName, true, true);
2400         ParseCommand('voicepack ' + MissionTeam^.Voicepack^.name, true, true);
2401         ParseCommand('flag ' + MissionTeam^.Flag, true, true);
2402         CurrentTeam^.Binds:= MissionTeam^.Binds;
2403         // push real team name and team index
2404         lua_pushstring(L, str2pchar(CurrentTeam^.TeamName));
2405         lua_pushnumber(L, TeamsCount - 1);
2406         end
2407     else
2408         begin
2409         lua_pushnil(L);
2410         lua_pushnil(L);
2411         end;
2412     lc_addmissionteam:= 2;
2413 end;
2414 
lc_setteamlabelnull2415 function lc_setteamlabel(L : Plua_State) : LongInt; Cdecl;
2416 var teamValue: ansistring;
2417     i, n: LongInt;
2418     success: boolean;
2419 begin
2420 	success:= false;
2421     if CheckAndFetchParamCount(L, 1, 2, 'SetTeamLabel', 'teamname[, label]', n) then
2422         begin
2423         success:= false;
2424         // fetch team
2425         if TeamsCount > 0 then
2426             for i:= 0 to Pred(TeamsCount) do
2427                 begin
2428                 // skip teams that don't have matching name
2429                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
2430                     continue;
2431 
2432                 // value of type nil? Then let's clear the team value
2433                 if (n < 2) or lua_isnil(L, 2) then
2434                     begin
2435                     FreeAndNilTexture(TeamsArray[i]^.LuaTeamValueTex);
2436                     TeamsArray[i]^.hasLuaTeamValue:= false;
2437                     success:= true;
2438                     end
2439                 // value of type string? Then let's set the team value
2440                 else if (lua_isstring(L, 2)) then
2441                     begin
2442                     teamValue:= lua_tostring(L, 2);
2443                     TeamsArray[i]^.LuaTeamValue:= teamValue;
2444                     FreeAndNilTexture(TeamsArray[i]^.LuaTeamValueTex);
2445                     TeamsArray[i]^.LuaTeamValueTex := RenderStringTex(teamValue, TeamsArray[i]^.Clan^.Color, fnt16);
2446                     TeamsArray[i]^.hasLuaTeamValue:= true;
2447                     success:= true;
2448                     end;
2449                 // don't change more than one team
2450                 break;
2451                 end;
2452         end;
2453     // return true if operation was successful, false otherwise
2454     lua_pushboolean(L, success);
2455     lc_setteamlabel:= 1;
2456 end;
2457 
lc_setteampassivenull2458 function lc_setteampassive(L : Plua_State) : LongInt; Cdecl;
2459 var i, j: LongInt;
2460     success, passive, passiveClan: boolean;
2461 begin
2462 	success:= false;
2463     if CheckLuaParamCount(L, 2, 'SetTeamPassive', 'teamname, isPassive') then
2464         begin
2465         success:= false;
2466         // fetch team
2467         if TeamsCount > 0 then
2468             for i:= 0 to Pred(TeamsCount) do
2469                 if TeamsArray[i]^.TeamName = lua_tostring(L, 1) then
2470                     begin
2471                     passive:= lua_toboolean(L, 2);
2472                     TeamsArray[i]^.Passive:= passive;
2473                     // also update clan state
2474                     if passive then
2475                         begin
2476                         passiveClan:= true;
2477                         for j:= 0 to Pred(TeamsCount) do
2478                             if (not TeamsArray[j]^.Passive) then
2479                                 begin
2480                                 passiveClan:= false;
2481                                 break;
2482                                 end;
2483                         end
2484                     else
2485                         passiveClan:= false;
2486                     TeamsArray[i]^.Clan^.Passive:= passiveClan;
2487 
2488                     success:= true;
2489                     // don't change more than one team
2490                     break;
2491                     end;
2492         end;
2493     // return true if operation was successful, false otherwise
2494     lua_pushboolean(L, success);
2495     lc_setteampassive:= 1;
2496 end;
2497 
2498 function lc_getteamname(L : Plua_State) : LongInt; Cdecl;
2499 var t: LongInt;
2500 begin
2501     if CheckLuaParamCount(L, 1, 'GetTeamName', 'teamIdx') then
2502         begin
2503         t:= Trunc(lua_tonumber(L, 1));
2504         if (t < 0) or (t >= TeamsCount) then
2505             lua_pushnil(L)
2506         else
2507             lua_pushstring(L, str2pchar(TeamsArray[t]^.TeamName));
2508         end
2509     else
2510         lua_pushnil(L);
2511     lc_getteamname:= 1;
2512 end;
2513 
2514 function lc_getteamindex(L : Plua_state) : LongInt; Cdecl;
2515 var i: LongInt;
2516     found: boolean;
2517 begin
2518     found:= false;
2519     if CheckLuaParamCount(L, 1, 'GetTeamIndex', 'teamname') then
2520         if TeamsCount > 0 then
2521             for i:= 0 to Pred(TeamsCount) do
2522                 begin
2523                 // skip teams that don't have matching name
2524                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
2525                     continue;
2526                 lua_pushnumber(L, i);
2527                 found:= true;
2528                 break;
2529                 end;
2530     if (not found) then
2531         lua_pushnil(L);
2532     lc_getteamindex:= 1;
2533 end;
2534 
lc_getteamclannull2535 function lc_getteamclan(L : Plua_state) : LongInt; Cdecl;
2536 var i: LongInt;
2537     found: boolean;
2538 begin
2539     found:= false;
2540     if CheckLuaParamCount(L, 1, 'GetTeamClan', 'teamname') then
2541         if TeamsCount > 0 then
2542             for i:= 0 to Pred(TeamsCount) do
2543                 begin
2544                 // skip teams that don't have matching name
2545                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
2546                     continue;
2547                 lua_pushnumber(L, TeamsArray[i]^.Clan^.ClanIndex);
2548                 found:= true;
2549                 break;
2550                 end;
2551     if (not found) then
2552         lua_pushnil(L);
2553     lc_getteamclan:= 1;
2554 end;
2555 
2556 function lc_dismissteam(L : Plua_State) : LongInt; Cdecl;
2557 var HHGear: PGear;
2558     i, h  : LongInt;
2559     hidden: boolean;
2560 begin
2561     if CheckLuaParamCount(L, 1, 'DismissTeam', 'teamname') then
2562         begin
2563         if TeamsCount > 0 then
2564             for i:= 0 to Pred(TeamsCount) do
2565                 begin
2566                 // skip teams that don't have matching name
2567                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
2568                     continue;
2569 
2570                 // destroy all hogs of matching team, including the hidden ones
2571                 for h:= 0 to cMaxHHIndex do
2572                     begin
2573                     hidden:= (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil);
2574                     if hidden then
2575                         RestoreHog(@TeamsArray[i]^.Hedgehogs[h]);
2576                     // destroy hedgehog gear, if any
2577                     HHGear:= TeamsArray[i]^.Hedgehogs[h].Gear;
2578                     if HHGear <> nil then
2579                         begin
2580                         // smoke effect
2581                         if (not hidden) then
2582                             begin
2583                             AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtSmokeWhite);
2584                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
2585                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
2586                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
2587                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
2588                             end;
2589                         HHGear^.Message:= HHGear^.Message or gmDestroy;
2590                         HHGear^.Active:= true;
2591                         AllInactive:= false;
2592                         end;
2593                     end;
2594                 // can't dismiss more than one team
2595                 break;
2596                 end;
2597         end;
2598     lc_dismissteam:= 0;
2599 end;
2600 
2601 function lc_getteamstats(L : Plua_State) : LongInt; Cdecl;
2602 var i: LongInt;
2603 begin
2604     if CheckLuaParamCount(L, 1, 'GetTeamStats', 'teamname') then
2605         begin
2606         if TeamsCount > 0 then
2607             for i:= 0 to Pred(TeamsCount) do
2608                 begin
2609                 // skip teams that don't have matching name
2610                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
2611                     continue;
2612 
2613                 lua_newtable(L);
2614 
2615                 lua_pushstring(L, str2pchar('Kills'));
2616                 lua_pushnumber(L, TeamsArray[i]^.stats.Kills);
2617                 lua_settable(L, -3);
2618 
2619                 lua_pushstring(L, str2pchar('Suicides'));
2620                 lua_pushnumber(L, TeamsArray[i]^.stats.Suicides);
2621                 lua_settable(L, -3);
2622 
2623                 lua_pushstring(L, str2pchar('AIKills'));
2624                 lua_pushnumber(L, TeamsArray[i]^.stats.AIKills);
2625                 lua_settable(L, -3);
2626 
2627                 lua_pushstring(L, str2pchar('TeamKills'));
2628                 lua_pushnumber(L, TeamsArray[i]^.stats.TeamKills);
2629                 lua_settable(L, -3);
2630 
2631                 lua_pushstring(L, str2pchar('TurnSkips'));
2632                 lua_pushnumber(L, TeamsArray[i]^.stats.TurnSkips);
2633                 lua_settable(L, -3);
2634 
2635                 lua_pushstring(L, str2pchar('TeamDamage'));
2636                 lua_pushnumber(L, TeamsArray[i]^.stats.TeamDamage);
2637                 lua_settable(L, -3);
2638 
2639                 end;
2640         end
2641     else
2642         lua_pushnil(L);
2643     lc_getteamstats:= 1;
2644 end;
2645 
2646 
2647 
lc_addhognull2648 function lc_addhog(L : Plua_State) : LongInt; Cdecl;
2649 var hatName: ShortString;
2650 begin
2651     if CheckLuaParamCount(L, 4, 'AddHog', 'hogname, botlevel, health, hat') then
2652         begin
2653         hatName:= lua_tostring(L, 4);
2654         ParseCommand('addhh ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 3) + ' ' + lua_tostring(L, 1), true, true);
2655         ParseCommand('hat ' + hatName, true, true);
2656         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then
2657             lua_pushnumber(L, CurrentHedgehog^.Gear^.uid)
2658         else
2659             OutError('Lua error: AddHog: Error adding hog. Maybe function was called outside of onGameInit.', true);
2660         end
2661     else
2662         lua_pushnil(L);
2663     lc_addhog:= 1;
2664 end;
2665 
lc_addmissionhognull2666 function lc_addmissionhog(L : Plua_State) : LongInt; Cdecl;
2667 var hatName: ShortString;
2668 begin
2669     if CheckLuaParamCount(L, 1, 'AddMissionHog', 'health') then
2670         begin
2671         if(MissionTeam = nil) then
2672             begin
2673             OutError('Lua error: AddMissionHog: Could not add hog. Mission team is not set!', true);
2674             lua_pushnil(L);
2675             lc_addmissionhog:= 1;
2676             exit;
2677             end;
2678         with MissionTeam^.Hedgehogs[CurrentTeam^.HedgehogsNumber] do
2679             begin
2680             hatName:= Hat;
2681             ParseCommand('addhh ' + IntToStr(BotLevel) + ' ' + lua_tostring(L, 1) + ' ' + Name, true, true);
2682             ParseCommand('hat ' + hatName, true, true);
2683             end;
2684         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then
2685             lua_pushnumber(L, CurrentHedgehog^.Gear^.uid)
2686         else
2687             OutError('Lua error: AddMissionHog: Error adding hog. Maybe function was called outside of onGameInit.', true);
2688         end
2689     else
2690         lua_pushnil(L);
2691     lc_addmissionhog:= 1;
2692 end;
2693 
lc_hogturnleftnull2694 function lc_hogturnleft(L : Plua_State) : LongInt; Cdecl;
2695 var gear: PGear;
2696 begin
2697     if CheckLuaParamCount(L, 2, 'HogTurnLeft', 'gearUid, boolean') then
2698         begin
2699         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2700         if gear <> nil then
2701             gear^.dX.isNegative:= lua_toboolean(L, 2);
2702         end;
2703     lc_hogturnleft:= 0;
2704 end;
2705 
lc_getgearpositionnull2706 function lc_getgearposition(L : Plua_State) : LongInt; Cdecl;
2707 var gear: PGear;
2708 begin
2709     if CheckLuaParamCount(L, 1, 'GetGearPosition', 'gearUid') then
2710         begin
2711         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2712         if gear <> nil then
2713             begin
2714             lua_pushnumber(L, hwRound(gear^.X));
2715             lua_pushnumber(L, hwRound(gear^.Y))
2716             end
2717         else
2718             begin
2719             lua_pushnil(L);
2720             lua_pushnil(L)
2721             end;
2722         end
2723     else
2724         begin
2725         lua_pushnil(L);
2726         lua_pushnil(L)
2727         end;
2728     lc_getgearposition:= 2;
2729 end;
2730 
lc_setgearpositionnull2731 function lc_setgearposition(L : Plua_State) : LongInt; Cdecl;
2732 var gear: PGear;
2733     col: boolean;
2734     x, y: LongInt;
2735 begin
2736     if CheckLuaParamCount(L, 3, 'SetGearPosition', 'gearUid, x, y') then
2737         begin
2738         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2739         if gear <> nil then
2740             begin
2741             col:= gear^.CollisionIndex >= 0;
2742             x:= Trunc(lua_tonumber(L, 2));
2743             y:= Trunc(lua_tonumber(L, 3));
2744             if col then
2745                 DeleteCI(gear);
2746             gear^.X:= int2hwfloat(x);
2747             gear^.Y:= int2hwfloat(y);
2748             if col then
2749                 AddCI(gear);
2750             SetAllToActive
2751             end
2752         end;
2753     lc_setgearposition:= 0
2754 end;
2755 
lc_getgeartargetnull2756 function lc_getgeartarget(L : Plua_State) : LongInt; Cdecl;
2757 var gear: PGear;
2758 begin
2759     if CheckLuaParamCount(L, 1, 'GetGearTarget', 'gearUid') then
2760         begin
2761         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2762         if gear <> nil then
2763             begin
2764             lua_pushnumber(L, gear^.Target.X);
2765             lua_pushnumber(L, gear^.Target.Y)
2766             end
2767         else
2768             begin
2769             lua_pushnil(L);
2770             lua_pushnil(L)
2771             end
2772         end
2773     else
2774         begin
2775         lua_pushnil(L);
2776         lua_pushnil(L)
2777         end;
2778     lc_getgeartarget:= 2;
2779 end;
2780 
lc_setgeartargetnull2781 function lc_setgeartarget(L : Plua_State) : LongInt; Cdecl;
2782 var gear: PGear;
2783 begin
2784     if CheckLuaParamCount(L, 3, 'SetGearTarget', 'gearUid, x, y') then
2785         begin
2786         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2787         if gear <> nil then
2788             begin
2789             gear^.Target.X:= Trunc(lua_tonumber(L, 2));
2790             gear^.Target.Y:= Trunc(lua_tonumber(L, 3))
2791             end
2792         end;
2793     lc_setgeartarget:= 0
2794 end;
2795 
lc_getgearvelocitynull2796 function lc_getgearvelocity(L : Plua_State) : LongInt; Cdecl;
2797 var gear: PGear;
2798 var t: LongInt;
2799 begin
2800     if CheckLuaParamCount(L, 1, 'GetGearVelocity', 'gearUid') then
2801         begin
2802         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2803         if gear <> nil then
2804             begin
2805             t:= hwRound(gear^.dX * 1000000);
2806             // gear dX determines hog orientation
2807             if (gear^.dX.isNegative) and (t = 0) then t:= -1;
2808             lua_pushnumber(L, t);
2809             lua_pushnumber(L, hwRound(gear^.dY * 1000000))
2810             end
2811         end
2812     else
2813         begin
2814         lua_pushnil(L);
2815         lua_pushnil(L);
2816         end;
2817     lc_getgearvelocity:= 2;
2818 end;
2819 
lc_setgearvelocitynull2820 function lc_setgearvelocity(L : Plua_State) : LongInt; Cdecl;
2821 var gear: PGear;
2822 begin
2823     if CheckLuaParamCount(L, 3, 'SetGearVelocity', 'gearUid, dx, dy') then
2824         begin
2825         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
2826         if gear <> nil then
2827             begin
2828             gear^.dX:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 1000000;
2829             gear^.dY:= int2hwFloat(Trunc(lua_tonumber(L, 3))) / 1000000;
2830             SetAllToActive;
2831             end
2832         end;
2833     lc_setgearvelocity:= 0
2834 end;
2835 
lc_setzoomnull2836 function lc_setzoom(L : Plua_State) : LongInt; Cdecl;
2837 begin
2838     if CheckLuaParamCount(L, 1, 'SetZoom', 'zoomLevel') then
2839         begin
2840         ZoomValue:= lua_tonumber(L, 1);
2841         if ZoomValue < cMaxZoomLevel then
2842             ZoomValue:= cMaxZoomLevel;
2843         if ZoomValue > cMinZoomLevel then
2844             ZoomValue:= cMinZoomLevel;
2845         end;
2846     lc_setzoom:= 0
2847 end;
2848 
lc_getzoomnull2849 function lc_getzoom(L : Plua_State) : LongInt; Cdecl;
2850 begin
2851     if CheckLuaParamCount(L, 0, 'GetZoom', '') then
2852         lua_pushnumber(L, ZoomValue)
2853     else
2854         lua_pushnil(L);
2855     lc_getzoom:= 1
2856 end;
2857 
lc_setammonull2858 function lc_setammo(L : Plua_State) : LongInt; Cdecl;
2859 var np, at: LongInt;
2860 const
2861     call = 'SetAmmo';
2862     params = 'ammoType, count, probability, delay [, numberInCrate]';
2863 begin
2864     if CheckAndFetchParamCount(L, 4, 5, call, params, np) then
2865         begin
2866         at:= LuaToAmmoTypeOrd(L, 1, call, params);
2867         if at >= 0 then
2868             begin
2869             if np = 4 then
2870                 ScriptSetAmmo(TAmmoType(at), Trunc(lua_tonumber(L, 2)), Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)), 1)
2871             else
2872                 ScriptSetAmmo(TAmmoType(at), Trunc(lua_tonumber(L, 2)), Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)), Trunc(lua_tonumber(L, 5)));
2873             end;
2874         end;
2875     lc_setammo:= 0
2876 end;
2877 
2878 
lc_getammonull2879 function lc_getammo(L : Plua_State) : LongInt; Cdecl;
2880 var i, at, rawProb, probLevel: LongInt;
2881 const
2882     call = 'GetAmmo';
2883     params = 'ammoType';
2884 begin
2885     lc_getammo:= 0;
2886     if CheckLuaParamCount(L, 1, call, params) then
2887         begin
2888         at:= LuaToAmmoTypeOrd(L, 1, call, params);
2889         if at >= 0 then
2890             begin
2891             // Ammo count
2892             i:= InitialAmmoCounts[TAmmoType(at)];
2893             if i = AMMO_INFINITE then
2894                 i:= 9;
2895             lua_pushnumber(L, i);
2896             // Probability
2897             rawProb:=  Ammoz[TAmmoType(at)].Probability;
2898             probLevel:= -1;
2899             for i := 0 to High(probabilityLevels) do
2900                 if rawProb = probabilityLevels[i] then
2901                     probLevel:= i;
2902             lua_pushnumber(L, probLevel);
2903             // Delay in turns
2904             lua_pushnumber(L, Ammoz[TAmmoType(at)].SkipTurns);
2905             // Number in case
2906             lua_pushnumber(L, Ammoz[TAmmoType(at)].NumberInCase);
2907             lc_getammo:= 4
2908             end
2909         end;
2910 end;
2911 
2912 
lc_setammodelaynull2913 function lc_setammodelay(L : Plua_State) : LongInt; Cdecl;
2914 var at, delay: LongInt;
2915 const
2916     call = 'SetAmmoDelay';
2917     params = 'ammoType, delay';
2918 begin
2919     if CheckLuaParamCount(L, 2, call, params) then
2920         begin
2921         at:= LuaToAmmoTypeOrd(L, 1, call, params);
2922         delay:= Trunc(lua_tonumber(L, 2));
2923         if (at >= 0) and (TAmmoType(at) <> amNothing) then
2924             begin
2925             ScriptSetAmmoDelay(TAmmoType(at), delay);
2926             // Unselect weapon if neccessary
2927             if (delay > 0) and (CurrentHedgehog <> nil) and (CurrentHedgehog^.CurAmmoType = TAmmoType(at)) then
2928                 ParseCommand('setweap ' + char(0), true, true);
2929             end;
2930         end;
2931     lc_setammodelay:= 0
2932 end;
2933 
lc_setammoslotnull2934 function lc_setammoslot(L : Plua_State) : LongInt; Cdecl;
2935 var at, slot: LongInt;
2936 begin
2937     if CheckLuaParamCount(L, 2, 'SetAmmoSlot', 'ammoType, slot') then
2938         begin
2939         at:= Trunc(lua_tonumber(L, 1));
2940         slot:= Trunc(lua_tonumber(L, 2));
2941         Ammoz[TAmmoType(at)].Slot:= slot - 1;
2942         AmmoMenuInvalidated:= true;
2943         end;
2944     lc_setammoslot:= 0;
2945 end;
2946 
lc_getrandomnull2947 function lc_getrandom(L : Plua_State) : LongInt; Cdecl;
2948 var m : LongInt;
2949 begin
2950     if CheckLuaParamCount(L, 1, 'GetRandom', 'number') then
2951         begin
2952         m:= Trunc(lua_tonumber(L, 1));
2953         if (m > 0) then
2954             lua_pushnumber(L, GetRandom(m))
2955         else
2956             begin
2957             LuaError('Lua: Tried to pass 0 to GetRandom!');
2958             lua_pushnil(L);
2959             end
2960         end
2961     else
2962         lua_pushnil(L); // return value on stack (nil)
2963     lc_getrandom:= 1
2964 end;
2965 
lc_setwindnull2966 function lc_setwind(L : Plua_State) : LongInt; Cdecl;
2967 var vg: PVisualGear;
2968 begin
2969     if CheckLuaParamCount(L, 1, 'SetWind', 'windSpeed') then
2970         begin
2971         cWindSpeed:= int2hwfloat(Trunc(lua_tonumber(L, 1))) / 100 * cMaxWindSpeed;
2972         cWindSpeedf:= SignAs(cWindSpeed,cWindSpeed).QWordValue / SignAs(_1,_1).QWordValue;
2973         if cWindSpeed.isNegative then
2974             cWindSpeedf := -cWindSpeedf;
2975         vg:= AddVisualGear(0, 0, vgtSmoothWindBar);
2976         if vg <> nil then vg^.dAngle:= hwFloat2Float(cWindSpeed);
2977             AddFileLog('Script set wind = '+FloatToStr(cWindSpeed));
2978         end;
2979     lc_setwind:= 0
2980 end;
2981 
lc_getwindnull2982 function lc_getwind(L : Plua_State) : LongInt; Cdecl;
2983 var wind: extended;
2984 begin
2985     if CheckLuaParamCount(L, 0, 'GetWind', '') then
2986         begin
2987         wind:= hwFloat2float((cWindSpeed / cMaxWindSpeed) * 100);
2988         if wind < -100 then
2989             wind:= -100
2990         else if wind > 100 then
2991             wind:= 100;
2992         lua_pushnumber(L, wind);
2993         end
2994     else
2995         lua_pushnil(L);
2996     lc_getwind:= 1
2997 end;
2998 
lc_maphasbordernull2999 function lc_maphasborder(L : Plua_State) : LongInt; Cdecl;
3000 begin
3001     if CheckLuaParamCount(L, 0, 'MapHasBorder', '') then
3002         lua_pushboolean(L, hasBorder)
3003     else
3004         lua_pushnil(L);
3005     lc_maphasborder:= 1
3006 end;
3007 
lc_getgearradiusnull3008 function lc_getgearradius(L : Plua_State) : LongInt; Cdecl;
3009 var gear : PGear;
3010 begin
3011     if CheckLuaParamCount(L, 1, 'GetGearRadius', 'gearUid') then
3012         begin
3013         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
3014         if gear <> nil then
3015             lua_pushnumber(L, gear^.Radius)
3016         else
3017             lua_pushnil(L);
3018         end
3019     else
3020         lua_pushnil(L); // return value on stack (nil)
3021     lc_getgearradius:= 1
3022 end;
3023 
lc_gethoghatnull3024 function lc_gethoghat(L : Plua_State): LongInt; Cdecl;
3025 var gear : PGear;
3026 begin
3027     if CheckLuaParamCount(L, 1, 'GetHogHat', 'gearUid') then
3028         begin
3029         gear := GearByUID(Trunc(lua_tonumber(L, 1)));
3030         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
3031             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Hat))
3032         else
3033             lua_pushnil(L);
3034         end
3035     else
3036         lua_pushnil(L);
3037     lc_gethoghat := 1;
3038 end;
3039 
lc_sethoghatnull3040 function lc_sethoghat(L : Plua_State) : LongInt; Cdecl;
3041 var gear : PGear;
3042     hat: ShortString;
3043 begin
3044     if CheckLuaParamCount(L, 2, 'SetHogHat', 'gearUid, hat') then
3045         begin
3046         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
3047         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
3048             begin
3049             hat:= lua_tostring(L, 2);
3050             gear^.Hedgehog^.Hat:= hat;
3051             AddFileLog('Changed hat to: '+hat);
3052             if (Length(hat) > 39) and (Copy(hat,1,8) = 'Reserved') and (Copy(hat,9,32) = gear^.Hedgehog^.Team^.PlayerHash) then
3053                 LoadHedgehogHat(gear^.Hedgehog^, 'Reserved/' + Copy(hat,9,Length(hat)-8))
3054             else
3055                 LoadHedgehogHat(gear^.Hedgehog^, hat)
3056             end
3057         end;
3058     lc_sethoghat:= 0;
3059 end;
3060 
lc_placespritenull3061 function lc_placesprite(L : Plua_State) : LongInt; Cdecl;
3062 var spr   : TSprite;
3063     lf    : Word;
3064     tint  : LongWord;
3065     i, n : LongInt;
3066     placed, behind, flipHoriz, flipVert : boolean;
3067 const
3068     call = 'PlaceSprite';
3069     params = 'x, y, sprite, frameIdx, tint, behind, flipHoriz, flipVert [, landFlag, ... ]';
3070 begin
3071     placed:= false;
3072     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
3073         begin
3074         if not lua_isnoneornil(L, 5) then
3075             tint := Trunc(lua_tonumber(L, 5))
3076         else tint := $FFFFFFFF;
3077         if not lua_isnoneornil(L, 6) then
3078             behind := lua_toboolean(L, 6)
3079         else behind := false;
3080         if not lua_isnoneornil(L, 7) then
3081             flipHoriz := lua_toboolean(L, 7)
3082         else flipHoriz := false;
3083         if not lua_isnoneornil(L, 8) then
3084             flipVert := lua_toboolean(L, 8)
3085         else flipVert := false;
3086         lf:= 0;
3087 
3088         // accept any amount of landflags, loop is never executed if n<9
3089         for i:= 9 to n do
3090             lf:= lf or Trunc(lua_tonumber(L, i));
3091 
3092         n:= LuaToSpriteOrd(L, 3, call, params);
3093         if n >= 0 then
3094             begin
3095             spr:= TSprite(n);
3096             if SpritesData[spr].Surface = nil then
3097                 LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
3098             else
3099                 placed:= ForcePlaceOnLand(
3100                     Trunc(lua_tonumber(L, 1)) - SpritesData[spr].Width div 2,
3101                     Trunc(lua_tonumber(L, 2)) - SpritesData[spr].Height div 2,
3102                     spr, Trunc(lua_tonumber(L, 4)), lf, tint, behind, flipHoriz, flipVert);
3103             end;
3104         end;
3105 
3106     lua_pushboolean(L, placed);
3107     lc_placesprite:= 1
3108 end;
3109 
lc_erasespritenull3110 function lc_erasesprite(L : Plua_State) : LongInt; Cdecl;
3111 var spr   : TSprite;
3112     lf    : Word;
3113     i, n : LongInt;
3114     eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert : boolean;
3115 const
3116     call = 'EraseSprite';
3117     params = 'x, y, sprite, frameIdx, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert [, landFlag, ... ]';
3118 begin
3119     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
3120         begin
3121         if not lua_isnoneornil(L, 5) then
3122             eraseOnLFMatch := lua_toboolean(L, 5)
3123         else eraseOnLFMatch := false;
3124         if not lua_isnoneornil(L, 6) then
3125             onlyEraseLF := lua_toboolean(L, 6)
3126         else onlyEraseLF := false;
3127         if not lua_isnoneornil(L, 7) then
3128             flipHoriz := lua_toboolean(L, 7)
3129         else flipHoriz := false;
3130         if not lua_isnoneornil(L, 8) then
3131             flipVert := lua_toboolean(L, 8)
3132         else flipVert := false;
3133         lf:= 0;
3134 
3135         // accept any amount of landflags, loop is never executed if n<9
3136         for i:= 9 to n do
3137             lf:= lf or Trunc(lua_tonumber(L, i));
3138 
3139         n:= LuaToSpriteOrd(L, 3, call, params);
3140         if n >= 0 then
3141             begin
3142             spr:= TSprite(n);
3143             if SpritesData[spr].Surface = nil then
3144                 LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
3145             else
3146                 EraseLand(
3147                     Trunc(lua_tonumber(L, 1)) - SpritesData[spr].Width div 2,
3148                     Trunc(lua_tonumber(L, 2)) - SpritesData[spr].Height div 2,
3149                     spr, Trunc(lua_tonumber(L, 4)), lf, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert);
3150             end;
3151         end;
3152     lc_erasesprite:= 0
3153 end;
3154 
lc_placegirdernull3155 function lc_placegirder(L : Plua_State) : LongInt; Cdecl;
3156 var placed: boolean;
3157 begin
3158     placed:= false;
3159     if CheckLuaParamCount(L, 3, 'PlaceGirder', 'x, y, frameIdx') then
3160         placed:= TryPlaceOnLandSimple(
3161             Trunc(lua_tonumber(L, 1)) - SpritesData[sprAmGirder].Width div 2,
3162             Trunc(lua_tonumber(L, 2)) - SpritesData[sprAmGirder].Height div 2,
3163             sprAmGirder, Trunc(lua_tonumber(L, 3)), true, false);
3164 
3165     lua_pushboolean(L, placed);
3166     lc_placegirder:= 1
3167 end;
3168 
lc_placerubbernull3169 function lc_placerubber(L : Plua_State) : LongInt; Cdecl;
3170 var placed: boolean;
3171 begin
3172     placed:= false;
3173     if CheckLuaParamCount(L, 3, 'PlaceRubber', 'x, y, frameIdx') then
3174         placed:= TryPlaceOnLand(
3175             Trunc(lua_tonumber(L, 1)) - SpritesData[sprAmRubber].Width div 2,
3176             Trunc(lua_tonumber(L, 2)) - SpritesData[sprAmRubber].Height div 2,
3177             sprAmRubber, Trunc(lua_tonumber(L, 3)), true, lfBouncy);
3178 
3179     lua_pushboolean(L, placed);
3180     lc_placerubber:= 1
3181 end;
3182 
lc_getcurammotypenull3183 function lc_getcurammotype(L : Plua_State): LongInt; Cdecl;
3184 begin
3185     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, 'GetCurAmmoType', '')) then
3186         lua_pushnumber(L, ord(CurrentHedgehog^.CurAmmoType))
3187     else
3188         lua_pushnumber(L, ord(amNothing));
3189     lc_getcurammotype := 1;
3190 end;
3191 
lc_savecampaignvarnull3192 function lc_savecampaignvar(L : Plua_State): LongInt; Cdecl;
3193 begin
3194     if CheckLuaParamCount(L, 2, 'SaveCampaignVar', 'varname, value') then
3195         SendIPC('V!' + lua_tostring(L, 1) + ' ' + lua_tostring(L, 2) + #0);
3196     lc_savecampaignvar := 0;
3197 end;
3198 
lc_getcampaignvarnull3199 function lc_getcampaignvar(L : Plua_State): LongInt; Cdecl;
3200 begin
3201     if CheckLuaParamCount(L, 1, 'GetCampaignVar', 'varname') then
3202         SendIPCAndWaitReply('V?' + lua_tostring(L, 1) + #0);
3203     lua_pushstring(L, str2pchar(CampaignVariable));
3204     lc_getcampaignvar := 1;
3205 end;
3206 
lc_savemissionvarnull3207 function lc_savemissionvar(L : Plua_State): LongInt; Cdecl;
3208 begin
3209     if CheckLuaParamCount(L, 2, 'SaveMissionVar', 'varname, value') then
3210         SendIPC('v!' + lua_tostring(L, 1) + ' ' + lua_tostring(L, 2) + #0);
3211     lc_savemissionvar := 0;
3212 end;
3213 
lc_getmissionvarnull3214 function lc_getmissionvar(L : Plua_State): LongInt; Cdecl;
3215 begin
3216     if CheckLuaParamCount(L, 1, 'GetMissionVar', 'varname') then
3217         SendIPCAndWaitReply('v?' + lua_tostring(L, 1) + #0);
3218     lua_pushstring(L, str2pchar(MissionVariable));
3219     lc_getmissionvar := 1;
3220 end;
3221 
lc_hidehognull3222 function lc_hidehog(L: Plua_State): LongInt; Cdecl;
3223 var gear: PGear;
3224 begin
3225     if CheckLuaParamCount(L, 1, 'HideHog', 'gearUid') then
3226         begin
3227         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
3228         if (gear <> nil) and (gear^.hedgehog <> nil) then
3229             begin
3230             HideHog(gear^.hedgehog);
3231             lua_pushboolean(L, true);
3232             end
3233         else
3234             lua_pushboolean(L, false);
3235         end;
3236     lc_hidehog := 1;
3237 end;
3238 
lc_restorehognull3239 function lc_restorehog(L: Plua_State): LongInt; Cdecl;
3240 var i, h: LongInt;
3241     uid: LongWord;
3242 begin
3243     if CheckLuaParamCount(L, 1, 'RestoreHog', 'gearUid') then
3244         begin
3245         uid:= LongWord(Trunc(lua_tonumber(L, 1)));
3246         if TeamsCount > 0 then
3247             for i:= 0 to Pred(TeamsCount) do
3248                 for h:= 0 to cMaxHHIndex do
3249                     if (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil) and (TeamsArray[i]^.Hedgehogs[h].GearHidden^.uid = uid) then
3250                         begin
3251                         RestoreHog(@TeamsArray[i]^.Hedgehogs[h]);
3252                         exit(0)
3253                         end
3254         end;
3255     lc_restorehog := 0;
3256 end;
3257 
lc_ishoghiddennull3258 function lc_ishoghidden(L: Plua_State): LongInt; Cdecl;
3259 var i, h: LongInt;
3260     uid: LongWord;
3261     gear: PGear;
3262 begin
3263     if CheckLuaParamCount(L, 1, 'IsHogHidden', 'gearUid') then
3264         begin
3265         uid:= LongWord(Trunc(lua_tonumber(L, 1)));
3266         gear:= GearByUID(uid);
3267         if (gear <> nil) and (gear^.hedgehog <> nil) then
3268             begin
3269             lua_pushboolean(L, false);
3270             lc_ishoghidden:= 1;
3271             exit;
3272             end
3273         else
3274             if TeamsCount > 0 then
3275                 for i:= 0 to Pred(TeamsCount) do
3276                     for h:= 0 to cMaxHHIndex do
3277                         if (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil) and (TeamsArray[i]^.Hedgehogs[h].GearHidden^.uid = uid) then
3278                             begin
3279                             lua_pushboolean(L, true);
3280                             lc_ishoghidden:= 1;
3281                             exit;
3282                             end
3283         end;
3284     lua_pushnil(L);
3285     lc_ishoghidden:= 1;
3286 end;
3287 
3288 // boolean TestRectForObstacle(x1, y1, x2, y2, landOnly)
lc_testrectforobstaclenull3289 function lc_testrectforobstacle(L : Plua_State) : LongInt; Cdecl;
3290 var rtn: Boolean;
3291 begin
3292     if CheckLuaParamCount(L, 5, 'TestRectForObstacle', 'x1, y1, x2, y2, landOnly') then
3293         begin
3294         rtn:= TestRectangleForObstacle(
3295                     Trunc(lua_tonumber(L, 1)),
3296                     Trunc(lua_tonumber(L, 2)),
3297                     Trunc(lua_tonumber(L, 3)),
3298                     Trunc(lua_tonumber(L, 4)),
3299                     lua_toboolean(L, 5)
3300                     );
3301         lua_pushboolean(L, rtn);
3302         end
3303     else
3304         lua_pushnil(L); // return value on stack (nil)
3305     lc_testrectforobstacle:= 1
3306 end;
3307 
3308 
lc_getgravitynull3309 function lc_getgravity(L : Plua_State) : LongInt; Cdecl;
3310 begin
3311     if CheckLuaParamCount(L, 0, 'GetGravity', '') then
3312         lua_pushnumber(L, hwRound(SignAs(_0_5, cGravity) + (cGravity * 50 / cMaxWindSpeed)));
3313     lc_getgravity:= 1
3314 end;
3315 
lc_setgravitynull3316 function lc_setgravity(L : Plua_State) : LongInt; Cdecl;
3317 begin
3318     if CheckLuaParamCount(L, 1, 'SetGravity', 'percent') then
3319         begin
3320         cGravity:= _0_02 * Trunc(lua_tonumber(L, 1)) * cMaxWindSpeed;
3321         cGravityf:= 0.00025 * Trunc(lua_tonumber(L, 1)) * 0.02
3322         end;
3323     lc_setgravity:= 0
3324 end;
3325 
lc_setwaterlinenull3326 function lc_setwaterline(L : Plua_State) : LongInt; Cdecl;
3327 var iterator: PGear;
3328 begin
3329     if CheckLuaParamCount(L, 1, 'SetWaterLine', 'waterline') then
3330         begin
3331         cWaterLine:= Trunc(lua_tonumber(L,1));
3332         AllInactive:= false;
3333         iterator:= GearsList;
3334         while iterator <> nil do
3335             begin
3336             if not (iterator^.Kind in [gtPortal, gtAirAttack]) and (iterator^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) then
3337                 begin
3338                 iterator^.Active:= true;
3339                 if iterator^.dY.QWordValue = 0 then iterator^.dY.isNegative:= false;
3340                 iterator^.State:= iterator^.State or gstMoving;
3341                 DeleteCI(iterator)
3342                 end;
3343             iterator:= iterator^.NextGear
3344             end
3345         end;
3346     lc_setwaterline:= 0
3347 end;
3348 
lc_setgearaihintsnull3349 function lc_setgearaihints(L : Plua_State) : LongInt; Cdecl;
3350 var gear: PGear;
3351 begin
3352     if CheckLuaParamCount(L, 2, 'SetGearAIHints', 'gearUid, aiHints') then
3353         begin
3354         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
3355         if gear <> nil then
3356             gear^.aihints:= Trunc(lua_tonumber(L, 2));
3357         end;
3358     lc_setgearaihints:= 0
3359 end;
3360 
3361 
lc_hedgewarsscriptloadnull3362 function lc_hedgewarsscriptload(L : Plua_State) : LongInt; Cdecl;
3363 var success : boolean;
3364     n : LongInt;
3365 begin
3366 	success:= false;
3367     if CheckAndFetchParamCount(L, 1, 2, 'HedgewarsScriptLoad', 'scriptPath [, mustExist]', n) then
3368         begin
3369         if n = 1 then
3370             success:= ScriptLoad(lua_tostring(L, 1), true)
3371         else
3372             success:= ScriptLoad(lua_tostring(L, 1), lua_toboolean(L, 2));
3373         end
3374     else
3375         success:= false;
3376     lua_pushboolean(L, success);
3377     lc_hedgewarsscriptload:= 1;
3378 end;
3379 
3380 
lc_declareachievementnull3381 function lc_declareachievement(L : Plua_State) : LongInt; Cdecl;
3382 begin
3383     if CheckLuaParamCount(L, 4, 'DeclareAchievement', 'achievementId, teamname, location, value') then
3384         declareAchievement(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), Trunc(lua_tonumber(L, 4)));
3385     lc_declareachievement:= 0
3386 end;
3387 
lc_getammonamenull3388 function lc_getammoname(L : Plua_state) : LongInt; Cdecl;
3389 var np, at: LongInt;
3390     ignoreOverwrite: Boolean;
3391 const call = 'GetAmmoName';
3392       params = 'ammoType [, ignoreOverwrite ]';
3393 begin
3394     if CheckAndFetchParamCountRange(L, 1, 2, call, params, np) then
3395         begin
3396         at:= LuaToAmmoTypeOrd(L, 1, call, params);
3397         ignoreOverwrite := false;
3398         if np > 1 then
3399             ignoreOverwrite := lua_toboolean(L, 2);
3400         if at >= 0 then
3401             if (not ignoreOverwrite) and (length(trluaammo[Ammoz[TAmmoType(at)].NameId]) > 0) then
3402                 lua_pushstring(L, PChar(trluaammo[Ammoz[TAmmoType(at)].NameId]))
3403             else
3404                 lua_pushstring(L, PChar(trammo[Ammoz[TAmmoType(at)].NameId]));
3405         end
3406     else
3407         lua_pushnil(L);
3408     lc_getammoname:= 1;
3409 end;
3410 
lc_getammotimernull3411 function lc_getammotimer(L : Plua_state) : LongInt; Cdecl;
3412 var at: LongInt;
3413     weapon: PAmmo;
3414     gear: PGear;
3415 const call = 'GetAmmoTimer';
3416       params = 'gearUid, ammoType';
3417 begin
3418     if CheckLuaParamCount(L, 2, call, params) then
3419         begin
3420         gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
3421         if (gear <> nil) and (gear^.Hedgehog <> nil) then
3422             begin
3423             at:= LuaToAmmoTypeOrd(L, 2, call, params);
3424             weapon:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(at));
3425             if (Ammoz[TAmmoType(at)].Ammo.Propz and ammoprop_Timerable) <> 0 then
3426                 lua_pushnumber(L, weapon^.Timer)
3427             else
3428                 lua_pushnil(L);
3429             end
3430         else
3431             lua_pushnil(L);
3432         end
3433     else
3434         lua_pushnil(L);
3435     lc_getammotimer:= 1;
3436 end;
3437 
lc_setvampiricnull3438 function lc_setvampiric(L : Plua_state) : LongInt; Cdecl;
3439 begin
3440     if CheckLuaParamCount(L, 1, 'SetVampiric', 'bool') then
3441         cVampiric := lua_toboolean(L, 1);
3442     lc_setvampiric := 0;
3443 end;
3444 
lc_getvampiricnull3445 function lc_getvampiric(L : Plua_state) : LongInt; Cdecl;
3446 begin
3447     lua_pushboolean(L, cVampiric);
3448     lc_getvampiric := 1;
3449 end;
3450 
lc_setlasersightnull3451 function lc_setlasersight(L : Plua_state) : LongInt; Cdecl;
3452 begin
3453     if CheckLuaParamCount(L, 1, 'SetLaserSight', 'bool') then
3454         cLaserSighting:= lua_toboolean(L, 1);
3455     lc_setlasersight:= 0;
3456 end;
3457 
lc_getlasersightnull3458 function lc_getlasersight(L : Plua_state) : LongInt; Cdecl;
3459 begin
3460     lua_pushboolean(L, cLaserSighting);
3461     lc_getlasersight:= 1;
3462 end;
3463 
lc_explodenull3464 function lc_explode(L : Plua_state) : LongInt; Cdecl;
3465 var mask: LongWord;
3466     n: LongInt;
3467 begin
3468     if CheckAndFetchParamCount(L, 3, 4, 'Explode', 'x, y, radius[, options]', n) then
3469         if CurrentHedgehog <> nil then
3470             begin
3471             mask:= EXPLAutoSound;
3472             if (n = 4) then
3473                 mask:= Trunc(lua_tonumber(L, 4));
3474             doMakeExplosion(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), Trunc(lua_tonumber(L, 3)), CurrentHedgehog, mask);
3475             lua_pushboolean(L, true);
3476             end
3477         else
3478             lua_pushboolean(L, false)
3479     else
3480         lua_pushboolean(L, false);
3481     lc_explode:= 1;
3482 end;
3483 
lc_setturntimeleftnull3484 function lc_setturntimeleft(L : Plua_State) : LongInt; Cdecl;
3485 var number: Int64;
3486 begin
3487     if CheckLuaParamCount(L, 1, 'SetTurnTimeLeft', 'newTurnTimeLeft') then
3488         begin
3489         number:= Trunc(lua_tonumber(L, 1));
3490         if number < 0 then
3491             number:= 0;
3492         if number > cMaxTurnTime then
3493             number:= cMaxTurnTime;
3494         // The real TurnTimeLeft will be set in SetGlobals
3495         PendingTurnTimeLeft:= number;
3496         isPendingTurnTimeLeft:= true;
3497         end;
3498     lc_setturntimeleft:= 0;
3499 end;
3500 
lc_setreadytimeleftnull3501 function lc_setreadytimeleft(L : Plua_State) : LongInt; Cdecl;
3502 var number: Int64;
3503 begin
3504     if CheckLuaParamCount(L, 1, 'SetReadyTimeLeft', 'newReadyTimeLeft') then
3505         begin
3506         number:= Trunc(lua_tonumber(L, 1));
3507         if number < 0 then
3508             number:= 0;
3509         if number > cMaxTurnTime then
3510             number:= cMaxTurnTime;
3511         // The real ReadyTimeLeft will be set in SetGlobals
3512         PendingReadyTimeLeft:= number;
3513         isPendingReadyTimeLeft:= true;
3514         end;
3515     lc_setreadytimeleft:= 0;
3516 end;
3517 
lc_setturntimepausednull3518 function lc_setturntimepaused(L : Plua_State) : LongInt; Cdecl;
3519 begin
3520     if CheckLuaParamCount(L, 1, 'SetTurnTimePaused', 'isPaused') then
3521         LuaClockPaused:= lua_toboolean(L, 1);
3522     lc_setturntimepaused:= 0;
3523 end;
3524 
lc_getturntimepausednull3525 function lc_getturntimepaused(L : Plua_State) : LongInt; Cdecl;
3526 begin
3527     if CheckLuaParamCount(L, 0, 'GetTurnTimePaused', '') then
3528         lua_pushboolean(L, LuaClockPaused)
3529     else
3530         lua_pushnil(L);
3531     lc_getturntimepaused:= 1;
3532 end;
3533 
lc_startghostpointsnull3534 function lc_startghostpoints(L : Plua_State) : LongInt; Cdecl;
3535 begin
3536     if CheckLuaParamCount(L, 1, 'StartGhostPoints', 'count') then
3537         startGhostPoints(Trunc(lua_tonumber(L, 1)));
3538     lc_startghostpoints:= 0
3539 end;
3540 
lc_dumppointnull3541 function lc_dumppoint(L : Plua_State) : LongInt; Cdecl;
3542 begin
3543     if CheckLuaParamCount(L, 2, 'DumpPoint', 'x, y') then
3544         dumpPoint(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)));
3545     lc_dumppoint:= 0
3546 end;
3547 
3548 
3549 procedure ScriptFlushPoints();
3550 begin
3551     ParseCommand('draw ' + PointsBuffer, true, true);
3552     PointsBuffer:= '';
3553 end;
3554 
3555 
lc_addPointnull3556 function lc_addPoint(L : Plua_State) : LongInt; Cdecl;
3557 var np, param: LongInt;
3558 begin
3559     if CheckAndFetchParamCountRange(L, 2, 4, 'AddPoint', 'x, y [, width [, erase] ]', np) then
3560         begin
3561         // x
3562         param:= LongInt(Trunc(lua_tonumber(L,1)));
3563         PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
3564         PointsBuffer:= PointsBuffer + char((param and $FF));
3565         // y
3566         param:= LongInt(Trunc(lua_tonumber(L,2)));
3567         PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
3568         PointsBuffer:= PointsBuffer + char((param and $FF));
3569         // width
3570         if np > 2 then
3571             begin
3572             param:= Trunc(lua_tonumber(L,3));
3573             param:= (param or $80);
3574             // erase
3575             if (np > 3) and lua_toboolean(L, 4) then
3576                 param:= (param or $40);
3577             PointsBuffer:= PointsBuffer + char(param);
3578             end
3579         // no width defined
3580         else
3581             PointsBuffer:= PointsBuffer + char(0);
3582 
3583         // flush before shortstring limit length is reached
3584         if length(PointsBuffer) > 245 then
3585             ScriptFlushPoints();
3586         end;
3587     lc_addPoint:= 0
3588 end;
3589 
3590 
lc_flushPointsnull3591 function lc_flushPoints(L : Plua_State) : LongInt; Cdecl;
3592 begin
3593     if CheckLuaParamCount(L, 0, 'FlushPoints', '') then
3594         if length(PointsBuffer) > 0 then
3595             ScriptFlushPoints();
3596     lc_flushPoints:= 0
3597 end;
3598 
3599 // stuff for lua tests
lc_endluatestnull3600 function lc_endluatest(L : Plua_State) : LongInt; Cdecl;
3601 var rstring: shortstring;
3602 const
3603     call = 'EndLuaTest';
3604     params = 'TEST_SUCCESSFUL or TEST_FAILED';
3605 begin
3606     if CheckLuaParamCount(L, 1, call, params) then
3607         begin
3608 
3609         case Trunc(lua_tonumber(L, 1)) of
3610             HaltTestSuccess : rstring:= 'Success';
3611             HaltTestFailed: rstring:= 'FAILED';
3612         else
3613             begin
3614             LuaCallError('Parameter must be either ' + params, call, params);
3615             exit(0);
3616             end;
3617         end;
3618 
3619         if cTestLua then
3620             begin
3621             WriteLnToConsole('Lua test finished, result: ' + rstring);
3622             halt(Trunc(lua_tonumber(L, 1)));
3623             end
3624         else LuaError('Not in lua test mode, engine will keep running. Reported test result: ' + rstring);
3625 
3626         end;
3627 
3628     lc_endluatest:= 0;
3629 end;
3630 ///////////////////
3631 
3632 procedure ScriptPrintStack;
3633 var n, i : LongInt;
3634 begin
3635     n:= lua_gettop(luaState);
3636     WriteLnToConsole('Lua: Stack (' + inttostr(n) + ' elements):');
3637     for i:= 1 to n do
3638         if not lua_isboolean(luaState, i) then
3639             WriteLnToConsole('Lua:  ' + inttostr(i) + ': ' + lua_tostring(luaState, i))
3640         else if lua_toboolean(luaState, i) then
3641             WriteLnToConsole('Lua:  ' + inttostr(i) + ': true')
3642         else
3643             WriteLnToConsole('Lua:  ' + inttostr(i) + ': false');
3644 end;
3645 
3646 procedure ScriptClearStack;
3647 begin
3648     lua_settop(luaState, 0)
3649 end;
3650 
3651 procedure ScriptSetNil(name : shortstring);
3652 begin
3653     lua_pushnil(luaState);
3654     lua_setglobal(luaState, Str2PChar(name));
3655 end;
3656 
3657 procedure ScriptSetInteger(name : shortstring; value : LongInt);
3658 begin
3659     lua_pushnumber(luaState, value);
3660     lua_setglobal(luaState, Str2PChar(name));
3661 end;
3662 
3663 procedure ScriptSetLongWord(name : shortstring; value : LongWord);
3664 begin
3665     lua_pushnumber(luaState, value);
3666     lua_setglobal(luaState, Str2PChar(name));
3667 end;
3668 
3669 procedure ScriptSetString(name : shortstring; value : shortstring);
3670 begin
3671     lua_pushstring(luaState, Str2PChar(value));
3672     lua_setglobal(luaState, Str2PChar(name));
3673 end;
3674 
ScriptGetIntegernull3675 function ScriptGetInteger(name : shortstring) : LongInt;
3676 begin
3677     lua_getglobal(luaState, Str2PChar(name));
3678     ScriptGetInteger:= Trunc(lua_tonumber(luaState, -1));
3679     lua_pop(luaState, 1);
3680 end;
3681 
ScriptGetStringnull3682 function ScriptGetString(name : shortstring) : shortstring;
3683 begin
3684     lua_getglobal(luaState, Str2PChar(name));
3685     ScriptGetString:= lua_tostring(luaState, -1);
3686     lua_pop(luaState, 1);
3687 end;
3688 
ScriptGetAnsiStringnull3689 function ScriptGetAnsiString(name : shortstring) : ansistring;
3690 begin
3691     lua_getglobal(luaState, Str2PChar(name));
3692     ScriptGetAnsiString:= lua_tostringa(luaState, -1);
3693     lua_pop(luaState, 1);
3694 end;
3695 
3696 procedure ScriptOnPreviewInit;
3697 begin
3698 // not required if there is no script to run
3699 if not ScriptLoaded then
3700     exit;
3701 
3702 ScriptSetString('Seed', cSeed);
3703 ScriptSetInteger('TemplateFilter', cTemplateFilter);
3704 ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
3705 ScriptSetInteger('MapGen', ord(cMapGen));
3706 ScriptSetInteger('MapFeatureSize', cFeatureSize);
3707 
3708 ScriptCall('onPreviewInit');
3709 
3710 // pop game variables
3711 ParseCommand('seed ' + ScriptGetString('Seed'), true, true);
3712 cTemplateFilter  := ScriptGetInteger('TemplateFilter');
3713 LuaTemplateNumber:= ScriptGetInteger('TemplateNumber');
3714 cMapGen          := TMapGen(ScriptGetInteger('MapGen'));
3715 cFeatureSize     := ScriptGetInteger('MapFeatureSize');
3716 end;
3717 
3718 procedure ScriptOnGameInit;
3719 var i, j, k: LongInt;
3720 begin
3721 // not required if there is no script to run
3722 if not ScriptLoaded then
3723     exit;
3724 
3725 // push game variables so they may be modified by the script
3726 ScriptSetInteger('CursorX', NoPointX);
3727 ScriptSetInteger('CursorY', NoPointX);
3728 ScriptSetInteger('GameFlags', GameFlags);
3729 ScriptSetInteger('WorldEdge', ord(WorldEdge));
3730 ScriptSetString('Seed', cSeed);
3731 ScriptSetInteger('TemplateFilter', cTemplateFilter);
3732 ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
3733 ScriptSetInteger('MapGen', ord(cMapGen));
3734 ScriptSetInteger('MapFeatureSize', cFeatureSize);
3735 ScriptSetInteger('ScreenHeight', cScreenHeight);
3736 ScriptSetInteger('ScreenWidth', cScreenWidth);
3737 ScriptSetInteger('TurnTime', cHedgehogTurnTime);
3738 ScriptSetInteger('CaseFreq', cCaseFactor);
3739 ScriptSetInteger('MaxCaseDrops', cMaxCaseDrops);
3740 ScriptSetInteger('HealthCaseProb', cHealthCaseProb);
3741 ScriptSetInteger('HealthCaseAmount', cHealthCaseAmount);
3742 ScriptSetInteger('InitHealth', cInitHealth);
3743 ScriptSetInteger('DamagePercent', cDamagePercent);
3744 ScriptSetInteger('RopePercent', cRopePercent);
3745 ScriptSetInteger('MinesNum', cLandMines);
3746 ScriptSetInteger('MinesTime', cMinesTime);
3747 ScriptSetInteger('MineDudPercent', cMineDudPercent);
3748 ScriptSetInteger('AirMinesNum', cAirMines);
3749 ScriptSetInteger('Explosives', cExplosives);
3750 ScriptSetInteger('Delay', cInactDelay);
3751 ScriptSetInteger('Ready', cReadyDelay);
3752 ScriptSetInteger('SuddenDeathTurns', cSuddenDTurns);
3753 ScriptSetInteger('WaterRise', cWaterRise);
3754 ScriptSetInteger('HealthDecrease', cHealthDecrease);
3755 ScriptSetInteger('GetAwayTime', cGetAwayTime);
3756 ScriptSetInteger('AmmoTypeMax', Ord(High(TAmmoType)));
3757 ScriptSetString('Map', cMapName);
3758 ScriptSetString('Theme', Theme);
3759 ScriptSetString('Goals', '');
3760 
3761 ScriptCall('onGameInit');
3762 
3763 // pop game variables
3764 ParseCommand('seed ' + ScriptGetString('Seed'), true, true);
3765 cTemplateFilter  := ScriptGetInteger('TemplateFilter');
3766 LuaTemplateNumber:= ScriptGetInteger('TemplateNumber');
3767 cMapGen          := TMapGen(ScriptGetInteger('MapGen'));
3768 cFeatureSize     := ScriptGetInteger('MapFeatureSize');
3769 GameFlags        := ScriptGetInteger('GameFlags');
3770 WorldEdge        := TWorldEdge(ScriptGetInteger('WorldEdge'));
3771 cHedgehogTurnTime:= ScriptGetInteger('TurnTime');
3772 cCaseFactor      := ScriptGetInteger('CaseFreq');
3773 cMaxCaseDrops    := ScriptGetInteger('MaxCaseDrops');
3774 cHealthCaseProb  := ScriptGetInteger('HealthCaseProb');
3775 cHealthCaseAmount:= ScriptGetInteger('HealthCaseAmount');
3776 cInitHealth      := ScriptGetInteger('InitHealth');
3777 cDamagePercent   := ScriptGetInteger('DamagePercent');
3778 cRopePercent     := ScriptGetInteger('RopePercent');
3779 cLandMines       := ScriptGetInteger('MinesNum');
3780 cMinesTime       := ScriptGetInteger('MinesTime');
3781 cMineDudPercent  := ScriptGetInteger('MineDudPercent');
3782 cAirMines        := ScriptGetInteger('AirMinesNum');
3783 cExplosives      := ScriptGetInteger('Explosives');
3784 cInactDelay      := ScriptGetInteger('Delay');
3785 cReadyDelay      := ScriptGetInteger('Ready');
3786 cSuddenDTurns    := ScriptGetInteger('SuddenDeathTurns');
3787 cWaterRise       := ScriptGetInteger('WaterRise');
3788 cHealthDecrease  := ScriptGetInteger('HealthDecrease');
3789 cGetAwayTime     := ScriptGetInteger('GetAwayTime');
3790 
3791 if cMapName <> ScriptGetString('Map') then
3792     ParseCommand('map ' + ScriptGetString('Map'), true, true);
3793 if ScriptGetString('Theme') <> '' then
3794     ParseCommand('theme ' + ScriptGetString('Theme'), true, true);
3795 LuaGoals:= ScriptGetAnsiString('Goals');
3796 
3797 // Support lua changing the ammo layout - assume all hogs have same ammo, note this might leave a few ammo stores lying around.
3798 k:= 0;
3799 if (GameFlags and gfSharedAmmo) <> 0 then
3800     for i:= 0 to Pred(ClansCount) do
3801         for j:= 0 to Pred(ClansArray[i]^.TeamsNumber) do
3802             for k:= 0 to Pred(ClansArray[i]^.Teams[j]^.HedgehogsNumber) do
3803                 ClansArray[i]^.Teams[j]^.Hedgehogs[k].AmmoStore:= i
3804 else if (GameFlags and gfPerHogAmmo) <> 0 then
3805     for i:= 0 to Pred(TeamsCount) do
3806         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
3807             begin
3808             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= k;
3809             if StoreCnt-1 < k then AddAmmoStore;
3810             inc(k)
3811             end
3812 else
3813     for i:= 0 to Pred(TeamsCount) do
3814         begin
3815         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
3816             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= k;
3817         if StoreCnt-1 < k then AddAmmoStore;
3818         inc(k)
3819         end;
3820 if ScriptExists('onAmmoStoreInit') or ScriptExists('onNewAmmoStore') then
3821     begin
3822     // reset ammostore (quite unclean, but works?)
3823     uAmmos.freeModule;
3824     uAmmos.initModule;
3825     if ScriptExists('onAmmoStoreInit') then
3826         begin
3827         ScriptPrepareAmmoStore;
3828         ScriptCall('onAmmoStoreInit');
3829         SetAmmoLoadout(ScriptAmmoLoadout);
3830         SetAmmoProbability(ScriptAmmoProbability);
3831         SetAmmoDelay(ScriptAmmoDelay);
3832         SetAmmoReinforcement(ScriptAmmoReinforcement)
3833         end;
3834     ScriptApplyAmmoStore
3835     end;
3836 
3837 ScriptSetInteger('ClansCount', ClansCount);
3838 ScriptSetInteger('TeamsCount', TeamsCount);
3839 end;
3840 
3841 
3842 // Update values of screen dimensions and allow script to react to resolution change
3843 procedure ScriptOnScreenResize();
3844 begin
3845 ScriptSetInteger('ScreenHeight', cScreenHeight);
3846 ScriptSetInteger('ScreenWidth', cScreenWidth);
3847 ScriptCall('onScreenResize');
3848 end;
3849 
3850 // custom script loader via physfs, passed to lua_load
3851 const BUFSIZE = 1024;
3852 
3853 var inComment: boolean;
3854 var inQuote: boolean;
3855 var locSum: LongWord;
3856 var braceCount: LongWord;
3857 var wordCount: LongWord;
3858 var lastChar: char;
ScriptReadernull3859 function  ScriptReader(L: Plua_State; f: PFSFile; sz: Psize_t) : PChar; Cdecl;
3860 var mybuf: PChar;
3861     i: LongInt;
3862 begin
3863     SetRandomSeed(cSeed,true);
3864     mybuf := physfsReader(L, f, sz);
3865     if (mybuf <> nil) and ((sz^) > 0) then
3866         begin
3867             for i:= 0 to sz^-1 do
3868                 begin
3869                     if (lastChar = '-') and (mybuf[i] = '-') then
3870                         inComment := true
3871                     else if not inComment and (byte(mybuf[i]) > $20) and (byte(mybuf[i]) < $7F) and (mybuf[i]<>'-') then
3872                         begin
3873                         AddRandomness(byte(mybuf[i]));  // wish I had the seed...
3874                         CheckSum := CheckSum xor GetRandom($FFFFFFFF);
3875                         end;
3876                     lastChar := mybuf[i];
3877                     // lua apparently allows --  [===============[  as a valid block comment start.
3878                     // I can't be bothered to check for that nonsense. Will allow limited single line without [
3879                     if (byte(mybuf[i]) = $0D) or (byte(mybuf[i]) = $0A) or (mybuf[i] = '[') then
3880                         inComment := false
3881                 end;
3882         end;
3883     ScriptReader:= mybuf
3884 end;
3885 function  ScriptLocaleReader(L: Plua_State; f: PFSFile; sz: Psize_t) : PChar; Cdecl;
3886 var mybuf: PChar;
3887     i: LongInt;
3888 begin
3889     mybuf := physfsReader(L, f, sz);
3890     if (mybuf <> nil) and ((sz^) > 0) then
3891         begin
3892             for i:= 0 to sz^-1 do
3893                 begin
3894                     if not inComment and (mybuf[i] = '"') and (lastChar <> '\') then
3895                         inQuote := not inQuote;
3896                     if not inQuote and (lastChar = '-') and (mybuf[i] = '-') then
3897                         inComment := true;
3898                     if not inComment and (not inQuote) then
3899                        locSum := locSum xor (byte(mybuf[i]) shl (i mod 4));
3900                     if not inComment and (not inQuote) and
3901                         ((mybuf[i] = '(') or
3902                         (mybuf[i] = ')') or
3903                         (mybuf[i] = '+') or
3904                         (mybuf[i] = '#') or
3905                         (braceCount > 2) or
3906                         (wordCount > 6)) then
3907                        CheckSum := locSum;
3908                     if not inComment and (not inQuote) and ((mybuf[i] = '{') or (mybuf[i] = '}')) then
3909                         inc(braceCount);
3910                     if not inComment and (not inQuote) and
3911                         (((byte(mybuf[i]) > $40) and (byte(mybuf[i]) < $5B)) or
3912                         ((byte(mybuf[i]) > $60) and (byte(mybuf[i]) < $7B)) or
3913                         ((byte(mybuf[i]) >= $30) and (byte(mybuf[i]) < $3A))) then
3914                         inc(wordCount);
3915                     lastChar := mybuf[i];
3916                     // this allows at least supporting the commented strings at end of line with lua script names
3917                     if (byte(mybuf[i]) = $0D) or (byte(mybuf[i]) = $0A) or (mybuf[i] = '[') then
3918                         inComment := false
3919                 end;
3920         end;
3921     ScriptLocaleReader:= mybuf
3922 end;
3923 
3924 function ScriptLoad(name : shortstring; mustExist : boolean): boolean;
3925 var ret : LongInt;
3926       s : shortstring;
3927       f : PFSFile;
3928     buf : array[0..Pred(BUFSIZE)] of byte;
3929 begin
3930 inComment:= false;
3931 inQuote:= false;
3932 lastChar:= 'X';
3933 braceCount:= 0;
3934 wordCount:= 0;
3935 locSum:= 0;
3936 s:= cPathz[ptData] + name;
3937 if not pfsExists(s) then
3938     begin
3939     if mustExist then
3940         OutError('Script not found: ' + name, true)
3941     else
3942         AddFileLog('[LUA] Script not found: ' + name);
3943     ScriptLoad:= false;
3944     exit;
3945     end;
3946 
3947 f:= pfsOpenRead(s);
3948 if f = nil then
3949     OutError('Error reading script: ' + name, true);
3950 
3951 hedgewarsMountPackage(Str2PChar(copy(s, 3, length(s)-6)+'.hwp'));
3952 
3953 physfsReaderSetBuffer(@buf);
3954 if (Pos('Locale/',s) <> 0) or (s = 'Scripts/OfficialChallengeHashes.lua') then
3955      ret:= lua_load(luaState, @ScriptLocaleReader, f, Str2PChar(s))
3956 else
3957     begin
3958     SetRandomSeed(cSeed,true);
3959     ret:= lua_load(luaState, @ScriptReader, f, Str2PChar(s))
3960     end;
3961 pfsClose(f);
3962 
3963 if ret <> 0 then
3964     begin
3965     LuaError('Failed to load ' + name + '(error ' + IntToStr(ret) + ')');
3966     LuaError(lua_tostring(luaState, -1));
3967     ScriptLoad:= false;
3968     end
3969 else
3970     begin
3971     WriteLnToConsole('Lua: ' + name + ' loaded');
3972     // call the script file
3973     lua_pcall(luaState, 0, 0, 0);
3974     ScriptLoaded:= true;
3975     ScriptLoad:= true;
3976     end;
3977 end;
3978 
3979 procedure SetGlobals;
3980 var x, y: LongInt;
3981 begin
3982 ScriptSetInteger('TurnTimeLeft', TurnTimeLeft);
3983 ScriptSetInteger('ReadyTimeLeft', ReadyTimeLeft);
3984 ScriptSetInteger('GameTime', GameTicks);
3985 ScriptSetInteger('TotalRounds', TotalRoundsReal);
3986 ScriptSetInteger('WaterLine', cWaterLine);
3987 if isCursorVisible and (not bShowAmmoMenu) then
3988     begin
3989     x:= CursorPoint.X - WorldDx;
3990     y:= cScreenHeight - CursorPoint.Y - WorldDy;
3991     if (PrevCursorX <> x) or
3992        (PrevCursorY <> y) then
3993         begin
3994         ScriptSetInteger('CursorX', x);
3995         ScriptSetInteger('CursorY', y);
3996         PrevCursorX:= x;
3997         PrevCursorY:= y;
3998         end
3999     end
4000 else
4001     begin
4002     ScriptSetInteger('CursorX', NoPointX);
4003     ScriptSetInteger('CursorY', NoPointX);
4004     PrevCursorX:= NoPointX;
4005     PrevCursorY:= NoPointX
4006     end;
4007 
4008 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then
4009     ScriptSetInteger('CurrentHedgehog', CurrentHedgehog^.Gear^.UID)
4010 else
4011     ScriptSetNil('CurrentHedgehog');
4012 end;
4013 
4014 procedure ScriptSetMapGlobals;
4015 begin
4016 ScriptSetInteger('LAND_WIDTH', LAND_WIDTH);
4017 ScriptSetInteger('LAND_HEIGHT', LAND_HEIGHT);
4018 ScriptSetInteger('LeftX', leftX);
4019 ScriptSetInteger('RightX', rightX);
4020 ScriptSetInteger('TopY', topY);
4021 end;
4022 
4023 procedure GetGlobals;
4024 var currentTTL, currentRTL, newTTL, newRTL: LongInt;
4025 begin
4026 // Setting TurnTimeLeft and ReadyTimeLeft should now be done in the setter functions.
4027 // SetTurnTimeLeft and SetReadTimeLeft.
4028 // GetGloals should be removed in a future release.
4029 
4030 // DEPRECATED: Read TurnTimeLeft and ReadyTimeLeft from script directly.
4031 // TODO: Remove this behaviour in a future version.
4032 currentTTL:= TurnTimeLeft;
4033 currentRTL:= ReadyTimeLeft;
4034 newTTL:= ScriptGetInteger('TurnTimeLeft');
4035 newRTL:= ScriptGetInteger('ReadyTimeLeft');
4036 if (currentTTL <> newTTL) and (not isPendingTurnTimeLeft) then
4037     begin
4038     TurnTimeLeft:= newTTL;
4039     LuaWarning('Writing to TurnTimeLeft directly is deprecated! Use SetTurnTimeLeft instead!');
4040     end;
4041 
4042 if (currentRTL <> newRTL) and (not isPendingReadyTimeLeft) then
4043     begin
4044     ReadyTimeLeft:= newRTL;
4045     LuaWarning('Writing to ReadyTimeLeft directly is deprecated! Use SetReadyTimeLeft instead!');
4046     end;
4047 
4048 // Set TurnTimeLeft and ReadyTimeLeft if activated by SetTurnTimeLeft and SetReadyTimeLeft before
4049 if isPendingTurnTimeLeft then
4050     begin
4051     TurnTimeLeft:= PendingTurnTimeLeft;
4052     ScriptSetInteger('TurnTimeLeft', TurnTimeLeft);
4053     isPendingTurnTimeLeft:= false;
4054     end;
4055 if isPendingReadyTimeLeft then
4056     begin
4057     ReadyTimeLeft:= PendingReadyTimeLeft;
4058     ScriptSetInteger('ReadyTimeLeft', ReadyTimeLeft);
4059     isPendingReadyTimeLeft:= false;
4060     end;
4061 end;
4062 
4063 procedure ScriptCall(fname : shortstring);
4064 begin
4065 if (not ScriptLoaded) or (not ScriptExists(fname)) then
4066     exit;
4067 SetGlobals;
4068 lua_getglobal(luaState, Str2PChar(fname));
4069 if lua_pcall(luaState, 0, 0, 0) <> 0 then
4070     begin
4071     LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1));
4072     lua_pop(luaState, 1)
4073     end;
4074 GetGlobals;
4075 end;
4076 
4077 (*
4078 function ParseCommandOverride(key, value : shortstring) : shortstring;
4079 begin
4080 ParseCommandOverride:= value;
4081 if not ScriptExists('ParseCommandOverride') then
4082     exit;
4083 lua_getglobal(luaState, Str2PChar('ParseCommandOverride'));
4084 lua_pushstring(luaState, Str2PChar(key));
4085 lua_pushstring(luaState, Str2PChar(value));
4086 if lua_pcall(luaState, 2, 1, 0) <> 0 then
4087     begin
4088     LuaError('Lua: Error while calling ParseCommandOverride: ' + lua_tostring(luaState, -1));
4089     lua_pop(luaState, 1)
4090     end
4091 else
4092     begin
4093     ParseCommandOverride:= lua_tostring(luaState, -1);
4094     lua_pop(luaState, 1)
4095     end;
4096 end;
4097 *)
4098 
4099 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
4100 begin
4101 ScriptCall:= ScriptCall(fname, par1, 0, 0, 0)
4102 end;
4103 
4104 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
4105 begin
4106 ScriptCall:= ScriptCall(fname, par1, par2, 0, 0)
4107 end;
4108 
4109 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
4110 begin
4111 ScriptCall:= ScriptCall(fname, par1, par2, par3, 0)
4112 end;
4113 
4114 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
4115 begin
4116 if (not ScriptLoaded) or (not ScriptExists(fname)) then
4117     exit(0);
4118 SetGlobals;
4119 lua_getglobal(luaState, Str2PChar(fname));
4120 lua_pushnumber(luaState, par1);
4121 lua_pushnumber(luaState, par2);
4122 lua_pushnumber(luaState, par3);
4123 lua_pushnumber(luaState, par4);
4124 ScriptCall:= 0;
4125 if lua_pcall(luaState, 4, 1, 0) <> 0 then
4126     begin
4127     LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1));
4128     lua_pop(luaState, 1)
4129     end
4130 else
4131     begin
4132     ScriptCall:= Trunc(lua_tonumber(luaState, -1));
4133     lua_pop(luaState, 1)
4134     end;
4135 GetGlobals;
4136 end;
4137 
4138 function ScriptExists(fname : shortstring) : boolean;
4139 begin
4140 if not ScriptLoaded then
4141     begin
4142     ScriptExists:= false;
4143     exit
4144     end;
4145 lua_getglobal(luaState, Str2PChar(fname));
4146 ScriptExists:= not lua_isnoneornil(luaState, -1);
4147 lua_pop(luaState, 1)
4148 end;
4149 
4150 procedure ScriptPrepareAmmoStore;
4151 var i: ShortInt;
4152 begin
4153 ScriptAmmoLoadout:= '';
4154 ScriptAmmoDelay:= '';
4155 ScriptAmmoProbability:= '';
4156 ScriptAmmoReinforcement:= '';
4157 for i:=1 to ord(High(TAmmoType)) do
4158     begin
4159     ScriptAmmoLoadout:= ScriptAmmoLoadout + '0';
4160     ScriptAmmoProbability:= ScriptAmmoProbability + '0';
4161     ScriptAmmoDelay:= ScriptAmmoDelay + '0';
4162     ScriptAmmoReinforcement:= ScriptAmmoReinforcement + '0';
4163     end;
4164 end;
4165 
4166 procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte);
4167 begin
4168 //if (ord(ammo) < 1) or (count > 9) or (count < 0) or (probability < 0) or (probability > 8) or (delay < 0) or (delay > 9) or (reinforcement < 0) or (reinforcement > 8) then
4169 if (ord(ammo) < 1) or (count > 9) or (probability > 8) or (delay > 9) or (reinforcement > 8) then
4170     exit;
4171 ScriptAmmoLoadout[ord(ammo)]:= inttostr(count)[1];
4172 ScriptAmmoProbability[ord(ammo)]:= inttostr(probability)[1];
4173 ScriptSetAmmoDelay(ammo, delay);
4174 ScriptAmmoReinforcement[ord(ammo)]:= inttostr(reinforcement)[1];
4175 end;
4176 
4177 procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: LongWord);
4178 begin
4179 // change loadout string if ammo store has not been initialized yet
4180 if (StoreCnt = 0) then
4181     begin
4182     if (delay <= 9) then
4183         ScriptAmmoDelay[ord(ammo)]:= inttostr(delay)[1];
4184     end
4185 // change 'live' delay values
4186 else if (CurrentTeam <> nil) then
4187     begin
4188     ammoz[ammo].SkipTurns:= CurrentTeam^.Clan^.TurnNumber + delay;
4189     if ammoz[ammo].SkipTurns > 0 then
4190         dec(ammoz[ammo].SkipTurns);
4191     AmmoMenuInvalidated:= true;
4192     end;
4193 end;
4194 
4195 procedure ScriptApplyAmmoStore;
4196 var i, j, k : LongInt;
4197 begin
4198 if (GameFlags and gfSharedAmmo) <> 0 then
4199     for i:= 0 to Pred(ClansCount) do
4200         begin
4201         if ScriptExists('onNewAmmoStore') then
4202             begin
4203             ScriptPrepareAmmoStore;
4204             ScriptCall('onNewAmmoStore',i,-1);
4205             SetAmmoLoadout(ScriptAmmoLoadout);
4206             SetAmmoProbability(ScriptAmmoProbability);
4207             SetAmmoDelay(ScriptAmmoDelay);
4208             SetAmmoReinforcement(ScriptAmmoReinforcement)
4209             end;
4210         AddAmmoStore;
4211         for j:= 0 to Pred(ClansArray[i]^.TeamsNumber) do
4212             for k:= 0 to Pred(ClansArray[i]^.Teams[j]^.HedgehogsNumber) do
4213                 ClansArray[i]^.Teams[j]^.Hedgehogs[k].AmmoStore:= StoreCnt - 1
4214         end
4215 else if (GameFlags and gfPerHogAmmo) <> 0 then
4216     for i:= 0 to Pred(TeamsCount) do
4217         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
4218             begin
4219             if ScriptExists('onNewAmmoStore') then
4220                 begin
4221                 ScriptPrepareAmmoStore;
4222                 ScriptCall('onNewAmmoStore',i,j);
4223                 SetAmmoLoadout(ScriptAmmoLoadout);
4224                 SetAmmoProbability(ScriptAmmoProbability);
4225                 SetAmmoDelay(ScriptAmmoDelay);
4226                 SetAmmoReinforcement(ScriptAmmoReinforcement)
4227                 end;
4228             AddAmmoStore;
4229             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= StoreCnt - 1
4230             end
4231 else
4232     for i:= 0 to Pred(TeamsCount) do
4233         begin
4234         if ScriptExists('onNewAmmoStore') then
4235             begin
4236             ScriptPrepareAmmoStore;
4237             ScriptCall('onNewAmmoStore',i,-1);
4238             SetAmmoLoadout(ScriptAmmoLoadout);
4239             SetAmmoProbability(ScriptAmmoProbability);
4240             SetAmmoDelay(ScriptAmmoDelay);
4241             SetAmmoReinforcement(ScriptAmmoReinforcement)
4242             end;
4243         AddAmmoStore;
4244         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
4245             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= StoreCnt - 1
4246         end
4247 end;
4248 
4249 procedure initModule;
4250 var at : TGearType;
4251     vgt: TVisualGearType;
4252     am : TAmmoType;
4253     si : TStatInfoType;
4254     st : TSound;
4255     he : THogEffect;
4256     cg : TCapGroup;
4257     spr: TSprite;
4258     mg : TMapGen;
4259     we : TWorldEdge;
4260 begin
4261 // initialize lua
4262 luaState:= lua_open;
4263 if checkFails(luaState <> nil, 'lua_open failed', true) then exit;
4264 
4265 // open internal libraries
4266 luaopen_base(luaState);
4267 luaopen_string(luaState);
4268 luaopen_math(luaState);
4269 luaopen_table(luaState);
4270 
4271 // import some variables
4272 ScriptSetString(_S'LOCALE', cLanguage);
4273 
4274 {$IFDEF USE_TOUCH_INTERFACE}
4275 ScriptSetString(_S'INTERFACE', 'touch');
4276 {$ELSE}
4277 ScriptSetString(_S'INTERFACE', 'desktop');
4278 {$ENDIF}
4279 
4280 // Add aliases for amDuck and gtDuck because rubber duck was removed.
4281 // amDuck and gtDuck are deprecated and should be removed later.
4282 // TODO: Remove these aliases in a later version.
4283 ScriptSetInteger('amDuck', Ord(amCreeper));
4284 ScriptSetInteger('gtDuck', Ord(gtCreeper));
4285 
4286 // import game flags
4287 ScriptSetInteger('gfSwitchHog', gfSwitchHog);
4288 ScriptSetInteger('gfMultiWeapon', gfMultiWeapon);
4289 ScriptSetInteger('gfSolidLand', gfSolidLand);
4290 ScriptSetInteger('gfBorder', gfBorder);
4291 ScriptSetInteger('gfBottomBorder', gfBottomBorder);
4292 ScriptSetInteger('gfDivideTeams', gfDivideTeams);
4293 ScriptSetInteger('gfLowGravity', gfLowGravity);
4294 ScriptSetInteger('gfLaserSight', gfLaserSight);
4295 ScriptSetInteger('gfInvulnerable', gfInvulnerable);
4296 ScriptSetInteger('gfResetHealth', gfResetHealth);
4297 ScriptSetInteger('gfVampiric', gfVampiric);
4298 ScriptSetInteger('gfKarma', gfKarma);
4299 ScriptSetInteger('gfArtillery', gfArtillery);
4300 ScriptSetInteger('gfOneClanMode', gfOneClanMode);
4301 ScriptSetInteger('gfRandomOrder', gfRandomOrder);
4302 ScriptSetInteger('gfKing', gfKing);
4303 ScriptSetInteger('gfPlaceHog', gfPlaceHog);
4304 ScriptSetInteger('gfSharedAmmo', gfSharedAmmo);
4305 ScriptSetInteger('gfDisableGirders', gfDisableGirders);
4306 ScriptSetInteger('gfDisableLandObjects', gfDisableLandObjects);
4307 ScriptSetInteger('gfAISurvival', gfAISurvival);
4308 ScriptSetInteger('gfInfAttack', gfInfAttack);
4309 ScriptSetInteger('gfResetWeps', gfResetWeps);
4310 ScriptSetInteger('gfPerHogAmmo', gfPerHogAmmo);
4311 ScriptSetInteger('gfDisableWind', gfDisableWind);
4312 ScriptSetInteger('gfMoreWind', gfMoreWind);
4313 ScriptSetInteger('gfTagTeam', gfTagTeam);
4314 ScriptSetInteger('gfShoppaBorder', gfShoppaBorder);
4315 
4316 ScriptSetInteger('gmLeft', gmLeft);
4317 ScriptSetInteger('gmRight', gmRight);
4318 ScriptSetInteger('gmUp', gmUp);
4319 ScriptSetInteger('gmDown', gmDown);
4320 ScriptSetInteger('gmSwitch', gmSwitch);
4321 ScriptSetInteger('gmAttack', gmAttack);
4322 ScriptSetInteger('gmLJump', gmLJump);
4323 ScriptSetInteger('gmHJump', gmHJump);
4324 ScriptSetInteger('gmDestroy', gmDestroy);
4325 ScriptSetInteger('gmSlot', gmSlot);
4326 ScriptSetInteger('gmWeapon', gmWeapon);
4327 ScriptSetInteger('gmTimer', gmTimer);
4328 ScriptSetInteger('gmAnimate', gmAnimate);
4329 ScriptSetInteger('gmPrecise', gmPrecise);
4330 ScriptSetInteger('gmAllStoppable', gmAllStoppable);
4331 
4332 // speech bubbles
4333 ScriptSetInteger('SAY_SAY', 1);
4334 ScriptSetInteger('SAY_THINK', 2);
4335 ScriptSetInteger('SAY_SHOUT', 3);
4336 
4337 // other
4338 ScriptSetInteger('AMMO_INFINITE', AMMO_INFINITE);
4339 ScriptSetInteger('JETPACK_FUEL_INFINITE', JETPACK_FUEL_INFINITE);
4340 ScriptSetInteger('BIRDY_ENERGY_INFINITE', BIRDY_ENERGY_INFINITE);
4341 ScriptSetInteger('NO_CURSOR', NoPointX);
4342 ScriptSetInteger('MAX_HOG_HEALTH', cMaxHogHealth);
4343 ScriptSetInteger('MAX_TURN_TIME', cMaxTurnTime);
4344 
4345 // register gear types
4346 for at:= Low(TGearType) to High(TGearType) do
4347     ScriptSetInteger(EnumToStr(at), ord(at));
4348 
4349 for vgt:= Low(TVisualGearType) to High(TVisualGearType) do
4350     ScriptSetInteger(EnumToStr(vgt), ord(vgt));
4351 
4352 // register sounds
4353 for st:= Low(TSound) to High(TSound) do
4354     ScriptSetInteger(EnumToStr(st), ord(st));
4355 
4356 // register ammo types
4357 for am:= Low(TAmmoType) to High(TAmmoType) do
4358     ScriptSetInteger(EnumToStr(am), ord(am));
4359 
4360 for si:= Low(TStatInfoType) to High(TStatInfoType) do
4361     ScriptSetInteger(EnumToStr(si), ord(si));
4362 
4363 for he:= Low(THogEffect) to High(THogEffect) do
4364     ScriptSetInteger(EnumToStr(he), ord(he));
4365 
4366 for cg:= Low(TCapGroup) to High(TCapGroup) do
4367     ScriptSetInteger(EnumToStr(cg), ord(cg));
4368 
4369 for spr:= Low(TSprite) to High(TSprite) do
4370     ScriptSetInteger(EnumToStr(spr), ord(spr));
4371 
4372 for mg:= Low(TMapGen) to High(TMapGen) do
4373     ScriptSetInteger(EnumToStr(mg), ord(mg));
4374 
4375 for we:= Low(TWorldEdge) to High(TWorldEdge) do
4376     ScriptSetInteger(EnumToStr(we), ord(we));
4377 
4378 ScriptSetLongWord('capcolDefault'   , capcolDefaultLua);
4379 ScriptSetLongWord('capcolSetting'   , capcolSettingLua);
4380 
4381 ScriptSetInteger('gstDrowning'      , gstDrowning);
4382 ScriptSetInteger('gstHHDriven'      , gstHHDriven);
4383 ScriptSetInteger('gstMoving'        , gstMoving);
4384 ScriptSetInteger('gstAttacked'      , gstAttacked);
4385 ScriptSetInteger('gstAttacking'     , gstAttacking);
4386 ScriptSetInteger('gstCollision'     , gstCollision);
4387 ScriptSetInteger('gstChooseTarget'  , gstChooseTarget);
4388 ScriptSetInteger('gstHHJumping'     , gstHHJumping);
4389 ScriptSetInteger('gsttmpFlag'       , gsttmpFlag);
4390 ScriptSetInteger('gstHHThinking'    , gstHHThinking);
4391 ScriptSetInteger('gstNoDamage'      , gstNoDamage);
4392 ScriptSetInteger('gstHHHJump'       , gstHHHJump);
4393 ScriptSetInteger('gstAnimation'     , gstAnimation);
4394 ScriptSetInteger('gstHHDeath'       , gstHHDeath);
4395 ScriptSetInteger('gstWinner'        , gstWinner);
4396 ScriptSetInteger('gstWait'          , gstWait);
4397 ScriptSetInteger('gstNotKickable'   , gstNotKickable);
4398 ScriptSetInteger('gstLoser'         , gstLoser);
4399 ScriptSetInteger('gstHHGone'        , gstHHGone);
4400 ScriptSetInteger('gstInvisible'     , gstInvisible);
4401 ScriptSetInteger('gstSubmersible'   , gstSubmersible);
4402 ScriptSetInteger('gstFrozen'        , gstFrozen);
4403 ScriptSetInteger('gstNoGravity'     , gstNoGravity);
4404 
4405 // ai hints
4406 ScriptSetInteger('aihUsualProcessing', aihUsualProcessing);
4407 ScriptSetInteger('aihDoesntMatter'   , aihDoesntMatter);
4408 
4409 // land flags (partial)
4410 ScriptSetInteger('lfIndestructible', lfIndestructible);
4411 ScriptSetInteger('lfIce'           , lfIce);
4412 ScriptSetInteger('lfBouncy'        , lfBouncy);
4413 
4414 ScriptSetInteger('lfLandMask'      , lfLandMask);
4415 ScriptSetInteger('lfCurHogCrate'   , lfCurHogCrate);
4416 ScriptSetInteger('lfHHMask'        , lfHHMask);
4417 ScriptSetInteger('lfNotHHObjMask'  , lfNotHHObjMask);
4418 ScriptSetInteger('lfAllObjMask'    , lfAllObjMask);
4419 
4420 // explosion constants
4421 ScriptSetInteger('EXPLAutoSound'    , EXPLAutoSound);
4422 ScriptSetInteger('EXPLNoDamage'     , EXPLNoDamage);
4423 ScriptSetInteger('EXPLDoNotTouchHH' , EXPLDoNotTouchHH);
4424 ScriptSetInteger('EXPLDontDraw'     , EXPLDontDraw);
4425 ScriptSetInteger('EXPLNoGfx'        , EXPLNoGfx);
4426 ScriptSetInteger('EXPLPoisoned'     , EXPLPoisoned);
4427 ScriptSetInteger('EXPLDoNotTouchAny', EXPLDoNotTouchAny);
4428 ScriptSetInteger('EXPLForceDraw'    , EXPLForceDraw);
4429 
4430 // register functions
4431 lua_register(luaState, _P'HideHog', @lc_hidehog);
4432 lua_register(luaState, _P'RestoreHog', @lc_restorehog);
4433 lua_register(luaState, _P'IsHogHidden', @lc_ishoghidden);
4434 lua_register(luaState, _P'SaveCampaignVar', @lc_savecampaignvar);
4435 lua_register(luaState, _P'GetCampaignVar', @lc_getcampaignvar);
4436 lua_register(luaState, _P'SaveMissionVar', @lc_savemissionvar);
4437 lua_register(luaState, _P'GetMissionVar', @lc_getmissionvar);
4438 lua_register(luaState, _P'band', @lc_band);
4439 lua_register(luaState, _P'bor', @lc_bor);
4440 lua_register(luaState, _P'bnot', @lc_bnot);
4441 lua_register(luaState, _P'div', @lc_div);
4442 lua_register(luaState, _P'GetInputMask', @lc_getinputmask);
4443 lua_register(luaState, _P'SetInputMask', @lc_setinputmask);
4444 lua_register(luaState, _P'AddGear', @lc_addgear);
4445 lua_register(luaState, _P'DismissTeam', @lc_dismissteam);
4446 lua_register(luaState, _P'EnableGameFlags', @lc_enablegameflags);
4447 lua_register(luaState, _P'DisableGameFlags', @lc_disablegameflags);
4448 lua_register(luaState, _P'ClearGameFlags', @lc_cleargameflags);
4449 lua_register(luaState, _P'GetGameFlag', @lc_getgameflag);
4450 lua_register(luaState, _P'DeleteGear', @lc_deletegear);
4451 lua_register(luaState, _P'AddVisualGear', @lc_addvisualgear);
4452 lua_register(luaState, _P'DeleteVisualGear', @lc_deletevisualgear);
4453 lua_register(luaState, _P'GetVisualGearType', @lc_getvisualgeartype);
4454 lua_register(luaState, _P'GetVisualGearValues', @lc_getvisualgearvalues);
4455 lua_register(luaState, _P'SetVisualGearValues', @lc_setvisualgearvalues);
4456 lua_register(luaState, _P'GetGearValues', @lc_getgearvalues);
4457 lua_register(luaState, _P'SetGearValues', @lc_setgearvalues);
4458 lua_register(luaState, _P'SpawnHealthCrate', @lc_spawnhealthcrate);
4459 lua_register(luaState, _P'SpawnAmmoCrate', @lc_spawnammocrate);
4460 lua_register(luaState, _P'SpawnUtilityCrate', @lc_spawnutilitycrate);
4461 lua_register(luaState, _P'SpawnSupplyCrate', @lc_spawnsupplycrate);
4462 lua_register(luaState, _P'SpawnFakeHealthCrate', @lc_spawnfakehealthcrate);
4463 lua_register(luaState, _P'SpawnFakeAmmoCrate', @lc_spawnfakeammocrate);
4464 lua_register(luaState, _P'SpawnFakeUtilityCrate', @lc_spawnfakeutilitycrate);
4465 lua_register(luaState, _P'WriteLnToConsole', @lc_writelntoconsole);
4466 lua_register(luaState, _P'WriteLnToChat', @lc_writelntochat);
4467 lua_register(luaState, _P'GetGearType', @lc_getgeartype);
4468 lua_register(luaState, _P'EndGame', @lc_endgame);
4469 lua_register(luaState, _P'EndTurn', @lc_endturn);
4470 lua_register(luaState, _P'Retreat', @lc_retreat);
4471 lua_register(luaState, _P'SkipTurn', @lc_skipturn);
4472 lua_register(luaState, _P'GetTeamStats', @lc_getteamstats);
4473 lua_register(luaState, _P'SendStat', @lc_sendstat);
4474 lua_register(luaState, _P'SendGameResultOff', @lc_sendgameresultoff);
4475 lua_register(luaState, _P'SendRankingStatsOff', @lc_sendrankingstatsoff);
4476 lua_register(luaState, _P'SendAchievementsStatsOff', @lc_sendachievementsstatsoff);
4477 lua_register(luaState, _P'SendHealthStatsOff', @lc_sendhealthstatsoff);
4478 lua_register(luaState, _P'FindPlace', @lc_findplace);
4479 lua_register(luaState, _P'SetGearPosition', @lc_setgearposition);
4480 lua_register(luaState, _P'GetGearPosition', @lc_getgearposition);
4481 lua_register(luaState, _P'SetGearTarget', @lc_setgeartarget);
4482 lua_register(luaState, _P'GetGearTarget', @lc_getgeartarget);
4483 lua_register(luaState, _P'SetGearVelocity', @lc_setgearvelocity);
4484 lua_register(luaState, _P'GetGearVelocity', @lc_getgearvelocity);
4485 lua_register(luaState, _P'ParseCommand', @lc_parsecommand);
4486 lua_register(luaState, _P'ShowMission', @lc_showmission);
4487 lua_register(luaState, _P'HideMission', @lc_hidemission);
4488 lua_register(luaState, _P'SetAmmoTexts', @lc_setammotexts);
4489 lua_register(luaState, _P'SetAmmoDescriptionAppendix', @lc_setammodescriptionappendix);
4490 lua_register(luaState, _P'AddCaption', @lc_addcaption);
4491 lua_register(luaState, _P'SetAmmo', @lc_setammo);
4492 lua_register(luaState, _P'GetAmmo', @lc_getammo);
4493 lua_register(luaState, _P'SetAmmoDelay', @lc_setammodelay);
4494 lua_register(luaState, _P'SetAmmoSlot', @lc_setammoslot);
4495 lua_register(luaState, _P'PlaySound', @lc_playsound);
4496 lua_register(luaState, _P'PlayMusicSound', @lc_playmusicsound);
4497 lua_register(luaState, _P'StopMusicSound', @lc_stopmusicsound);
4498 lua_register(luaState, _P'SetSoundMask', @lc_setsoundmask);
4499 lua_register(luaState, _P'GetTeamName', @lc_getteamname);
4500 lua_register(luaState, _P'GetTeamIndex', @lc_getteamindex);
4501 lua_register(luaState, _P'GetTeamClan', @lc_getteamclan);
4502 lua_register(luaState, _P'AddTeam', @lc_addteam);
4503 lua_register(luaState, _P'AddMissionTeam', @lc_addmissionteam);
4504 lua_register(luaState, _P'SetTeamLabel', @lc_setteamlabel);
4505 lua_register(luaState, _P'SetTeamPassive', @lc_setteampassive);
4506 lua_register(luaState, _P'AddHog', @lc_addhog);
4507 lua_register(luaState, _P'AddMissionHog', @lc_addmissionhog);
4508 lua_register(luaState, _P'AddAmmo', @lc_addammo);
4509 lua_register(luaState, _P'GetAmmoCount', @lc_getammocount);
4510 lua_register(luaState, _P'HealHog', @lc_healhog);
4511 lua_register(luaState, _P'SetHealth', @lc_sethealth);
4512 lua_register(luaState, _P'GetHealth', @lc_gethealth);
4513 lua_register(luaState, _P'SetEffect', @lc_seteffect);
4514 lua_register(luaState, _P'GetEffect', @lc_geteffect);
4515 lua_register(luaState, _P'GetHogClan', @lc_gethogclan);
4516 lua_register(luaState, _P'GetClanColor', @lc_getclancolor);
4517 lua_register(luaState, _P'SetClanColor', @lc_setclancolor);
4518 lua_register(luaState, _P'GetHogVoicepack', @lc_gethogvoicepack);
4519 lua_register(luaState, _P'GetHogFlag', @lc_gethogflag);
4520 lua_register(luaState, _P'GetHogFort', @lc_gethogfort);
4521 lua_register(luaState, _P'GetHogGrave', @lc_gethoggrave);
4522 lua_register(luaState, _P'IsHogAlive', @lc_ishogalive);
4523 lua_register(luaState, _P'IsHogLocal', @lc_ishoglocal);
4524 lua_register(luaState, _P'GetHogTeamName', @lc_gethogteamname);
4525 lua_register(luaState, _P'SetHogTeamName', @lc_sethogteamname);
4526 lua_register(luaState, _P'GetHogName', @lc_gethogname);
4527 lua_register(luaState, _P'SetHogName', @lc_sethogname);
4528 lua_register(luaState, _P'GetHogLevel', @lc_gethoglevel);
4529 lua_register(luaState, _P'SetHogLevel', @lc_sethoglevel);
4530 lua_register(luaState, _P'GetX', @lc_getx);
4531 lua_register(luaState, _P'GetY', @lc_gety);
4532 lua_register(luaState, _P'CopyPV', @lc_copypv);
4533 lua_register(luaState, _P'FollowGear', @lc_followgear);
4534 lua_register(luaState, _P'GetFollowGear', @lc_getfollowgear);
4535 lua_register(luaState, _P'SetState', @lc_setstate);
4536 lua_register(luaState, _P'GetState', @lc_getstate);
4537 lua_register(luaState, _P'GetTag', @lc_gettag);
4538 lua_register(luaState, _P'SetTag', @lc_settag);
4539 lua_register(luaState, _P'SetTimer', @lc_settimer);
4540 lua_register(luaState, _P'GetTimer', @lc_gettimer);
4541 lua_register(luaState, _P'SetFlightTime', @lc_setflighttime);
4542 lua_register(luaState, _P'GetFlightTime', @lc_getflighttime);
4543 lua_register(luaState, _P'SetZoom', @lc_setzoom);
4544 lua_register(luaState, _P'GetZoom', @lc_getzoom);
4545 lua_register(luaState, _P'HogSay', @lc_hogsay);
4546 lua_register(luaState, _P'SwitchHog', @lc_switchhog);
4547 lua_register(luaState, _P'EnableSwitchHog', @lc_enableswitchhog);
4548 lua_register(luaState, _P'HogTurnLeft', @lc_hogturnleft);
4549 lua_register(luaState, _P'GetGearElasticity', @lc_getgearelasticity);
4550 lua_register(luaState, _P'SetGearElasticity', @lc_setgearelasticity);
4551 lua_register(luaState, _P'GetGearFriction', @lc_getgearfriction);
4552 lua_register(luaState, _P'SetGearFriction', @lc_setgearfriction);
4553 lua_register(luaState, _P'GetGearRadius', @lc_getgearradius);
4554 lua_register(luaState, _P'GetGearMessage', @lc_getgearmessage);
4555 lua_register(luaState, _P'SetGearMessage', @lc_setgearmessage);
4556 lua_register(luaState, _P'GetGearPos', @lc_getgearpos);
4557 lua_register(luaState, _P'SetGearPos', @lc_setgearpos);
4558 lua_register(luaState, _P'GetGearCollisionMask', @lc_getgearcollisionmask);
4559 lua_register(luaState, _P'SetGearCollisionMask', @lc_setgearcollisionmask);
4560 lua_register(luaState, _P'GetRandom', @lc_getrandom);
4561 lua_register(luaState, _P'SetWind', @lc_setwind);
4562 lua_register(luaState, _P'GetWind', @lc_getwind);
4563 lua_register(luaState, _P'MapHasBorder', @lc_maphasborder);
4564 lua_register(luaState, _P'GetHogHat', @lc_gethoghat);
4565 lua_register(luaState, _P'SetHogHat', @lc_sethoghat);
4566 lua_register(luaState, _P'EraseSprite', @lc_erasesprite);
4567 lua_register(luaState, _P'PlaceSprite', @lc_placesprite);
4568 lua_register(luaState, _P'PlaceGirder', @lc_placegirder);
4569 lua_register(luaState, _P'PlaceRubber', @lc_placerubber);
4570 lua_register(luaState, _P'GetCurAmmoType', @lc_getcurammotype);
4571 lua_register(luaState, _P'TestRectForObstacle', @lc_testrectforobstacle);
4572 lua_register(luaState, _P'GetGravity', @lc_getgravity);
4573 lua_register(luaState, _P'SetGravity', @lc_setgravity);
4574 lua_register(luaState, _P'SetWaterLine', @lc_setwaterline);
4575 lua_register(luaState, _P'SetNextWeapon', @lc_setnextweapon);
4576 lua_register(luaState, _P'SetWeapon', @lc_setweapon);
4577 lua_register(luaState, _P'SetCinematicMode', @lc_setcinematicmode);
4578 lua_register(luaState, _P'SetMaxBuildDistance', @lc_setmaxbuilddistance);
4579 lua_register(luaState, _P'GetAmmoName', @lc_getammoname);
4580 lua_register(luaState, _P'GetAmmoTimer', @lc_getammotimer);
4581 lua_register(luaState, _P'SetVampiric', @lc_setvampiric);
4582 lua_register(luaState, _P'GetVampiric', @lc_getvampiric);
4583 lua_register(luaState, _P'SetLaserSight', @lc_setlasersight);
4584 lua_register(luaState, _P'GetLaserSight', @lc_getlasersight);
4585 lua_register(luaState, _P'Explode', @lc_explode);
4586 lua_register(luaState, _P'SetTurnTimeLeft', @lc_setturntimeleft);
4587 lua_register(luaState, _P'SetReadyTimeLeft', @lc_setreadytimeleft);
4588 lua_register(luaState, _P'SetTurnTimePaused', @lc_setturntimepaused);
4589 lua_register(luaState, _P'GetTurnTimePaused', @lc_getturntimepaused);
4590 // drawn map functions
4591 lua_register(luaState, _P'AddPoint', @lc_addPoint);
4592 lua_register(luaState, _P'FlushPoints', @lc_flushPoints);
4593 
4594 lua_register(luaState, _P'SetGearAIHints', @lc_setgearaihints);
4595 lua_register(luaState, _P'HedgewarsScriptLoad', @lc_hedgewarsscriptload);
4596 lua_register(luaState, _P'DeclareAchievement', @lc_declareachievement);
4597 lua_register(luaState, _P'StartGhostPoints', @lc_startghostpoints);
4598 lua_register(luaState, _P'DumpPoint', @lc_dumppoint);
4599 
4600 ScriptSetInteger('TEST_SUCCESSFUL'   , HaltTestSuccess);
4601 ScriptSetInteger('TEST_FAILED'       , HaltTestFailed);
4602 lua_register(luaState, _P'EndLuaTest', @lc_endluatest);
4603 
4604 ScriptClearStack; // just to be sure stack is empty
4605 ScriptLoaded:= false;
4606 end;
4607 
4608 procedure freeModule;
4609 begin
4610 lua_close(luaState);
4611 end;
4612 
4613 {$ELSE}
4614 procedure ScriptPrintStack;
4615 begin
4616 end;
4617 
4618 procedure ScriptClearStack;
4619 begin
4620 end;
4621 
4622 procedure ScriptLoad(name : shortstring);
4623 begin
4624     name:= name; // avoid hint
4625 end;
4626 
4627 procedure ScriptOnGameInit;
4628 begin
4629 end;
4630 
4631 procedure ScriptCall(fname : shortstring);
4632 begin
4633     fname:= fname; // avoid hint
4634 end;
4635 
4636 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
4637 begin
4638     // avoid hints
4639     fname:= fname;
4640     par1:= par1;
4641     par2:= par2;
4642     par3:= par3;
4643     par4:= par4;
4644     ScriptCall:= 0
4645 end;
4646 
4647 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
4648 begin
4649     // avoid hints
4650     fname:= fname;
4651     par1:= par1;
4652     ScriptCall:= 0
4653 end;
4654 
4655 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
4656 begin
4657     // avoid hints
4658     fname:= fname;
4659     par1:= par1;
4660     par2:= par2;
4661     ScriptCall:= 0
4662 end;
4663 
4664 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
4665 begin
4666     // avoid hints
4667     fname:= fname;
4668     par1:= par1;
4669     par2:= par2;
4670     par3:= par3;
4671     ScriptCall:= 0
4672 end;
4673 
4674 function ScriptExists(fname : shortstring) : boolean;
4675 begin
4676     fname:= fname; // avoid hint
4677     ScriptExists:= false
4678 end;
4679 (*
4680 function ParseCommandOverride(key, value : shortstring) : shortstring;
4681 begin
4682     // avoid hints
4683     key:= key;
4684     value:= value;
4685     ParseCommandOverride:= ''
4686 end;
4687 *)
4688 
4689 procedure ScriptOnScreenResize;
4690 begin
4691 end;
4692 
4693 procedure ScriptOnPreviewInit;
4694 begin
4695 end;
4696 
4697 procedure ScriptSetInteger(name : shortstring; value : LongInt);
4698 begin
4699 end;
4700 
4701 procedure ScriptSetString(name : shortstring; value : shortstring);
4702 begin
4703 end;
4704 
4705 procedure LuaParseString(s : ShortString);
4706 begin
4707 end;
4708 
4709 procedure initModule;
4710 begin
4711 PointsBuffer:= '';
4712 PrevCursorX:= NoPointX;
4713 PrevCursorY:= NoPointX;
4714 isPendingTurnTimeLeft:= false;
4715 isPendingReadyTimeLeft:= false;
4716 end;
4717 
4718 procedure freeModule;
4719 begin
4720 end;
4721 
4722 {$ENDIF}
4723 end.
4724