DEADSOFTWARE

make turret explosions ignore the turret trigger
[d2df-sdl.git] / src / game / g_scriptprocs.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$MODE DELPHI}
17 unit g_scriptprocs;
19 interface
21 uses
22 g_scripts;
24 function SP_Lua_ConPrint(L: PScriptContext): Integer; cdecl;
25 function SP_Lua_PlaySound(L: PScriptContext): Integer; cdecl;
26 function SP_Lua_Message(L: PScriptContext): Integer; cdecl;
27 function SP_Lua_GetGameMode(L: PScriptContext): Integer; cdecl;
28 function SP_Lua_GetGameType(L: PScriptContext): Integer; cdecl;
29 function SP_Lua_GetTime(L: PScriptContext): Integer; cdecl;
31 function SP_Lua_PlayerGetKeys(L: PScriptContext): Integer; cdecl;
32 function SP_Lua_PlayerGetArmor(L: PScriptContext): Integer; cdecl;
33 function SP_Lua_PlayerGetTeam(L: PScriptContext): Integer; cdecl;
34 function SP_Lua_PlayerGetScore(L: PScriptContext): Integer; cdecl;
35 function SP_Lua_PlayerGetName(L: PScriptContext): Integer; cdecl;
37 function SP_Lua_ActorGetPos(L: PScriptContext): Integer; cdecl;
38 function SP_Lua_ActorGetHealth(L: PScriptContext): Integer; cdecl;
39 function SP_Lua_ActorGetState(L: PScriptContext): Integer; cdecl;
40 function SP_Lua_ActorGetType(L: PScriptContext): Integer; cdecl;
41 function SP_Lua_ActorNearest(L: PScriptContext): Integer; cdecl;
42 function SP_Lua_ActorFarthest(L: PScriptContext): Integer; cdecl;
43 function SP_Lua_ActorDamage(L: PScriptContext): Integer; cdecl;
44 function SP_Lua_ActorTeleport(L: PScriptContext): Integer; cdecl;
45 function SP_Lua_ActorPush(L: PScriptContext): Integer; cdecl;
47 function SP_Lua_TriggerActivate(L: PScriptContext): Integer; cdecl;
48 function SP_Lua_TriggerGetEnabled(L: PScriptContext): Integer; cdecl;
49 function SP_Lua_TriggerSetEnabled(L: PScriptContext): Integer; cdecl;
50 function SP_Lua_TriggerGetPos(L: PScriptContext): Integer; cdecl;
51 function SP_Lua_TriggerSetPos(L: PScriptContext): Integer; cdecl;
53 function SP_Lua_PanelGetType(L: PScriptContext): Integer; cdecl;
54 function SP_Lua_PanelGetPos(L: PScriptContext): Integer; cdecl;
55 function SP_Lua_PanelGetSize(L: PScriptContext): Integer; cdecl;
56 function SP_Lua_PanelSetPos(L: PScriptContext): Integer; cdecl;
57 function SP_Lua_PanelSwitchTexture(L: PScriptContext): Integer; cdecl;
59 function SP_Lua_DoorGetState(L: PScriptContext): Integer; cdecl;
60 function SP_Lua_DoorOpen(L: PScriptContext): Integer; cdecl;
61 function SP_Lua_DoorClose(L: PScriptContext): Integer; cdecl;
62 function SP_Lua_DoorToggle(L: PScriptContext): Integer; cdecl;
63 function SP_Lua_DoorCloseTrap(L: PScriptContext): Integer; cdecl;
64 function SP_Lua_LiftSetDir(L: PScriptContext): Integer; cdecl;
65 function SP_Lua_LiftGetDir(L: PScriptContext): Integer; cdecl;
67 function SP_Lua_SpawnShot(L: PScriptContext): Integer; cdecl;
68 function SP_Lua_SpawnEffect(L: PScriptContext): Integer; cdecl;
69 function SP_Lua_SpawnMonster(L: PScriptContext): Integer; cdecl;
70 function SP_Lua_SpawnItem(L: PScriptContext): Integer; cdecl;
72 implementation
74 uses
75 lua, lauxlib,
76 g_player, g_map, Math, g_gfx, g_game, g_textures,
77 g_console, g_monsters, g_items, g_phys, g_weapons,
78 g_main, SysUtils, e_log, g_language, g_basic,
79 g_options, g_net, g_netmsg, g_triggers, g_panel,
80 g_sound, MAPDEF;
82 function CheckArgs(L: PScriptContext; MinArgs: Integer; Error: Boolean = True): Boolean; inline;
83 begin
84 Result := True;
85 if lua_gettop(L) < MinArgs then
86 begin
87 if Error then g_Console_Add('SCRIPT: ERROR: expected at least ' + IntToStr(MinArgs) + ' argument(s)');
88 Result := False;
89 end;
90 end;
92 // system //
94 function SP_Lua_ConPrint(L: PScriptContext): Integer; cdecl;
95 // game.con_print(text)
96 const
97 MINARGS = 1;
98 begin
99 Result := 0;
100 if not CheckArgs(L, MINARGS) then Exit;
101 g_Console_Add(luaL_checkstring(L, 1));
102 end;
104 function SP_Lua_Message(L: PScriptContext): Integer; cdecl;
105 // game.message(type, text, channel[, uid=0, timeout=144])
106 const
107 MINARGS = 3;
108 var
109 MText: string;
110 MChan, MKind, MID, MTime: Integer;
111 begin
112 Result := 0;
113 if not CheckArgs(L, MINARGS) then exit;
115 MKind := luaL_checkinteger(L, 1);
116 MText := luaL_checkstring(L, 2);
117 MChan := luaL_checkinteger(L, 3);
119 MID := lua_tointeger(L, 4);
120 MTime := lua_tointeger(L, 5);
121 if MTime = 0 then MTime := 144;
123 tr_Message(MKind, MText, MChan, MTime, MID);
124 end;
126 function SP_Lua_GetGameMode(L: PScriptContext): Integer; cdecl;
127 // game.get_gamemode()
128 const
129 MINARGS = 0;
130 begin
131 Result := 1;
132 lua_pushinteger(L, gGameSettings.GameMode);
133 end;
135 function SP_Lua_GetGameType(L: PScriptContext): Integer; cdecl;
136 // game.get_gametype()
137 const
138 MINARGS = 0;
139 begin
140 Result := 1;
141 lua_pushinteger(L, gGameSettings.GameType);
142 end;
144 function SP_Lua_GetTime(L: PScriptContext): Integer; cdecl;
145 // game.get_time()
146 const
147 MINARGS = 0;
148 begin
149 Result := 1;
150 lua_pushinteger(L, gTime);
151 end;
153 function SP_Lua_PlaySound(L: PScriptContext): Integer; cdecl;
154 // game.sound(name[positional=false, x=0, y=0])
155 const
156 MINARGS = 1;
157 var
158 SName: string;
159 SPos: Boolean;
160 SX, SY: Integer;
161 begin
162 Result := 0;
163 if not CheckArgs(L, MINARGS) then exit;
165 SName := luaL_checkstring(L, 1);
167 SPos := lua_toboolean(L, 2);
168 SX := lua_tointeger(L, 3);
169 SY := lua_tointeger(L, 4);
171 if SPos then
172 g_Sound_PlayExAt(SName, SX, SY)
173 else
174 g_Sound_PlayEx(SName);
176 if g_Game_IsNet then
177 MH_SEND_Sound(SX, SY, SName, SPos);
178 end;
180 // players //
182 function SP_Lua_PlayerGetKeys(L: PScriptContext): Integer; cdecl;
183 // game.player_get_keys(uid)
184 const
185 MINARGS = 1;
186 var
187 UID: Integer;
188 P: TPlayer;
189 begin
190 Result := 1;
191 if not CheckArgs(L, MINARGS) then
192 begin
193 Result := 0;
194 exit;
195 end;
197 UID := luaL_checkinteger(L, 1);
199 if g_GetUIDType(UID) <> UID_PLAYER then
200 lua_pushnil(L)
201 else
202 begin
203 P := g_Player_Get(UID);
204 if P = nil then
205 begin
206 lua_pushnil(L);
207 exit;
208 end;
209 lua_pushinteger(L, P.GetKeys);
210 end;
211 end;
213 function SP_Lua_PlayerGetArmor(L: PScriptContext): Integer; cdecl;
214 // game.player_get_armor(uid)
215 const
216 MINARGS = 1;
217 var
218 UID: Integer;
219 P: TPlayer;
220 begin
221 Result := 1;
222 if not CheckArgs(L, MINARGS) then
223 begin
224 Result := 0;
225 exit;
226 end;
228 UID := luaL_checkinteger(L, 1);
230 if g_GetUIDType(UID) <> UID_PLAYER then
231 lua_pushnil(L)
232 else
233 begin
234 P := g_Player_Get(UID);
235 if P = nil then
236 begin
237 lua_pushnil(L);
238 exit;
239 end;
240 lua_pushinteger(L, P.Armor);
241 end;
242 end;
244 function SP_Lua_PlayerGetName(L: PScriptContext): Integer; cdecl;
245 // game.player_get_name(uid)
246 const
247 MINARGS = 1;
248 var
249 UID: Integer;
250 P: TPlayer;
251 begin
252 Result := 1;
253 if not CheckArgs(L, MINARGS) then
254 begin
255 Result := 0;
256 exit;
257 end;
259 UID := luaL_checkinteger(L, 1);
261 if g_GetUIDType(UID) <> UID_PLAYER then
262 lua_pushnil(L)
263 else
264 begin
265 P := g_Player_Get(UID);
266 if P = nil then
267 begin
268 lua_pushnil(L);
269 exit;
270 end;
271 lua_pushstring(L, P.Name);
272 end;
273 end;
275 function SP_Lua_PlayerGetTeam(L: PScriptContext): Integer; cdecl;
276 // game.player_get_team(uid)
277 const
278 MINARGS = 1;
279 var
280 UID: Integer;
281 P: TPlayer;
282 begin
283 Result := 1;
284 if not CheckArgs(L, MINARGS) then
285 begin
286 Result := 0;
287 exit;
288 end;
290 UID := luaL_checkinteger(L, 1);
292 if g_GetUIDType(UID) <> UID_PLAYER then
293 lua_pushnil(L)
294 else
295 begin
296 P := g_Player_Get(UID);
297 if P = nil then
298 begin
299 lua_pushnil(L);
300 exit;
301 end;
302 lua_pushinteger(L, P.Team);
303 end;
304 end;
306 function SP_Lua_PlayerGetScore(L: PScriptContext): Integer; cdecl;
307 // game.player_get_score(uid)
308 const
309 MINARGS = 1;
310 var
311 UID: Integer;
312 P: TPlayer;
313 begin
314 Result := 1;
315 if not CheckArgs(L, MINARGS) then
316 begin
317 Result := 0;
318 exit;
319 end;
321 UID := luaL_checkinteger(L, 1);
323 if g_GetUIDType(UID) <> UID_PLAYER then
324 lua_pushnil(L)
325 else
326 begin
327 P := g_Player_Get(UID);
328 if P = nil then
329 begin
330 lua_pushnil(L);
331 exit;
332 end;
333 lua_pushinteger(L, P.Frags);
334 end;
335 end;
337 // actors //
339 function SP_Lua_ActorGetPos(L: PScriptContext): Integer; cdecl;
340 // game.uid_get_pos(uid)
341 const
342 MINARGS = 1;
343 var
344 UID: Integer;
345 P: TPlayer;
346 M: TMonster;
347 begin
348 Result := 2;
349 if not CheckArgs(L, MINARGS) then
350 begin
351 Result := 0;
352 exit;
353 end;
355 UID := luaL_checkinteger(L, 1);
357 if g_GetUIDType(UID) = UID_PLAYER then
358 begin
359 P := g_Player_Get(UID);
360 if P = nil then
361 begin
362 lua_pushnil(L);
363 lua_pushnil(L);
364 exit;
365 end;
366 lua_pushinteger(L, P.GameX + PLAYER_RECT_CX);
367 lua_pushinteger(L, P.GameY + PLAYER_RECT_CY);
368 end
369 else if g_GetUIDType(UID) = UID_MONSTER then
370 begin
371 M := g_Monsters_Get(UID);
372 if M = nil then
373 begin
374 lua_pushnil(L);
375 lua_pushnil(L);
376 exit;
377 end;
378 lua_pushinteger(L, M.Obj.X+M.Obj.Rect.X+(M.Obj.Rect.Width div 2));
379 lua_pushinteger(L, M.Obj.Y+M.Obj.Rect.Y+(M.Obj.Rect.Height div 2));
380 end
381 else
382 begin
383 lua_pushnil(L);
384 lua_pushnil(L);
385 end;
386 end;
388 function SP_Lua_ActorNearest(L: PScriptContext): Integer; cdecl;
389 // game.uid_nearest(x, y, [type=all, min, max])
390 const
391 MINARGS = 2;
392 var
393 i, UID, AType: Integer;
394 X, Y, Dist, MinDist, MaxDist, FMin: Double;
395 begin
396 Result := 1;
397 if not CheckArgs(L, MINARGS) then
398 begin
399 Result := 0;
400 exit;
401 end;
403 X := luaL_checkinteger(L, 1);
404 Y := luaL_checkinteger(L, 2);
406 AType := lua_tointeger(L, 3);
407 MinDist := Sqr(lua_tonumber(L, 4));
408 MaxDist := Sqr(lua_tonumber(L, 5));
409 if MaxDist < 0.01 then MaxDist := 1e15;
410 if MinDist < 0.01 then MinDist := 0;
411 FMin := MaxDist;
412 UID := -1;
414 if (AType in [UID_GAME, UID_PLAYER]) and (gPlayers <> nil) then
415 for i := 0 to High(gPlayers) do
416 begin
417 if gPlayers[i] = nil then continue;
418 Dist := Sqr(X - gPlayers[i].GameX) + Sqr(Y - gPlayers[i].GameY);
419 if (Dist > MinDist) and (Dist < FMin) then
420 begin
421 UID := gPlayers[i].UID;
422 FMin := Dist;
423 end;
424 end;
425 if (AType in [UID_GAME, UID_MONSTER]) and (gMonsters <> nil) then
426 for i := 0 to High(gMonsters) do
427 begin
428 if gMonsters[i] = nil then continue;
429 Dist := Sqr(X - gMonsters[i].GameX) + Sqr(Y - gMonsters[i].GameY);
430 if (Dist > MinDist) and (Dist < FMin) then
431 begin
432 UID := gMonsters[i].UID;
433 FMin := Dist;
434 end;
435 end;
437 lua_pushinteger(L, UID);
438 end;
440 function SP_Lua_ActorFarthest(L: PScriptContext): Integer; cdecl;
441 // game.uid_farthest(x, y, [type=all, min, max])
442 const
443 MINARGS = 2;
444 var
445 i, UID, AType: Integer;
446 X, Y, Dist, MinDist, MaxDist, FMax: Double;
447 begin
448 Result := 1;
449 if not CheckArgs(L, MINARGS) then
450 begin
451 Result := 0;
452 exit;
453 end;
455 X := luaL_checkinteger(L, 1);
456 Y := luaL_checkinteger(L, 2);
458 AType := lua_tointeger(L, 3);
459 MinDist := Sqr(lua_tonumber(L, 4));
460 MaxDist := Sqr(lua_tonumber(L, 5));
461 if MaxDist < 0.01 then MaxDist := 1e15;
462 if MinDist < 0.01 then MinDist := 0;
463 FMax := MinDist;
464 UID := -1;
466 if (AType in [UID_GAME, UID_PLAYER]) and (gPlayers <> nil) then
467 for i := 0 to High(gPlayers) do
468 begin
469 if gPlayers[i] = nil then continue;
470 Dist := Sqr(X - gPlayers[i].GameX) + Sqr(Y - gPlayers[i].GameY);
471 if (Dist < MaxDist) and (Dist > FMax) then
472 begin
473 UID := gPlayers[i].UID;
474 FMax := Dist;
475 end;
476 end;
477 if (AType in [UID_GAME, UID_MONSTER]) and (gMonsters <> nil) then
478 for i := 0 to High(gMonsters) do
479 begin
480 if gMonsters[i] = nil then continue;
481 Dist := Sqr(X - gMonsters[i].GameX) + Sqr(Y - gMonsters[i].GameY);
482 if (Dist < MaxDist) and (Dist > FMax) then
483 begin
484 UID := gMonsters[i].UID;
485 FMax := Dist;
486 end;
487 end;
489 lua_pushinteger(L, UID);
490 end;
492 function SP_Lua_ActorGetType(L: PScriptContext): Integer; cdecl;
493 // game.uid_type(uid)
494 const
495 MINARGS = 2;
496 var
497 UID, UType: Integer;
498 begin
499 Result := 1;
500 if not CheckArgs(L, MINARGS) then
501 begin
502 Result := 0;
503 exit;
504 end;
506 UID := luaL_checkinteger(L, 1);
507 if (UID < 0) or (UID > $FFFF) then
508 lua_pushnil(L)
509 else
510 begin
511 UType := g_GetUIDType(UID);
512 if not (UType in [UID_PLAYER, UID_MONSTER{*, UID_ITEM*}]) then
513 lua_pushnil(L)
514 else
515 lua_pushinteger(L, UType);
516 end;
517 end;
519 function SP_Lua_ActorDamage(L: PScriptContext): Integer; cdecl;
520 // game.uid_damage(uid, amount[, hit_type=hit_some, vx=0, vy=0, attacker_uid=0])
521 const
522 MINARGS = 2;
523 var
524 UID, AUID, Dmg, Atk, VX, VY: Integer;
525 P: TPlayer;
526 M: TMonster;
527 begin
528 Result := 0;
529 if not CheckArgs(L, MINARGS) then exit;
531 UID := luaL_checkinteger(L, 1);
532 Dmg := luaL_checkinteger(L, 2);
534 Atk := lua_tointeger(L, 3);
535 VX := lua_tointeger(L, 4);
536 VY := lua_tointeger(L, 5);
537 AUID := lua_tointeger(L, 6);
539 if g_GetUIDType(UID) = UID_PLAYER then
540 begin
541 P := g_Player_Get(UID);
542 if P = nil then exit;
543 if Dmg >= 0 then
544 P.Damage(Dmg, AUID, VX, VY, Atk)
545 else
546 P.Heal(-Dmg, False);
547 end
548 else if g_GetUIDType(UID) = UID_MONSTER then
549 begin
550 M := g_Monsters_Get(UID);
551 if M = nil then exit;
552 if Dmg >= 0 then
553 M.Damage(Dmg, AUID, VX, VY, Atk)
554 else
555 M.Heal(-Dmg);
556 end;
557 end;
559 function SP_Lua_ActorGetHealth(L: PScriptContext): Integer; cdecl;
560 // game.uid_get_health(uid)
561 const
562 MINARGS = 1;
563 var
564 UID: Integer;
565 P: TPlayer;
566 M: TMonster;
567 begin
568 Result := 1;
569 if not CheckArgs(L, MINARGS) then
570 begin
571 Result := 0;
572 exit;
573 end;
575 UID := luaL_checkinteger(L, 1);
577 if g_GetUIDType(UID) = UID_PLAYER then
578 begin
579 P := g_Player_Get(UID);
580 if P = nil then
581 begin
582 lua_pushnil(L);
583 exit;
584 end;
585 lua_pushinteger(L, P.Health);
586 end
587 else if g_GetUIDType(UID) = UID_MONSTER then
588 begin
589 M := g_Monsters_Get(UID);
590 if M = nil then
591 begin
592 lua_pushnil(L);
593 exit;
594 end;
595 lua_pushinteger(L, M.MonsterHealth);
596 end
597 else
598 lua_pushnil(L);
599 end;
601 function SP_Lua_ActorGetState(L: PScriptContext): Integer; cdecl;
602 // game.uid_get_state(uid)
603 const
604 MINARGS = 1;
605 var
606 UID: Integer;
607 P: TPlayer;
608 M: TMonster;
609 begin
610 Result := 1;
611 if not CheckArgs(L, MINARGS) then
612 begin
613 Result := 0;
614 exit;
615 end;
617 UID := luaL_checkinteger(L, 1);
619 if g_GetUIDType(UID) = UID_PLAYER then
620 begin
621 P := g_Player_Get(UID);
622 if P = nil then
623 begin
624 lua_pushnil(L);
625 exit;
626 end;
627 if P.Live then
628 lua_pushinteger(L, 1)
629 else if P.FSpectator then
630 lua_pushinteger(L, -1)
631 else
632 lua_pushinteger(L, 0);
633 end
634 else if g_GetUIDType(UID) = UID_MONSTER then
635 begin
636 M := g_Monsters_Get(UID);
637 if M = nil then
638 begin
639 lua_pushnil(L);
640 exit;
641 end;
642 lua_pushinteger(L, IfThen(M.Live, 1, 0));
643 end
644 else
645 lua_pushnil(L);
646 end;
648 function SP_Lua_ActorTeleport(L: PScriptContext): Integer; cdecl;
649 // game.uid_teleport(uid, to_x, to_y[, dir=left, silent=false, d2d_like=false])
650 const
651 MINARGS = 3;
652 var
653 D2D, NoSound: Boolean;
654 UID, TX, TY: Integer;
655 TDir: Integer;
656 begin
657 Result := 0;
658 if not CheckArgs(L, MINARGS) then exit;
660 UID := luaL_checkinteger(L, 1);
661 TX := luaL_checkinteger(L, 2);
662 TY := luaL_checkinteger(L, 3);
664 TDir := lua_tointeger(L, 4) mod 2;
665 NoSound := lua_toboolean(L, 5);
666 D2D := lua_toboolean(L, 6);
668 tr_Teleport(UID, TX, TY, TDir, NoSound, D2D);
669 end;
671 function SP_Lua_ActorPush(L: PScriptContext): Integer; cdecl;
672 // game.uid_push(uid, vx, vy[, reset_vel=false])
673 const
674 MINARGS = 3;
675 var
676 ResetVel: Boolean;
677 UID, VX, VY: Integer;
678 begin
679 Result := 0;
680 if not CheckArgs(L, MINARGS) then exit;
682 UID := luaL_checkinteger(L, 1);
683 VX := luaL_checkinteger(L, 2);
684 VY := luaL_checkinteger(L, 3);
686 ResetVel := lua_toboolean(L, 4);
688 tr_Push(UID, VX, VY, ResetVel);
689 end;
691 // triggers //
693 function SP_Lua_TriggerSetEnabled(L: PScriptContext): Integer; cdecl;
694 // game.trigger_set_enabled(id, active)
695 const
696 MINARGS = 2;
697 var
698 TID: Integer;
699 Enabled: Boolean;
700 begin
701 Result := 0;
702 if not CheckArgs(L, MINARGS) then exit;
704 TID := luaL_checkinteger(L, 1);
705 Enabled := lua_toboolean(L, 2);
707 if (TID < 0) or (TID > High(gTriggers)) then exit;
708 if gTriggers[TID].TriggerType = TRIGGER_NONE then exit;
709 gTriggers[TID].Enabled := Enabled;
710 end;
712 function SP_Lua_TriggerGetEnabled(L: PScriptContext): Integer; cdecl;
713 // game.trigger_get_enabled(id)
714 const
715 MINARGS = 1;
716 var
717 TID: Integer;
718 begin
719 Result := 1;
720 if not CheckArgs(L, MINARGS) then
721 begin
722 Result := 0;
723 exit;
724 end;
726 TID := luaL_checkinteger(L, 1);
728 if (TID < 0) or (TID > High(gTriggers)) or (gTriggers[TID].TriggerType = TRIGGER_NONE) then
729 lua_pushnil(L)
730 else
731 lua_pushboolean(L, gTriggers[TID].Enabled);
732 end;
734 function SP_Lua_TriggerActivate(L: PScriptContext): Integer; cdecl;
735 // game.trigger_activate(id[, activate_type=custom, activator_uid=0])
736 const
737 MINARGS = 1;
738 var
739 TID, UID: Integer;
740 TAct: Byte;
741 begin
742 Result := 0;
743 if not CheckArgs(L, MINARGS) then exit;
745 TID := luaL_checkinteger(L, 1);
747 TAct := lua_tointeger(L, 2);
748 if TAct = 0 then TAct := 255;
749 UID := lua_tointeger(L, 3);
751 if (TID < 0) or (TID > High(gTriggers)) then exit;
752 if gTriggers[TID].TriggerType = TRIGGER_NONE then exit;
753 if ByteBool(gTriggers[TID].ActivateType and TAct) then
754 g_Triggers_Press(TID, TAct, UID);
755 end;
757 function SP_Lua_TriggerGetPos(L: PScriptContext): Integer; cdecl;
758 // game.trigger_get_pos(id)
759 const
760 MINARGS = 1;
761 var
762 TID: Integer;
763 begin
764 Result := 2;
765 if not CheckArgs(L, MINARGS) then
766 begin
767 Result := 0;
768 exit;
769 end;
771 TID := luaL_checkinteger(L, 1);
773 if (TID < 0) or (TID > High(gTriggers)) or (gTriggers[TID].TriggerType = TRIGGER_NONE) then
774 begin
775 lua_pushnil(L);
776 lua_pushnil(L);
777 end
778 else
779 begin
780 lua_pushinteger(L, gTriggers[TID].X);
781 lua_pushinteger(L, gTriggers[TID].Y);
782 end;
783 end;
785 function SP_Lua_TriggerSetPos(L: PScriptContext): Integer; cdecl;
786 // game.trigger_set_pos(id, x, y)
787 const
788 MINARGS = 3;
789 var
790 TID, X, Y: Integer;
791 begin
792 Result := 0;
793 if not CheckArgs(L, MINARGS) then exit;
795 TID := luaL_checkinteger(L, 1);
796 X := luaL_checkinteger(L, 2);
797 Y := luaL_checkinteger(L, 3);
799 if (TID < 0) or (TID > High(gTriggers)) then exit;
800 if gTriggers[TID].TriggerType in [TRIGGER_NONE, TRIGGER_SOUND] then exit;
801 gTriggers[TID].X := X;
802 gTriggers[TID].Y := Y;
803 end;
805 // doors & panels //
807 function SP_Lua_PanelGetType(L: PScriptContext): Integer; cdecl;
808 // game.panel_get_type(panel_id)
809 const
810 MINARGS = 1;
811 var
812 PID, WID: Integer;
813 Pan: PPanel;
814 begin
815 Result := 1;
816 if not CheckArgs(L, MINARGS) then
817 begin
818 Result := 0;
819 exit;
820 end;
822 PID := luaL_checkinteger(L, 1);
824 WID := -1;
825 Pan := g_Map_PanelForPID(PID, WID);
826 if (Pan = nil) then
827 lua_pushnil(L)
828 else
829 lua_pushinteger(L, Pan^.PanelType);
830 end;
832 function SP_Lua_PanelGetPos(L: PScriptContext): Integer; cdecl;
833 // game.panel_get_pos(panel_id)
834 const
835 MINARGS = 1;
836 var
837 PID, WID: Integer;
838 Pan: PPanel;
839 begin
840 Result := 2;
841 if not CheckArgs(L, MINARGS) then
842 begin
843 Result := 0;
844 exit;
845 end;
847 PID := luaL_checkinteger(L, 1);
849 WID := -1;
850 Pan := g_Map_PanelForPID(PID, WID);
851 if (Pan = nil) then
852 begin
853 lua_pushnil(L);
854 lua_pushnil(L);
855 end
856 else
857 begin
858 lua_pushinteger(L, Pan^.X);
859 lua_pushinteger(L, Pan^.Y);
860 end;
861 end;
863 function SP_Lua_PanelGetSize(L: PScriptContext): Integer; cdecl;
864 // game.panel_get_size(panel_id)
865 const
866 MINARGS = 1;
867 var
868 PID, WID: Integer;
869 Pan: PPanel;
870 begin
871 Result := 2;
872 if not CheckArgs(L, MINARGS) then
873 begin
874 Result := 0;
875 exit;
876 end;
878 PID := luaL_checkinteger(L, 1);
880 WID := -1;
881 Pan := g_Map_PanelForPID(PID, WID);
882 if (Pan = nil) then
883 begin
884 lua_pushnil(L);
885 lua_pushnil(L);
886 end
887 else
888 begin
889 lua_pushinteger(L, Pan^.Width);
890 lua_pushinteger(L, Pan^.Height);
891 end;
892 end;
894 function SP_Lua_PanelSwitchTexture(L: PScriptContext): Integer; cdecl;
895 // game.panel_switch_texture(panel_id)
896 const
897 MINARGS = 1;
898 var
899 PID, WID: Integer;
900 Pan: PPanel;
901 begin
902 Result := 0;
903 if not CheckArgs(L, MINARGS) then exit;
905 PID := luaL_checkinteger(L, 1);
907 WID := -1;
908 Pan := g_Map_PanelForPID(PID, WID);
909 if (Pan = nil) then exit;
910 g_Map_SwitchTexture(Pan^.PanelType, WID, 0);
911 end;
913 function SP_Lua_PanelSetPos(L: PScriptContext): Integer; cdecl;
914 // game.panel_set_pos(panel_id, x, y)
915 const
916 MINARGS = 3;
917 var
918 PID, WID, X, Y: Integer;
919 Pan: PPanel;
920 begin
921 Result := 0;
922 if not CheckArgs(L, MINARGS) then exit;
924 PID := luaL_checkinteger(L, 1);
925 X := luaL_checkinteger(L, 2);
926 Y := luaL_checkinteger(L, 3);
928 WID := -1;
929 Pan := g_Map_PanelForPID(PID, WID);
930 if (Pan = nil) then exit;
931 if not (Pan.PanelType in [PANEL_BACK, PANEL_FORE]) then
932 begin
933 g_Console_Add('SCRIPT: panel_set_pos(): can only set pos for BACK and FORE right now');
934 exit;
935 end;
936 Pan^.X := X;
937 Pan^.Y := Y;
938 if g_Game_IsNet then
939 MH_SEND_PanelState(Pan^.PanelType, WID);
940 end;
942 function SP_Lua_DoorGetState(L: PScriptContext): Integer; cdecl;
943 // game.door_get_open(panel_id)
944 const
945 MINARGS = 1;
946 var
947 PID, WID: Integer;
948 Pan: PPanel;
949 begin
950 Result := 1;
951 if not CheckArgs(L, MINARGS) then
952 begin
953 Result := 0;
954 exit;
955 end;
957 PID := luaL_checkinteger(L, 1);
959 WID := -1;
960 Pan := g_Map_PanelForPID(PID, WID);
961 if (Pan = nil) or (not Pan^.Door) then
962 lua_pushnil(L)
963 else
964 lua_pushboolean(L, Pan^.Enabled);
965 end;
967 function SP_Lua_LiftGetDir(L: PScriptContext): Integer; cdecl;
968 // game.lift_get_dir(panel_id)
969 const
970 MINARGS = 1;
971 var
972 PID, WID: Integer;
973 Pan: PPanel;
974 begin
975 Result := 1;
976 if not CheckArgs(L, MINARGS) then
977 begin
978 Result := 0;
979 exit;
980 end;
982 PID := luaL_checkinteger(L, 1);
984 WID := -1;
985 Pan := g_Map_PanelForPID(PID, WID);
986 if (Pan = nil) or ((Pan^.LiftType = 0) and (Pan^.PanelType <> PANEL_LIFTUP)) then
987 lua_pushnil(L)
988 else
989 lua_pushinteger(L, Pan^.LiftType);
990 end;
992 function SP_Lua_DoorOpen(L: PScriptContext): Integer; cdecl;
993 // game.door_open(panel_id[, silent=false, d2d_like=false])
994 const
995 MINARGS = 1;
996 var
997 D2D, NoSound: Boolean;
998 PID, WID: Integer;
999 Pan: PPanel;
1000 begin
1001 Result := 0;
1002 if not CheckArgs(L, MINARGS) then exit;
1004 PID := luaL_checkinteger(L, 1);
1005 NoSound := lua_toboolean(L, 2);
1006 D2D := lua_toboolean(L, 3);
1008 WID := -1;
1009 Pan := g_Map_PanelForPID(PID, WID);
1010 if (Pan = nil) or (not Pan^.Door) then exit;
1011 tr_OpenDoor(WID, NoSound, D2D);
1012 end;
1014 function SP_Lua_DoorClose(L: PScriptContext): Integer; cdecl;
1015 // game.door_close(panel_id[, silent=false, d2d_like=false])
1016 const
1017 MINARGS = 1;
1018 var
1019 D2D, NoSound: Boolean;
1020 PID, WID: Integer;
1021 Pan: PPanel;
1022 begin
1023 Result := 0;
1024 if not CheckArgs(L, MINARGS) then exit;
1026 PID := luaL_checkinteger(L, 1);
1027 NoSound := lua_toboolean(L, 2);
1028 D2D := lua_toboolean(L, 3);
1030 WID := -1;
1031 Pan := g_Map_PanelForPID(PID, WID);
1032 if (Pan = nil) or (not Pan^.Door) then exit;
1033 tr_CloseDoor(WID, NoSound, D2D);
1034 end;
1036 function SP_Lua_DoorToggle(L: PScriptContext): Integer; cdecl;
1037 // game.door_toggle(panel_id[, silent=false, d2d_like=false])
1038 const
1039 MINARGS = 1;
1040 var
1041 D2D, NoSound: Boolean;
1042 PID, WID: Integer;
1043 Pan: PPanel;
1044 begin
1045 Result := 0;
1046 if not CheckArgs(L, MINARGS) then exit;
1048 PID := luaL_checkinteger(L, 1);
1049 NoSound := lua_toboolean(L, 2);
1050 D2D := lua_toboolean(L, 3);
1052 WID := -1;
1053 Pan := g_Map_PanelForPID(PID, WID);
1054 if (Pan = nil) or (not Pan^.Door) then exit;
1055 if gWalls[WID].Enabled then
1056 tr_OpenDoor(WID, NoSound, D2D)
1057 else
1058 tr_CloseDoor(WID, NoSound, D2D);
1059 end;
1061 function SP_Lua_DoorCloseTrap(L: PScriptContext): Integer; cdecl;
1062 // game.door_close_trap(panel_id[, silent=false, d2d_like=false])
1063 const
1064 MINARGS = 1;
1065 var
1066 D2D, NoSound: Boolean;
1067 PID, WID: Integer;
1068 Pan: PPanel;
1069 begin
1070 Result := 0;
1071 if not CheckArgs(L, MINARGS) then exit;
1073 PID := luaL_checkinteger(L, 1);
1074 NoSound := lua_toboolean(L, 2);
1075 D2D := lua_toboolean(L, 3);
1077 WID := -1;
1078 Pan := g_Map_PanelForPID(PID, WID);
1079 if (Pan = nil) or (not Pan^.Door) then exit;
1080 tr_CloseTrap(WID, NoSound, D2D);
1081 end;
1083 function SP_Lua_LiftSetDir(L: PScriptContext): Integer; cdecl;
1084 // game.lift_set_dir(panel_id, dir[, silent=false, d2d_like=false])
1085 const
1086 MINARGS = 2;
1087 var
1088 D2D, NoSound: Boolean;
1089 PID, WID, Dir: Integer;
1090 Pan: PPanel;
1091 begin
1092 Result := 0;
1093 if not CheckArgs(L, MINARGS) then exit;
1095 PID := luaL_checkinteger(L, 1);
1096 Dir := luaL_checkinteger(L, 2);
1097 NoSound := lua_toboolean(L, 3);
1098 D2D := lua_toboolean(L, 4);
1100 WID := -1;
1101 Pan := g_Map_PanelForPID(PID, WID);
1102 if (Pan = nil) or ((Pan^.LiftType = 0) and (Pan^.PanelType <> PANEL_LIFTUP)) then
1103 exit;
1104 tr_SetLift(WID, Dir, NoSound, D2D);
1105 end;
1107 // spawners //
1109 function SP_Lua_SpawnShot(L: PScriptContext): Integer; cdecl;
1110 // game.spawn_shot(type, x, y, vel_x, vel_y[, silent=false, target_id=0(noone)])
1111 const
1112 MINARGS = 5;
1113 var
1114 wx, wy, dx, dy, ShotType, ShotTarget: Integer;
1115 Silent: Boolean;
1116 ShotTargetW: Word;
1117 begin
1118 Result := 1;
1119 if not CheckArgs(L, MINARGS) then
1120 begin
1121 Result := 0;
1122 exit;
1123 end;
1125 ShotType := luaL_checkinteger(L, 1);
1126 wx := luaL_checkinteger(L, 2);
1127 wy := luaL_checkinteger(L, 3);
1128 dx := luaL_checkinteger(L, 4);
1129 dy := luaL_checkinteger(L, 5);
1131 Silent := lua_toboolean(L, 6);
1132 ShotTarget := lua_tointeger(L, 7);
1133 ShotTargetW := 0;
1134 if (ShotTarget > 0) and (ShotTarget < $FFFF) then
1135 ShotTargetW := ShotTarget;
1137 lua_pushinteger(L, tr_SpawnShot(ShotType, wx, wy, dx, dy, not Silent, ShotTargetW, DWORD(-1)));
1138 end;
1140 function SP_Lua_SpawnEffect(L: PScriptContext): Integer; cdecl;
1141 // game.spawn_effect(type, subtype, x, y, vel_x, vel_y[, silent=false, r=0, g=0, b=0])
1142 const
1143 MINARGS = 6;
1144 var
1145 X, Y, VX, VY: Integer;
1146 EType, ESubType: Integer;
1147 ER, EG, EB: Integer;
1148 Silent: Boolean;
1149 begin
1150 Result := 0;
1151 if not CheckArgs(L, MINARGS) then exit;
1153 EType := luaL_checkinteger(L, 1);
1154 ESubType := luaL_checkinteger(L, 2);
1155 X := luaL_checkinteger(L, 3);
1156 Y := luaL_checkinteger(L, 4);
1157 VX := luaL_checkinteger(L, 5);
1158 VY := luaL_checkinteger(L, 6);
1160 Silent := lua_toboolean(L, 7);
1161 ER := lua_tointeger(L, 8);
1162 EG := lua_tointeger(L, 8);
1163 EB := lua_tointeger(L, 8);
1165 tr_MakeEffect(X, Y, VX, VY, EType, ESubType, ER, EG, EB, Silent, True);
1166 end;
1168 function SP_Lua_SpawnMonster(L: PScriptContext): Integer; cdecl;
1169 // game.spawn_monster(type, x, y[, dir=left, awake=false, health=default, aitype=normal])
1170 const
1171 MINARGS = 3;
1172 var
1173 X, Y: Integer;
1174 Dir: TDirection;
1175 MType, MBType, MHP: Integer;
1176 MAwake: Boolean;
1177 MID, i: Integer;
1178 begin
1179 Result := 1;
1180 if not CheckArgs(L, MINARGS) then
1181 begin
1182 Result := 0;
1183 exit;
1184 end;
1186 MType := luaL_checkinteger(L, 1);
1187 X := luaL_checkinteger(L, 2);
1188 Y := luaL_checkinteger(L, 3);
1190 Dir := TDirection(lua_tointeger(L, 4) mod 2);
1191 MAwake := lua_toboolean(L, 5);
1192 MHP := lua_tointeger(L, 6);
1193 MBType := lua_tointeger(L, 7);
1195 MID := -1;
1197 if MType in [MONSTER_DEMON..MONSTER_MAN] then
1198 begin
1199 i := g_Monsters_Create(MType, X, Y, Dir, True);
1200 if i < 0 then exit;
1201 if MHP > 0 then
1202 gMonsters[i].SetHealth(MHP);
1203 gMonsters[i].MonsterBehaviour := MBType;
1204 gMonsters[i].FNoRespawn := True;
1205 if g_Game_IsNet then
1206 MH_SEND_MonsterSpawn(gMonsters[i].UID);
1207 if MAwake then
1208 gMonsters[i].WakeUp();
1209 if MType <> MONSTER_BARREL then Inc(gTotalMonsters);
1210 if g_Game_IsNet then
1211 begin
1212 SetLength(gMonstersSpawned, Length(gMonstersSpawned)+1);
1213 gMonstersSpawned[High(gMonstersSpawned)] := gMonsters[i].UID;
1214 MH_SEND_GameStats();
1215 MH_SEND_CoopStats();
1216 end;
1217 MID := gMonsters[i].UID;
1218 end;
1220 lua_pushinteger(L, MID);
1221 end;
1223 function SP_Lua_SpawnItem(L: PScriptContext): Integer; cdecl;
1224 // game.spawn_item(type, x, y[, falls=false])
1225 const
1226 MINARGS = 3;
1227 var
1228 X, Y: Integer;
1229 IType: Integer;
1230 IFalls: Boolean;
1231 i: Integer;
1232 begin
1233 Result := 1;
1234 if not CheckArgs(L, MINARGS) then
1235 begin
1236 Result := 0;
1237 exit;
1238 end;
1240 IType := luaL_checkinteger(L, 1);
1241 X := luaL_checkinteger(L, 2);
1242 Y := luaL_checkinteger(L, 3);
1244 IFalls := lua_toboolean(L, 4);
1246 i := -1;
1247 if IType in [ITEM_MEDKIT_SMALL..ITEM_MAX] then
1248 begin
1249 i := g_Items_Create(X, Y, IType, IFalls, False, True);
1250 if g_Game_IsNet then
1251 MH_SEND_ItemSpawn(True, i);
1252 end;
1254 lua_pushinteger(L, i);
1255 end;
1257 end.