hedgewars/uScript.pas.temp
changeset 12383 e3d9abcc427a
equal deleted inserted replaced
12326:0a6d232b4c49 12383:e3d9abcc427a
       
     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 
       
    37 procedure ScriptLoad(name : shortstring);
       
    38 procedure ScriptOnPreviewInit;
       
    39 procedure ScriptOnGameInit;
       
    40 procedure ScriptOnScreenResize;
       
    41 procedure ScriptSetInteger(name : shortstring; value : LongInt);
       
    42 procedure ScriptSetString(name : shortstring; value : shortstring);
       
    43 
       
    44 procedure ScriptCall(fname : shortstring);
       
    45 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
       
    46 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
       
    47 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
       
    48 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
       
    49 function ScriptExists(fname : shortstring) : boolean;
       
    50 
       
    51 procedure LuaParseString(s: shortString);
       
    52 
       
    53 //function ParseCommandOverride(key, value : shortstring) : shortstring;  This did not work out well
       
    54 
       
    55 procedure initModule;
       
    56 procedure freeModule;
       
    57 
       
    58 implementation
       
    59 
       
    60 uses LuaPas,
       
    61     uConsole,
       
    62     uConsts,
       
    63     uGears,
       
    64     uGearsList,
       
    65     uGearsUtils,
       
    66     uFloat,
       
    67     uWorld,
       
    68     uAmmos,
       
    69     uTeams,
       
    70     uSound,
       
    71     uChat,
       
    72     uStats,
       
    73     uStore,
       
    74     uRandom,
       
    75     uTypes,
       
    76     uVariables,
       
    77     uCommands,
       
    78     uCaptions,
       
    79     uDebug,
       
    80     uCollisions,
       
    81     uRenderUtils,
       
    82     uTextures,
       
    83     uLandGraphics,
       
    84     uUtils,
       
    85     uIO,
       
    86     uVisualGearsList,
       
    87     uGearsHandlersMess,
       
    88     uPhysFSLayer,
       
    89     SDLh
       
    90 {$IFNDEF PAS2C}
       
    91     , typinfo
       
    92 {$ENDIF}
       
    93     ;
       
    94 
       
    95 var luaState : Plua_State;
       
    96     ScriptAmmoLoadout : shortstring;
       
    97     ScriptAmmoProbability : shortstring;
       
    98     ScriptAmmoDelay : shortstring;
       
    99     ScriptAmmoReinforcement : shortstring;
       
   100     ScriptLoaded : boolean;
       
   101     mapDims : boolean;
       
   102     PointsBuffer: shortstring;
       
   103     prevCursorPoint: TPoint;  // why is tpoint still in sdlh...
       
   104 
       
   105 {$IFDEF USE_LUA_SCRIPT}
       
   106 procedure ScriptPrepareAmmoStore; forward;
       
   107 procedure ScriptApplyAmmoStore; forward;
       
   108 procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte); forward;
       
   109 procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: Byte); forward;
       
   110 
       
   111 var LuaDebugInfo: lua_Debug;
       
   112 
       
   113 procedure SetGlobals; forward;
       
   114 procedure LuaParseString(s: shortString);
       
   115 begin
       
   116     SetGlobals;
       
   117     AddFileLog('[Lua] input string: ' + s);
       
   118     AddChatString(#3 + '[Lua] > ' + s);
       
   119     if luaL_dostring(luaState, Str2PChar(s)) <> 0 then
       
   120         begin
       
   121         AddFileLog('[Lua] input string parsing error!');
       
   122         AddChatString(#5 + '[Lua] Error while parsing!');
       
   123         end;
       
   124 end;
       
   125 
       
   126 function LuaUpdateDebugInfo(): Boolean;
       
   127 begin
       
   128     FillChar(LuaDebugInfo, sizeof(LuaDebugInfo), 0);
       
   129 
       
   130     if lua_getstack(luaState, 1, @LuaDebugInfo) = 0 then
       
   131         exit(false); // stack not deep enough
       
   132 
       
   133     // get source name and line count
       
   134     lua_getinfo(luaState, PChar('Sl'), @LuaDebugInfo);
       
   135     exit(true);
       
   136 end;
       
   137 
       
   138 procedure LuaError(s: shortstring);
       
   139 var src: shortstring;
       
   140 const
       
   141     maxsrclen = 20;
       
   142 begin
       
   143     if LuaUpdateDebugInfo() then
       
   144         begin
       
   145         src:= StrPas(LuaDebugInfo.source);
       
   146         s:= 'LUA ERROR [ ... '
       
   147             + copy(src, Length(src) - maxsrclen, maxsrclen - 3) + ':'
       
   148             + inttostr(LuaDebugInfo.currentLine) + ']: ' + s;
       
   149         end
       
   150     else
       
   151         s:= 'LUA ERROR: ' + s;
       
   152     WriteLnToConsole(s);
       
   153     AddChatString(#5 + s);
       
   154     if cTestLua then
       
   155         halt(HaltTestLuaError);
       
   156 end;
       
   157 
       
   158 procedure LuaCallError(error, call, paramsyntax: shortstring);
       
   159 begin
       
   160     LuaError(call + ': ' + error);
       
   161     LuaError('-- SYNTAX: ' + call + ' ( ' + paramsyntax + ' )');
       
   162 end;
       
   163 
       
   164 procedure LuaParameterCountError(expected, call, paramsyntax: shortstring; wrongcount: LongInt); inline;
       
   165 begin
       
   166     // TODO: i18n?
       
   167     LuaCallError('Wrong number of parameters! (is: ' + inttostr(wrongcount) + ', should be: '+ expected + ')', call, paramsyntax);
       
   168 end;
       
   169 
       
   170 // compare with allowed count
       
   171 function CheckLuaParamCount(L : Plua_State; count: LongInt; call, paramsyntax: shortstring): boolean; inline;
       
   172 var c: LongInt;
       
   173 begin
       
   174     c:= lua_gettop(L);
       
   175     if c <> count then
       
   176         begin
       
   177         LuaParameterCountError('exactly ' + inttostr(count), call, paramsyntax, c);
       
   178         exit(false);
       
   179         end;
       
   180 
       
   181     CheckLuaParamCount:= true;
       
   182 end;
       
   183 
       
   184 // check if is either count1 or count2
       
   185 function CheckAndFetchParamCount(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
       
   186 begin
       
   187     actual:= lua_gettop(L);
       
   188     if (actual <> count1) and (actual <> count2) then
       
   189         begin
       
   190         LuaParameterCountError('either ' + inttostr(count1) + ' or ' + inttostr(count2), call, paramsyntax, actual);
       
   191         exit(false);
       
   192         end;
       
   193 
       
   194     CheckAndFetchParamCount:= true;
       
   195 end;
       
   196 
       
   197 // check if is in range of count1 and count2
       
   198 function CheckAndFetchParamCountRange(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
       
   199 begin
       
   200     actual:= lua_gettop(L);
       
   201     if (actual < count1) or (actual > count2) then
       
   202         begin
       
   203         LuaParameterCountError('at least ' + inttostr(count1) + ', but at most ' + inttostr(count2), call, paramsyntax, actual);
       
   204         exit(false);
       
   205         end;
       
   206 
       
   207     CheckAndFetchParamCountRange:= true;
       
   208 end;
       
   209 
       
   210 // check if is same or higher as minCount
       
   211 function CheckAndFetchLuaParamMinCount(L : Plua_State; minCount: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline;
       
   212 begin
       
   213     actual:= lua_gettop(L);
       
   214     if (actual < minCount) then
       
   215         begin
       
   216         LuaParameterCountError(inttostr(minCount) + ' or more', call, paramsyntax, actual);
       
   217         exit(false);
       
   218         end;
       
   219 
       
   220     CheckAndFetchLuaParamMinCount:= true;
       
   221 end;
       
   222 
       
   223 function LuaToGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   224 begin
       
   225     if lua_isnoneornil(L, i) then i:= -1
       
   226     else i:= lua_tointeger(L, i);
       
   227     if (i < ord(Low(TGearType))) or (i > ord(High(TGearType))) then
       
   228         begin
       
   229         LuaCallError('Invalid gearType!', call, paramsyntax);
       
   230         LuaToGearTypeOrd:= -1;
       
   231         end
       
   232     else
       
   233         LuaToGearTypeOrd:= i;
       
   234 end;
       
   235 
       
   236 function LuaToVisualGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   237 begin
       
   238     if lua_isnoneornil(L, i) then i:= -1
       
   239     else i:= lua_tointeger(L, i);
       
   240     if (i < ord(Low(TVisualGearType))) or (i > ord(High(TVisualGearType))) then
       
   241         begin
       
   242         LuaCallError('Invalid visualGearType!', call, paramsyntax);
       
   243         LuaToVisualGearTypeOrd:= -1;
       
   244         end
       
   245     else
       
   246         LuaToVisualGearTypeOrd:= i;
       
   247 end;
       
   248 
       
   249 function LuaToAmmoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   250 begin
       
   251     if lua_isnoneornil(L, i) then i:= -1
       
   252     else i:= lua_tointeger(L, i);
       
   253     if (i < ord(Low(TAmmoType))) or (i > ord(High(TAmmoType))) then
       
   254         begin
       
   255         LuaCallError('Invalid ammoType!', call, paramsyntax);
       
   256         LuaToAmmoTypeOrd:= -1;
       
   257         end
       
   258     else
       
   259         LuaToAmmoTypeOrd:= i;
       
   260 end;
       
   261 
       
   262 function LuaToStatInfoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   263 begin
       
   264     if lua_isnoneornil(L, i) then i:= -1
       
   265     else i:= lua_tointeger(L, i);
       
   266     if (i < ord(Low(TStatInfoType))) or (i > ord(High(TStatInfoType))) then
       
   267         begin
       
   268         LuaCallError('Invalid statInfoType!', call, paramsyntax);
       
   269         LuaToStatInfoTypeOrd:= -1;
       
   270         end
       
   271     else
       
   272         LuaToStatInfoTypeOrd:= i;
       
   273 end;
       
   274 
       
   275 function LuaToSoundOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   276 begin
       
   277     if lua_isnoneornil(L, i) then i:= -1
       
   278     else i:= lua_tointeger(L, i);
       
   279     if (i < ord(Low(TSound))) or (i > ord(High(TSound))) then
       
   280         begin
       
   281         LuaCallError('Invalid soundId!', call, paramsyntax);
       
   282         LuaToSoundOrd:= -1;
       
   283         end
       
   284     else
       
   285         LuaToSoundOrd:= i;
       
   286 end;
       
   287 
       
   288 function LuaToHogEffectOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   289 begin
       
   290     if lua_isnoneornil(L, i) then i:= -1
       
   291     else i:= lua_tointeger(L, i);
       
   292     if (i < ord(Low(THogEffect))) or (i > ord(High(THogEffect))) then
       
   293         begin
       
   294         LuaCallError('Invalid effect type!', call, paramsyntax);
       
   295         LuaToHogEffectOrd:= -1;
       
   296         end
       
   297     else
       
   298         LuaToHogEffectOrd:= i;
       
   299 end;
       
   300 
       
   301 function LuaToCapGroupOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   302 begin
       
   303     if lua_isnoneornil(L, i) then i:= -1
       
   304     else i:= lua_tointeger(L, i);
       
   305     if (i < ord(Low(TCapGroup))) or (i > ord(High(TCapGroup))) then
       
   306         begin
       
   307         LuaCallError('Invalid capgroup type!', call, paramsyntax);
       
   308         LuaToCapGroupOrd:= -1;
       
   309         end
       
   310     else
       
   311         LuaToCapGroupOrd:= i;
       
   312 end;
       
   313 
       
   314 function LuaToSpriteOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   315 begin
       
   316     if lua_isnoneornil(L, i) then i:= -1
       
   317     else i:= lua_tointeger(L, i);
       
   318     if (i < ord(Low(TSprite))) or (i > ord(High(TSprite))) then
       
   319         begin
       
   320         LuaCallError('Invalid sprite id!', call, paramsyntax);
       
   321         LuaToSpriteOrd:= -1;
       
   322         end
       
   323     else
       
   324         LuaToSpriteOrd:= i;
       
   325 end;
       
   326 
       
   327 function LuaToMapGenOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
       
   328 begin
       
   329     if lua_isnoneornil(L, i) then i:= -1
       
   330     else i:= lua_tointeger(L, i);
       
   331     if (i < ord(Low(TMapGen))) or (i > ord(High(TMapGen))) then
       
   332         begin
       
   333         LuaCallError('Invalid mapgen id!', call, paramsyntax);
       
   334         LuaToMapGenOrd:= -1;
       
   335         end
       
   336     else
       
   337         LuaToMapGenOrd:= i;
       
   338 end;
       
   339 
       
   340 // wrapped calls
       
   341 
       
   342 // functions called from Lua:
       
   343 // function(L : Plua_State) : LongInt; Cdecl;
       
   344 // where L contains the state, returns the number of return values on the stack
       
   345 // call CheckLuaParamCount or CheckAndFetchParamCount
       
   346 // to validate/get the number of passed arguments (see their call definitions)
       
   347 //
       
   348 // use as return value the number of variables pushed back to the lua script
       
   349 
       
   350 function lc_band(L: PLua_State): LongInt; Cdecl;
       
   351 begin
       
   352     if CheckLuaParamCount(L, 2, 'band', 'value1, value2') then
       
   353         lua_pushinteger(L, lua_tointeger(L, 2) and lua_tointeger(L, 1))
       
   354     else
       
   355         lua_pushnil(L);
       
   356     lc_band := 1;
       
   357 end;
       
   358 
       
   359 function lc_bor(L: PLua_State): LongInt; Cdecl;
       
   360 begin
       
   361     if CheckLuaParamCount(L, 2, 'bor', 'value1, value2') then
       
   362         lua_pushinteger(L, lua_tointeger(L, 2) or lua_tointeger(L, 1))
       
   363     else
       
   364         lua_pushnil(L);
       
   365     lc_bor := 1;
       
   366 end;
       
   367 
       
   368 function lc_bnot(L: PLua_State): LongInt; Cdecl;
       
   369 begin
       
   370     if CheckLuaParamCount(L, 1, 'bnot', 'value') then
       
   371         lua_pushinteger(L, (not lua_tointeger(L, 1)))
       
   372     else
       
   373         lua_pushnil(L);
       
   374     lc_bnot := 1;
       
   375 end;
       
   376 
       
   377 function lc_div(L: PLua_State): LongInt; Cdecl;
       
   378 begin
       
   379     if CheckLuaParamCount(L, 2, 'div', 'dividend, divisor') then
       
   380         lua_pushinteger(L, lua_tointeger(L, 1) div lua_tointeger(L, 2))
       
   381     else
       
   382         lua_pushnil(L);
       
   383     lc_div := 1;
       
   384 end;
       
   385 
       
   386 function lc_getinputmask(L : Plua_State) : LongInt; Cdecl;
       
   387 begin
       
   388     if CheckLuaParamCount(L, 0, 'GetInputMask', '') then
       
   389         lua_pushinteger(L, InputMask);
       
   390     lc_getinputmask:= 1
       
   391 end;
       
   392 
       
   393 function lc_setinputmask(L : Plua_State) : LongInt; Cdecl;
       
   394 begin
       
   395     if CheckLuaParamCount(L, 1, 'SetInputMask', 'mask') then
       
   396         InputMask:= lua_tointeger(L, 1);
       
   397     lc_setinputmask:= 0
       
   398 end;
       
   399 
       
   400 function lc_writelntoconsole(L : Plua_State) : LongInt; Cdecl;
       
   401 begin
       
   402     if CheckLuaParamCount(L, 1, 'WriteLnToConsole', 'string') then
       
   403         WriteLnToConsole('Lua: ' + lua_tostring(L ,1));
       
   404     lc_writelntoconsole:= 0;
       
   405 end;
       
   406 
       
   407 function lc_parsecommand(L : Plua_State) : LongInt; Cdecl;
       
   408 var t: PChar;
       
   409     i,c: LongWord;
       
   410     s: shortstring;
       
   411 begin
       
   412     if CheckLuaParamCount(L, 1, 'ParseCommand', 'string') then
       
   413         begin
       
   414         t:= lua_tolstring(L, 1, Psize_t(@c));
       
   415 
       
   416         for i:= 1 to c do s[i]:= t[i-1];
       
   417         s[0]:= char(c);
       
   418 
       
   419         ParseCommand(s, true, true);
       
   420 
       
   421         end;
       
   422     lc_parsecommand:= 0;
       
   423 end;
       
   424 
       
   425 // sets weapon to the desired ammo type
       
   426 function lc_setweapon(L : Plua_State) : LongInt; Cdecl;
       
   427 var at: LongInt;
       
   428 const
       
   429     call = 'SetWeapon';
       
   430     params = 'ammoType';
       
   431 begin
       
   432     // no point to run this without any CurrentHedgehog
       
   433     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 1, call, params)) then
       
   434         begin
       
   435         at:= LuaToAmmoTypeOrd(L, 1, call, params);
       
   436         if at >= 0 then
       
   437             ParseCommand('setweap ' + char(at), true, true);
       
   438         end;
       
   439     lc_setweapon:= 0;
       
   440 end;
       
   441 
       
   442 // enable/disable cinematic effects
       
   443 function lc_setcinematicmode(L : Plua_State) : LongInt; Cdecl;
       
   444 const
       
   445     call = 'SetCinematicMode';
       
   446     params = 'enable';
       
   447 begin
       
   448     if (CheckLuaParamCount(L, 1, call, params)) then
       
   449         begin
       
   450         CinematicScript:= lua_toboolean(L, 1);
       
   451         end;
       
   452     lc_setcinematicmode:= 0;
       
   453 end;
       
   454 
       
   455 // no parameter means reset to default (and 0 means unlimited)
       
   456 function lc_setmaxbuilddistance(L : Plua_State) : LongInt; Cdecl;
       
   457 var np: LongInt;
       
   458 const
       
   459     call = 'SetMaxBuildDistance';
       
   460     params = '[ distInPx ]';
       
   461 begin
       
   462     if CheckAndFetchParamCountRange(L, 0, 1, call, params, np) then
       
   463         begin
       
   464         if np = 0 then
       
   465             begin
       
   466             // no args? reset
       
   467             cBuildMaxDist:= cDefaultBuildMaxDist;
       
   468             end
       
   469         else
       
   470             CBuildMaxDist:= lua_tointeger(L, 1);
       
   471         end;
       
   472     lc_setmaxbuilddistance:= 0;
       
   473 end;
       
   474 
       
   475 // sets weapon to whatever weapons is next (wraps around, amSkip is skipped)
       
   476 function lc_setnextweapon(L : Plua_State) : LongInt; Cdecl;
       
   477 var at          : LongInt;
       
   478     nextAmmo    : TAmmo;
       
   479     s, a, cs, fa: LongInt;
       
   480 const
       
   481     call = 'SetNextWeapon';
       
   482     params = '';
       
   483 begin
       
   484     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, call, params)) then
       
   485         begin
       
   486         at:= -1;
       
   487         with CurrentHedgehog^ do
       
   488             begin
       
   489             cs:= 0; // current slot
       
   490             fa:= 0; // first ammo item to check
       
   491 
       
   492             // if something is selected, find it is successor
       
   493             if curAmmoType <> amNothing then
       
   494                 begin
       
   495                 // get current slot index
       
   496                 cs:= Ammoz[CurAmmoType].Slot;
       
   497                 // find current ammo index
       
   498                 while (fa < cMaxSlotAmmoIndex)
       
   499                     and (Ammo^[cs, fa].AmmoType <> CurAmmoType) do
       
   500                         inc(fa);
       
   501                 // increase once more because we will not successor
       
   502                 inc(fa);
       
   503                 end;
       
   504 
       
   505             // find first available ammo
       
   506             // revisit current slot too (current item might not be first)
       
   507             for s:= cs to cs + cMaxSlotIndex + 1 do
       
   508                 begin
       
   509                 for a:= fa to cMaxSlotAmmoIndex do
       
   510                     begin
       
   511                     // check if we went full circle
       
   512                     if (a = fa) and (s = cs + cMaxSlotIndex + 1)  then
       
   513                         exit(0);
       
   514 
       
   515                     // get ammo
       
   516                     nextAmmo:= Ammo^[s mod (cMaxSlotIndex + 1), a];
       
   517                     // only switch to ammos the hog actually has
       
   518                     if (nextAmmo.AmmoType <> amNothing)
       
   519                         and (nextAmmo.AmmoType <> amSkip) and (nextAmmo.Count > 0) then
       
   520                             begin
       
   521                             at:= ord(nextAmmo.AmmoType);
       
   522                             break;
       
   523                             end;
       
   524                     end;
       
   525                 // stop slot loop if something was found
       
   526                 if at >= 0 then
       
   527                     break;
       
   528                 // check following slots starting with first item
       
   529                 fa:= 0;
       
   530                 end;
       
   531             end;
       
   532 
       
   533         if at >= 0 then
       
   534             ParseCommand('setweap ' + char(at), true, true);
       
   535         end;
       
   536     lc_setnextweapon:= 0;
       
   537 end;
       
   538 
       
   539 function lc_showmission(L : Plua_State) : LongInt; Cdecl;
       
   540 begin
       
   541     if CheckLuaParamCount(L, 5, 'ShowMission', 'caption, subcaption, text, icon, time') then
       
   542         ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
       
   543     lc_showmission:= 0;
       
   544 end;
       
   545 
       
   546 function lc_hidemission(L : Plua_State) : LongInt; Cdecl;
       
   547 begin
       
   548     L:= L; // avoid compiler hint
       
   549     HideMission;
       
   550     lc_hidemission:= 0;
       
   551 end;
       
   552 
       
   553 function lc_setammotexts(L : Plua_State) : LongInt; Cdecl;
       
   554 const
       
   555     call = 'SetAmmoTexts';
       
   556     params = 'ammoType, name, caption, description';
       
   557 begin
       
   558     if CheckLuaParamCount(L, 4, call, params) then
       
   559         SetAmmoTexts(TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params)), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tostringA(L, 4));
       
   560     lc_setammotexts:= 0;
       
   561 end;
       
   562 
       
   563 function lc_setammodescriptionappendix(L : Plua_State) : LongInt; Cdecl;
       
   564 const
       
   565     call = 'SetAmmoDescriptionAppendix';
       
   566     params = 'ammoType, descAppend';
       
   567 var
       
   568     ammoType: TAmmoType;
       
   569     descAppend: ansistring;
       
   570 begin
       
   571     if CheckLuaParamCount(L, 2, call, params) then
       
   572         begin
       
   573         ammoType := TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params));
       
   574         descAppend := lua_tostringA(L, 2);
       
   575         trluaammoa[Ammoz[ammoType].NameId] := descAppend;
       
   576         end;
       
   577     lc_setammodescriptionappendix := 0;
       
   578 end;
       
   579 
       
   580 function lc_enablegameflags(L : Plua_State) : LongInt; Cdecl;
       
   581 var i, n : integer;
       
   582 begin
       
   583     // can have 1 or more arguments
       
   584     if CheckAndFetchLuaParamMinCount(L, 1, 'EnableGameFlags', 'gameFlag, ... ', n) then
       
   585         begin
       
   586         for i:= 1 to n do
       
   587             GameFlags := GameFlags or LongWord(lua_tointeger(L, i));
       
   588         ScriptSetInteger('GameFlags', GameFlags);
       
   589         end;
       
   590     lc_enablegameflags:= 0;
       
   591 end;
       
   592 
       
   593 function lc_disablegameflags(L : Plua_State) : LongInt; Cdecl;
       
   594 var i , n: integer;
       
   595 begin
       
   596     // can have 1 or more arguments
       
   597     if CheckAndFetchLuaParamMinCount(L, 1, 'DisableGameFlags', 'gameFlag, ... ', n) then
       
   598         begin
       
   599         for i:= 1 to n do
       
   600             GameFlags := GameFlags and (not LongWord(lua_tointeger(L, i)));
       
   601         ScriptSetInteger('GameFlags', GameFlags);
       
   602         end;
       
   603     lc_disablegameflags:= 0;
       
   604 end;
       
   605 
       
   606 function lc_cleargameflags(L : Plua_State) : LongInt; Cdecl;
       
   607 begin
       
   608     if CheckLuaParamCount(L, 0, 'ClearGameFlags', '') then
       
   609         begin
       
   610         GameFlags:= 0;
       
   611         ScriptSetInteger('GameFlags', GameFlags);
       
   612         end;
       
   613     lc_cleargameflags:= 0;
       
   614 end;
       
   615 
       
   616 function lc_getgameflag(L : Plua_State) : LongInt; Cdecl;
       
   617 begin
       
   618     if CheckLuaParamCount(L, 1, 'GetGameFlag', 'gameflag') then
       
   619         lua_pushboolean(L, (GameFlags and LongWord(lua_tointeger(L, 1)) <> 0))
       
   620     else
       
   621         lua_pushnil(L);
       
   622     lc_getgameflag:= 1;
       
   623 end;
       
   624 
       
   625 function lc_addcaption(L : Plua_State) : LongInt; Cdecl;
       
   626 var cg: LongInt;
       
   627 const
       
   628     call = 'AddCaption';
       
   629     params = 'text [, color, captiongroup]';
       
   630 begin
       
   631     if CheckAndFetchParamCount(L, 1, 3, call, params, cg) then
       
   632         begin
       
   633         if cg = 1 then
       
   634             AddCaption(lua_tostringA(L, 1), cWhiteColor, capgrpMessage)
       
   635         else
       
   636             begin
       
   637             cg:= LuaToCapGroupOrd(L, 3, call, params);
       
   638             if cg >= 0 then
       
   639                 AddCaption(lua_tostringA(L, 1), lua_tointeger(L, 2) shr 8, TCapGroup(cg));
       
   640             end
       
   641         end;
       
   642     lc_addcaption:= 0;
       
   643 end;
       
   644 
       
   645 function lc_campaignlock(L : Plua_State) : LongInt; Cdecl;
       
   646 begin
       
   647     if CheckLuaParamCount(L, 1, 'CampaignLock', 'TODO') then
       
   648         begin
       
   649         // TODO
       
   650         end;
       
   651     lc_campaignlock:= 0;
       
   652 end;
       
   653 
       
   654 function lc_campaignunlock(L : Plua_State) : LongInt; Cdecl;
       
   655 begin
       
   656     if CheckLuaParamCount(L, 1, 'CampaignUnlock', 'TODO') then
       
   657         begin
       
   658         // TODO
       
   659         end;
       
   660     lc_campaignunlock:= 0;
       
   661 end;
       
   662 
       
   663 function lc_spawnfakehealthcrate(L: Plua_State) : LongInt; Cdecl;
       
   664 var gear: PGear;
       
   665 begin
       
   666     if CheckLuaParamCount(L, 4,'SpawnFakeHealthCrate', 'x, y, explode, poison') then
       
   667         begin
       
   668         gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
       
   669         HealthCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
       
   670         if gear <> nil then
       
   671              lua_pushinteger(L, gear^.uid)
       
   672         else lua_pushnil(L)
       
   673         end
       
   674     else
       
   675         lua_pushnil(L);
       
   676     lc_spawnfakehealthcrate := 1;
       
   677 end;
       
   678 
       
   679 function lc_spawnfakeammocrate(L: PLua_State): LongInt; Cdecl;
       
   680 var gear: PGear;
       
   681 begin
       
   682     if CheckLuaParamCount(L, 4,'SpawnFakeAmmoCrate', 'x, y, explode, poison') then
       
   683         begin
       
   684         gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
       
   685         AmmoCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
       
   686         if gear <> nil then
       
   687              lua_pushinteger(L, gear^.uid)
       
   688         else lua_pushnil(L)
       
   689         end
       
   690     else
       
   691         lua_pushnil(L);
       
   692     lc_spawnfakeammocrate := 1;
       
   693 end;
       
   694 
       
   695 function lc_spawnfakeutilitycrate(L: PLua_State): LongInt; Cdecl;
       
   696 var gear: PGear;
       
   697 begin
       
   698     if CheckLuaParamCount(L, 4,'SpawnFakeUtilityCrate', 'x, y, explode, poison') then
       
   699         begin
       
   700         gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
       
   701         UtilityCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
       
   702         if gear <> nil then
       
   703              lua_pushinteger(L, gear^.uid)
       
   704         else lua_pushnil(L)
       
   705         end
       
   706     else
       
   707         lua_pushnil(L);
       
   708     lc_spawnfakeutilitycrate := 1;
       
   709 end;
       
   710 
       
   711 function lc_spawnhealthcrate(L: Plua_State) : LongInt; Cdecl;
       
   712 var gear: PGear;
       
   713 var health, n: LongInt;
       
   714 begin
       
   715     if CheckAndFetchParamCount(L, 2, 3, 'SpawnHealthCrate', 'x, y [, health]', n) then
       
   716         begin
       
   717         if n = 3 then
       
   718             health:= lua_tointeger(L, 3)
       
   719         else
       
   720             health:= cHealthCaseAmount;
       
   721         gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), HealthCrate, health, 0);
       
   722         if gear <> nil then
       
   723              lua_pushinteger(L, gear^.uid)
       
   724         else lua_pushnil(L);
       
   725         end
       
   726     else
       
   727         lua_pushnil(L);
       
   728     lc_spawnhealthcrate := 1;
       
   729 end;
       
   730 
       
   731 function lc_spawnammocrate(L: PLua_State): LongInt; Cdecl;
       
   732 var gear: PGear;
       
   733     n   : LongInt;
       
   734 begin
       
   735     if CheckAndFetchParamCount(L, 3, 4, 'SpawnAmmoCrate', 'x, y, content [, amount]', n) then
       
   736         begin
       
   737         if n = 3 then
       
   738              gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), 0)
       
   739         else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
       
   740         if gear <> nil then
       
   741              lua_pushinteger(L, gear^.uid)
       
   742         else lua_pushnil(L);
       
   743         end
       
   744     else
       
   745         lua_pushnil(L);
       
   746     lc_spawnammocrate := 1;
       
   747 end;
       
   748 
       
   749 function lc_spawnutilitycrate(L: PLua_State): LongInt; Cdecl;
       
   750 var gear: PGear;
       
   751     n   : LongInt;
       
   752 begin
       
   753     if CheckAndFetchParamCount(L, 3, 4, 'SpawnUtilityCrate', 'x, y, content [, amount]', n) then
       
   754         begin
       
   755         if n = 3 then
       
   756              gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), 0)
       
   757         else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
       
   758         if gear <> nil then
       
   759              lua_pushinteger(L, gear^.uid)
       
   760         else lua_pushnil(L);
       
   761        end
       
   762     else
       
   763         lua_pushnil(L);
       
   764     lc_spawnutilitycrate := 1;
       
   765 end;
       
   766 
       
   767 function lc_addgear(L : Plua_State) : LongInt; Cdecl;
       
   768 var gear : PGear;
       
   769     x, y, s, t: LongInt;
       
   770     dx, dy: hwFloat;
       
   771     gt: TGearType;
       
   772 const
       
   773     call = 'AddGear';
       
   774     params = 'x, y, gearType, state, dx, dy, timer';
       
   775 begin
       
   776     if CheckLuaParamCount(L, 7, call, params) then
       
   777         begin
       
   778         t:= LuaToGearTypeOrd(L, 3, call, params);
       
   779         if t >= 0 then
       
   780             begin
       
   781             gt:= TGearType(t);
       
   782             x:= lua_tointeger(L, 1);
       
   783             y:= lua_tointeger(L, 2);
       
   784             s:= lua_tointeger(L, 4);
       
   785             dx:= int2hwFloat(lua_tointeger(L, 5)) / 1000000;
       
   786             dy:= int2hwFloat(lua_tointeger(L, 6)) / 1000000;
       
   787             t:= lua_tointeger(L, 7);
       
   788 
       
   789             gear:= AddGear(x, y, gt, s, dx, dy, t);
       
   790             lastGearByUID:= gear;
       
   791             lua_pushinteger(L, gear^.uid)
       
   792             end
       
   793         else
       
   794             lua_pushnil(L);
       
   795         end
       
   796     else
       
   797         lua_pushnil(L);
       
   798     lc_addgear:= 1; // 1 return value
       
   799 end;
       
   800 
       
   801 function lc_deletegear(L : Plua_State) : LongInt; Cdecl;
       
   802 var gear : PGear;
       
   803 begin
       
   804     if CheckLuaParamCount(L, 1, 'DeleteGear', 'gearUid') then
       
   805         begin
       
   806         gear:= GearByUID(lua_tointeger(L, 1));
       
   807         if gear <> nil then
       
   808             gear^.Message:= gear^.Message or gmDelete;
       
   809         end;
       
   810     lc_deletegear:= 0
       
   811 end;
       
   812 
       
   813 function lc_addvisualgear(L : Plua_State) : LongInt; Cdecl;
       
   814 var vg : PVisualGear;
       
   815     x, y, s, n, layer: LongInt;
       
   816     c: Boolean;
       
   817     vgt: TVisualGearType;
       
   818     uid: Longword;
       
   819 const
       
   820     call = 'AddVisualGear';
       
   821     params = 'x, y, visualGearType, state, critical [, layer]';
       
   822 begin
       
   823     uid:= 0;
       
   824     if CheckAndFetchParamCount(L, 5, 6, call, params, n) then
       
   825         begin
       
   826         s:= LuaToVisualGearTypeOrd(L, 3, call, params);
       
   827         if s >= 0 then
       
   828             begin
       
   829             vgt:= TVisualGearType(s);
       
   830             x:= lua_tointeger(L, 1);
       
   831             y:= lua_tointeger(L, 2);
       
   832             s:= lua_tointeger(L, 4);
       
   833             c:= lua_toboolean(L, 5);
       
   834 
       
   835             if n = 6 then
       
   836                 begin
       
   837                 layer:= lua_tointeger(L, 6);
       
   838                 vg:= AddVisualGear(x, y, vgt, s, c, layer);
       
   839                 end
       
   840             else
       
   841                 vg:= AddVisualGear(x, y, vgt, s, c);
       
   842 
       
   843             if vg <> nil then
       
   844                 begin
       
   845                 lastVisualGearByUID:= vg;
       
   846                 uid:= vg^.uid;
       
   847                 lua_pushinteger(L, uid);
       
   848                 end;
       
   849             end
       
   850             else
       
   851                 lua_pushnil(L);
       
   852         end
       
   853     else
       
   854         lua_pushnil(L); // return value on stack (nil)
       
   855     lc_addvisualgear:= 1; // 1 return value
       
   856 end;
       
   857 
       
   858 function lc_deletevisualgear(L : Plua_State) : LongInt; Cdecl;
       
   859 var vg : PVisualGear;
       
   860 begin
       
   861     vg:= nil;
       
   862     if CheckLuaParamCount(L, 1, 'DeleteVisualGear', 'vgUid') then
       
   863         begin
       
   864         vg:= VisualGearByUID(lua_tointeger(L, 1));
       
   865         if vg <> nil then
       
   866             DeleteVisualGear(vg);
       
   867         end;
       
   868     // allow caller to know whether there was something to delete
       
   869     lua_pushboolean(L, vg <> nil);
       
   870     lc_deletevisualgear:= 1
       
   871 end;
       
   872 
       
   873 function lc_getvisualgeartype(L : Plua_State) : LongInt; Cdecl;
       
   874 var vg : PVisualGear;
       
   875 begin
       
   876     if CheckLuaParamCount(L, 1, 'GetVisualGearType', 'vgUid') then
       
   877         begin
       
   878         vg := VisualGearByUID(lua_tointeger(L, 1));
       
   879         if vg <> nil then
       
   880             lua_pushinteger(L, ord(vg^.Kind))
       
   881         else
       
   882             lua_pushnil(L);
       
   883         end
       
   884     else
       
   885         lua_pushnil(L); // return value on stack (nil)
       
   886     lc_getvisualgeartype:= 1
       
   887 end;
       
   888 
       
   889 
       
   890 function lc_getvisualgearvalues(L : Plua_State) : LongInt; Cdecl;
       
   891 var vg: PVisualGear;
       
   892 begin
       
   893     if CheckLuaParamCount(L, 1, 'GetVisualGearValues', 'vgUid') then
       
   894         begin
       
   895         vg:= VisualGearByUID(lua_tointeger(L, 1));
       
   896         if vg <> nil then
       
   897             begin
       
   898             lua_pushinteger(L, round(vg^.X));
       
   899             lua_pushinteger(L, round(vg^.Y));
       
   900             lua_pushnumber(L, vg^.dX);
       
   901             lua_pushnumber(L, vg^.dY);
       
   902             lua_pushnumber(L, vg^.Angle);
       
   903             lua_pushinteger(L, vg^.Frame);
       
   904             lua_pushinteger(L, vg^.FrameTicks);
       
   905             lua_pushinteger(L, vg^.State);
       
   906             lua_pushinteger(L, vg^.Timer);
       
   907             lua_pushinteger(L, vg^.Tint);
       
   908             end
       
   909         else
       
   910             begin
       
   911             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   912             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   913             end
       
   914         end
       
   915     else
       
   916         begin
       
   917         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   918         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   919         end;
       
   920     lc_getvisualgearvalues:= 10
       
   921 end;
       
   922 
       
   923 function lc_setvisualgearvalues(L : Plua_State) : LongInt; Cdecl;
       
   924 var vg : PVisualGear;
       
   925 begin
       
   926 // Param count can be 1-11 at present
       
   927 //    if CheckLuaParamCount(L, 11, 'SetVisualGearValues', 'vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint') then
       
   928 //        begin
       
   929         vg:= VisualGearByUID(lua_tointeger(L, 1));
       
   930         if vg <> nil then
       
   931             begin
       
   932             if not lua_isnoneornil(L, 2) then
       
   933                 vg^.X:= lua_tointeger(L, 2);
       
   934             if not lua_isnoneornil(L, 3) then
       
   935                 vg^.Y:= lua_tointeger(L, 3);
       
   936             if not lua_isnoneornil(L, 4) then
       
   937                 vg^.dX:= lua_tonumber(L, 4);
       
   938             if not lua_isnoneornil(L, 5) then
       
   939                 vg^.dY:= lua_tonumber(L, 5);
       
   940             if not lua_isnoneornil(L, 6) then
       
   941                 vg^.Angle:= lua_tonumber(L, 6);
       
   942             if not lua_isnoneornil(L, 7) then
       
   943                 vg^.Frame:= lua_tointeger(L, 7);
       
   944             if not lua_isnoneornil(L, 8) then
       
   945                 vg^.FrameTicks:= lua_tointeger(L, 8);
       
   946             if not lua_isnoneornil(L, 9) then
       
   947                 vg^.State:= lua_tointeger(L, 9);
       
   948             if not lua_isnoneornil(L, 10) then
       
   949                 vg^.Timer:= lua_tointeger(L, 10);
       
   950             if not lua_isnoneornil(L, 11) then
       
   951                 vg^.Tint:= lua_tointeger(L, 11)
       
   952             end;
       
   953 //        end
       
   954 //    else
       
   955 //        lua_pushnil(L); // return value on stack (nil)
       
   956     lc_setvisualgearvalues:= 0
       
   957 end;
       
   958 
       
   959 // so. going to use this to get/set some of the more obscure gear values which were not already exposed elsewhere
       
   960 // can keep adding things in the future. isnoneornil makes it safe
       
   961 function lc_getgearvalues(L : Plua_State) : LongInt; Cdecl;
       
   962 var gear: PGear;
       
   963 begin
       
   964     if CheckLuaParamCount(L, 1, 'GetGearValues', 'gearUid') then
       
   965         begin
       
   966         gear:= GearByUID(lua_tointeger(L, 1));
       
   967         if gear <> nil then
       
   968             begin
       
   969             lua_pushinteger(L, gear^.Angle);
       
   970             lua_pushinteger(L, gear^.Power);
       
   971             lua_pushinteger(L, gear^.WDTimer);
       
   972             lua_pushinteger(L, gear^.Radius);
       
   973             lua_pushinteger(L, hwRound(gear^.Density * _10000));
       
   974             lua_pushinteger(L, gear^.Karma);
       
   975             lua_pushnumber(L,  gear^.DirAngle);
       
   976             lua_pushinteger(L, gear^.AdvBounce);
       
   977             lua_pushinteger(L, Integer(gear^.ImpactSound));
       
   978             lua_pushinteger(L, gear^.nImpactSounds);
       
   979             lua_pushinteger(L, gear^.Tint);
       
   980             lua_pushinteger(L, gear^.Damage);
       
   981             lua_pushinteger(L, gear^.Boom)
       
   982             end
       
   983         else
       
   984             begin
       
   985             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   986             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   987             lua_pushnil(L); lua_pushnil(L); lua_pushnil(L)
       
   988             end
       
   989         end
       
   990     else
       
   991         begin
       
   992         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   993         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
       
   994         lua_pushnil(L); lua_pushnil(L); lua_pushnil(L)
       
   995         end;
       
   996     lc_getgearvalues:= 13
       
   997 end;
       
   998 
       
   999 function lc_setgearvalues(L : Plua_State) : LongInt; Cdecl;
       
  1000 var gear : PGear;
       
  1001 begin
       
  1002 // Currently allows 1-14 params
       
  1003 //    if CheckLuaParamCount(L, 14, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint, Damage, Boom') then
       
  1004 //        begin
       
  1005         gear:= GearByUID(lua_tointeger(L, 1));
       
  1006         if gear <> nil then
       
  1007             begin
       
  1008             if not lua_isnoneornil(L, 2) then
       
  1009                 gear^.Angle := lua_tointeger(L, 2);
       
  1010             if not lua_isnoneornil(L, 3) then
       
  1011                 gear^.Power := lua_tointeger(L, 3);
       
  1012             if not lua_isnoneornil(L, 4) then
       
  1013                 gear^.WDTimer := lua_tointeger(L, 4);
       
  1014             if not lua_isnoneornil(L, 5) then
       
  1015                 gear^.Radius := lua_tointeger(L, 5);
       
  1016             if not lua_isnoneornil(L, 6) then
       
  1017                 gear^.Density:= int2hwFloat(lua_tointeger(L, 6)) / 10000;
       
  1018             if not lua_isnoneornil(L, 7) then
       
  1019                 gear^.Karma := lua_tointeger(L, 7);
       
  1020             if not lua_isnoneornil(L, 8) then
       
  1021                 gear^.DirAngle:= lua_tonumber(L, 8);
       
  1022             if not lua_isnoneornil(L, 9) then
       
  1023                 gear^.AdvBounce := lua_tointeger(L, 9);
       
  1024             if not lua_isnoneornil(L, 10) then
       
  1025                 gear^.ImpactSound := TSound(lua_tointeger(L, 10));
       
  1026             if not lua_isnoneornil(L, 11) then
       
  1027                 gear^.nImpactSounds := lua_tointeger(L, 11);
       
  1028             if not lua_isnoneornil(L, 12) then
       
  1029                 gear^.Tint := lua_tointeger(L, 12);
       
  1030             if not lua_isnoneornil(L, 13) then
       
  1031                 gear^.Damage := lua_tointeger(L, 13);
       
  1032             if not lua_isnoneornil(L, 14) then
       
  1033                 gear^.Boom := lua_tointeger(L, 14);
       
  1034             end;
       
  1035 //        end
       
  1036 //    else
       
  1037 //        lua_pushnil(L); // return value on stack (nil)
       
  1038     lc_setgearvalues:= 0
       
  1039 end;
       
  1040 
       
  1041 function lc_getfollowgear(L : Plua_State) : LongInt; Cdecl;
       
  1042 begin
       
  1043     if CheckLuaParamCount(L, 0, 'GetFollowGear', '') then
       
  1044         begin
       
  1045         if FollowGear = nil then
       
  1046             lua_pushnil(L)
       
  1047         else
       
  1048             lua_pushinteger(L, FollowGear^.uid);
       
  1049         end
       
  1050     else
       
  1051         lua_pushnil(L);
       
  1052     lc_getfollowgear:= 1; // 1 return value
       
  1053 end;
       
  1054 
       
  1055 function lc_getgeartype(L : Plua_State) : LongInt; Cdecl;
       
  1056 var gear : PGear;
       
  1057 begin
       
  1058     if CheckLuaParamCount(L, 1, 'GetGearType', 'gearUid') then
       
  1059         begin
       
  1060         gear:= GearByUID(lua_tointeger(L, 1));
       
  1061         if gear <> nil then
       
  1062             lua_pushinteger(L, ord(gear^.Kind))
       
  1063         else
       
  1064             lua_pushnil(L);
       
  1065         end
       
  1066     else
       
  1067         lua_pushnil(L); // return value on stack (nil)
       
  1068     lc_getgeartype:= 1
       
  1069 end;
       
  1070 
       
  1071 function lc_getgearmessage(L : Plua_State) : LongInt; Cdecl;
       
  1072 var gear : PGear;
       
  1073 begin
       
  1074     if CheckLuaParamCount(L, 1, 'GetGearMessage', 'gearUid') then
       
  1075         begin
       
  1076         gear:= GearByUID(lua_tointeger(L, 1));
       
  1077         if gear <> nil then
       
  1078             lua_pushinteger(L, gear^.message)
       
  1079         else
       
  1080             lua_pushnil(L);
       
  1081         end
       
  1082     else
       
  1083         lua_pushnil(L); // return value on stack (nil)
       
  1084     lc_getgearmessage:= 1
       
  1085 end;
       
  1086 
       
  1087 function lc_getgearelasticity(L : Plua_State) : LongInt; Cdecl;
       
  1088 var gear : PGear;
       
  1089 begin
       
  1090     if CheckLuaParamCount(L, 1, 'GetGearElasticity', 'gearUid') then
       
  1091         begin
       
  1092         gear:= GearByUID(lua_tointeger(L, 1));
       
  1093         if gear <> nil then
       
  1094             lua_pushinteger(L, hwRound(gear^.elasticity * _10000))
       
  1095         else
       
  1096             lua_pushnil(L);
       
  1097         end
       
  1098     else
       
  1099         lua_pushnil(L); // return value on stack (nil)
       
  1100     lc_getgearelasticity:= 1
       
  1101 end;
       
  1102 
       
  1103 function lc_setgearelasticity(L : Plua_State) : LongInt; Cdecl;
       
  1104 var gear: PGear;
       
  1105 begin
       
  1106     if CheckLuaParamCount(L, 2, 'SetGearElasticity', 'gearUid, Elasticity') then
       
  1107         begin
       
  1108         gear:= GearByUID(lua_tointeger(L, 1));
       
  1109         if gear <> nil then
       
  1110             gear^.Elasticity:= int2hwFloat(lua_tointeger(L, 2)) / 10000
       
  1111         end;
       
  1112     lc_setgearelasticity:= 0
       
  1113 end;
       
  1114 
       
  1115 function lc_getgearfriction(L : Plua_State) : LongInt; Cdecl;
       
  1116 var gear : PGear;
       
  1117 begin
       
  1118     if CheckLuaParamCount(L, 1, 'GetGearFriction', 'gearUid') then
       
  1119         begin
       
  1120         gear:= GearByUID(lua_tointeger(L, 1));
       
  1121         if gear <> nil then
       
  1122             lua_pushinteger(L, hwRound(gear^.friction * _10000))
       
  1123         else
       
  1124             lua_pushnil(L);
       
  1125         end
       
  1126     else
       
  1127         lua_pushnil(L); // return value on stack (nil)
       
  1128     lc_getgearfriction:= 1
       
  1129 end;
       
  1130 
       
  1131 function lc_setgearfriction(L : Plua_State) : LongInt; Cdecl;
       
  1132 var gear: PGear;
       
  1133 begin
       
  1134     if CheckLuaParamCount(L, 2, 'SetGearFriction', 'gearUid, Friction') then
       
  1135         begin
       
  1136         gear:= GearByUID(lua_tointeger(L, 1));
       
  1137         if gear <> nil then
       
  1138             gear^.Friction:= int2hwFloat(lua_tointeger(L, 2)) / 10000
       
  1139         end;
       
  1140     lc_setgearfriction:= 0
       
  1141 end;
       
  1142 
       
  1143 function lc_setgearmessage(L : Plua_State) : LongInt; Cdecl;
       
  1144 var gear : PGear;
       
  1145 begin
       
  1146     if CheckLuaParamCount(L, 2, 'SetGearMessage', 'gearUid, message') then
       
  1147         begin
       
  1148         gear:= GearByUID(lua_tointeger(L, 1));
       
  1149         if gear <> nil then
       
  1150             gear^.message:= lua_tointeger(L, 2);
       
  1151         end;
       
  1152     lc_setgearmessage:= 0
       
  1153 end;
       
  1154 
       
  1155 function lc_getgearpos(L : Plua_State) : LongInt; Cdecl;
       
  1156 var gear : PGear;
       
  1157 begin
       
  1158     if CheckLuaParamCount(L, 1, 'GetGearPos', 'gearUid') then
       
  1159         begin
       
  1160         gear:= GearByUID(lua_tointeger(L, 1));
       
  1161         if gear <> nil then
       
  1162             lua_pushinteger(L, gear^.Pos)
       
  1163         else
       
  1164             lua_pushnil(L);
       
  1165         end
       
  1166     else
       
  1167         lua_pushnil(L); // return value on stack (nil)
       
  1168     lc_getgearpos:= 1
       
  1169 end;
       
  1170 
       
  1171 function lc_setgearpos(L : Plua_State) : LongInt; Cdecl;
       
  1172 var gear : PGear;
       
  1173 begin
       
  1174     if CheckLuaParamCount(L, 2, 'SetGearPos', 'gearUid, value') then
       
  1175         begin
       
  1176         gear:= GearByUID(lua_tointeger(L, 1));
       
  1177         if gear <> nil then
       
  1178             gear^.Pos:= lua_tointeger(L, 2);
       
  1179         end;
       
  1180     lc_setgearpos:= 0
       
  1181 end;
       
  1182 
       
  1183 function lc_getgearcollisionmask(L : Plua_State) : LongInt; Cdecl;
       
  1184 var gear : PGear;
       
  1185 begin
       
  1186     if CheckLuaParamCount(L, 1, 'GetGearCollisionMask', 'gearUid') then
       
  1187         begin
       
  1188         gear:= GearByUID(lua_tointeger(L, 1));
       
  1189         if gear <> nil then
       
  1190             lua_pushinteger(L, gear^.CollisionMask)
       
  1191         else
       
  1192             lua_pushnil(L);
       
  1193         end
       
  1194     else
       
  1195         lua_pushnil(L); // return value on stack (nil)
       
  1196     lc_getgearcollisionmask:= 1
       
  1197 end;
       
  1198 
       
  1199 function lc_setgearcollisionmask(L : Plua_State) : LongInt; Cdecl;
       
  1200 var gear : PGear;
       
  1201 begin
       
  1202     if CheckLuaParamCount(L, 2, 'SetGearCollisionMask', 'gearUid, mask') then
       
  1203         begin
       
  1204         gear:= GearByUID(lua_tointeger(L, 1));
       
  1205         if gear <> nil then
       
  1206             gear^.CollisionMask:= lua_tointeger(L, 2);
       
  1207         end;
       
  1208     lc_setgearcollisionmask:= 0
       
  1209 end;
       
  1210 
       
  1211 function lc_gethoglevel(L : Plua_State): LongInt; Cdecl;
       
  1212 var gear : PGear;
       
  1213 begin
       
  1214     if CheckLuaParamCount(L, 1, 'GetHogLevel', 'gearUid') then
       
  1215         begin
       
  1216         gear := GearByUID(lua_tointeger(L, 1));
       
  1217         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1218             lua_pushinteger(L, gear^.Hedgehog^.BotLevel)
       
  1219         else
       
  1220             lua_pushnil(L);
       
  1221     end;
       
  1222     lc_gethoglevel := 1;
       
  1223 end;
       
  1224 
       
  1225 function lc_sethoglevel(L : Plua_State) : LongInt; Cdecl;
       
  1226 var gear : PGear;
       
  1227 begin
       
  1228     if CheckLuaParamCount(L, 2, 'SetHogLevel', 'gearUid, level') then
       
  1229         begin
       
  1230         gear:= GearByUID(lua_tointeger(L, 1));
       
  1231         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1232             gear^.Hedgehog^.BotLevel:= lua_tointeger(L, 2);
       
  1233         end;
       
  1234     lc_sethoglevel:= 0
       
  1235 end;
       
  1236 
       
  1237 function lc_gethogclan(L : Plua_State) : LongInt; Cdecl;
       
  1238 var gear : PGear;
       
  1239 begin
       
  1240     if CheckLuaParamCount(L, 1, 'GetHogClan', 'gearUid') then
       
  1241         begin
       
  1242         gear:= GearByUID(lua_tointeger(L, 1));
       
  1243         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1244             begin
       
  1245             lua_pushinteger(L, gear^.Hedgehog^.Team^.Clan^.ClanIndex)
       
  1246             end
       
  1247         else
       
  1248             lua_pushnil(L);
       
  1249         end
       
  1250     else
       
  1251         lua_pushnil(L); // return value on stack (nil)
       
  1252     lc_gethogclan:= 1
       
  1253 end;
       
  1254 
       
  1255 function lc_getclancolor(L : Plua_State) : LongInt; Cdecl;
       
  1256 var idx: integer;
       
  1257 begin
       
  1258     if CheckLuaParamCount(L, 1, 'GetClanColor', 'clanIdx') then
       
  1259         begin
       
  1260         idx:= lua_tointeger(L, 1);
       
  1261         if (not lua_isnumber(L, 1)) then
       
  1262             begin
       
  1263             LuaError('Argument ''clanIdx'' must be a number!');
       
  1264             lua_pushnil(L);
       
  1265             end
       
  1266         else if (idx < 0) or (idx >= ClansCount) then
       
  1267             begin
       
  1268             LuaError('Argument ''clanIdx'' out of range! (There are currently ' + IntToStr(ClansCount) + ' clans, so valid range is: 0-' + IntToStr(ClansCount-1) + ')');
       
  1269             lua_pushnil(L);
       
  1270             end
       
  1271         else
       
  1272             lua_pushinteger(L, ClansArray[idx]^.Color shl 8 or $FF);
       
  1273         end
       
  1274     else
       
  1275         lua_pushnil(L); // return value on stack (nil)
       
  1276     lc_getclancolor:= 1
       
  1277 end;
       
  1278 
       
  1279 function lc_setclancolor(L : Plua_State) : LongInt; Cdecl;
       
  1280 var clan : PClan;
       
  1281     team : PTeam;
       
  1282     hh   : THedgehog;
       
  1283     i, j : LongInt;
       
  1284 begin
       
  1285     if CheckLuaParamCount(L, 2, 'SetClanColor', 'clan, color') then
       
  1286         begin
       
  1287         i:= lua_tointeger(L,1);
       
  1288         if i >= ClansCount then exit(0);
       
  1289         clan := ClansArray[i];
       
  1290         clan^.Color:= lua_tointeger(L, 2) shr 8;
       
  1291 
       
  1292         for i:= 0 to Pred(clan^.TeamsNumber) do
       
  1293             begin
       
  1294             team:= clan^.Teams[i];
       
  1295             for j:= 0 to 7 do
       
  1296                 begin
       
  1297                 hh:= team^.Hedgehogs[j];
       
  1298                 if (hh.Gear <> nil) or (hh.GearHidden <> nil) then
       
  1299                     begin
       
  1300                     FreeAndNilTexture(hh.NameTagTex);
       
  1301                     hh.NameTagTex:= RenderStringTex(ansistring(hh.Name), clan^.Color, fnt16);
       
  1302                     RenderHealth(hh);
       
  1303                     end;
       
  1304                 end;
       
  1305             FreeAndNilTexture(team^.NameTagTex);
       
  1306             team^.NameTagTex:= RenderStringTex(ansistring(clan^.Teams[i]^.TeamName), clan^.Color, fnt16);
       
  1307             end;
       
  1308 
       
  1309         FreeAndNilTexture(clan^.HealthTex);
       
  1310         clan^.HealthTex:= makeHealthBarTexture(cTeamHealthWidth + 5, clan^.Teams[0]^.NameTagTex^.h, clan^.Color);
       
  1311         end;
       
  1312 
       
  1313     lc_setclancolor:= 0
       
  1314 end;
       
  1315 
       
  1316 function lc_gethogvoicepack(L : Plua_State) : LongInt; Cdecl;
       
  1317 var gear : PGear;
       
  1318 begin
       
  1319     if CheckLuaParamCount(L, 1, 'GetHogVoicepack', 'gearUid') then
       
  1320         begin
       
  1321         gear:= GearByUID(lua_tointeger(L, 1));
       
  1322         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1323             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Voicepack^.name))
       
  1324         else
       
  1325             lua_pushnil(L);
       
  1326         end
       
  1327     else
       
  1328         lua_pushnil(L); // return value on stack (nil)
       
  1329     lc_gethogvoicepack:= 1
       
  1330 end;
       
  1331 
       
  1332 function lc_gethoggrave(L : Plua_State) : LongInt; Cdecl;
       
  1333 var gear : PGear;
       
  1334 begin
       
  1335     if CheckLuaParamCount(L, 1, 'GetHogGrave', 'gearUid') then
       
  1336         begin
       
  1337         gear:= GearByUID(lua_tointeger(L, 1));
       
  1338         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1339             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.GraveName))
       
  1340         else
       
  1341             lua_pushnil(L);
       
  1342         end
       
  1343     else
       
  1344         lua_pushnil(L); // return value on stack (nil)
       
  1345     lc_gethoggrave:= 1
       
  1346 end;
       
  1347 
       
  1348 function lc_gethogflag(L : Plua_State) : LongInt; Cdecl;
       
  1349 var gear : PGear;
       
  1350 begin
       
  1351     if CheckLuaParamCount(L, 1, 'GetHogFlag', 'gearUid') then
       
  1352         begin
       
  1353         gear:= GearByUID(lua_tointeger(L, 1));
       
  1354         // TODO error messages
       
  1355         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1356             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Flag))
       
  1357         else
       
  1358             lua_pushnil(L);
       
  1359         end
       
  1360     else
       
  1361         lua_pushnil(L); // return value on stack (nil)
       
  1362     lc_gethogflag:= 1
       
  1363 end;
       
  1364 
       
  1365 function lc_gethogfort(L : Plua_State) : LongInt; Cdecl;
       
  1366 var gear : PGear;
       
  1367 begin
       
  1368     if CheckLuaParamCount(L, 1, 'GetHogFort', 'gearUid') then
       
  1369         begin
       
  1370         gear:= GearByUID(lua_tointeger(L, 1));
       
  1371         // TODO error messages
       
  1372         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1373             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.FortName))
       
  1374         else
       
  1375             lua_pushnil(L);
       
  1376         end
       
  1377     else
       
  1378         lua_pushnil(L); // return value on stack (nil)
       
  1379     lc_gethogfort:= 1
       
  1380 end;
       
  1381 
       
  1382 function lc_ishoglocal(L : Plua_State) : LongInt; Cdecl;
       
  1383 var gear : PGear;
       
  1384 begin
       
  1385     if CheckLuaParamCount(L, 1, 'IsHogLocal', 'gearUid') then
       
  1386         begin
       
  1387         gear:= GearByUID(lua_tointeger(L, 1));
       
  1388         // TODO error messages
       
  1389         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1390             lua_pushboolean(L, IsHogLocal(gear^.Hedgehog))
       
  1391         else
       
  1392             lua_pushnil(L);
       
  1393         end
       
  1394     else
       
  1395         lua_pushnil(L); // return value on stack (nil)
       
  1396     lc_ishoglocal:= 1
       
  1397 end;
       
  1398 
       
  1399 function lc_gethogteamname(L : Plua_State) : LongInt; Cdecl;
       
  1400 var gear : PGear;
       
  1401 begin
       
  1402     if CheckLuaParamCount(L, 1, 'GetHogTeamName', 'gearUid') then
       
  1403         begin
       
  1404         gear:= GearByUID(lua_tointeger(L, 1));
       
  1405         // TODO error messages
       
  1406         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1407             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.TeamName))
       
  1408         else
       
  1409             lua_pushnil(L);
       
  1410         end
       
  1411     else
       
  1412         lua_pushnil(L); // return value on stack (nil)
       
  1413     lc_gethogteamname:= 1
       
  1414 end;
       
  1415 
       
  1416 function lc_sethogteamname(L : Plua_State) : LongInt; Cdecl;
       
  1417 var gear : PGear;
       
  1418 begin
       
  1419     if CheckLuaParamCount(L, 2, 'SetHogTeamName', 'gearUid, name') then
       
  1420         begin
       
  1421         gear := GearByUID(lua_tointeger(L, 1));
       
  1422         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1423             begin
       
  1424             gear^.Hedgehog^.Team^.TeamName := lua_tostring(L, 2);
       
  1425 
       
  1426             FreeAndNilTexture(gear^.Hedgehog^.Team^.NameTagTex);
       
  1427             gear^.Hedgehog^.Team^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Team^.TeamName), gear^.Hedgehog^.Team^.Clan^.Color, fnt16);
       
  1428             end
       
  1429         else
       
  1430             lua_pushnil(L);
       
  1431         end
       
  1432     else
       
  1433         lua_pushnil(L); // return value on stack (nil)
       
  1434     lc_sethogteamname:= 1
       
  1435 end;
       
  1436 
       
  1437 function lc_gethogname(L : Plua_State) : LongInt; Cdecl;
       
  1438 var gear : PGear;
       
  1439 begin
       
  1440     if CheckLuaParamCount(L, 1, 'GetHogName', 'gearUid') then
       
  1441         begin
       
  1442         gear:= GearByUID(lua_tointeger(L, 1));
       
  1443         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  1444             begin
       
  1445             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Name))
       
  1446             end
       
  1447         else
       
  1448             lua_pushnil(L);
       
  1449         end
       
  1450     else
       
  1451         lua_pushnil(L); // return value on stack (nil)
       
  1452     lc_gethogname:= 1
       
  1453 end;
       
  1454 
       
  1455 function lc_sethogname(L : Plua_State) : LongInt; Cdecl;
       
  1456 var gear : PGear;
       
  1457 begin
       
  1458     if CheckLuaParamCount(L, 2, 'SetHogName', 'gearUid, name') then
       
  1459         begin
       
  1460         gear:= GearByUID(lua_tointeger(L, 1));
       
  1461         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1462             begin
       
  1463             gear^.Hedgehog^.Name:= lua_tostring(L, 2);
       
  1464 
       
  1465             FreeAndNilTexture(gear^.Hedgehog^.NameTagTex);
       
  1466             gear^.Hedgehog^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Name), gear^.Hedgehog^.Team^.Clan^.Color, fnt16)
       
  1467             end
       
  1468         end;
       
  1469     lc_sethogname:= 0;
       
  1470 end;
       
  1471 
       
  1472 function lc_gettimer(L : Plua_State) : LongInt; Cdecl;
       
  1473 var gear : PGear;
       
  1474 begin
       
  1475     if CheckLuaParamCount(L, 1, 'GetTimer', 'gearUid') then
       
  1476         begin
       
  1477         gear:= GearByUID(lua_tointeger(L, 1));
       
  1478         if gear <> nil then
       
  1479             lua_pushinteger(L, gear^.Timer)
       
  1480         else
       
  1481             lua_pushnil(L);
       
  1482         end
       
  1483     else
       
  1484         lua_pushnil(L); // return value on stack (nil)
       
  1485     lc_gettimer:= 1
       
  1486 end;
       
  1487 
       
  1488 function lc_getflighttime(L : Plua_State) : LongInt; Cdecl;
       
  1489 var gear : PGear;
       
  1490 begin
       
  1491     if CheckLuaParamCount(L, 1, 'GetFlightTime', 'gearUid') then
       
  1492         begin
       
  1493         gear:= GearByUID(lua_tointeger(L, 1));
       
  1494         if gear <> nil then
       
  1495             lua_pushinteger(L, gear^.FlightTime)
       
  1496         else
       
  1497             lua_pushnil(L);
       
  1498         end
       
  1499     else
       
  1500         lua_pushnil(L); // return value on stack (nil)
       
  1501     lc_getflighttime:= 1
       
  1502 end;
       
  1503 
       
  1504 function lc_gethealth(L : Plua_State) : LongInt; Cdecl;
       
  1505 var gear : PGear;
       
  1506 begin
       
  1507     if CheckLuaParamCount(L, 1, 'GetHealth', 'gearUid') then
       
  1508         begin
       
  1509         gear:= GearByUID(lua_tointeger(L, 1));
       
  1510         if gear <> nil then
       
  1511             lua_pushinteger(L, gear^.Health)
       
  1512         else
       
  1513             lua_pushnil(L);
       
  1514         end
       
  1515     else
       
  1516         lua_pushnil(L); // return value on stack (nil)
       
  1517     lc_gethealth:= 1
       
  1518 end;
       
  1519 
       
  1520 function lc_getx(L : Plua_State) : LongInt; Cdecl;
       
  1521 var gear : PGear;
       
  1522 begin
       
  1523     if CheckLuaParamCount(L, 1, 'GetX', 'gearUid') then
       
  1524         begin
       
  1525         gear:= GearByUID(lua_tointeger(L, 1));
       
  1526         if gear <> nil then
       
  1527             lua_pushinteger(L, hwRound(gear^.X))
       
  1528         else
       
  1529             lua_pushnil(L);
       
  1530         end
       
  1531     else
       
  1532         lua_pushnil(L); // return value on stack (nil)
       
  1533     lc_getx:= 1
       
  1534 end;
       
  1535 
       
  1536 function lc_gety(L : Plua_State) : LongInt; Cdecl;
       
  1537 var gear : PGear;
       
  1538 begin
       
  1539     if CheckLuaParamCount(L, 1, 'GetY', 'gearUid') then
       
  1540         begin
       
  1541         gear:= GearByUID(lua_tointeger(L, 1));
       
  1542         if gear <> nil then
       
  1543             lua_pushinteger(L, hwRound(gear^.Y))
       
  1544         else
       
  1545             lua_pushnil(L);
       
  1546         end
       
  1547     else
       
  1548         lua_pushnil(L); // return value on stack (nil)
       
  1549     lc_gety:= 1
       
  1550 end;
       
  1551 
       
  1552 function lc_copypv(L : Plua_State) : LongInt; Cdecl;
       
  1553 var gears, geard : PGear;
       
  1554 begin
       
  1555     if CheckLuaParamCount(L, 2, 'CopyPV', 'fromGearUid, toGearUid') then
       
  1556         begin
       
  1557         gears:= GearByUID(lua_tointeger(L, 1));
       
  1558         geard:= GearByUID(lua_tointeger(L, 2));
       
  1559         if (gears <> nil) and (geard <> nil) then
       
  1560             begin
       
  1561             geard^.X:= gears^.X;
       
  1562             geard^.Y:= gears^.Y;
       
  1563             geard^.dX:= gears^.dX;
       
  1564             geard^.dY:= gears^.dY;
       
  1565             end
       
  1566         end;
       
  1567     lc_copypv:= 0
       
  1568 end;
       
  1569 
       
  1570 function lc_followgear(L : Plua_State) : LongInt; Cdecl;
       
  1571 var gear : PGear;
       
  1572 begin
       
  1573     if CheckLuaParamCount(L, 1, 'FollowGear', 'gearUid') then
       
  1574         begin
       
  1575         gear:= GearByUID(lua_tointeger(L, 1));
       
  1576         if gear <> nil then FollowGear:= gear
       
  1577         end;
       
  1578     lc_followgear:= 0
       
  1579 end;
       
  1580 
       
  1581 function lc_hogsay(L : Plua_State) : LongInt; Cdecl;
       
  1582 var gear : PGear;
       
  1583    vgear : PVisualGear;
       
  1584        s : LongWord;
       
  1585        n : LongInt;
       
  1586 begin
       
  1587     if CheckAndFetchParamCount(L, 3, 4, 'HogSay', 'gearUid, text, manner [, vgState]', n) then
       
  1588         begin
       
  1589         gear:= GearByUID(lua_tointeger(L, 1));
       
  1590         if gear <> nil then
       
  1591             begin
       
  1592             // state defaults to 0 if state param is given
       
  1593             if n = 4 then
       
  1594                 s:= lua_tointeger(L, 4)
       
  1595             else
       
  1596                 s:= 0;
       
  1597             vgear:= AddVisualGear(0, 0, vgtSpeechBubble, s, true);
       
  1598             if vgear <> nil then
       
  1599                begin
       
  1600                vgear^.Text:= lua_tostring(L, 2);
       
  1601                if Gear^.Kind = gtHedgehog then
       
  1602                    begin
       
  1603                    AddChatString(#9+'[' + gear^.Hedgehog^.Name + '] '+vgear^.text);
       
  1604                    vgear^.Hedgehog:= gear^.Hedgehog
       
  1605                    end
       
  1606                else vgear^.Frame:= gear^.uid;
       
  1607 
       
  1608                vgear^.FrameTicks:= lua_tointeger(L, 3);
       
  1609                if (vgear^.FrameTicks < 1) or (vgear^.FrameTicks > 3) then
       
  1610                    vgear^.FrameTicks:= 1;
       
  1611                lua_pushinteger(L, vgear^.Uid);
       
  1612                end
       
  1613             end
       
  1614         else
       
  1615             lua_pushnil(L)
       
  1616         end
       
  1617     else
       
  1618         lua_pushnil(L);
       
  1619     lc_hogsay:= 1
       
  1620 end;
       
  1621 
       
  1622 function lc_switchhog(L : Plua_State) : LongInt; Cdecl;
       
  1623 var gear, prevgear : PGear;
       
  1624 begin
       
  1625     if CheckLuaParamCount(L, 1, 'SwitchHog', 'gearUid') then
       
  1626         begin
       
  1627         gear:= GearByUID(lua_tointeger(L, 1));
       
  1628 // should we allow this when there is no current hedgehog? might do some odd(er) things to turn sequence.
       
  1629         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) and (CurrentHedgehog <> nil) then
       
  1630             begin
       
  1631             prevgear := CurrentHedgehog^.Gear;
       
  1632             if prevgear <> nil then
       
  1633                 begin
       
  1634                 prevgear^.Active := false;
       
  1635                 prevgear^.State:= prevgear^.State and (not gstHHDriven);
       
  1636                 prevgear^.Z := cHHZ;
       
  1637                 prevgear^.Message:= prevgear^.Message or gmRemoveFromList or gmAddToList;
       
  1638                 end;
       
  1639 
       
  1640             SwitchCurrentHedgehog(gear^.Hedgehog);
       
  1641             CurrentTeam:= CurrentHedgehog^.Team;
       
  1642 
       
  1643             gear^.State:= gear^.State or gstHHDriven;
       
  1644             gear^.Active := true;
       
  1645             gear^.Z := cCurrHHZ;
       
  1646             gear^.Message:= gear^.Message or gmRemoveFromList or gmAddToList;
       
  1647             end
       
  1648         end;
       
  1649     lc_switchhog:= 0
       
  1650 end;
       
  1651 
       
  1652 function lc_addammo(L : Plua_State) : LongInt; Cdecl;
       
  1653 var gear : PGear;
       
  1654     at, n: LongInt;
       
  1655 const
       
  1656     call = 'AddAmmo';
       
  1657     params = 'gearUid, ammoType [, ammoCount]';
       
  1658 begin
       
  1659     if CheckAndFetchParamCount(L, 2, 3, call, params, n) then
       
  1660         begin
       
  1661         at:= LuaToAmmoTypeOrd(L, 2, call, params);
       
  1662         if at >= 0 then
       
  1663             begin
       
  1664             gear:= GearByUID(lua_tointeger(L, 1));
       
  1665             if (gear <> nil) and (gear^.Hedgehog <> nil) then
       
  1666                 if n = 2 then
       
  1667                     AddAmmo(gear^.Hedgehog^, TAmmoType(at))
       
  1668                 else
       
  1669                     SetAmmo(gear^.Hedgehog^, TAmmoType(at), lua_tointeger(L, 3))
       
  1670             end;
       
  1671         end;
       
  1672     lc_addammo:= 0
       
  1673 end;
       
  1674 
       
  1675 function lc_getammocount(L : Plua_State) : LongInt; Cdecl;
       
  1676 var gear : PGear;
       
  1677     ammo : PAmmo;
       
  1678     at   : LongInt;
       
  1679 const
       
  1680     call = 'GetAmmoCount';
       
  1681     params = 'gearUid, ammoType';
       
  1682 begin
       
  1683     if CheckLuaParamCount(L, 2, call, params) then
       
  1684         begin
       
  1685         gear:= GearByUID(lua_tointeger(L, 1));
       
  1686         if (gear <> nil) and (gear^.Hedgehog <> nil) then
       
  1687             begin
       
  1688             at:= LuaToAmmoTypeOrd(L, 2, call, params);
       
  1689             if at >= 0 then
       
  1690                 begin
       
  1691                 ammo:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(at));
       
  1692                 if ammo^.AmmoType = amNothing then
       
  1693                     lua_pushinteger(L, 0)
       
  1694                 else
       
  1695                     lua_pushinteger(L, ammo^.Count);
       
  1696                 end;
       
  1697             end
       
  1698         else lua_pushinteger(L, 0);
       
  1699         end
       
  1700     else
       
  1701         lua_pushnil(L);
       
  1702     lc_getammocount:= 1
       
  1703 end;
       
  1704 
       
  1705 function lc_sethealth(L : Plua_State) : LongInt; Cdecl;
       
  1706 var gear : PGear;
       
  1707 begin
       
  1708     if CheckLuaParamCount(L, 2, 'SetHealth', 'gearUid, health') then
       
  1709         begin
       
  1710         gear:= GearByUID(lua_tointeger(L, 1));
       
  1711         if gear <> nil then
       
  1712             begin
       
  1713             gear^.Health:= lua_tointeger(L, 2);
       
  1714 
       
  1715             if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1716                 begin
       
  1717                 RenderHealth(gear^.Hedgehog^);
       
  1718                 RecountTeamHealth(gear^.Hedgehog^.Team)
       
  1719                 end;
       
  1720             // Why did this do a "setalltoactive" ?
       
  1721             //SetAllToActive;
       
  1722             Gear^.Active:= true;
       
  1723             AllInactive:= false
       
  1724             end
       
  1725         end;
       
  1726     lc_sethealth:= 0
       
  1727 end;
       
  1728 
       
  1729 function lc_settimer(L : Plua_State) : LongInt; Cdecl;
       
  1730 var gear : PGear;
       
  1731 begin
       
  1732     if CheckLuaParamCount(L, 2, 'SetTimer', 'gearUid, timer') then
       
  1733         begin
       
  1734         gear:= GearByUID(lua_tointeger(L, 1));
       
  1735         if gear <> nil then gear^.Timer:= lua_tointeger(L, 2)
       
  1736         end;
       
  1737     lc_settimer:= 0
       
  1738 end;
       
  1739 
       
  1740 function lc_setflighttime(L : Plua_State) : LongInt; Cdecl;
       
  1741 var gear : PGear;
       
  1742 begin
       
  1743     if CheckLuaParamCount(L, 2, 'SetFlightTime', 'gearUid, flighttime') then
       
  1744         begin
       
  1745         gear:= GearByUID(lua_tointeger(L, 1));
       
  1746         if gear <> nil then gear^.FlightTime:= lua_tointeger(L, 2)
       
  1747         end;
       
  1748     lc_setflighttime:= 0
       
  1749 end;
       
  1750 
       
  1751 function lc_seteffect(L : Plua_State) : LongInt; Cdecl;
       
  1752 var gear: PGear;
       
  1753     t   : LongInt;
       
  1754 const
       
  1755     call = 'SetEffect';
       
  1756     params = 'gearUid, effect, effectState';
       
  1757 begin
       
  1758     if CheckLuaParamCount(L, 3, call, params) then
       
  1759         begin
       
  1760         t:= LuaToHogEffectOrd(L, 2, call, params);
       
  1761         if t >= 0 then
       
  1762             begin
       
  1763             gear := GearByUID(lua_tointeger(L, 1));
       
  1764             if (gear <> nil) and (gear^.Hedgehog <> nil) then
       
  1765                 gear^.Hedgehog^.Effects[THogEffect(t)]:= lua_tointeger(L, 3);
       
  1766             end;
       
  1767         end;
       
  1768     lc_seteffect := 0;
       
  1769 end;
       
  1770 
       
  1771 function lc_geteffect(L : Plua_State) : LongInt; Cdecl;
       
  1772 var gear : PGear;
       
  1773     t    : LongInt;
       
  1774 const
       
  1775     call = 'GetEffect';
       
  1776     params = 'gearUid, effect';
       
  1777 begin
       
  1778     if CheckLuaParamCount(L, 2, call, params) then
       
  1779         begin
       
  1780         t:= LuaToHogEffectOrd(L, 2, call, params);
       
  1781         if t >= 0 then
       
  1782             begin
       
  1783             gear:= GearByUID(lua_tointeger(L, 1));
       
  1784             if (gear <> nil) and (gear^.Hedgehog <> nil) then
       
  1785                 lua_pushinteger(L, gear^.Hedgehog^.Effects[THogEffect(t)])
       
  1786             else
       
  1787                 lua_pushinteger(L, 0)
       
  1788             end;
       
  1789         end
       
  1790     else
       
  1791         lua_pushinteger(L, 0);
       
  1792     lc_geteffect:= 1
       
  1793 end;
       
  1794 
       
  1795 function lc_setstate(L : Plua_State) : LongInt; Cdecl;
       
  1796 var gear : PGear;
       
  1797 begin
       
  1798     if CheckLuaParamCount(L, 2, 'SetState', 'gearUid, state') then
       
  1799         begin
       
  1800         gear:= GearByUID(lua_tointeger(L, 1));
       
  1801         if gear <> nil then
       
  1802             begin
       
  1803             gear^.State:= lua_tointeger(L, 2);
       
  1804             SetAllToActive;
       
  1805             end
       
  1806         end;
       
  1807     lc_setstate:= 0
       
  1808 end;
       
  1809 
       
  1810 function lc_getstate(L : Plua_State) : LongInt; Cdecl;
       
  1811 var gear : PGear;
       
  1812 begin
       
  1813     if CheckLuaParamCount(L, 1, 'GetState', 'gearUid') then
       
  1814         begin
       
  1815         gear:= GearByUID(lua_tointeger(L, 1));
       
  1816         if gear <> nil then
       
  1817             lua_pushinteger(L, gear^.State)
       
  1818         else
       
  1819             lua_pushnil(L)
       
  1820         end
       
  1821     else
       
  1822         lua_pushnil(L); // return value on stack (nil)
       
  1823     lc_getstate:= 1
       
  1824 end;
       
  1825 
       
  1826 function lc_gettag(L : Plua_State) : LongInt; Cdecl;
       
  1827 var gear : PGear;
       
  1828 begin
       
  1829     if CheckLuaParamCount(L, 1, 'GetTag', 'gearUid') then
       
  1830         begin
       
  1831         gear:= GearByUID(lua_tointeger(L, 1));
       
  1832         if gear <> nil then
       
  1833             lua_pushinteger(L, gear^.Tag)
       
  1834         else
       
  1835             lua_pushnil(L);
       
  1836         end
       
  1837     else
       
  1838         lua_pushnil(L); // return value on stack (nil)
       
  1839     lc_gettag:= 1
       
  1840 end;
       
  1841 
       
  1842 function lc_settag(L : Plua_State) : LongInt; Cdecl;
       
  1843 var gear : PGear;
       
  1844 begin
       
  1845     if CheckLuaParamCount(L, 2, 'SetTag', 'gearUid, tag') then
       
  1846         begin
       
  1847         gear:= GearByUID(lua_tointeger(L, 1));
       
  1848         if gear <> nil then
       
  1849             begin
       
  1850             gear^.Tag:= lua_tointeger(L, 2);
       
  1851             SetAllToActive;
       
  1852             end
       
  1853         end;
       
  1854     lc_settag:= 0
       
  1855 end;
       
  1856 
       
  1857 function lc_endgame(L : Plua_State) : LongInt; Cdecl;
       
  1858 begin
       
  1859     L:= L; // avoid compiler hint
       
  1860     AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000);
       
  1861     lc_endgame:= 0
       
  1862 end;
       
  1863 
       
  1864 function lc_sendstat(L : Plua_State) : LongInt; Cdecl;
       
  1865 var statInfo : TStatInfoType;
       
  1866     i, n     : LongInt;
       
  1867     color, tn: shortstring;
       
  1868     needsTn  : boolean;
       
  1869 const
       
  1870     call = 'SendStat';
       
  1871     params = 'statInfoType, color [, teamname]';
       
  1872 begin
       
  1873     if CheckAndFetchParamCount(L, 2, 3, call, params, n) then
       
  1874         begin
       
  1875         i:= LuaToStatInfoTypeOrd(L, 1, call, params);
       
  1876         if i >= 0 then
       
  1877             begin
       
  1878             statInfo:= TStatInfoType(i);
       
  1879             needsTn:= ((statInfo = siPlayerKills) or (statInfo = siClanHealth));
       
  1880             // check if param count is correct for the used statInfo
       
  1881             if (n = 3) <> needsTn then
       
  1882                 begin
       
  1883                 if n = 3 then
       
  1884                     LuaCallError(EnumToStr(statInfo) + ' does not support the teamname parameter', call, params)
       
  1885                 else
       
  1886                     LuaCallError(EnumToStr(statInfo) + ' requires the teamname parameter', call, params);
       
  1887                 end
       
  1888             else // count is correct!
       
  1889                 begin
       
  1890                 if needsTn then
       
  1891                     begin
       
  1892                     // 3: team name
       
  1893                     for i:= 0 to Pred(TeamsCount) do
       
  1894                         begin
       
  1895                         color:= _S'0';
       
  1896                         tn:= lua_tostring(L, 3);
       
  1897                         with TeamsArray[i]^ do
       
  1898                             begin
       
  1899                                 if TeamName = tn then
       
  1900                                     begin
       
  1901                                     color := uUtils.IntToStr(Clan^.Color);
       
  1902                                     Break;
       
  1903                                     end
       
  1904                             end
       
  1905                         end;
       
  1906                     if (statInfo = siPlayerKills) then
       
  1907                         begin
       
  1908                             SendStat(siPlayerKills, color + ' ' +
       
  1909                                 lua_tostring(L, 2) + ' ' + tn);
       
  1910                         end
       
  1911                     else if (statInfo = siClanHealth) then
       
  1912                         begin
       
  1913                             SendStat(siClanHealth, color + ' ' +
       
  1914                                 lua_tostring(L, 2));
       
  1915                         end
       
  1916                     end
       
  1917                 else
       
  1918                     begin
       
  1919                     SendStat(statInfo,lua_tostring(L, 2));
       
  1920                     end;
       
  1921                 end;
       
  1922             end;
       
  1923         end;
       
  1924     lc_sendstat:= 0
       
  1925 end;
       
  1926 
       
  1927 function lc_sendhealthstatsoff(L : Plua_State) : LongInt; Cdecl;
       
  1928 begin
       
  1929     L:= L; // avoid compiler hint
       
  1930     uStats.SendHealthStatsOn := false;
       
  1931     lc_sendhealthstatsoff:= 0
       
  1932 end;
       
  1933 
       
  1934 function lc_findplace(L : Plua_State) : LongInt; Cdecl;
       
  1935 var gear: PGear;
       
  1936     fall: boolean;
       
  1937     tryhard: boolean;
       
  1938     left, right, n: LongInt;
       
  1939 begin
       
  1940     if CheckAndFetchParamCount(L, 4, 5, 'FindPlace', 'gearUid, fall, left, right [, tryHarder]', n) then
       
  1941         begin
       
  1942         gear:= GearByUID(lua_tointeger(L, 1));
       
  1943         fall:= lua_toboolean(L, 2);
       
  1944         left:= lua_tointeger(L, 3);
       
  1945         right:= lua_tointeger(L, 4);
       
  1946         if n = 5 then
       
  1947             tryhard:= lua_toboolean(L, 5)
       
  1948         else
       
  1949             tryhard:= false;
       
  1950         if gear <> nil then
       
  1951             FindPlace(gear, fall, left, right, tryhard);
       
  1952         if gear <> nil then
       
  1953             lua_pushinteger(L, gear^.uid)
       
  1954         else
       
  1955             lua_pushnil(L);
       
  1956         end
       
  1957     else
       
  1958         lua_pushnil(L); // return value on stack (nil)
       
  1959     lc_findplace:= 1
       
  1960 end;
       
  1961 
       
  1962 function lc_playsound(L : Plua_State) : LongInt; Cdecl;
       
  1963 var gear: PGear;
       
  1964     n, s: LongInt;
       
  1965 const
       
  1966     call = 'PlaySound';
       
  1967     params = 'soundId [, hhGearUid]';
       
  1968 begin
       
  1969     if CheckAndFetchParamCount(L, 1, 2, call, params, n) then
       
  1970         begin
       
  1971         s:= LuaToSoundOrd(L, 1, call, params);
       
  1972         if s >= 0 then
       
  1973             begin
       
  1974             // no gear specified
       
  1975             if n = 1 then
       
  1976                 PlaySound(TSound(s))
       
  1977             else
       
  1978                 begin
       
  1979                 gear:= GearByUID(lua_tointeger(L, 2));
       
  1980                 if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  1981                     AddVoice(TSound(s),gear^.Hedgehog^.Team^.Voicepack)
       
  1982                 end;
       
  1983             end;
       
  1984         end;
       
  1985     lc_playsound:= 0;
       
  1986 end;
       
  1987 
       
  1988 function lc_addteam(L : Plua_State) : LongInt; Cdecl;
       
  1989 var np: LongInt;
       
  1990 begin
       
  1991     if CheckAndFetchParamCount(L, 5, 6, 'AddTeam', 'teamname, color, grave, fort, voicepack [, flag]', np) then
       
  1992         begin
       
  1993         ParseCommand('addteam x ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 1), true, true);
       
  1994         ParseCommand('grave ' + lua_tostring(L, 3), true, true);
       
  1995         ParseCommand('fort ' + lua_tostring(L, 4), true, true);
       
  1996         ParseCommand('voicepack ' + lua_tostring(L, 5), true, true);
       
  1997         if (np = 6) then ParseCommand('flag ' + lua_tostring(L, 6), true, true);
       
  1998         CurrentTeam^.Binds:= DefaultBinds
       
  1999         // fails on x64
       
  2000         //lua_pushinteger(L, LongInt(CurrentTeam));
       
  2001         end;
       
  2002     //else
       
  2003         //lua_pushnil(L)
       
  2004     lc_addteam:= 0;//1;
       
  2005 end;
       
  2006 
       
  2007 function lc_dismissteam(L : Plua_State) : LongInt; Cdecl;
       
  2008 var HHGear: PGear;
       
  2009     i, h  : LongInt;
       
  2010     hidden: boolean;
       
  2011 begin
       
  2012     if CheckLuaParamCount(L, 1, 'DismissTeam', 'teamname') then
       
  2013         begin
       
  2014         if TeamsCount > 0 then
       
  2015             for i:= 0 to Pred(TeamsCount) do
       
  2016                 begin
       
  2017                 // skip teams that don't have matching name
       
  2018                 if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
       
  2019                     continue;
       
  2020 
       
  2021                 // destroy all hogs of matching team, including the hidden ones
       
  2022                 for h:= 0 to cMaxHHIndex do
       
  2023                     begin
       
  2024                     hidden:= (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil);
       
  2025                     if hidden then
       
  2026                         RestoreHog(@TeamsArray[i]^.Hedgehogs[h]);
       
  2027                     // destroy hedgehog gear, if any
       
  2028                     HHGear:= TeamsArray[i]^.Hedgehogs[h].Gear;
       
  2029                     if HHGear <> nil then
       
  2030                         begin
       
  2031                         // smoke effect
       
  2032                         if (not hidden) then
       
  2033                             begin
       
  2034                             AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtSmokeWhite);
       
  2035                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
       
  2036                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
       
  2037                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
       
  2038                             AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite);
       
  2039                             end;
       
  2040                         HHGear^.Message:= HHGear^.Message or gmDestroy;
       
  2041                         end;
       
  2042                     end;
       
  2043                 // can't dismiss more than one team
       
  2044                 break;
       
  2045                 end;
       
  2046         end;
       
  2047     lc_dismissteam:= 0;
       
  2048 end;
       
  2049 
       
  2050 function lc_addhog(L : Plua_State) : LongInt; Cdecl;
       
  2051 var temp: ShortString;
       
  2052 begin
       
  2053     if CheckLuaParamCount(L, 4, 'AddHog', 'hogname, botlevel, health, hat') then
       
  2054         begin
       
  2055         temp:= lua_tostring(L, 4);
       
  2056         ParseCommand('addhh ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 3) + ' ' + lua_tostring(L, 1), true, true);
       
  2057         ParseCommand('hat ' + temp, true, true);
       
  2058         lua_pushinteger(L, CurrentHedgehog^.Gear^.uid);
       
  2059         end
       
  2060     else
       
  2061         lua_pushnil(L);
       
  2062     lc_addhog:= 1;
       
  2063 end;
       
  2064 
       
  2065 function lc_hogturnleft(L : Plua_State) : LongInt; Cdecl;
       
  2066 var gear: PGear;
       
  2067 begin
       
  2068     if CheckLuaParamCount(L, 2, 'HogTurnLeft', 'gearUid, boolean') then
       
  2069         begin
       
  2070         gear:= GearByUID(lua_tointeger(L, 1));
       
  2071         if gear <> nil then
       
  2072             gear^.dX.isNegative:= lua_toboolean(L, 2);
       
  2073         end;
       
  2074     lc_hogturnleft:= 0;
       
  2075 end;
       
  2076 
       
  2077 function lc_getgearposition(L : Plua_State) : LongInt; Cdecl;
       
  2078 var gear: PGear;
       
  2079 begin
       
  2080     if CheckLuaParamCount(L, 1, 'GetGearPosition', 'gearUid') then
       
  2081         begin
       
  2082         gear:= GearByUID(lua_tointeger(L, 1));
       
  2083         if gear <> nil then
       
  2084             begin
       
  2085             lua_pushinteger(L, hwRound(gear^.X));
       
  2086             lua_pushinteger(L, hwRound(gear^.Y))
       
  2087             end
       
  2088         else
       
  2089             begin
       
  2090             lua_pushnil(L);
       
  2091             lua_pushnil(L)
       
  2092             end;
       
  2093         end
       
  2094     else
       
  2095         begin
       
  2096         lua_pushnil(L);
       
  2097         lua_pushnil(L)
       
  2098         end;
       
  2099     lc_getgearposition:= 2;
       
  2100 end;
       
  2101 
       
  2102 function lc_setgearposition(L : Plua_State) : LongInt; Cdecl;
       
  2103 var gear: PGear;
       
  2104     col: boolean;
       
  2105     x, y: LongInt;
       
  2106 begin
       
  2107     if CheckLuaParamCount(L, 3, 'SetGearPosition', 'gearUid, x, y') then
       
  2108         begin
       
  2109         gear:= GearByUID(lua_tointeger(L, 1));
       
  2110         if gear <> nil then
       
  2111             begin
       
  2112             col:= gear^.CollisionIndex >= 0;
       
  2113             x:= lua_tointeger(L, 2);
       
  2114             y:= lua_tointeger(L, 3);
       
  2115             if col then
       
  2116                 DeleteCI(gear);
       
  2117             gear^.X:= int2hwfloat(x);
       
  2118             gear^.Y:= int2hwfloat(y);
       
  2119             if col then
       
  2120                 AddCI(gear);
       
  2121             SetAllToActive
       
  2122             end
       
  2123         end;
       
  2124     lc_setgearposition:= 0
       
  2125 end;
       
  2126 
       
  2127 function lc_getgeartarget(L : Plua_State) : LongInt; Cdecl;
       
  2128 var gear: PGear;
       
  2129 begin
       
  2130     if CheckLuaParamCount(L, 1, 'GetGearTarget', 'gearUid') then
       
  2131         begin
       
  2132         gear:= GearByUID(lua_tointeger(L, 1));
       
  2133         if gear <> nil then
       
  2134             begin
       
  2135             lua_pushinteger(L, gear^.Target.X);
       
  2136             lua_pushinteger(L, gear^.Target.Y)
       
  2137             end
       
  2138         else
       
  2139             begin
       
  2140             lua_pushnil(L);
       
  2141             lua_pushnil(L)
       
  2142             end
       
  2143         end
       
  2144     else
       
  2145         begin
       
  2146         lua_pushnil(L);
       
  2147         lua_pushnil(L)
       
  2148         end;
       
  2149     lc_getgeartarget:= 2;
       
  2150 end;
       
  2151 
       
  2152 function lc_setgeartarget(L : Plua_State) : LongInt; Cdecl;
       
  2153 var gear: PGear;
       
  2154 begin
       
  2155     if CheckLuaParamCount(L, 3, 'SetGearTarget', 'gearUid, x, y') then
       
  2156         begin
       
  2157         gear:= GearByUID(lua_tointeger(L, 1));
       
  2158         if gear <> nil then
       
  2159             begin
       
  2160             gear^.Target.X:= lua_tointeger(L, 2);
       
  2161             gear^.Target.Y:= lua_tointeger(L, 3)
       
  2162             end
       
  2163         end;
       
  2164     lc_setgeartarget:= 0
       
  2165 end;
       
  2166 
       
  2167 function lc_getgearvelocity(L : Plua_State) : LongInt; Cdecl;
       
  2168 var gear: PGear;
       
  2169 var t: LongInt;
       
  2170 begin
       
  2171     if CheckLuaParamCount(L, 1, 'GetGearVelocity', 'gearUid') then
       
  2172         begin
       
  2173         gear:= GearByUID(lua_tointeger(L, 1));
       
  2174         if gear <> nil then
       
  2175             begin
       
  2176             t:= hwRound(gear^.dX * 1000000);
       
  2177             // gear dX determines hog orientation
       
  2178             if (gear^.dX.isNegative) and (t = 0) then t:= -1;
       
  2179             lua_pushinteger(L, t);
       
  2180             lua_pushinteger(L, hwRound(gear^.dY * 1000000))
       
  2181             end
       
  2182         end
       
  2183     else
       
  2184         begin
       
  2185         lua_pushnil(L);
       
  2186         lua_pushnil(L);
       
  2187         end;
       
  2188     lc_getgearvelocity:= 2;
       
  2189 end;
       
  2190 
       
  2191 function lc_setgearvelocity(L : Plua_State) : LongInt; Cdecl;
       
  2192 var gear: PGear;
       
  2193 begin
       
  2194     if CheckLuaParamCount(L, 3, 'SetGearVelocity', 'gearUid, dx, dy') then
       
  2195         begin
       
  2196         gear:= GearByUID(lua_tointeger(L, 1));
       
  2197         if gear <> nil then
       
  2198             begin
       
  2199             gear^.dX:= int2hwFloat(lua_tointeger(L, 2)) / 1000000;
       
  2200             gear^.dY:= int2hwFloat(lua_tointeger(L, 3)) / 1000000;
       
  2201             SetAllToActive;
       
  2202             end
       
  2203         end;
       
  2204     lc_setgearvelocity:= 0
       
  2205 end;
       
  2206 
       
  2207 function lc_setzoom(L : Plua_State) : LongInt; Cdecl;
       
  2208 begin
       
  2209     if CheckLuaParamCount(L, 1, 'SetZoom', 'zoomLevel') then
       
  2210         begin
       
  2211         ZoomValue:= lua_tonumber(L, 1);
       
  2212         if ZoomValue < cMaxZoomLevel then
       
  2213             ZoomValue:= cMaxZoomLevel;
       
  2214         if ZoomValue > cMinZoomLevel then
       
  2215             ZoomValue:= cMinZoomLevel;
       
  2216         end;
       
  2217     lc_setzoom:= 0
       
  2218 end;
       
  2219 
       
  2220 function lc_getzoom(L : Plua_State) : LongInt; Cdecl;
       
  2221 begin
       
  2222     if CheckLuaParamCount(L, 0, 'GetZoom', '') then
       
  2223         lua_pushnumber(L, ZoomValue)
       
  2224     else
       
  2225         lua_pushnil(L);
       
  2226     lc_getzoom:= 1
       
  2227 end;
       
  2228 
       
  2229 function lc_setammo(L : Plua_State) : LongInt; Cdecl;
       
  2230 var np, at: LongInt;
       
  2231 const
       
  2232     call = 'SetAmmo';
       
  2233     params = 'ammoType, count, probability, delay [, numberInCrate]';
       
  2234 begin
       
  2235     if CheckAndFetchParamCount(L, 4, 5, call, params, np) then
       
  2236         begin
       
  2237         at:= LuaToAmmoTypeOrd(L, 1, call, params);
       
  2238         if at >= 0 then
       
  2239             begin
       
  2240             if np = 4 then
       
  2241                 ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), 1)
       
  2242             else
       
  2243                 ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
       
  2244             end;
       
  2245         end;
       
  2246     lc_setammo:= 0
       
  2247 end;
       
  2248 
       
  2249 function lc_setammodelay(L : Plua_State) : LongInt; Cdecl;
       
  2250 var at: LongInt;
       
  2251 const
       
  2252     call = 'SetAmmoDelay';
       
  2253     params = 'ammoType, delay';
       
  2254 begin
       
  2255     if CheckLuaParamCount(L, 2, call, params) then
       
  2256         begin
       
  2257         at:= LuaToAmmoTypeOrd(L, 1, call, params);
       
  2258         if at >= 0 then
       
  2259             ScriptSetAmmoDelay(TAmmoType(at), lua_tointeger(L, 2));
       
  2260         end;
       
  2261     lc_setammodelay:= 0
       
  2262 end;
       
  2263 
       
  2264 function lc_setammostore(L : Plua_State) : LongInt; Cdecl;
       
  2265 begin
       
  2266     if CheckLuaParamCount(L, 4, 'SetAmmoStore', 'loadouts, probabilities, delays, reinforments') then
       
  2267         begin
       
  2268         ScriptAmmoLoadout:= lua_tostring(L, 1);
       
  2269         ScriptAmmoProbability:= lua_tostring(L, 2);
       
  2270         ScriptAmmoDelay:= lua_tostring(L, 3);
       
  2271         ScriptAmmoReinforcement:= lua_tostring(L, 4);
       
  2272         end;
       
  2273     lc_setammostore:= 0
       
  2274 end;
       
  2275 
       
  2276 function lc_getrandom(L : Plua_State) : LongInt; Cdecl;
       
  2277 var m : LongInt;
       
  2278 begin
       
  2279     if CheckLuaParamCount(L, 1, 'GetRandom', 'number') then
       
  2280         begin
       
  2281         m:= lua_tointeger(L, 1);
       
  2282         if (m > 0) then
       
  2283             lua_pushinteger(L, GetRandom(m))
       
  2284         else
       
  2285             begin
       
  2286             LuaError('Lua: Tried to pass 0 to GetRandom!');
       
  2287             lua_pushnil(L);
       
  2288             end
       
  2289         end
       
  2290     else
       
  2291         lua_pushnil(L); // return value on stack (nil)
       
  2292     lc_getrandom:= 1
       
  2293 end;
       
  2294 
       
  2295 function lc_setwind(L : Plua_State) : LongInt; Cdecl;
       
  2296 begin
       
  2297     if CheckLuaParamCount(L, 1, 'SetWind', 'windSpeed') then
       
  2298         begin
       
  2299         cWindSpeed:= int2hwfloat(lua_tointeger(L, 1)) / 100 * cMaxWindSpeed;
       
  2300         cWindSpeedf:= SignAs(cWindSpeed,cWindSpeed).QWordValue / SignAs(_1,_1).QWordValue;
       
  2301         if cWindSpeed.isNegative then
       
  2302             CWindSpeedf := -cWindSpeedf;
       
  2303         AddVisualGear(0, 0, vgtSmoothWindBar);
       
  2304         end;
       
  2305     lc_setwind:= 0
       
  2306 end;
       
  2307 
       
  2308 function lc_maphasborder(L : Plua_State) : LongInt; Cdecl;
       
  2309 begin
       
  2310     if CheckLuaParamCount(L, 0, 'MapHasBorder', '') then
       
  2311         lua_pushboolean(L, hasBorder)
       
  2312     else
       
  2313         lua_pushnil(L);
       
  2314     lc_maphasborder:= 1
       
  2315 end;
       
  2316 
       
  2317 function lc_getgearradius(L : Plua_State) : LongInt; Cdecl;
       
  2318 var gear : PGear;
       
  2319 begin
       
  2320     if CheckLuaParamCount(L, 1, 'GetGearRadius', 'gearUid') then
       
  2321         begin
       
  2322         gear:= GearByUID(lua_tointeger(L, 1));
       
  2323         if gear <> nil then
       
  2324             lua_pushinteger(L, gear^.Radius)
       
  2325         else
       
  2326             lua_pushnil(L);
       
  2327         end
       
  2328     else
       
  2329         lua_pushnil(L); // return value on stack (nil)
       
  2330     lc_getgearradius:= 1
       
  2331 end;
       
  2332 
       
  2333 function lc_gethoghat(L : Plua_State): LongInt; Cdecl;
       
  2334 var gear : PGear;
       
  2335 begin
       
  2336     if CheckLuaParamCount(L, 1, 'GetHogHat', 'gearUid') then
       
  2337         begin
       
  2338         gear := GearByUID(lua_tointeger(L, 1));
       
  2339         if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
       
  2340             lua_pushstring(L, str2pchar(gear^.Hedgehog^.Hat))
       
  2341         else
       
  2342             lua_pushnil(L);
       
  2343         end
       
  2344     else
       
  2345         lua_pushnil(L);
       
  2346     lc_gethoghat := 1;
       
  2347 end;
       
  2348 
       
  2349 function lc_sethoghat(L : Plua_State) : LongInt; Cdecl;
       
  2350 var gear : PGear;
       
  2351     hat: ShortString;
       
  2352 begin
       
  2353     if CheckLuaParamCount(L, 2, 'SetHogHat', 'gearUid, hat') then
       
  2354         begin
       
  2355         gear:= GearByUID(lua_tointeger(L, 1));
       
  2356         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
       
  2357             begin
       
  2358             hat:= lua_tostring(L, 2);
       
  2359             gear^.Hedgehog^.Hat:= hat;
       
  2360             AddFileLog('Changed hat to: '+hat);
       
  2361             if (Length(hat) > 39) and (Copy(hat,1,8) = 'Reserved') and (Copy(hat,9,32) = gear^.Hedgehog^.Team^.PlayerHash) then
       
  2362                 LoadHedgehogHat(gear^.Hedgehog^, 'Reserved/' + Copy(hat,9,Length(hat)-8))
       
  2363             else
       
  2364                 LoadHedgehogHat(gear^.Hedgehog^, hat)
       
  2365             end
       
  2366         end;
       
  2367     lc_sethoghat:= 0;
       
  2368 end;
       
  2369 
       
  2370 function lc_placesprite(L : Plua_State) : LongInt; Cdecl;
       
  2371 var spr   : TSprite;
       
  2372     lf    : Word;
       
  2373     tint  : LongWord;
       
  2374     i, n : LongInt;
       
  2375     placed, behind, flipHoriz, flipVert : boolean;
       
  2376 const
       
  2377     call = 'PlaceSprite';
       
  2378     params = 'x, y, sprite, frameIdx, tint, behind, flipHoriz, flipVert, [, landFlag, ... ]';
       
  2379 begin
       
  2380     placed:= false;
       
  2381     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
       
  2382         begin
       
  2383         if not lua_isnoneornil(L, 5) then
       
  2384             tint := lua_tointeger(L, 5)
       
  2385         else tint := $FFFFFFFF;
       
  2386         if not lua_isnoneornil(L, 6) then
       
  2387             behind := lua_toboolean(L, 6)
       
  2388         else behind := false;
       
  2389         if not lua_isnoneornil(L, 7) then
       
  2390             flipHoriz := lua_toboolean(L, 7)
       
  2391         else flipHoriz := false;
       
  2392         if not lua_isnoneornil(L, 8) then
       
  2393             flipVert := lua_toboolean(L, 8)
       
  2394         else flipVert := false;
       
  2395         lf:= 0;
       
  2396 
       
  2397         // accept any amount of landflags, loop is never executed if n<9
       
  2398         for i:= 9 to n do
       
  2399             lf:= lf or lua_tointeger(L, i);
       
  2400 
       
  2401         n:= LuaToSpriteOrd(L, 3, call, params);
       
  2402         if n >= 0 then
       
  2403             begin
       
  2404             spr:= TSprite(n);
       
  2405             if SpritesData[spr].Surface = nil then
       
  2406                 LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
       
  2407             else
       
  2408                 placed:= ForcePlaceOnLand(
       
  2409                     lua_tointeger(L, 1) - SpritesData[spr].Width div 2,
       
  2410                     lua_tointeger(L, 2) - SpritesData[spr].Height div 2,
       
  2411                     spr, lua_tointeger(L, 4), lf, tint, behind, flipHoriz, flipVert);
       
  2412             end;
       
  2413         end;
       
  2414 
       
  2415     lua_pushboolean(L, placed);
       
  2416     lc_placesprite:= 1
       
  2417 end;
       
  2418 
       
  2419 function lc_erasesprite(L : Plua_State) : LongInt; Cdecl;
       
  2420 var spr   : TSprite;
       
  2421     lf    : Word;
       
  2422     i, n : LongInt;
       
  2423     eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert : boolean;
       
  2424 const
       
  2425     call = 'EraseSprite';
       
  2426     params = 'x, y, sprite, frameIdx, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert, [, landFlag, ... ]';
       
  2427 begin
       
  2428     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
       
  2429         begin
       
  2430         if not lua_isnoneornil(L, 5) then
       
  2431             eraseOnLFMatch := lua_toboolean(L, 5)
       
  2432         else eraseOnLFMatch := false;
       
  2433         if not lua_isnoneornil(L, 6) then
       
  2434             onlyEraseLF := lua_toboolean(L, 6)
       
  2435         else onlyEraseLF := false;
       
  2436         if not lua_isnoneornil(L, 7) then
       
  2437             flipHoriz := lua_toboolean(L, 7)
       
  2438         else flipHoriz := false;
       
  2439         if not lua_isnoneornil(L, 8) then
       
  2440             flipVert := lua_toboolean(L, 8)
       
  2441         else flipVert := false;
       
  2442         lf:= 0;
       
  2443 
       
  2444         // accept any amount of landflags, loop is never executed if n<9
       
  2445         for i:= 9 to n do
       
  2446             lf:= lf or lua_tointeger(L, i);
       
  2447 
       
  2448         n:= LuaToSpriteOrd(L, 3, call, params);
       
  2449         if n >= 0 then
       
  2450             begin
       
  2451             spr:= TSprite(n);
       
  2452             if SpritesData[spr].Surface = nil then
       
  2453                 LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
       
  2454             else
       
  2455                 EraseLand(
       
  2456                     lua_tointeger(L, 1) - SpritesData[spr].Width div 2,
       
  2457                     lua_tointeger(L, 2) - SpritesData[spr].Height div 2,
       
  2458                     spr, lua_tointeger(L, 4), lf, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert);
       
  2459             end;
       
  2460         end;
       
  2461     lc_erasesprite:= 0
       
  2462 end;
       
  2463 
       
  2464 function lc_placegirder(L : Plua_State) : LongInt; Cdecl;
       
  2465 var placed: boolean;
       
  2466 begin
       
  2467     placed:= false;
       
  2468     if CheckLuaParamCount(L, 3, 'PlaceGirder', 'x, y, frameIdx') then
       
  2469         placed:= TryPlaceOnLandSimple(
       
  2470             lua_tointeger(L, 1) - SpritesData[sprAmGirder].Width div 2,
       
  2471             lua_tointeger(L, 2) - SpritesData[sprAmGirder].Height div 2,
       
  2472             sprAmGirder, lua_tointeger(L, 3), true, false);
       
  2473 
       
  2474     lua_pushboolean(L, placed);
       
  2475     lc_placegirder:= 1
       
  2476 end;
       
  2477 
       
  2478 function lc_placerubber(L : Plua_State) : LongInt; Cdecl;
       
  2479 var placed: boolean;
       
  2480 begin
       
  2481     placed:= false;
       
  2482     if CheckLuaParamCount(L, 3, 'PlaceRubber', 'x, y, frameIdx') then
       
  2483         placed:= TryPlaceOnLand(
       
  2484             lua_tointeger(L, 1) - SpritesData[sprAmRubber].Width div 2,
       
  2485             lua_tointeger(L, 2) - SpritesData[sprAmRubber].Height div 2,
       
  2486             sprAmRubber, lua_tointeger(L, 3), true, lfBouncy);
       
  2487 
       
  2488     lua_pushboolean(L, placed);
       
  2489     lc_placerubber:= 1
       
  2490 end;
       
  2491 
       
  2492 function lc_getcurammotype(L : Plua_State): LongInt; Cdecl;
       
  2493 begin
       
  2494     if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, 'GetCurAmmoType', '')) then
       
  2495         lua_pushinteger(L, ord(CurrentHedgehog^.CurAmmoType))
       
  2496     else
       
  2497         lua_pushinteger(L, ord(amNothing));
       
  2498     lc_getcurammotype := 1;
       
  2499 end;
       
  2500 
       
  2501 function lc_savecampaignvar(L : Plua_State): LongInt; Cdecl;
       
  2502 begin
       
  2503     if CheckLuaParamCount(L, 2, 'SaveCampaignVar', 'varname, value') then
       
  2504         SendIPC('V!' + lua_tostring(L, 1) + ' ' + lua_tostring(L, 2) + #0);
       
  2505     lc_savecampaignvar := 0;
       
  2506 end;
       
  2507 
       
  2508 function lc_getcampaignvar(L : Plua_State): LongInt; Cdecl;
       
  2509 begin
       
  2510     if CheckLuaParamCount(L, 1, 'GetCampaignVar', 'varname') then
       
  2511         SendIPCAndWaitReply('V?' + lua_tostring(L, 1) + #0);
       
  2512     lua_pushstring(L, str2pchar(CampaignVariable));
       
  2513     lc_getcampaignvar := 1;
       
  2514 end;
       
  2515 
       
  2516 function lc_hidehog(L: Plua_State): LongInt; Cdecl;
       
  2517 var gear: PGear;
       
  2518 begin
       
  2519     if CheckLuaParamCount(L, 1, 'HideHog', 'gearUid') then
       
  2520         begin
       
  2521         gear:= GearByUID(lua_tointeger(L, 1));
       
  2522         HideHog(gear^.hedgehog)
       
  2523         end;
       
  2524     lc_hidehog := 0;
       
  2525 end;
       
  2526 
       
  2527 function lc_restorehog(L: Plua_State): LongInt; Cdecl;
       
  2528 var i, h: LongInt;
       
  2529     uid: LongWord;
       
  2530 begin
       
  2531     if CheckLuaParamCount(L, 1, 'RestoreHog', 'gearUid') then
       
  2532         begin
       
  2533         uid:= LongWord(lua_tointeger(L, 1));
       
  2534         if TeamsCount > 0 then
       
  2535             for i:= 0 to Pred(TeamsCount) do
       
  2536                 for h:= 0 to cMaxHHIndex do
       
  2537                     if (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil) and (TeamsArray[i]^.Hedgehogs[h].GearHidden^.uid = uid) then
       
  2538                         begin
       
  2539                         RestoreHog(@TeamsArray[i]^.Hedgehogs[h]);
       
  2540                         exit(0)
       
  2541                         end
       
  2542         end;
       
  2543     lc_restorehog := 0;
       
  2544 end;
       
  2545 
       
  2546 // boolean TestRectForObstacle(x1, y1, x2, y2, landOnly)
       
  2547 function lc_testrectforobstacle(L : Plua_State) : LongInt; Cdecl;
       
  2548 var rtn: Boolean;
       
  2549 begin
       
  2550     if CheckLuaParamCount(L, 5, 'TestRectForObstacle', 'x1, y1, x2, y2, landOnly') then
       
  2551         begin
       
  2552         rtn:= TestRectangleForObstacle(
       
  2553                     lua_tointeger(L, 1),
       
  2554                     lua_tointeger(L, 2),
       
  2555                     lua_tointeger(L, 3),
       
  2556                     lua_tointeger(L, 4),
       
  2557                     lua_toboolean(L, 5)
       
  2558                     );
       
  2559         lua_pushboolean(L, rtn);
       
  2560         end
       
  2561     else
       
  2562         lua_pushnil(L); // return value on stack (nil)
       
  2563     lc_testrectforobstacle:= 1
       
  2564 end;
       
  2565 
       
  2566 
       
  2567 function lc_getgravity(L : Plua_State) : LongInt; Cdecl;
       
  2568 begin
       
  2569     if CheckLuaParamCount(L, 0, 'GetGravity', '') then
       
  2570         lua_pushinteger(L, hwRound(SignAs(_0_5, cGravity) + (cGravity * 50 / cMaxWindSpeed)));
       
  2571     lc_getgravity:= 1
       
  2572 end;
       
  2573 
       
  2574 function lc_setgravity(L : Plua_State) : LongInt; Cdecl;
       
  2575 begin
       
  2576     if CheckLuaParamCount(L, 1, 'SetGravity', 'percent') then
       
  2577         begin
       
  2578         cGravity:= _0_02 * lua_tointeger(L, 1) * cMaxWindSpeed;
       
  2579         cGravityf:= 0.00025 * lua_tointeger(L, 1) * 0.02
       
  2580         end;
       
  2581     lc_setgravity:= 0
       
  2582 end;
       
  2583 
       
  2584 function lc_setwaterline(L : Plua_State) : LongInt; Cdecl;
       
  2585 var iterator: PGear;
       
  2586 begin
       
  2587     if CheckLuaParamCount(L, 1, 'SetWaterLine', 'waterline') then
       
  2588         begin
       
  2589         cWaterLine:= lua_tointeger(L,1);
       
  2590         AllInactive:= false;
       
  2591         iterator:= GearsList;
       
  2592         while iterator <> nil do
       
  2593             begin
       
  2594             if not (iterator^.Kind in [gtPortal, gtAirAttack]) and (iterator^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) then
       
  2595                 begin
       
  2596                 iterator^.Active:= true;
       
  2597                 if iterator^.dY.QWordValue = 0 then iterator^.dY.isNegative:= false;
       
  2598                 iterator^.State:= iterator^.State or gstMoving;
       
  2599                 DeleteCI(iterator)
       
  2600                 end;
       
  2601             iterator:= iterator^.NextGear
       
  2602             end
       
  2603         end;
       
  2604     lc_setwaterline:= 0
       
  2605 end;
       
  2606 
       
  2607 function lc_setgearaihints(L : Plua_State) : LongInt; Cdecl;
       
  2608 var gear: PGear;
       
  2609 begin
       
  2610     if CheckLuaParamCount(L, 2, 'SetAIHintOnGear', 'gearUid, aiHints') then
       
  2611         begin
       
  2612         gear:= GearByUID(lua_tointeger(L, 1));
       
  2613         if gear <> nil then
       
  2614             gear^.aihints:= lua_tointeger(L, 2);
       
  2615         end;
       
  2616     lc_setgearaihints:= 0
       
  2617 end;
       
  2618 
       
  2619 
       
  2620 function lc_hedgewarsscriptload(L : Plua_State) : LongInt; Cdecl;
       
  2621 begin
       
  2622     if CheckLuaParamCount(L, 1, 'HedgewarsScriptLoad', 'scriptPath') then
       
  2623         ScriptLoad(lua_tostring(L, 1))
       
  2624     else
       
  2625         lua_pushnil(L);
       
  2626     lc_hedgewarsscriptload:= 0;
       
  2627 end;
       
  2628 
       
  2629 
       
  2630 function lc_declareachievement(L : Plua_State) : LongInt; Cdecl;
       
  2631 begin
       
  2632     if CheckLuaParamCount(L, 4, 'DeclareAchievement', 'achievementId, teamname, location, value') then
       
  2633         declareAchievement(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), lua_tointeger(L, 4));
       
  2634     lc_declareachievement:= 0
       
  2635 end;
       
  2636 
       
  2637 function lc_getammoname(L : Plua_state) : LongInt; Cdecl;
       
  2638 var np, at: LongInt;
       
  2639     ignoreOverwrite: Boolean;
       
  2640 const call = 'GetAmmoName';
       
  2641       params = 'ammoType [, ignoreOverwrite ]';
       
  2642 begin
       
  2643     if CheckAndFetchParamCountRange(L, 1, 2, call, params, np) then
       
  2644         begin
       
  2645         at:= LuaToAmmoTypeOrd(L, 1, call, params);                                                                                                   
       
  2646         ignoreOverwrite := false;
       
  2647         if np > 1 then
       
  2648             ignoreOverwrite := lua_toboolean(L, 2);
       
  2649         if at >= 0 then   
       
  2650             if (not ignoreOverwrite) and (length(trluaammo[Ammoz[TAmmoType(at)].NameId]) > 0) then
       
  2651                 lua_pushstring(L, PChar(trluaammo[Ammoz[TAmmoType(at)].NameId]))
       
  2652             else
       
  2653                 lua_pushstring(L, PChar(trammo[Ammoz[TAmmoType(at)].NameId]));
       
  2654         end
       
  2655     else
       
  2656         lua_pushnil(L);
       
  2657     lc_getammoname:= 1;
       
  2658 end;
       
  2659 
       
  2660 function lc_startghostpoints(L : Plua_State) : LongInt; Cdecl;
       
  2661 begin
       
  2662     if CheckLuaParamCount(L, 1, 'StartGhostPoints', 'count') then
       
  2663         startGhostPoints(lua_tointeger(L, 1));
       
  2664     lc_startghostpoints:= 0
       
  2665 end;
       
  2666 
       
  2667 function lc_dumppoint(L : Plua_State) : LongInt; Cdecl;
       
  2668 begin
       
  2669     if CheckLuaParamCount(L, 2, 'DumpPoint', 'x, y') then
       
  2670         dumpPoint(lua_tointeger(L, 1), lua_tointeger(L, 2));
       
  2671     lc_dumppoint:= 0
       
  2672 end;
       
  2673 
       
  2674 
       
  2675 procedure ScriptFlushPoints();
       
  2676 begin
       
  2677     ParseCommand('draw ' + PointsBuffer, true, true);
       
  2678     PointsBuffer:= '';
       
  2679 end;
       
  2680 
       
  2681 
       
  2682 function lc_addPoint(L : Plua_State) : LongInt; Cdecl;
       
  2683 var np, param: LongInt;
       
  2684 begin
       
  2685     if CheckAndFetchParamCountRange(L, 2, 4, 'AddPoint', 'x, y [, width [, erase] ]', np) then
       
  2686         begin
       
  2687         // x
       
  2688         param:= LongInt(lua_tointeger(L,1));
       
  2689         PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
       
  2690         PointsBuffer:= PointsBuffer + char((param and $FF));
       
  2691         // y
       
  2692         param:= LongInt(lua_tointeger(L,2));
       
  2693         PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
       
  2694         PointsBuffer:= PointsBuffer + char((param and $FF));
       
  2695         // width
       
  2696         if np > 2 then
       
  2697             begin
       
  2698             param:= lua_tointeger(L,3);
       
  2699             param:= (param or $80);
       
  2700             // erase
       
  2701             if (np > 3) and lua_toboolean(L, 4) then
       
  2702                 param:= (param or $40);
       
  2703             PointsBuffer:= PointsBuffer + char(param);
       
  2704             end
       
  2705         // no width defined
       
  2706         else
       
  2707             PointsBuffer:= PointsBuffer + char(0);
       
  2708 
       
  2709         // flush before shortstring limit length is reached
       
  2710         if length(PointsBuffer) > 245 then
       
  2711             ScriptFlushPoints();
       
  2712         end;
       
  2713     lc_addPoint:= 0
       
  2714 end;
       
  2715 
       
  2716 
       
  2717 function lc_flushPoints(L : Plua_State) : LongInt; Cdecl;
       
  2718 begin
       
  2719     if CheckLuaParamCount(L, 0, 'FlushPoints', '') then
       
  2720         if length(PointsBuffer) > 0 then
       
  2721             ScriptFlushPoints();
       
  2722     lc_flushPoints:= 0
       
  2723 end;
       
  2724 
       
  2725 // stuff for lua tests
       
  2726 function lc_endluatest(L : Plua_State) : LongInt; Cdecl;
       
  2727 var rstring: shortstring;
       
  2728 const
       
  2729     call = 'EndLuaTest';
       
  2730     params = 'TEST_SUCCESSFUL or TEST_FAILED';
       
  2731 begin
       
  2732     if CheckLuaParamCount(L, 1, call, params) then
       
  2733         begin
       
  2734 
       
  2735         case lua_tointeger(L, 1) of
       
  2736             HaltTestSuccess : rstring:= 'Success';
       
  2737             HaltTestFailed: rstring:= 'FAILED';
       
  2738         else
       
  2739             begin
       
  2740             LuaCallError('Parameter must be either ' + params, call, params);
       
  2741             exit(0);
       
  2742             end;
       
  2743         end;
       
  2744 
       
  2745         if cTestLua then
       
  2746             begin
       
  2747             WriteLnToConsole('Lua test finished, result: ' + rstring);
       
  2748             halt(lua_tointeger(L, 1));
       
  2749             end
       
  2750         else LuaError('Not in lua test mode, engine will keep running. Reported test result: ' + rstring);
       
  2751 
       
  2752         end;
       
  2753 
       
  2754     lc_endluatest:= 0;
       
  2755 end;
       
  2756 ///////////////////
       
  2757 
       
  2758 procedure ScriptPrintStack;
       
  2759 var n, i : LongInt;
       
  2760 begin
       
  2761     n:= lua_gettop(luaState);
       
  2762     WriteLnToConsole('Lua: Stack (' + inttostr(n) + ' elements):');
       
  2763     for i:= 1 to n do
       
  2764         if not lua_isboolean(luaState, i) then
       
  2765             WriteLnToConsole('Lua:  ' + inttostr(i) + ': ' + lua_tostring(luaState, i))
       
  2766         else if lua_toboolean(luaState, i) then
       
  2767             WriteLnToConsole('Lua:  ' + inttostr(i) + ': true')
       
  2768         else
       
  2769             WriteLnToConsole('Lua:  ' + inttostr(i) + ': false');
       
  2770 end;
       
  2771 
       
  2772 procedure ScriptClearStack;
       
  2773 begin
       
  2774     lua_settop(luaState, 0)
       
  2775 end;
       
  2776 
       
  2777 procedure ScriptSetNil(name : shortstring);
       
  2778 begin
       
  2779     lua_pushnil(luaState);
       
  2780     lua_setglobal(luaState, Str2PChar(name));
       
  2781 end;
       
  2782 
       
  2783 procedure ScriptSetInteger(name : shortstring; value : LongInt);
       
  2784 begin
       
  2785     lua_pushinteger(luaState, value);
       
  2786     lua_setglobal(luaState, Str2PChar(name));
       
  2787 end;
       
  2788 
       
  2789 procedure ScriptSetString(name : shortstring; value : shortstring);
       
  2790 begin
       
  2791     lua_pushstring(luaState, Str2PChar(value));
       
  2792     lua_setglobal(luaState, Str2PChar(name));
       
  2793 end;
       
  2794 
       
  2795 function ScriptGetInteger(name : shortstring) : LongInt;
       
  2796 begin
       
  2797     lua_getglobal(luaState, Str2PChar(name));
       
  2798     ScriptGetInteger:= lua_tointeger(luaState, -1);
       
  2799     lua_pop(luaState, 1);
       
  2800 end;
       
  2801 
       
  2802 function ScriptGetString(name : shortstring) : shortstring;
       
  2803 begin
       
  2804     lua_getglobal(luaState, Str2PChar(name));
       
  2805     ScriptGetString:= lua_tostring(luaState, -1);
       
  2806     lua_pop(luaState, 1);
       
  2807 end;
       
  2808 
       
  2809 procedure ScriptOnPreviewInit;
       
  2810 begin
       
  2811 // not required if there is no script to run
       
  2812 if not ScriptLoaded then
       
  2813     exit;
       
  2814 
       
  2815 ScriptSetString('Seed', cSeed);
       
  2816 ScriptSetInteger('TemplateFilter', cTemplateFilter);
       
  2817 ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
       
  2818 ScriptSetInteger('MapGen', ord(cMapGen));
       
  2819 ScriptSetInteger('MapFeatureSize', cFeatureSize);
       
  2820 
       
  2821 ScriptCall('onPreviewInit');
       
  2822 
       
  2823 // pop game variables
       
  2824 ParseCommand('seed ' + ScriptGetString('Seed'), true, true);
       
  2825 cTemplateFilter  := ScriptGetInteger('TemplateFilter');
       
  2826 LuaTemplateNumber:= ScriptGetInteger('TemplateNumber');
       
  2827 cMapGen          := TMapGen(ScriptGetInteger('MapGen'));
       
  2828 cFeatureSize     := ScriptGetInteger('MapFeatureSize');
       
  2829 end;
       
  2830 
       
  2831 procedure ScriptOnGameInit;
       
  2832 var i, j, k: LongInt;
       
  2833 begin
       
  2834 // not required if there is no script to run
       
  2835 if not ScriptLoaded then
       
  2836     exit;
       
  2837 
       
  2838 // push game variables so they may be modified by the script
       
  2839 ScriptSetInteger('CursorX', CursorPoint.X);
       
  2840 ScriptSetInteger('CursorY', CursorPoint.Y);
       
  2841 ScriptSetInteger('BorderColor', ExplosionBorderColor);
       
  2842 ScriptSetInteger('GameFlags', GameFlags);
       
  2843 ScriptSetInteger('WorldEdge', ord(WorldEdge));
       
  2844 ScriptSetString('Seed', cSeed);
       
  2845 ScriptSetInteger('TemplateFilter', cTemplateFilter);
       
  2846 ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
       
  2847 ScriptSetInteger('MapGen', ord(cMapGen));
       
  2848 ScriptSetInteger('MapFeatureSize', cFeatureSize);
       
  2849 ScriptSetInteger('ScreenHeight', cScreenHeight);
       
  2850 ScriptSetInteger('ScreenWidth', cScreenWidth);
       
  2851 ScriptSetInteger('TurnTime', cHedgehogTurnTime);
       
  2852 ScriptSetInteger('CaseFreq', cCaseFactor);
       
  2853 ScriptSetInteger('HealthCaseProb', cHealthCaseProb);
       
  2854 ScriptSetInteger('HealthCaseAmount', cHealthCaseAmount);
       
  2855 ScriptSetInteger('DamagePercent', cDamagePercent);
       
  2856 ScriptSetInteger('RopePercent', cRopePercent);
       
  2857 ScriptSetInteger('MinesNum', cLandMines);
       
  2858 ScriptSetInteger('MinesTime', cMinesTime);
       
  2859 ScriptSetInteger('MineDudPercent', cMineDudPercent);
       
  2860 ScriptSetInteger('AirMinesNum', cAirMines);
       
  2861 ScriptSetInteger('Explosives', cExplosives);
       
  2862 ScriptSetInteger('Delay', cInactDelay);
       
  2863 ScriptSetInteger('Ready', cReadyDelay);
       
  2864 ScriptSetInteger('SuddenDeathTurns', cSuddenDTurns);
       
  2865 ScriptSetInteger('WaterRise', cWaterRise);
       
  2866 ScriptSetInteger('HealthDecrease', cHealthDecrease);
       
  2867 ScriptSetInteger('GetAwayTime', cGetAwayTime);
       
  2868 ScriptSetString('Map', cMapName);
       
  2869 ScriptSetString('Theme', Theme);
       
  2870 ScriptSetString('Goals', '');
       
  2871 
       
  2872 ScriptCall('onGameInit');
       
  2873 
       
  2874 // pop game variables
       
  2875 ParseCommand('seed ' + ScriptGetString('Seed'), true, true);
       
  2876 cTemplateFilter  := ScriptGetInteger('TemplateFilter');
       
  2877 LuaTemplateNumber:= ScriptGetInteger('TemplateNumber');
       
  2878 cMapGen          := TMapGen(ScriptGetInteger('MapGen'));
       
  2879 cFeatureSize     := ScriptGetInteger('MapFeatureSize');
       
  2880 GameFlags        := ScriptGetInteger('GameFlags');
       
  2881 WorldEdge        := TWorldEdge(ScriptGetInteger('WorldEdge'));
       
  2882 cHedgehogTurnTime:= ScriptGetInteger('TurnTime');
       
  2883 cCaseFactor      := ScriptGetInteger('CaseFreq');
       
  2884 cHealthCaseProb  := ScriptGetInteger('HealthCaseProb');
       
  2885 cHealthCaseAmount:= ScriptGetInteger('HealthCaseAmount');
       
  2886 cDamagePercent   := ScriptGetInteger('DamagePercent');
       
  2887 cRopePercent     := ScriptGetInteger('RopePercent');
       
  2888 cLandMines       := ScriptGetInteger('MinesNum');
       
  2889 cMinesTime       := ScriptGetInteger('MinesTime');
       
  2890 cMineDudPercent  := ScriptGetInteger('MineDudPercent');
       
  2891 cAirMines        := ScriptGetInteger('AirMinesNum');
       
  2892 cExplosives      := ScriptGetInteger('Explosives');
       
  2893 cInactDelay      := ScriptGetInteger('Delay');
       
  2894 cReadyDelay      := ScriptGetInteger('Ready');
       
  2895 cSuddenDTurns    := ScriptGetInteger('SuddenDeathTurns');
       
  2896 cWaterRise       := ScriptGetInteger('WaterRise');
       
  2897 cHealthDecrease  := ScriptGetInteger('HealthDecrease');
       
  2898 cGetAwayTime     := ScriptGetInteger('GetAwayTime');
       
  2899 
       
  2900 if cMapName <> ScriptGetString('Map') then
       
  2901     ParseCommand('map ' + ScriptGetString('Map'), true, true);
       
  2902 if ScriptGetString('Theme') <> '' then
       
  2903     ParseCommand('theme ' + ScriptGetString('Theme'), true, true);
       
  2904 LuaGoals:= ScriptGetString('Goals');
       
  2905 
       
  2906 // Support lua changing the ammo layout - assume all hogs have same ammo, note this might leave a few ammo stores lying around.
       
  2907 k:= 0;
       
  2908 if (GameFlags and gfSharedAmmo) <> 0 then
       
  2909     for i:= 0 to Pred(ClansCount) do
       
  2910         for j:= 0 to Pred(ClansArray[i]^.TeamsNumber) do
       
  2911             for k:= 0 to Pred(ClansArray[i]^.Teams[j]^.HedgehogsNumber) do
       
  2912                 ClansArray[i]^.Teams[j]^.Hedgehogs[k].AmmoStore:= i
       
  2913 else if (GameFlags and gfPerHogAmmo) <> 0 then
       
  2914     for i:= 0 to Pred(TeamsCount) do
       
  2915         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
       
  2916             begin
       
  2917             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= k;
       
  2918             if StoreCnt-1 < k then AddAmmoStore;
       
  2919             inc(k)
       
  2920             end
       
  2921 else
       
  2922     for i:= 0 to Pred(TeamsCount) do
       
  2923         begin
       
  2924         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
       
  2925             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= k;
       
  2926         if StoreCnt-1 < k then AddAmmoStore;
       
  2927         inc(k)
       
  2928         end;
       
  2929 if ScriptExists('onAmmoStoreInit') or ScriptExists('onNewAmmoStore') then
       
  2930     begin
       
  2931     // reset ammostore (quite unclean, but works?)
       
  2932     uAmmos.freeModule;
       
  2933     uAmmos.initModule;
       
  2934     if ScriptExists('onAmmoStoreInit') then
       
  2935         begin
       
  2936         ScriptPrepareAmmoStore;
       
  2937         ScriptCall('onAmmoStoreInit');
       
  2938         SetAmmoLoadout(ScriptAmmoLoadout);
       
  2939         SetAmmoProbability(ScriptAmmoProbability);
       
  2940         SetAmmoDelay(ScriptAmmoDelay);
       
  2941         SetAmmoReinforcement(ScriptAmmoReinforcement)
       
  2942         end;
       
  2943     ScriptApplyAmmoStore
       
  2944     end;
       
  2945 
       
  2946 ScriptSetInteger('ClansCount', ClansCount);
       
  2947 ScriptSetInteger('TeamsCount', TeamsCount);
       
  2948 mapDims:= false
       
  2949 end;
       
  2950 
       
  2951 
       
  2952 // Update values of screen dimensions and allow script to react to resolution change
       
  2953 procedure ScriptOnScreenResize();
       
  2954 begin
       
  2955 ScriptSetInteger('ScreenHeight', cScreenHeight);
       
  2956 ScriptSetInteger('ScreenWidth', cScreenWidth);
       
  2957 ScriptCall('onScreenResize');
       
  2958 end;
       
  2959 
       
  2960 // custom script loader via physfs, passed to lua_load
       
  2961 const BUFSIZE = 1024;
       
  2962 
       
  2963 procedure ScriptLoad(name : shortstring);
       
  2964 var ret : LongInt;
       
  2965       s : shortstring;
       
  2966       f : PFSFile;
       
  2967     buf : array[0..Pred(BUFSIZE)] of byte;
       
  2968 //lua_buf : luaL_Buffer;
       
  2969 begin
       
  2970 s:= cPathz[ptData] + name;
       
  2971 if not pfsExists(s) then
       
  2972     begin
       
  2973     AddFileLog('[LUA] Script not found: ' + name);
       
  2974     exit;
       
  2975     end;
       
  2976 
       
  2977 f:= pfsOpenRead(s);
       
  2978 if f = nil then
       
  2979     exit;
       
  2980 
       
  2981 physfsReaderSetBuffer(@buf);
       
  2982 ret:= lua_load(luaState, @physfsReader, f, Str2PChar(s));
       
  2983 pfsClose(f);
       
  2984 
       
  2985 if ret <> 0 then
       
  2986     begin
       
  2987     LuaError('Failed to load ' + name + '(error ' + IntToStr(ret) + ')');
       
  2988     LuaError(lua_tostring(luaState, -1));
       
  2989     end
       
  2990 else
       
  2991     begin
       
  2992     WriteLnToConsole('Lua: ' + name + ' loaded');
       
  2993     // dump and hash all functions currently known by lua
       
  2994     // use hash to salt map hash
       
  2995 // init buffer
       
  2996 //luaL_buffinit(luaState, @lua_buf);
       
  2997 //lua_dump(luaState, @lua_dump_digester, @lua_buf);
       
  2998 // cleanup buffer
       
  2999 //luaL_pushresult(@lua_buf);
       
  3000     // --
       
  3001     // could first read the file, then hash it, then use load_string
       
  3002     // call the script file
       
  3003     lua_pcall(luaState, 0, 0, 0);
       
  3004     ScriptLoaded:= true
       
  3005     end;
       
  3006 hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp'));
       
  3007 end;
       
  3008 
       
  3009 procedure SetGlobals;
       
  3010 begin
       
  3011 ScriptSetInteger('TurnTimeLeft', TurnTimeLeft);
       
  3012 ScriptSetInteger('GameTime', GameTicks);
       
  3013 ScriptSetInteger('TotalRounds', TotalRounds);
       
  3014 ScriptSetInteger('WaterLine', cWaterLine);
       
  3015 if isCursorVisible and (not bShowAmmoMenu) then
       
  3016     begin
       
  3017     if (prevCursorPoint.X <> CursorPoint.X) or
       
  3018        (prevCursorPoint.Y <> CursorPoint.Y) then
       
  3019         begin
       
  3020         ScriptSetInteger('CursorX', CursorPoint.X - WorldDx);
       
  3021         ScriptSetInteger('CursorY', cScreenHeight - CursorPoint.Y- WorldDy);
       
  3022         prevCursorPoint.X:= CursorPoint.X;
       
  3023         prevCursorPoint.Y:= CursorPoint.Y;
       
  3024         end
       
  3025     end
       
  3026 else
       
  3027     begin
       
  3028     ScriptSetInteger('CursorX', NoPointX);
       
  3029     ScriptSetInteger('CursorY', NoPointX);
       
  3030     prevCursorPoint.X:= NoPointX;
       
  3031     prevCursorPoint.Y:= NoPointX
       
  3032     end;
       
  3033 
       
  3034 if not mapDims then
       
  3035     begin
       
  3036     mapDims:= true;
       
  3037     ScriptSetInteger('LAND_WIDTH', LAND_WIDTH);
       
  3038     ScriptSetInteger('LAND_HEIGHT', LAND_HEIGHT);
       
  3039     ScriptSetInteger('LeftX', leftX);
       
  3040     ScriptSetInteger('RightX', rightX);
       
  3041     ScriptSetInteger('TopY', topY)
       
  3042     end;
       
  3043 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) then
       
  3044     ScriptSetInteger('CurrentHedgehog', CurrentHedgehog^.Gear^.UID)
       
  3045 else
       
  3046     ScriptSetNil('CurrentHedgehog');
       
  3047 end;
       
  3048 
       
  3049 procedure GetGlobals;
       
  3050 begin
       
  3051 // TODO
       
  3052 // Use setters instead, because globals should be read-only!
       
  3053 // Otherwise globals might be changed by Lua, but then unexpectatly overwritten by engine when a ScriptCall is triggered by whatever Lua is doing!
       
  3054 // Sure, one could work around that in engine (e.g. by setting writable globals in SetGlobals only when their engine-side value has actually changed since SetGlobals was called the last time...), but things just get messier and messier then.
       
  3055 // It is inconsistent anyway to have some globals be read-only and others not with no indication whatsoever.
       
  3056 // -- sheepluva
       
  3057 TurnTimeLeft:= ScriptGetInteger('TurnTimeLeft');
       
  3058 end;
       
  3059 
       
  3060 procedure ScriptCall(fname : shortstring);
       
  3061 begin
       
  3062 if (not ScriptLoaded) or (not ScriptExists(fname)) then
       
  3063     exit;
       
  3064 SetGlobals;
       
  3065 lua_getglobal(luaState, Str2PChar(fname));
       
  3066 if lua_pcall(luaState, 0, 0, 0) <> 0 then
       
  3067     begin
       
  3068     LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1));
       
  3069     lua_pop(luaState, 1)
       
  3070     end;
       
  3071 GetGlobals;
       
  3072 end;
       
  3073 
       
  3074 (*
       
  3075 function ParseCommandOverride(key, value : shortstring) : shortstring;
       
  3076 begin
       
  3077 ParseCommandOverride:= value;
       
  3078 if not ScriptExists('ParseCommandOverride') then
       
  3079     exit;
       
  3080 lua_getglobal(luaState, Str2PChar('ParseCommandOverride'));
       
  3081 lua_pushstring(luaState, Str2PChar(key));
       
  3082 lua_pushstring(luaState, Str2PChar(value));
       
  3083 if lua_pcall(luaState, 2, 1, 0) <> 0 then
       
  3084     begin
       
  3085     LuaError('Lua: Error while calling ParseCommandOverride: ' + lua_tostring(luaState, -1));
       
  3086     lua_pop(luaState, 1)
       
  3087     end
       
  3088 else
       
  3089     begin
       
  3090     ParseCommandOverride:= lua_tostring(luaState, -1);
       
  3091     lua_pop(luaState, 1)
       
  3092     end;
       
  3093 end;
       
  3094 *)
       
  3095 
       
  3096 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
       
  3097 begin
       
  3098 ScriptCall:= ScriptCall(fname, par1, 0, 0, 0)
       
  3099 end;
       
  3100 
       
  3101 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
       
  3102 begin
       
  3103 ScriptCall:= ScriptCall(fname, par1, par2, 0, 0)
       
  3104 end;
       
  3105 
       
  3106 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
       
  3107 begin
       
  3108 ScriptCall:= ScriptCall(fname, par1, par2, par3, 0)
       
  3109 end;
       
  3110 
       
  3111 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
       
  3112 begin
       
  3113 if (not ScriptLoaded) or (not ScriptExists(fname)) then
       
  3114     exit(0);
       
  3115 SetGlobals;
       
  3116 lua_getglobal(luaState, Str2PChar(fname));
       
  3117 lua_pushinteger(luaState, par1);
       
  3118 lua_pushinteger(luaState, par2);
       
  3119 lua_pushinteger(luaState, par3);
       
  3120 lua_pushinteger(luaState, par4);
       
  3121 ScriptCall:= 0;
       
  3122 if lua_pcall(luaState, 4, 1, 0) <> 0 then
       
  3123     begin
       
  3124     LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1));
       
  3125     lua_pop(luaState, 1)
       
  3126     end
       
  3127 else
       
  3128     begin
       
  3129     ScriptCall:= lua_tointeger(luaState, -1);
       
  3130     lua_pop(luaState, 1)
       
  3131     end;
       
  3132 GetGlobals;
       
  3133 end;
       
  3134 
       
  3135 function ScriptExists(fname : shortstring) : boolean;
       
  3136 begin
       
  3137 if not ScriptLoaded then
       
  3138     begin
       
  3139     ScriptExists:= false;
       
  3140     exit
       
  3141     end;
       
  3142 lua_getglobal(luaState, Str2PChar(fname));
       
  3143 ScriptExists:= not lua_isnoneornil(luaState, -1);
       
  3144 lua_pop(luaState, 1)
       
  3145 end;
       
  3146 
       
  3147 procedure ScriptPrepareAmmoStore;
       
  3148 var i: ShortInt;
       
  3149 begin
       
  3150 ScriptAmmoLoadout:= '';
       
  3151 ScriptAmmoDelay:= '';
       
  3152 ScriptAmmoProbability:= '';
       
  3153 ScriptAmmoReinforcement:= '';
       
  3154 for i:=1 to ord(High(TAmmoType)) do
       
  3155     begin
       
  3156     ScriptAmmoLoadout:= ScriptAmmoLoadout + '0';
       
  3157     ScriptAmmoProbability:= ScriptAmmoProbability + '0';
       
  3158     ScriptAmmoDelay:= ScriptAmmoDelay + '0';
       
  3159     ScriptAmmoReinforcement:= ScriptAmmoReinforcement + '0';
       
  3160     end;
       
  3161 end;
       
  3162 
       
  3163 procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte);
       
  3164 begin
       
  3165 //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
       
  3166 if (ord(ammo) < 1) or (count > 9) or (probability > 8) or (delay > 9) or (reinforcement > 8) then
       
  3167     exit;
       
  3168 ScriptAmmoLoadout[ord(ammo)]:= inttostr(count)[1];
       
  3169 ScriptAmmoProbability[ord(ammo)]:= inttostr(probability)[1];
       
  3170 ScriptSetAmmoDelay(ammo, delay);
       
  3171 ScriptAmmoReinforcement[ord(ammo)]:= inttostr(reinforcement)[1];
       
  3172 end;
       
  3173 
       
  3174 procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: Byte);
       
  3175 begin
       
  3176 // change loadout string if ammo store has not been initialized yet
       
  3177 if (StoreCnt = 0) then
       
  3178 begin
       
  3179     if (delay <= 9) then
       
  3180         ScriptAmmoDelay[ord(ammo)]:= inttostr(delay)[1];
       
  3181 end
       
  3182 // change 'live' delay values
       
  3183 else if (CurrentTeam <> nil) then
       
  3184         ammoz[ammo].SkipTurns:= CurrentTeam^.Clan^.TurnNumber + delay;
       
  3185 end;
       
  3186 
       
  3187 procedure ScriptApplyAmmoStore;
       
  3188 var i, j, k : LongInt;
       
  3189 begin
       
  3190 if (GameFlags and gfSharedAmmo) <> 0 then
       
  3191     for i:= 0 to Pred(ClansCount) do
       
  3192         begin
       
  3193         if ScriptExists('onNewAmmoStore') then
       
  3194             begin
       
  3195             ScriptPrepareAmmoStore;
       
  3196             ScriptCall('onNewAmmoStore',i,-1);
       
  3197             SetAmmoLoadout(ScriptAmmoLoadout);
       
  3198             SetAmmoProbability(ScriptAmmoProbability);
       
  3199             SetAmmoDelay(ScriptAmmoDelay);
       
  3200             SetAmmoReinforcement(ScriptAmmoReinforcement)
       
  3201             end;
       
  3202         AddAmmoStore;
       
  3203         for j:= 0 to Pred(ClansArray[i]^.TeamsNumber) do
       
  3204             for k:= 0 to Pred(ClansArray[i]^.Teams[j]^.HedgehogsNumber) do
       
  3205                 ClansArray[i]^.Teams[j]^.Hedgehogs[k].AmmoStore:= StoreCnt - 1
       
  3206         end
       
  3207 else if (GameFlags and gfPerHogAmmo) <> 0 then
       
  3208     for i:= 0 to Pred(TeamsCount) do
       
  3209         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
       
  3210             begin
       
  3211             if ScriptExists('onNewAmmoStore') then
       
  3212                 begin
       
  3213                 ScriptPrepareAmmoStore;
       
  3214                 ScriptCall('onNewAmmoStore',i,j);
       
  3215                 SetAmmoLoadout(ScriptAmmoLoadout);
       
  3216                 SetAmmoProbability(ScriptAmmoProbability);
       
  3217                 SetAmmoDelay(ScriptAmmoDelay);
       
  3218                 SetAmmoReinforcement(ScriptAmmoReinforcement)
       
  3219                 end;
       
  3220             AddAmmoStore;
       
  3221             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= StoreCnt - 1
       
  3222             end
       
  3223 else
       
  3224     for i:= 0 to Pred(TeamsCount) do
       
  3225         begin
       
  3226         if ScriptExists('onNewAmmoStore') then
       
  3227             begin
       
  3228             ScriptPrepareAmmoStore;
       
  3229             ScriptCall('onNewAmmoStore',i,-1);
       
  3230             SetAmmoLoadout(ScriptAmmoLoadout);
       
  3231             SetAmmoProbability(ScriptAmmoProbability);
       
  3232             SetAmmoDelay(ScriptAmmoDelay);
       
  3233             SetAmmoReinforcement(ScriptAmmoReinforcement)
       
  3234             end;
       
  3235         AddAmmoStore;
       
  3236         for j:= 0 to Pred(TeamsArray[i]^.HedgehogsNumber) do
       
  3237             TeamsArray[i]^.Hedgehogs[j].AmmoStore:= StoreCnt - 1
       
  3238         end
       
  3239 end;
       
  3240 
       
  3241 procedure initModule;
       
  3242 var at : TGearType;
       
  3243     vgt: TVisualGearType;
       
  3244     am : TAmmoType;
       
  3245     si : TStatInfoType;
       
  3246     st : TSound;
       
  3247     he : THogEffect;
       
  3248     cg : TCapGroup;
       
  3249     spr: TSprite;
       
  3250     mg : TMapGen;
       
  3251     we : TWorldEdge;
       
  3252 begin
       
  3253 // initialize lua
       
  3254 luaState:= lua_open;
       
  3255 if checkFails(luaState <> nil, 'lua_open failed', true) then exit;
       
  3256 
       
  3257 // open internal libraries
       
  3258 luaopen_base(luaState);
       
  3259 luaopen_string(luaState);
       
  3260 luaopen_math(luaState);
       
  3261 luaopen_table(luaState);
       
  3262 
       
  3263 // import some variables
       
  3264 ScriptSetString(_S'L', cLocale);
       
  3265 
       
  3266 // import game flags
       
  3267 ScriptSetInteger('gfForts', gfForts);
       
  3268 ScriptSetInteger('gfMultiWeapon', gfMultiWeapon);
       
  3269 ScriptSetInteger('gfSolidLand', gfSolidLand);
       
  3270 ScriptSetInteger('gfBorder', gfBorder);
       
  3271 ScriptSetInteger('gfBottomBorder', gfBottomBorder);
       
  3272 ScriptSetInteger('gfDivideTeams', gfDivideTeams);
       
  3273 ScriptSetInteger('gfLowGravity', gfLowGravity);
       
  3274 ScriptSetInteger('gfLaserSight', gfLaserSight);
       
  3275 ScriptSetInteger('gfInvulnerable', gfInvulnerable);
       
  3276 ScriptSetInteger('gfResetHealth', gfResetHealth);
       
  3277 ScriptSetInteger('gfVampiric', gfVampiric);
       
  3278 ScriptSetInteger('gfKarma', gfKarma);
       
  3279 ScriptSetInteger('gfArtillery', gfArtillery);
       
  3280 ScriptSetInteger('gfOneClanMode', gfOneClanMode);
       
  3281 ScriptSetInteger('gfRandomOrder', gfRandomOrder);
       
  3282 ScriptSetInteger('gfKing', gfKing);
       
  3283 ScriptSetInteger('gfPlaceHog', gfPlaceHog);
       
  3284 ScriptSetInteger('gfSharedAmmo', gfSharedAmmo);
       
  3285 ScriptSetInteger('gfDisableGirders', gfDisableGirders);
       
  3286 ScriptSetInteger('gfDisableLandObjects', gfDisableLandObjects);
       
  3287 ScriptSetInteger('gfAISurvival', gfAISurvival);
       
  3288 ScriptSetInteger('gfInfAttack', gfInfAttack);
       
  3289 ScriptSetInteger('gfResetWeps', gfResetWeps);
       
  3290 ScriptSetInteger('gfPerHogAmmo', gfPerHogAmmo);
       
  3291 ScriptSetInteger('gfDisableWind', gfDisableWind);
       
  3292 ScriptSetInteger('gfMoreWind', gfMoreWind);
       
  3293 ScriptSetInteger('gfTagTeam', gfTagTeam);
       
  3294 ScriptSetInteger('gfShoppaBorder', gfShoppaBorder);
       
  3295 
       
  3296 ScriptSetInteger('gmLeft', gmLeft);
       
  3297 ScriptSetInteger('gmRight', gmRight);
       
  3298 ScriptSetInteger('gmUp', gmUp);
       
  3299 ScriptSetInteger('gmDown', gmDown);
       
  3300 ScriptSetInteger('gmSwitch', gmSwitch);
       
  3301 ScriptSetInteger('gmAttack', gmAttack);
       
  3302 ScriptSetInteger('gmLJump', gmLJump);
       
  3303 ScriptSetInteger('gmHJump', gmHJump);
       
  3304 ScriptSetInteger('gmDestroy', gmDestroy);
       
  3305 ScriptSetInteger('gmSlot', gmSlot);
       
  3306 ScriptSetInteger('gmWeapon', gmWeapon);
       
  3307 ScriptSetInteger('gmTimer', gmTimer);
       
  3308 ScriptSetInteger('gmAnimate', gmAnimate);
       
  3309 ScriptSetInteger('gmPrecise', gmPrecise);
       
  3310 ScriptSetInteger('gmAllStoppable', gmAllStoppable);
       
  3311 
       
  3312 // speech bubbles
       
  3313 ScriptSetInteger('SAY_SAY', 1);
       
  3314 ScriptSetInteger('SAY_THINK', 2);
       
  3315 ScriptSetInteger('SAY_SHOUT', 3);
       
  3316 
       
  3317 // register gear types
       
  3318 for at:= Low(TGearType) to High(TGearType) do
       
  3319     ScriptSetInteger(EnumToStr(at), ord(at));
       
  3320 
       
  3321 for vgt:= Low(TVisualGearType) to High(TVisualGearType) do
       
  3322     ScriptSetInteger(EnumToStr(vgt), ord(vgt));
       
  3323 
       
  3324 // register sounds
       
  3325 for st:= Low(TSound) to High(TSound) do
       
  3326     ScriptSetInteger(EnumToStr(st), ord(st));
       
  3327 
       
  3328 // register ammo types
       
  3329 for am:= Low(TAmmoType) to High(TAmmoType) do
       
  3330     ScriptSetInteger(EnumToStr(am), ord(am));
       
  3331 
       
  3332 for si:= Low(TStatInfoType) to High(TStatInfoType) do
       
  3333     ScriptSetInteger(EnumToStr(si), ord(si));
       
  3334 
       
  3335 for he:= Low(THogEffect) to High(THogEffect) do
       
  3336     ScriptSetInteger(EnumToStr(he), ord(he));
       
  3337 
       
  3338 for cg:= Low(TCapGroup) to High(TCapGroup) do
       
  3339     ScriptSetInteger(EnumToStr(cg), ord(cg));
       
  3340 
       
  3341 for spr:= Low(TSprite) to High(TSprite) do
       
  3342     ScriptSetInteger(EnumToStr(spr), ord(spr));
       
  3343 
       
  3344 for mg:= Low(TMapGen) to High(TMapGen) do
       
  3345     ScriptSetInteger(EnumToStr(mg), ord(mg));
       
  3346 
       
  3347 for we:= Low(TWorldEdge) to High(TWorldEdge) do
       
  3348     ScriptSetInteger(EnumToStr(we), ord(we));
       
  3349 
       
  3350 ScriptSetInteger('gstDrowning'      , gstDrowning);
       
  3351 ScriptSetInteger('gstHHDriven'      , gstHHDriven);
       
  3352 ScriptSetInteger('gstMoving'        , gstMoving);
       
  3353 ScriptSetInteger('gstAttacked'      , gstAttacked);
       
  3354 ScriptSetInteger('gstAttacking'     , gstAttacking);
       
  3355 ScriptSetInteger('gstCollision'     , gstCollision);
       
  3356 ScriptSetInteger('gstChooseTarget'  , gstChooseTarget);
       
  3357 ScriptSetInteger('gstHHJumping'     , gstHHJumping);
       
  3358 ScriptSetInteger('gsttmpFlag'       , gsttmpFlag);
       
  3359 ScriptSetInteger('gstHHThinking'    , gstHHThinking);
       
  3360 ScriptSetInteger('gstNoDamage'      , gstNoDamage);
       
  3361 ScriptSetInteger('gstHHHJump'       , gstHHHJump);
       
  3362 ScriptSetInteger('gstAnimation'     , gstAnimation);
       
  3363 ScriptSetInteger('gstHHDeath'       , gstHHDeath);
       
  3364 ScriptSetInteger('gstWinner'        , gstWinner);
       
  3365 ScriptSetInteger('gstWait'          , gstWait);
       
  3366 ScriptSetInteger('gstNotKickable'   , gstNotKickable);
       
  3367 ScriptSetInteger('gstLoser'         , gstLoser);
       
  3368 ScriptSetInteger('gstHHGone'        , gstHHGone);
       
  3369 ScriptSetInteger('gstInvisible'     , gstInvisible);
       
  3370 ScriptSetInteger('gstSubmersible'   , gstSubmersible);
       
  3371 ScriptSetInteger('gstFrozen'        , gstFrozen);
       
  3372 ScriptSetInteger('gstNoGravity'     , gstNoGravity);
       
  3373 
       
  3374 // ai hints
       
  3375 ScriptSetInteger('aihUsualProcessing', aihUsualProcessing);
       
  3376 ScriptSetInteger('aihDoesntMatter'   , aihDoesntMatter);
       
  3377 
       
  3378 // land flags
       
  3379 ScriptSetInteger('lfIndestructible', lfIndestructible);
       
  3380 ScriptSetInteger('lfIce'           , lfIce);
       
  3381 ScriptSetInteger('lfBouncy'        , lfBouncy);
       
  3382 
       
  3383 // register functions
       
  3384 lua_register(luaState, _P'HideHog', @lc_hidehog);
       
  3385 lua_register(luaState, _P'RestoreHog', @lc_restorehog);
       
  3386 lua_register(luaState, _P'SaveCampaignVar', @lc_savecampaignvar);
       
  3387 lua_register(luaState, _P'GetCampaignVar', @lc_getcampaignvar);
       
  3388 lua_register(luaState, _P'band', @lc_band);
       
  3389 lua_register(luaState, _P'bor', @lc_bor);
       
  3390 lua_register(luaState, _P'bnot', @lc_bnot);
       
  3391 lua_register(luaState, _P'div', @lc_div);
       
  3392 lua_register(luaState, _P'GetInputMask', @lc_getinputmask);
       
  3393 lua_register(luaState, _P'SetInputMask', @lc_setinputmask);
       
  3394 lua_register(luaState, _P'AddGear', @lc_addgear);
       
  3395 lua_register(luaState, _P'DismissTeam', @lc_dismissteam);
       
  3396 lua_register(luaState, _P'EnableGameFlags', @lc_enablegameflags);
       
  3397 lua_register(luaState, _P'DisableGameFlags', @lc_disablegameflags);
       
  3398 lua_register(luaState, _P'ClearGameFlags', @lc_cleargameflags);
       
  3399 lua_register(luaState, _P'GetGameFlag', @lc_getgameflag);
       
  3400 lua_register(luaState, _P'DeleteGear', @lc_deletegear);
       
  3401 lua_register(luaState, _P'AddVisualGear', @lc_addvisualgear);
       
  3402 lua_register(luaState, _P'DeleteVisualGear', @lc_deletevisualgear);
       
  3403 lua_register(luaState, _P'GetVisualGearType', @lc_getvisualgeartype);
       
  3404 lua_register(luaState, _P'GetVisualGearValues', @lc_getvisualgearvalues);
       
  3405 lua_register(luaState, _P'SetVisualGearValues', @lc_setvisualgearvalues);
       
  3406 lua_register(luaState, _P'GetGearValues', @lc_getgearvalues);
       
  3407 lua_register(luaState, _P'SetGearValues', @lc_setgearvalues);
       
  3408 lua_register(luaState, _P'SpawnHealthCrate', @lc_spawnhealthcrate);
       
  3409 lua_register(luaState, _P'SpawnAmmoCrate', @lc_spawnammocrate);
       
  3410 lua_register(luaState, _P'SpawnUtilityCrate', @lc_spawnutilitycrate);
       
  3411 lua_register(luaState, _P'SpawnFakeHealthCrate', @lc_spawnfakehealthcrate);
       
  3412 lua_register(luaState, _P'SpawnFakeAmmoCrate', @lc_spawnfakeammocrate);
       
  3413 lua_register(luaState, _P'SpawnFakeUtilityCrate', @lc_spawnfakeutilitycrate);
       
  3414 lua_register(luaState, _P'WriteLnToConsole', @lc_writelntoconsole);
       
  3415 lua_register(luaState, _P'GetGearType', @lc_getgeartype);
       
  3416 lua_register(luaState, _P'EndGame', @lc_endgame);
       
  3417 lua_register(luaState, _P'SendStat', @lc_sendstat);
       
  3418 lua_register(luaState, _P'SendHealthStatsOff', @lc_sendhealthstatsoff);
       
  3419 lua_register(luaState, _P'FindPlace', @lc_findplace);
       
  3420 lua_register(luaState, _P'SetGearPosition', @lc_setgearposition);
       
  3421 lua_register(luaState, _P'GetGearPosition', @lc_getgearposition);
       
  3422 lua_register(luaState, _P'SetGearTarget', @lc_setgeartarget);
       
  3423 lua_register(luaState, _P'GetGearTarget', @lc_getgeartarget);
       
  3424 lua_register(luaState, _P'SetGearVelocity', @lc_setgearvelocity);
       
  3425 lua_register(luaState, _P'GetGearVelocity', @lc_getgearvelocity);
       
  3426 lua_register(luaState, _P'ParseCommand', @lc_parsecommand);
       
  3427 lua_register(luaState, _P'ShowMission', @lc_showmission);
       
  3428 lua_register(luaState, _P'HideMission', @lc_hidemission);
       
  3429 lua_register(luaState, _P'SetAmmoTexts', @lc_setammotexts);
       
  3430 lua_register(luaState, _P'SetAmmoDescriptionAppendix', @lc_setammodescriptionappendix);
       
  3431 lua_register(luaState, _P'AddCaption', @lc_addcaption);
       
  3432 lua_register(luaState, _P'SetAmmo', @lc_setammo);
       
  3433 lua_register(luaState, _P'SetAmmoDelay', @lc_setammodelay);
       
  3434 lua_register(luaState, _P'SetAmmoStore', @lc_setammostore);
       
  3435 lua_register(luaState, _P'PlaySound', @lc_playsound);
       
  3436 lua_register(luaState, _P'AddTeam', @lc_addteam);
       
  3437 lua_register(luaState, _P'AddHog', @lc_addhog);
       
  3438 lua_register(luaState, _P'AddAmmo', @lc_addammo);
       
  3439 lua_register(luaState, _P'GetAmmoCount', @lc_getammocount);
       
  3440 lua_register(luaState, _P'SetHealth', @lc_sethealth);
       
  3441 lua_register(luaState, _P'GetHealth', @lc_gethealth);
       
  3442 lua_register(luaState, _P'SetEffect', @lc_seteffect);
       
  3443 lua_register(luaState, _P'GetEffect', @lc_geteffect);
       
  3444 lua_register(luaState, _P'GetHogClan', @lc_gethogclan);
       
  3445 lua_register(luaState, _P'GetClanColor', @lc_getclancolor);
       
  3446 lua_register(luaState, _P'SetClanColor', @lc_setclancolor);
       
  3447 lua_register(luaState, _P'GetHogVoicepack', @lc_gethogvoicepack);
       
  3448 lua_register(luaState, _P'GetHogFlag', @lc_gethogflag);
       
  3449 lua_register(luaState, _P'GetHogFort', @lc_gethogfort);
       
  3450 lua_register(luaState, _P'GetHogGrave', @lc_gethoggrave);
       
  3451 lua_register(luaState, _P'IsHogLocal', @lc_ishoglocal);
       
  3452 lua_register(luaState, _P'GetHogTeamName', @lc_gethogteamname);
       
  3453 lua_register(luaState, _P'SetHogTeamName', @lc_sethogteamname);
       
  3454 lua_register(luaState, _P'GetHogName', @lc_gethogname);
       
  3455 lua_register(luaState, _P'SetHogName', @lc_sethogname);
       
  3456 lua_register(luaState, _P'GetHogLevel', @lc_gethoglevel);
       
  3457 lua_register(luaState, _P'SetHogLevel', @lc_sethoglevel);
       
  3458 lua_register(luaState, _P'GetX', @lc_getx);
       
  3459 lua_register(luaState, _P'GetY', @lc_gety);
       
  3460 lua_register(luaState, _P'CopyPV', @lc_copypv);
       
  3461 lua_register(luaState, _P'FollowGear', @lc_followgear);
       
  3462 lua_register(luaState, _P'GetFollowGear', @lc_getfollowgear);
       
  3463 lua_register(luaState, _P'SetState', @lc_setstate);
       
  3464 lua_register(luaState, _P'GetState', @lc_getstate);
       
  3465 lua_register(luaState, _P'GetTag', @lc_gettag);
       
  3466 lua_register(luaState, _P'SetTag', @lc_settag);
       
  3467 lua_register(luaState, _P'SetTimer', @lc_settimer);
       
  3468 lua_register(luaState, _P'GetTimer', @lc_gettimer);
       
  3469 lua_register(luaState, _P'SetFlightTime', @lc_setflighttime);
       
  3470 lua_register(luaState, _P'GetFlightTime', @lc_getflighttime);
       
  3471 lua_register(luaState, _P'SetZoom', @lc_setzoom);
       
  3472 lua_register(luaState, _P'GetZoom', @lc_getzoom);
       
  3473 lua_register(luaState, _P'HogSay', @lc_hogsay);
       
  3474 lua_register(luaState, _P'SwitchHog', @lc_switchhog);
       
  3475 lua_register(luaState, _P'HogTurnLeft', @lc_hogturnleft);
       
  3476 lua_register(luaState, _P'CampaignLock', @lc_campaignlock);
       
  3477 lua_register(luaState, _P'CampaignUnlock', @lc_campaignunlock);
       
  3478 lua_register(luaState, _P'GetGearElasticity', @lc_getgearelasticity);
       
  3479 lua_register(luaState, _P'SetGearElasticity', @lc_setgearelasticity);
       
  3480 lua_register(luaState, _P'GetGearFriction', @lc_getgearfriction);
       
  3481 lua_register(luaState, _P'SetGearFriction', @lc_setgearfriction);
       
  3482 lua_register(luaState, _P'GetGearRadius', @lc_getgearradius);
       
  3483 lua_register(luaState, _P'GetGearMessage', @lc_getgearmessage);
       
  3484 lua_register(luaState, _P'SetGearMessage', @lc_setgearmessage);
       
  3485 lua_register(luaState, _P'GetGearPos', @lc_getgearpos);
       
  3486 lua_register(luaState, _P'SetGearPos', @lc_setgearpos);
       
  3487 lua_register(luaState, _P'GetGearCollisionMask', @lc_getgearcollisionmask);
       
  3488 lua_register(luaState, _P'SetGearCollisionMask', @lc_setgearcollisionmask);
       
  3489 lua_register(luaState, _P'GetRandom', @lc_getrandom);
       
  3490 lua_register(luaState, _P'SetWind', @lc_setwind);
       
  3491 lua_register(luaState, _P'MapHasBorder', @lc_maphasborder);
       
  3492 lua_register(luaState, _P'GetHogHat', @lc_gethoghat);
       
  3493 lua_register(luaState, _P'SetHogHat', @lc_sethoghat);
       
  3494 lua_register(luaState, _P'EraseSprite', @lc_erasesprite);
       
  3495 lua_register(luaState, _P'PlaceSprite', @lc_placesprite);
       
  3496 lua_register(luaState, _P'PlaceGirder', @lc_placegirder);
       
  3497 lua_register(luaState, _P'PlaceRubber', @lc_placerubber);
       
  3498 lua_register(luaState, _P'GetCurAmmoType', @lc_getcurammotype);
       
  3499 lua_register(luaState, _P'TestRectForObstacle', @lc_testrectforobstacle);
       
  3500 lua_register(luaState, _P'GetGravity', @lc_getgravity);
       
  3501 lua_register(luaState, _P'SetGravity', @lc_setgravity);
       
  3502 lua_register(luaState, _P'SetWaterLine', @lc_setwaterline);
       
  3503 lua_register(luaState, _P'SetNextWeapon', @lc_setnextweapon);
       
  3504 lua_register(luaState, _P'SetWeapon', @lc_setweapon);
       
  3505 lua_register(luaState, _P'SetCinematicMode', @lc_setcinematicmode);
       
  3506 lua_register(luaState, _P'SetMaxBuildDistance', @lc_setmaxbuilddistance);
       
  3507 lua_register(luaState, _P'GetAmmoName', @lc_getammoname);
       
  3508 // drawn map functions
       
  3509 lua_register(luaState, _P'AddPoint', @lc_addPoint);
       
  3510 lua_register(luaState, _P'FlushPoints', @lc_flushPoints);
       
  3511 
       
  3512 lua_register(luaState, _P'SetGearAIHints', @lc_setgearaihints);
       
  3513 lua_register(luaState, _P'HedgewarsScriptLoad', @lc_hedgewarsscriptload);
       
  3514 lua_register(luaState, _P'DeclareAchievement', @lc_declareachievement);
       
  3515 lua_register(luaState, _P'StartGhostPoints', @lc_startghostpoints);
       
  3516 lua_register(luaState, _P'DumpPoint', @lc_dumppoint);
       
  3517 
       
  3518 ScriptSetInteger('TEST_SUCCESSFUL'   , HaltTestSuccess);
       
  3519 ScriptSetInteger('TEST_FAILED'       , HaltTestFailed);
       
  3520 lua_register(luaState, _P'EndLuaTest', @lc_endluatest);
       
  3521 
       
  3522 ScriptClearStack; // just to be sure stack is empty
       
  3523 ScriptLoaded:= false;
       
  3524 end;
       
  3525 
       
  3526 procedure freeModule;
       
  3527 begin
       
  3528 lua_close(luaState);
       
  3529 end;
       
  3530 
       
  3531 {$ELSE}
       
  3532 procedure ScriptPrintStack;
       
  3533 begin
       
  3534 end;
       
  3535 
       
  3536 procedure ScriptClearStack;
       
  3537 begin
       
  3538 end;
       
  3539 
       
  3540 procedure ScriptLoad(name : shortstring);
       
  3541 begin
       
  3542     name:= name; // avoid hint
       
  3543 end;
       
  3544 
       
  3545 procedure ScriptOnGameInit;
       
  3546 begin
       
  3547 end;
       
  3548 
       
  3549 procedure ScriptCall(fname : shortstring);
       
  3550 begin
       
  3551     fname:= fname; // avoid hint
       
  3552 end;
       
  3553 
       
  3554 function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt;
       
  3555 begin
       
  3556     // avoid hints
       
  3557     fname:= fname;
       
  3558     par1:= par1;
       
  3559     par2:= par2;
       
  3560     par3:= par3;
       
  3561     par4:= par4;
       
  3562     ScriptCall:= 0
       
  3563 end;
       
  3564 
       
  3565 function ScriptCall(fname : shortstring; par1: LongInt) : LongInt;
       
  3566 begin
       
  3567     // avoid hints
       
  3568     fname:= fname;
       
  3569     par1:= par1;
       
  3570     ScriptCall:= 0
       
  3571 end;
       
  3572 
       
  3573 function ScriptCall(fname : shortstring; par1, par2: LongInt) : LongInt;
       
  3574 begin
       
  3575     // avoid hints
       
  3576     fname:= fname;
       
  3577     par1:= par1;
       
  3578     par2:= par2;
       
  3579     ScriptCall:= 0
       
  3580 end;
       
  3581 
       
  3582 function ScriptCall(fname : shortstring; par1, par2, par3: LongInt) : LongInt;
       
  3583 begin
       
  3584     // avoid hints
       
  3585     fname:= fname;
       
  3586     par1:= par1;
       
  3587     par2:= par2;
       
  3588     par3:= par3;
       
  3589     ScriptCall:= 0
       
  3590 end;
       
  3591 
       
  3592 function ScriptExists(fname : shortstring) : boolean;
       
  3593 begin
       
  3594     fname:= fname; // avoid hint
       
  3595     ScriptExists:= false
       
  3596 end;
       
  3597 (*
       
  3598 function ParseCommandOverride(key, value : shortstring) : shortstring;
       
  3599 begin
       
  3600     // avoid hints
       
  3601     key:= key;
       
  3602     value:= value;
       
  3603     ParseCommandOverride:= ''
       
  3604 end;
       
  3605 *)
       
  3606 
       
  3607 procedure ScriptOnScreenResize;
       
  3608 begin
       
  3609 end;
       
  3610 
       
  3611 procedure ScriptOnPreviewInit;
       
  3612 begin
       
  3613 end;
       
  3614 
       
  3615 procedure ScriptSetInteger(name : shortstring; value : LongInt);
       
  3616 begin
       
  3617 end;
       
  3618 
       
  3619 procedure ScriptSetString(name : shortstring; value : shortstring);
       
  3620 begin
       
  3621 end;
       
  3622 
       
  3623 procedure LuaParseString(s : ShortString);
       
  3624 begin
       
  3625 end;
       
  3626 
       
  3627 procedure initModule;
       
  3628 begin
       
  3629 mapDims:= false;
       
  3630 PointsBuffer:= '';
       
  3631 prevCursorPoint.X:= NoPointX;
       
  3632 prevCursorPoint.Y:= 0;
       
  3633 end;
       
  3634 
       
  3635 procedure freeModule;
       
  3636 begin
       
  3637 end;
       
  3638 
       
  3639 {$ENDIF}
       
  3640 end.