1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 extern "C" {
7 #include <lua.h>
8 #include <lualib.h>
9 #include <lauxlib.h>
10 }
11 
12 #include "script.h"
13 
14 #include "../core/system.h"
15 #include "../core/gl_text.h"
16 #include "../core/console.h"
17 #include "../core/vmath.h"
18 #include "../physics/physics.h"
19 #include "../mesh.h"
20 #include "../skeletal_model.h"
21 #include "../trigger.h"
22 #include "../room.h"
23 #include "../gui/gui_inventory.h"
24 #include "../inventory.h"
25 #include "../entity.h"
26 #include "../world.h"
27 #include "../engine.h"
28 
29 
Script_ExecEntity(lua_State * lua,int id_callback,int id_object,int id_activator)30 int Script_ExecEntity(lua_State *lua, int id_callback, int id_object, int id_activator)
31 {
32     int top = lua_gettop(lua);
33     int ret = -1;
34 
35     lua_getglobal(lua, "entity_funcs");
36     if(!lua_istable(lua, -1))
37     {
38         lua_settop(lua, top);
39         return -1;
40     }
41 
42     lua_rawgeti(lua, -1, id_object);
43     if(!lua_istable(lua, -1))
44     {
45         lua_settop(lua, top);
46         return -1;
47     }
48 
49     switch(id_callback)
50     {
51         case ENTITY_CALLBACK_ACTIVATE:
52             lua_pushstring(lua, "onActivate");
53             break;
54 
55         case ENTITY_CALLBACK_DEACTIVATE:
56             lua_pushstring(lua, "onDeactivate");
57             break;
58 
59         case ENTITY_CALLBACK_COLLISION:
60             lua_pushstring(lua, "onCollide");
61             break;
62 
63         case ENTITY_CALLBACK_STAND:
64             lua_pushstring(lua, "onStand");
65             break;
66 
67         case ENTITY_CALLBACK_HIT:
68             lua_pushstring(lua, "onHit");
69             break;
70 
71         case ENTITY_CALLBACK_ATTACK:
72             lua_pushstring(lua, "onAttack");
73             break;
74 
75         case ENTITY_CALLBACK_SHOOT:
76             lua_pushstring(lua, "onShoot");
77             break;
78 
79         default:
80             lua_settop(lua, top);
81             return -1;
82     }
83 
84     lua_rawget(lua, -2);
85     if(!lua_isfunction(lua, -1))
86     {
87         lua_settop(lua, top);
88         return -1;
89     }
90 
91     lua_pushinteger(lua, id_object);
92     if(id_activator >= 0)
93     {
94         lua_pushinteger(lua, id_activator);
95     }
96     else
97     {
98         lua_pushnil(lua);
99     }
100 
101     if(lua_pcall(lua, 2, 1, 0) == LUA_OK)
102     {
103         ret = lua_tointeger(lua, -1);
104     }
105 
106     lua_settop(lua, top);
107 
108     return ret;
109 }
110 
111 
Script_EntityUpdateCollisionInfo(lua_State * lua,int id,struct collision_node_s * cn)112 int Script_EntityUpdateCollisionInfo(lua_State *lua, int id, struct collision_node_s *cn)
113 {
114     int top = lua_gettop(lua);
115 
116     lua_getglobal(lua, "entity_funcs");
117     if(!lua_istable(lua, -1))
118     {
119         lua_settop(lua, top);
120         return 0;
121     }
122 
123     lua_rawgeti(lua, -1, id);
124     if(!lua_istable(lua, -1))
125     {
126         lua_settop(lua, top);
127         return 0;
128     }
129 
130     lua_pushstring(lua, "col_part_from");
131     lua_pushinteger(lua, cn->part_from);
132     lua_settable(lua, -3);
133 
134     lua_pushstring(lua, "col_part_self");
135     lua_pushinteger(lua, cn->part_self);
136     lua_settable(lua, -3);
137 
138     lua_pushstring(lua, "col_px");
139     lua_pushnumber(lua, cn->penetration[0] * cn->penetration[3]);
140     lua_settable(lua, -3);
141 
142     lua_pushstring(lua, "col_py");
143     lua_pushnumber(lua, cn->penetration[1] * cn->penetration[3]);
144     lua_settable(lua, -3);
145 
146     lua_pushstring(lua, "col_pz");
147     lua_pushnumber(lua, cn->penetration[2] * cn->penetration[3]);
148     lua_settable(lua, -3);
149 
150     lua_settop(lua, top);
151 
152     return 1;
153 }
154 
155 
Script_GetEntitySaveData(lua_State * lua,int id_entity,char * buf,size_t buf_size)156 size_t Script_GetEntitySaveData(lua_State *lua, int id_entity, char *buf, size_t buf_size)
157 {
158     int top = lua_gettop(lua);
159     size_t ret = 0;
160 
161     lua_getglobal(lua, "getEntitySaveData");
162     if(lua_isfunction(lua, -1))
163     {
164         lua_pushinteger(lua, id_entity);
165         if((lua_pcall(lua, 1, 1, 0) == LUA_OK) && lua_isstring(lua, -1))
166         {
167             strncpy(buf, lua_tolstring(lua, -1, &ret), buf_size);
168         }
169     }
170     lua_settop(lua, top);
171 
172     return ret;
173 }
174 
175 
Script_LoopEntity(lua_State * lua,struct entity_s * ent)176 void Script_LoopEntity(lua_State *lua, struct entity_s *ent)
177 {
178     if(lua && ent && (ent->state_flags & ENTITY_STATE_ACTIVE))
179     {
180         int top = lua_gettop(lua);
181         int tick_state = TICK_ACTIVE;
182 
183         if(ent->timer > 0.0f)
184         {
185             ent->timer -= engine_frame_time;
186             if(ent->timer <= 0.0f)
187             {
188                 ent->timer = 0.0f;
189                 tick_state = TICK_STOPPED;
190             }
191         }
192         else
193         {
194             tick_state = TICK_IDLE;
195         }
196 
197         lua_getglobal(lua, "entity_funcs");
198         if(!lua_istable(lua, -1))
199         {
200             lua_settop(lua, top);
201             return;
202         }
203 
204         lua_rawgeti(lua, -1, ent->id);
205         if(!lua_istable(lua, -1))
206         {
207             lua_settop(lua, top);
208             return;
209         }
210 
211         lua_pushstring(lua, "onLoop");
212         lua_rawget(lua, -2);
213         if(!lua_isfunction(lua, -1))
214         {
215             lua_settop(lua, top);
216             return;
217         }
218 
219         lua_pushinteger(lua, ent->id);
220         lua_pushinteger(lua, tick_state);
221         lua_CallAndLog(lua, 2, 0, 0);
222 
223         lua_settop(lua, top);
224     }
225 }
226 
227 /*
228  * Base Entity trigger functions
229  */
lua_ActivateEntity(lua_State * lua)230 int lua_ActivateEntity(lua_State *lua)
231 {
232     if(lua_gettop(lua) >= 6)
233     {
234         entity_p object = World_GetEntityByID(lua_tointeger(lua, 1));
235         if(object)
236         {
237             entity_p activator          = World_GetEntityByID(lua_tointeger(lua, 2));
238             uint16_t trigger_mask       = lua_tointeger(lua, 3);
239             uint16_t trigger_op         = lua_tointeger(lua, 4);
240             uint16_t trigger_lock       = lua_tointeger(lua, 5);
241             uint16_t trigger_timer      = lua_tointeger(lua, 6);
242             uint16_t ret = Entity_Activate(object, activator, trigger_mask, trigger_op, trigger_lock, trigger_timer);
243             lua_pushinteger(lua, ret);
244             return 1;
245         }
246     }
247     else
248     {
249         Con_Warning("activateEntity: expecting arguments (object_id, activator_id, trigger_mask, trigger_op, trigger_lock, trigger_timer)");
250     }
251 
252     return 0;
253 }
254 
255 
lua_DeactivateEntity(lua_State * lua)256 int lua_DeactivateEntity(lua_State *lua)
257 {
258     if(lua_gettop(lua) >= 2)
259     {
260         entity_p object = World_GetEntityByID(lua_tointeger(lua, 1));
261         if(object)
262         {
263             entity_p activator = World_GetEntityByID(lua_tointeger(lua, 2));
264             uint16_t ret = Entity_Deactivate(object, activator);
265             lua_pushinteger(lua, ret);
266             return 1;
267         }
268     }
269     else
270     {
271         Con_Warning("deactivateEntity: expecting arguments (object_id, activator_id)");
272     }
273 
274     return 0;
275 }
276 
277 
lua_NoFixEntityCollision(lua_State * lua)278 int lua_NoFixEntityCollision(lua_State *lua)
279 {
280     if(lua_gettop(lua) >= 2)
281     {
282         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
283         if(ent)
284         {
285             ent->no_fix_all = lua_toboolean(lua, 2);
286         }
287     }
288     else
289     {
290         Con_Warning("noFixEntityCollision: Expecting arguments (entity_id, value)");
291     }
292 
293     return 0;
294 }
295 
296 
lua_NoEntityMove(lua_State * lua)297 int lua_NoEntityMove(lua_State *lua)
298 {
299     if(lua_gettop(lua) >= 2)
300     {
301         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
302         if(ent)
303         {
304             ent->no_move = lua_toboolean(lua, 2);
305         }
306     }
307     else
308     {
309         Con_Warning("noEntityMove: Expecting arguments (entity_id, value)");
310     }
311 
312     return 0;
313 }
314 
315 
lua_EnableEntity(lua_State * lua)316 int lua_EnableEntity(lua_State * lua)
317 {
318     if(lua_gettop(lua) >= 1)
319     {
320         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
321         if(ent)
322         {
323             Entity_Enable(ent);
324         }
325     }
326     else
327     {
328         Con_Warning("enableEntity: Expecting arguments (entity_id)");
329     }
330 
331     return 0;
332 }
333 
334 
lua_DisableEntity(lua_State * lua)335 int lua_DisableEntity(lua_State * lua)
336 {
337     if(lua_gettop(lua) >= 1)
338     {
339         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
340         if(ent)
341         {
342             Entity_Disable(ent);
343         }
344     }
345     else
346     {
347         Con_Warning("disableEntity: Expecting arguments (entity_id)");
348     }
349 
350     return 0;
351 }
352 
353 
lua_GetEntitySectorFlags(lua_State * lua)354 int lua_GetEntitySectorFlags(lua_State *lua)
355 {
356     if(lua_gettop(lua) >= 1)
357     {
358         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
359         if(ent && (ent->self->sector))
360         {
361             lua_pushinteger(lua, ent->self->sector->flags);
362             return 1;
363         }
364     }
365 
366     return 0;
367 }
368 
369 
lua_GetEntitySectorIndex(lua_State * lua)370 int lua_GetEntitySectorIndex(lua_State *lua)
371 {
372     if(lua_gettop(lua) >= 1)
373     {
374         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
375         if(ent && (ent->self->sector))
376         {
377             lua_pushinteger(lua, ent->self->sector->trig_index);
378             return 1;
379         }
380     }
381 
382     return 0;
383 }
384 
385 
lua_GetEntitySectorMaterial(lua_State * lua)386 int lua_GetEntitySectorMaterial(lua_State *lua)
387 {
388     if(lua_gettop(lua) >= 1)
389     {
390         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
391         if(ent && ent->self->sector)
392         {
393             lua_pushinteger(lua, ent->self->sector->material);
394             return 1;
395         }
396     }
397 
398     return 0;
399 }
400 
401 
lua_GetEntityBoxID(lua_State * lua)402 int lua_GetEntityBoxID(lua_State *lua)
403 {
404     int top = lua_gettop(lua);
405     if(top >= 3)
406     {
407         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
408         if(ent && ent->self->room)
409         {
410             float pos[3] = {ent->transform.M4x4[12 + 0], ent->transform.M4x4[12 + 1], ent->transform.M4x4[12 + 2]};
411             float dx = TR_METERING_SECTORSIZE * lua_tointeger(lua, 2);
412             float dy = TR_METERING_SECTORSIZE * lua_tointeger(lua, 3);
413             pos[0] += dx * ent->transform.M4x4[0 + 0] + dy * ent->transform.M4x4[4 + 0];
414             pos[1] += dx * ent->transform.M4x4[0 + 1] + dy * ent->transform.M4x4[4 + 1];
415             room_sector_p rs = Room_GetSectorRaw(ent->self->room, pos);
416             rs = Sector_GetPortalSectorTargetRaw(rs);
417             if(rs && rs->box)
418             {
419                 lua_pushinteger(lua, rs->box->id);
420                 lua_pushboolean(lua, rs->box->is_blockable);
421                 return 2;
422             }
423         }
424     }
425 
426     return 0;
427 }
428 
429 
lua_GetEntityActivationOffset(lua_State * lua)430 int lua_GetEntityActivationOffset(lua_State * lua)
431 {
432     if(lua_gettop(lua) >= 1)
433     {
434         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
435         if(ent && ent->activation_point)
436         {
437             lua_pushnumber(lua, ent->activation_point->offset[0]);
438             lua_pushnumber(lua, ent->activation_point->offset[1]);
439             lua_pushnumber(lua, ent->activation_point->offset[2]);
440             lua_pushnumber(lua, ent->activation_point->offset[3]);
441             return 4;
442         }
443     }
444 
445     return 0;
446 }
447 
448 
lua_SetEntityActivationOffset(lua_State * lua)449 int lua_SetEntityActivationOffset(lua_State * lua)
450 {
451     int top = lua_gettop(lua);
452 
453     if(top >= 1)
454     {
455         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
456         if(ent)
457         {
458             if(!ent->activation_point)
459             {
460                 Entity_InitActivationPoint(ent);
461             }
462 
463             if(top >= 4)
464             {
465                 ent->activation_point->offset[0] = lua_tonumber(lua, 2);
466                 ent->activation_point->offset[1] = lua_tonumber(lua, 3);
467                 ent->activation_point->offset[2] = lua_tonumber(lua, 4);
468             }
469             if(top >= 5)
470             {
471                 ent->activation_point->offset[3] = lua_tonumber(lua, 5);
472             }
473         }
474         else
475         {
476             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
477         }
478     }
479     else
480     {
481         Con_Warning("setEntityActivationOffset: Expecting arguments (entity_id)");
482     }
483 
484     return 0;
485 }
486 
487 
lua_GetEntityActivationDirection(lua_State * lua)488 int lua_GetEntityActivationDirection(lua_State * lua)
489 {
490     if(lua_gettop(lua) >= 1)
491     {
492         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
493         if(ent)
494         {
495             lua_pushnumber(lua, ent->activation_point->direction[0]);
496             lua_pushnumber(lua, ent->activation_point->direction[1]);
497             lua_pushnumber(lua, ent->activation_point->direction[2]);
498             lua_pushnumber(lua, ent->activation_point->direction[3]);
499             return 4;
500         }
501     }
502 
503     return 0;
504 }
505 
506 
lua_SetEntityActivationDirection(lua_State * lua)507 int lua_SetEntityActivationDirection(lua_State * lua)
508 {
509     int top = lua_gettop(lua);
510 
511     if(top >= 4)
512     {
513         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
514         if(ent)
515         {
516             if(!ent->activation_point)
517             {
518                 Entity_InitActivationPoint(ent);
519             }
520 
521             ent->activation_point->direction[0] = lua_tonumber(lua, 2);
522             ent->activation_point->direction[1] = lua_tonumber(lua, 3);
523             ent->activation_point->direction[2] = lua_tonumber(lua, 4);
524             if(top >= 5)
525             {
526                 ent->activation_point->direction[3] = lua_tonumber(lua, 5);
527             }
528         }
529         else
530         {
531             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
532         }
533     }
534     else
535     {
536         Con_Warning("setEntityActivationDirection: Expecting arguments (entity_id, x, y, z, (w))");
537     }
538 
539     return 0;
540 }
541 
542 
543 /*
544  * Moveables script control section
545  */
lua_GetEntityVector(lua_State * lua)546 int lua_GetEntityVector(lua_State * lua)
547 {
548     if(lua_gettop(lua) >= 2)
549     {
550         entity_p e1 = World_GetEntityByID(lua_tointeger(lua, 1));
551         entity_p e2 = World_GetEntityByID(lua_tointeger(lua, 2));
552         if(e1 && e2)
553         {
554             lua_pushnumber(lua, e2->transform.M4x4[12 + 0] - e1->transform.M4x4[12 + 0]);
555             lua_pushnumber(lua, e2->transform.M4x4[12 + 1] - e1->transform.M4x4[12 + 1]);
556             lua_pushnumber(lua, e2->transform.M4x4[12 + 2] - e1->transform.M4x4[12 + 2]);
557             return 3;
558         }
559     }
560     else
561     {
562         Con_Warning("getEntityVector: expecting arguments (entity_id1, entity_id2)");
563     }
564 
565     return 0;
566 }
567 
568 
lua_GetEntityDistance(lua_State * lua)569 int lua_GetEntityDistance(lua_State * lua)
570 {
571     if(lua_gettop(lua) >= 2)
572     {
573         entity_p e1 = World_GetEntityByID(lua_tointeger(lua, 1));
574         entity_p e2 = World_GetEntityByID(lua_tointeger(lua, 2));
575         if(e1 && e2)
576         {
577             lua_pushnumber(lua, vec3_dist(e1->transform.M4x4 + 12, e2->transform.M4x4 + 12));
578             return 1;
579         }
580     }
581     else
582     {
583         Con_Warning("getEntityDistance: expecting arguments (entity_id1, entity_id2)");
584     }
585 
586     return 0;
587 }
588 
589 
lua_GetEntityDirDot(lua_State * lua)590 int lua_GetEntityDirDot(lua_State * lua)
591 {
592     if(lua_gettop(lua) >= 2)
593     {
594         entity_p e1 = World_GetEntityByID(lua_tointeger(lua, 1));
595         entity_p e2 = World_GetEntityByID(lua_tointeger(lua, 2));
596         if(e1 && e2)
597         {
598             lua_pushnumber(lua, vec3_dot(e1->transform.M4x4 + 4, e2->transform.M4x4 + 4));
599             return 1;
600         }
601     }
602     else
603     {
604         Con_Warning("getEntityDirDot: expecting arguments (id1, id2)");
605     }
606 
607     return 0;
608 }
609 
610 
lua_GetEntityRoom(lua_State * lua)611 int lua_GetEntityRoom(lua_State * lua)
612 {
613     if(lua_gettop(lua) >= 1)
614     {
615         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
616         if(ent)
617         {
618             if(ent->self->room)
619             {
620                 lua_pushinteger(lua, ent->self->room->id);
621             }
622             else
623             {
624                 lua_pushnil(lua);
625             }
626             return 1;
627         }
628         else
629         {
630             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
631         }
632     }
633     else
634     {
635         Con_Warning("getEntityRoom: expecting arguments (entity_id)");
636     }
637 
638     return 0;
639 }
640 
641 
lua_GetEntityPosition(lua_State * lua)642 int lua_GetEntityPosition(lua_State * lua)
643 {
644     if(lua_gettop(lua) >= 1)
645     {
646         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
647         if(ent)
648         {
649             lua_pushnumber(lua, ent->transform.M4x4[12 + 0]);
650             lua_pushnumber(lua, ent->transform.M4x4[12 + 1]);
651             lua_pushnumber(lua, ent->transform.M4x4[12 + 2]);
652             lua_pushnumber(lua, ent->transform.angles[0]);
653             lua_pushnumber(lua, ent->transform.angles[1]);
654             lua_pushnumber(lua, ent->transform.angles[2]);
655             return 6;
656         }
657         else
658         {
659             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
660         }
661     }
662     else
663     {
664         Con_Warning("getEntityPosition: expecting arguments (entity_id)");
665     }
666 
667     return 0;
668 }
669 
670 
lua_GetEntityAngles(lua_State * lua)671 int lua_GetEntityAngles(lua_State * lua)
672 {
673     if(lua_gettop(lua) >= 1)
674     {
675         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
676         if(ent)
677         {
678             lua_pushnumber(lua, ent->transform.angles[0]);
679             lua_pushnumber(lua, ent->transform.angles[1]);
680             lua_pushnumber(lua, ent->transform.angles[2]);
681             return 3;
682         }
683         else
684         {
685             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
686         }
687     }
688     else
689     {
690         Con_Warning("getEntityAngles: expecting arguments (entity_id)");
691     }
692 
693     return 0;
694 }
695 
696 
lua_GetEntityScaling(lua_State * lua)697 int lua_GetEntityScaling(lua_State * lua)
698 {
699     if(lua_gettop(lua) >= 1)
700     {
701         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
702         if(ent)
703         {
704             lua_pushnumber(lua, ent->transform.scaling[0]);
705             lua_pushnumber(lua, ent->transform.scaling[1]);
706             lua_pushnumber(lua, ent->transform.scaling[2]);
707             return 3;
708         }
709         else
710         {
711             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
712         }
713     }
714     else
715     {
716         Con_Warning("getEntityScaling: expecting arguments (entity_id)");
717     }
718 
719     return 0;
720 }
721 
722 
lua_SetEntityScaling(lua_State * lua)723 int lua_SetEntityScaling(lua_State * lua)
724 {
725     if(lua_gettop(lua) >= 4)
726     {
727         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
728         if(ent)
729         {
730             ent->transform.scaling[0] = lua_tonumber(lua, 2);
731             ent->transform.scaling[1] = lua_tonumber(lua, 3);
732             ent->transform.scaling[2] = lua_tonumber(lua, 4);
733 
734             Physics_SetCollisionScale(ent->physics, ent->transform.scaling);
735             Entity_UpdateRigidBody(ent, 1);
736         }
737         else
738         {
739             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
740         }
741     }
742     else
743     {
744         Con_Warning("setEntityScaling: expecting arguments (entity_id, x_scaling, y_scaling, z_scaling)");
745     }
746 
747     return 0;
748 }
749 
750 
lua_SetEntityPosition(lua_State * lua)751 int lua_SetEntityPosition(lua_State * lua)
752 {
753     switch(lua_gettop(lua))
754     {
755         case 4:
756             {
757                 entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
758                 if(ent)
759                 {
760                     ent->transform.M4x4[12 + 0] = lua_tonumber(lua, 2);
761                     ent->transform.M4x4[12 + 1] = lua_tonumber(lua, 3);
762                     ent->transform.M4x4[12 + 2] = lua_tonumber(lua, 4);
763                     Entity_UpdateRigidBody(ent, 1);
764                 }
765                 else
766                 {
767                     Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
768                 }
769             }
770             return 0;
771 
772         case 7:
773             {
774                 entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
775                 if(ent)
776                 {
777                     ent->transform.M4x4[12 + 0] = lua_tonumber(lua, 2);
778                     ent->transform.M4x4[12 + 1] = lua_tonumber(lua, 3);
779                     ent->transform.M4x4[12 + 2] = lua_tonumber(lua, 4);
780                     ent->transform.angles[0] = lua_tonumber(lua, 5);
781                     ent->transform.angles[1] = lua_tonumber(lua, 6);
782                     ent->transform.angles[2] = lua_tonumber(lua, 7);
783                     Entity_UpdateTransform(ent);
784                     Entity_UpdateRigidBody(ent, 1);
785                 }
786                 else
787                 {
788                     Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
789                 }
790             }
791             return 0;
792 
793         default:
794             Con_Warning("setEntityPosition: expecting arguments (entity_id, x, y, z, (fi_x, fi_y, fi_z))");
795             return 0;
796     }
797 
798     return 0;
799 }
800 
801 
lua_SetEntityAngles(lua_State * lua)802 int lua_SetEntityAngles(lua_State * lua)
803 {
804     if(lua_gettop(lua) >= 4)
805     {
806         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
807         if(ent)
808         {
809             ent->transform.angles[0] = lua_tonumber(lua, 2);
810             ent->transform.angles[1] = lua_tonumber(lua, 3);
811             ent->transform.angles[2] = lua_tonumber(lua, 4);
812             Entity_UpdateTransform(ent);
813         }
814         else
815         {
816             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
817         }
818     }
819     else
820     {
821         Con_Warning("setEntityAngles: expecting arguments (entity_id, fi_x, (fi_y, fi_z))");
822     }
823 
824     return 0;
825 }
826 
827 
lua_MoveEntityGlobal(lua_State * lua)828 int lua_MoveEntityGlobal(lua_State * lua)
829 {
830     switch(lua_gettop(lua))
831     {
832         case 4:
833             {
834                 entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
835                 if(ent)
836                 {
837                     ent->transform.M4x4[12 + 0] += lua_tonumber(lua, 2);
838                     ent->transform.M4x4[12 + 1] += lua_tonumber(lua, 3);
839                     ent->transform.M4x4[12 + 2] += lua_tonumber(lua, 4);
840                     Entity_UpdateRigidBody(ent, 1);
841                 }
842                 else
843                 {
844                     Con_Printf("can not find entity with id = %d", lua_tointeger(lua, 1));
845                 }
846             }
847             return 0;
848 
849         default:
850             Con_Warning("moveEntityGlobal: expecting arguments (entity_id, x, y, z)");
851             return 0;
852     }
853 
854     return 0;
855 }
856 
857 
lua_MoveEntityLocal(lua_State * lua)858 int lua_MoveEntityLocal(lua_State * lua)
859 {
860     if(lua_gettop(lua) >= 4)
861     {
862         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
863         if(ent)
864         {
865             float dx = lua_tonumber(lua, 2);
866             float dy = lua_tonumber(lua, 3);
867             float dz = lua_tonumber(lua, 4);
868 
869             ent->transform.M4x4[12 + 0] += dx * ent->transform.M4x4[0 + 0] + dy * ent->transform.M4x4[4 + 0] + dz * ent->transform.M4x4[8 + 0];
870             ent->transform.M4x4[12 + 1] += dx * ent->transform.M4x4[0 + 1] + dy * ent->transform.M4x4[4 + 1] + dz * ent->transform.M4x4[8 + 1];
871             ent->transform.M4x4[12 + 2] += dx * ent->transform.M4x4[0 + 2] + dy * ent->transform.M4x4[4 + 2] + dz * ent->transform.M4x4[8 + 2];
872 
873             Entity_UpdateRigidBody(ent, 1);
874         }
875         else
876         {
877             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
878         }
879     }
880     else
881     {
882         Con_Warning("moveEntityLocal: expecting arguments (entity_id, dx, dy, dz)");
883     }
884 
885     return 0;
886 }
887 
888 
lua_MoveEntityToSink(lua_State * lua)889 int lua_MoveEntityToSink(lua_State * lua)
890 {
891     if(lua_gettop(lua) >= 2)
892     {
893         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
894         if(ent)
895         {
896             Entity_MoveToSink(ent, World_GetStaticCameraSink(lua_tointeger(lua, 2)));
897         }
898     }
899     else
900     {
901         Con_Warning("moveEntityToSink: expecting arguments (entity_id, sink_id)");
902     }
903 
904     return 0;
905 }
906 
907 
lua_MoveEntityToEntity(lua_State * lua)908 int lua_MoveEntityToEntity(lua_State * lua)
909 {
910     int top = lua_gettop(lua);
911 
912     if(top >= 3)
913     {
914         entity_p ent1 = World_GetEntityByID(lua_tointeger(lua, 1));
915         entity_p ent2 = World_GetEntityByID(lua_tointeger(lua, 2));
916         if(ent1 && ent2)
917         {
918             float speed_mult = lua_tonumber(lua, 3);
919             float *ent1_pos = ent1->transform.M4x4 + 12;
920             float *ent2_pos = ent2->transform.M4x4 + 12;
921             float t, speed[3];
922 
923             vec3_sub(speed, ent2_pos, ent1_pos);
924             t = vec3_abs(speed);
925             t = (t == 0.0f) ? 1.0f : t; // Prevents division by zero.
926             t = speed_mult / t;
927 
928             ent1->transform.M4x4[12 + 0] += speed[0] * t;
929             ent1->transform.M4x4[12 + 1] += speed[1] * t;
930             if((top == 3) || !lua_toboolean(lua, 4))
931             {
932                 ent1->transform.M4x4[12 + 2] += speed[2] * t;
933             }
934 
935             Entity_UpdateRigidBody(ent1, 1);
936         }
937     }
938     else
939     {
940         Con_Warning("moveEntityToEntity: expecting arguments (moved_entity_id, target_entity_id, speed, (ignore_z))");
941     }
942 
943     return 0;
944 }
945 
946 
lua_RotateEntity(lua_State * lua)947 int lua_RotateEntity(lua_State *lua)
948 {
949     int top = lua_gettop(lua);
950 
951     if(top >= 2)
952     {
953         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
954         if(ent)
955         {
956             ent->transform.angles[0] += lua_tonumber(lua, 2);
957             if(top >= 4)
958             {
959                  ent->transform.angles[1] += lua_tonumber(lua, 3);
960                  ent->transform.angles[2] += lua_tonumber(lua, 4);
961             }
962             Entity_UpdateTransform(ent);
963             Entity_UpdateRigidBody(ent, 1);
964         }
965         else
966         {
967             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
968         }
969     }
970     else
971     {
972         Con_Warning("rotateEntity: expecting arguments (ent_id, rot_x, (rot_y, rot_z))");
973     }
974 
975     return 0;
976 }
977 
978 
lua_GetEntitySpeed(lua_State * lua)979 int lua_GetEntitySpeed(lua_State * lua)
980 {
981     if(lua_gettop(lua) >= 1)
982     {
983         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
984         if(ent)
985         {
986             lua_pushnumber(lua, ent->speed[0]);
987             lua_pushnumber(lua, ent->speed[1]);
988             lua_pushnumber(lua, ent->speed[2]);
989             return 3;
990         }
991         else
992         {
993             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
994         }
995     }
996     else
997     {
998         Con_Warning("getEntitySpeed: expecting arguments (entity_id)");
999     }
1000 
1001     return 0;
1002 }
1003 
1004 
lua_GetEntitySpeedLinear(lua_State * lua)1005 int lua_GetEntitySpeedLinear(lua_State * lua)
1006 {
1007     if(lua_gettop(lua) >= 1)
1008     {
1009         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1010         if(ent)
1011         {
1012             lua_pushnumber(lua, vec3_abs(ent->speed));
1013             return 1;
1014         }
1015         else
1016         {
1017             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1018         }
1019     }
1020     else
1021     {
1022         Con_Warning("getEntitySpeedLinear: expecting arguments (entity_id)");
1023     }
1024 
1025     return 0;
1026 }
1027 
1028 
lua_SetEntitySpeed(lua_State * lua)1029 int lua_SetEntitySpeed(lua_State * lua)
1030 {
1031     if(lua_gettop(lua) >= 4)
1032     {
1033         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1034         if(ent)
1035         {
1036             ent->speed[0] = lua_tonumber(lua, 2);
1037             ent->speed[1] = lua_tonumber(lua, 3);
1038             ent->speed[2] = lua_tonumber(lua, 4);
1039         }
1040         else
1041         {
1042             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1043         }
1044     }
1045     else
1046     {
1047         Con_Warning("setEntitySpeed: expecting arguments (id, speed_x, speed_y, speed_z)");
1048     }
1049 
1050     return 0;
1051 }
1052 
1053 
lua_SetEntityLinearSpeed(lua_State * lua)1054 int lua_SetEntityLinearSpeed(lua_State * lua)
1055 {
1056     if(lua_gettop(lua) >= 2)
1057     {
1058         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1059         if(ent)
1060         {
1061             ent->linear_speed = lua_tonumber(lua, 2);
1062         }
1063         else
1064         {
1065             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1066         }
1067     }
1068     else
1069     {
1070         Con_Warning("setEntityLinearSpeed: expecting arguments (id, speed");
1071     }
1072 
1073     return 0;
1074 }
1075 
1076 
lua_SetEntityBodyPartFlag(lua_State * lua)1077 int lua_SetEntityBodyPartFlag(lua_State * lua)
1078 {
1079     if(lua_gettop(lua) >= 3)
1080     {
1081         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1082         if(ent)
1083         {
1084             int bone_id = lua_tointeger(lua, 2);
1085             if((bone_id >= 0) && (bone_id < ent->bf->bone_tag_count))
1086             {
1087                 ent->bf->bone_tags[bone_id].body_part = lua_tointeger(lua, 3);
1088             }
1089         }
1090         else
1091         {
1092             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1093         }
1094     }
1095     else
1096     {
1097         Con_Warning("setEntityBodyPartFlag: expecting arguments (entity_id, bone_id, body_part_flag)");
1098     }
1099 
1100     return 0;
1101 }
1102 
1103 
lua_AddItem(lua_State * lua)1104 int lua_AddItem(lua_State * lua)
1105 {
1106     int top = lua_gettop(lua);
1107     if(top >= 2)
1108     {
1109         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1110         if(ent)
1111         {
1112             entity_p player = World_GetPlayer();
1113             int item_id = lua_tointeger(lua, 2);
1114             int count = (top >= 3) ? (lua_tointeger(lua, 3)) : (1);
1115             lua_pushinteger(lua, Inventory_AddItem(&ent->inventory, item_id, count));
1116             if(!player || ent->id == player->id)
1117             {
1118                 Gui_NotifierStart(item_id);
1119             }
1120             return 1;
1121         }
1122         else
1123         {
1124             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1125         }
1126     }
1127     else
1128     {
1129         Con_Warning("addItem: expecting arguments (entity_id, item_id, (items_count = pickup_count))");
1130     }
1131 
1132     return 0;
1133 }
1134 
1135 
lua_RemoveItem(lua_State * lua)1136 int lua_RemoveItem(lua_State * lua)
1137 {
1138     if(lua_gettop(lua) >= 3)
1139     {
1140         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1141         if(ent)
1142         {
1143             int item_id = lua_tointeger(lua, 2);
1144             int count = lua_tointeger(lua, 3);
1145             lua_pushinteger(lua, Inventory_RemoveItem(&ent->inventory, item_id, count));
1146             return 1;
1147         }
1148         else
1149         {
1150             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1151         }
1152     }
1153     else
1154     {
1155         Con_Warning("removeItem: expecting arguments (entity_id, item_id, items_count)");
1156     }
1157 
1158     return 0;
1159 }
1160 
1161 
lua_RemoveAllItems(lua_State * lua)1162 int lua_RemoveAllItems(lua_State * lua)
1163 {
1164     if(lua_gettop(lua) >= 1)
1165     {
1166         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1167         if(ent)
1168         {
1169             Inventory_RemoveAllItems(&ent->inventory);
1170         }
1171         else
1172         {
1173             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1174         }
1175     }
1176     else
1177     {
1178         Con_Warning("removeAllItems: expecting arguments (entity_id)");
1179     }
1180 
1181     return 0;
1182 }
1183 
1184 
lua_GetItemsCount(lua_State * lua)1185 int lua_GetItemsCount(lua_State * lua)
1186 {
1187     if(lua_gettop(lua) >= 2)
1188     {
1189         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1190         if(ent)
1191         {
1192             int item_id = lua_tointeger(lua, 2);
1193             lua_pushinteger(lua, Inventory_GetItemsCount(ent->inventory, item_id));
1194             return 1;
1195         }
1196         else
1197         {
1198             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1199         }
1200     }
1201     else
1202     {
1203         Con_Warning("getItemsCount: expecting arguments (entity_id, item_id)");
1204     }
1205 
1206     return 0;
1207 }
1208 
1209 
lua_GetItems(lua_State * lua)1210 int lua_GetItems(lua_State * lua)
1211 {
1212     if(lua_gettop(lua) >= 1)
1213     {
1214         entity_p  ent = World_GetEntityByID(lua_tointeger(lua, 1));
1215         if(ent)
1216         {
1217             lua_newtable(lua);
1218             int top = lua_gettop(lua);
1219             for(inventory_node_p i = ent->inventory; i; i = i->next)
1220             {
1221                 lua_pushinteger(lua, i->count);
1222                 lua_rawseti(lua, -2, i->id);
1223                 lua_settop(lua, top);
1224             }
1225 
1226             return 1;
1227         }
1228         else
1229         {
1230             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1231         }
1232     }
1233     else
1234     {
1235         Con_Warning("getItems: expecting arguments (entity_id)");
1236     }
1237 
1238     return 0;
1239 }
1240 
1241 
lua_CanTriggerEntity(lua_State * lua)1242 int lua_CanTriggerEntity(lua_State * lua)
1243 {
1244     if(lua_gettop(lua) >= 2)
1245     {
1246         lua_pushboolean(lua, Entity_CanTrigger(World_GetEntityByID(lua_tointeger(lua, 1)),
1247                                                World_GetEntityByID(lua_tointeger(lua, 2))));
1248     }
1249     else
1250     {
1251         lua_pushboolean(lua, false);
1252     }
1253 
1254     return 1;
1255 }
1256 
1257 
lua_EntityRotateToTriggerZ(lua_State * lua)1258 int lua_EntityRotateToTriggerZ(lua_State * lua)
1259 {
1260     if(lua_gettop(lua) >= 2)
1261     {
1262         Entity_RotateToTriggerZ(World_GetEntityByID(lua_tointeger(lua, 1)),
1263                                 World_GetEntityByID(lua_tointeger(lua, 2)));
1264     }
1265 
1266     return 0;
1267 }
1268 
1269 
lua_EntityRotateToTrigger(lua_State * lua)1270 int lua_EntityRotateToTrigger(lua_State * lua)
1271 {
1272     if(lua_gettop(lua) >= 3)
1273     {
1274         Entity_RotateToTrigger(World_GetEntityByID(lua_tointeger(lua, 1)),
1275                                World_GetEntityByID(lua_tointeger(lua, 2)),
1276                                lua_tointeger(lua, 3));
1277     }
1278 
1279     return 0;
1280 }
1281 
1282 
lua_EntityMoveToTriggerActivationPoint(lua_State * lua)1283 int lua_EntityMoveToTriggerActivationPoint(lua_State * lua)
1284 {
1285     if(lua_gettop(lua) >= 2)
1286     {
1287         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1288         entity_p trigger = World_GetEntityByID(lua_tointeger(lua, 2));
1289         if(ent && trigger && trigger->activation_point)
1290         {
1291             float *pos = ent->transform.M4x4 + 12;
1292             Mat4_vec3_mul_macro(pos, trigger->transform.M4x4, trigger->activation_point->offset);
1293         }
1294     }
1295 
1296     return 0;
1297 }
1298 
1299 
lua_GetEntityVisibility(lua_State * lua)1300 int lua_GetEntityVisibility(lua_State * lua)
1301 {
1302     if(lua_gettop(lua) >= 1)
1303     {
1304         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1305         if(ent)
1306         {
1307             lua_pushinteger(lua, (ent->state_flags & ENTITY_STATE_VISIBLE) != 0);
1308             return 1;
1309         }
1310         else
1311         {
1312             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1313         }
1314     }
1315     else
1316     {
1317         Con_Warning("getEntityVisibility: expecting arguments (entity_id)");
1318     }
1319 
1320     return 0;
1321 }
1322 
1323 
lua_SetEntityVisibility(lua_State * lua)1324 int lua_SetEntityVisibility(lua_State * lua)
1325 {
1326     if(lua_gettop(lua) >= 2)
1327     {
1328         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1329         if(ent)
1330         {
1331             if(lua_toboolean(lua, 2))
1332             {
1333                 ent->state_flags |= ENTITY_STATE_VISIBLE;
1334             }
1335             else
1336             {
1337                 ent->state_flags &= ~ENTITY_STATE_VISIBLE;
1338             }
1339         }
1340         else
1341         {
1342             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1343         }
1344     }
1345     else
1346     {
1347         Con_Warning("setEntityVisibility: expecting arguments (entity_id, value)");
1348     }
1349 
1350     return 0;
1351 }
1352 
1353 
lua_GetEntityEnability(lua_State * lua)1354 int lua_GetEntityEnability(lua_State * lua)
1355 {
1356     if(lua_gettop(lua) >= 1)
1357     {
1358         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1359         if(ent)
1360         {
1361             lua_pushboolean(lua, (ent->state_flags & ENTITY_STATE_ENABLED) != 0);
1362             return 1;
1363         }
1364         else
1365         {
1366             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1367         }
1368     }
1369     else
1370     {
1371         Con_Warning("getEntityEnability: expecting arguments (entity_id)");
1372     }
1373 
1374     return 0;
1375 }
1376 
1377 
lua_GetEntityActivity(lua_State * lua)1378 int lua_GetEntityActivity(lua_State * lua)
1379 {
1380     if(lua_gettop(lua) >= 1)
1381     {
1382         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1383         if(ent)
1384         {
1385             lua_pushboolean(lua, (ent->state_flags & ENTITY_STATE_ACTIVE) != 0);
1386             return 1;
1387         }
1388         else
1389         {
1390             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1391         }
1392     }
1393     else
1394     {
1395         Con_Warning("getEntityActivity: expecting arguments (entity_id)");
1396     }
1397 
1398     return 0;
1399 }
1400 
1401 
lua_SetEntityActivity(lua_State * lua)1402 int lua_SetEntityActivity(lua_State * lua)
1403 {
1404     if(lua_gettop(lua) >= 2)
1405     {
1406         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1407         if(ent)
1408         {
1409             if(lua_toboolean(lua, 2))
1410             {
1411                 ent->state_flags |= ENTITY_STATE_ACTIVE;
1412             }
1413             else
1414             {
1415                 ent->state_flags &= ~ENTITY_STATE_ACTIVE;
1416             }
1417         }
1418         else
1419         {
1420             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1421         }
1422     }
1423     else
1424     {
1425         Con_Warning("setEntityActivity: expecting arguments (entity_id, value)");
1426     }
1427 
1428     return 0;
1429 }
1430 
1431 
lua_GetEntityTriggerLayout(lua_State * lua)1432 int lua_GetEntityTriggerLayout(lua_State *lua)
1433 {
1434     if(lua_gettop(lua) >= 1)
1435     {
1436         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1437         if(ent)
1438         {
1439             lua_pushinteger(lua, (ent->trigger_layout & ENTITY_TLAYOUT_MASK));          // mask
1440             lua_pushinteger(lua, (ent->trigger_layout & ENTITY_TLAYOUT_EVENT) >> 5);    // event
1441             lua_pushinteger(lua, (ent->trigger_layout & ENTITY_TLAYOUT_LOCK) >> 6);     // lock
1442             return 3;
1443         }
1444     }
1445 
1446     return 0;
1447 }
1448 
1449 
lua_SetEntityTriggerLayout(lua_State * lua)1450 int lua_SetEntityTriggerLayout(lua_State *lua)
1451 {
1452     int top = lua_gettop(lua);
1453 
1454     if(top >= 2)
1455     {
1456         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1457         if(ent)
1458         {
1459             if(top == 2)
1460             {
1461                 ent->trigger_layout = (uint8_t)lua_tointeger(lua, 2);
1462             }
1463             else if(top == 4)
1464             {
1465                 uint8_t trigger_layout = ent->trigger_layout;
1466                 trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_MASK);
1467                 trigger_layout ^= (uint8_t)lua_tointeger(lua, 2);          // mask  - 00011111
1468                 trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_EVENT);
1469                 trigger_layout ^= ((uint8_t)lua_tointeger(lua, 3)) << 5;   // event - 00100000
1470                 trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_LOCK);
1471                 trigger_layout ^= ((uint8_t)lua_tointeger(lua, 4)) << 6;   // lock  - 01000000
1472                 ent->trigger_layout = trigger_layout;
1473             }
1474         }
1475         else
1476         {
1477             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1478         }
1479     }
1480     else
1481     {
1482         Con_Warning("setEntityTriggerLayout: expecting arguments (entity_id, layout) or (entity_id, mask, event, once)");
1483     }
1484 
1485     return 0;
1486 }
1487 
1488 
lua_SetEntityLock(lua_State * lua)1489 int lua_SetEntityLock(lua_State * lua)
1490 {
1491     if(lua_gettop(lua) >= 2)
1492     {
1493         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1494         if(ent)
1495         {
1496             uint8_t trigger_layout = ent->trigger_layout;
1497             trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_LOCK);
1498             trigger_layout ^= ((uint8_t)lua_tointeger(lua, 2)) << 6;   // lock  - 01000000
1499             ent->trigger_layout = trigger_layout;
1500         }
1501     }
1502 
1503     return 0;
1504 }
1505 
1506 
lua_GetEntityLock(lua_State * lua)1507 int lua_GetEntityLock(lua_State * lua)
1508 {
1509     if(lua_gettop(lua) >= 1)
1510     {
1511         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1512         if(ent)
1513         {
1514             lua_pushinteger(lua, ((ent->trigger_layout & ENTITY_TLAYOUT_LOCK) >> 6));      // lock
1515             return 1;
1516         }
1517     }
1518 
1519     return 0;
1520 }
1521 
1522 
lua_SetEntityEvent(lua_State * lua)1523 int lua_SetEntityEvent(lua_State * lua)
1524 {
1525     if(lua_gettop(lua) >= 2)
1526     {
1527         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1528         if(ent)
1529         {
1530             uint8_t trigger_layout = ent->trigger_layout;
1531             trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_EVENT);
1532             trigger_layout ^= ((uint8_t)lua_tointeger(lua, 2)) << 5;   // event - 00100000
1533             ent->trigger_layout = trigger_layout;
1534         }
1535     }
1536 
1537     return 0;
1538 }
1539 
1540 
lua_GetEntityEvent(lua_State * lua)1541 int lua_GetEntityEvent(lua_State *lua)
1542 {
1543     if(lua_gettop(lua) >= 1)
1544     {
1545         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1546         if(ent)
1547         {
1548             lua_pushinteger(lua, ((ent->trigger_layout & ENTITY_TLAYOUT_EVENT) >> 5));    // event
1549             return 1;
1550         }
1551     }
1552 
1553     return 0;
1554 }
1555 
1556 
lua_GetEntityMask(lua_State * lua)1557 int lua_GetEntityMask(lua_State * lua)
1558 {
1559     if(lua_gettop(lua) >= 1)
1560     {
1561         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1562         if(ent)
1563         {
1564             lua_pushinteger(lua, (ent->trigger_layout & ENTITY_TLAYOUT_MASK));      // mask
1565             return 1;
1566         }
1567     }
1568 
1569     return 0;
1570 }
1571 
1572 
lua_SetEntityMask(lua_State * lua)1573 int lua_SetEntityMask(lua_State * lua)
1574 {
1575     if(lua_gettop(lua) >= 2)
1576     {
1577         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1578         if(ent)
1579         {
1580             uint8_t trigger_layout = ent->trigger_layout;
1581             trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_MASK);
1582             trigger_layout ^= (uint8_t)lua_tointeger(lua, 2);   // mask  - 00011111
1583             ent->trigger_layout = trigger_layout;
1584         }
1585     }
1586 
1587     return 0;
1588 }
1589 
1590 
lua_GetEntitySectorStatus(lua_State * lua)1591 int lua_GetEntitySectorStatus(lua_State *lua)
1592 {
1593     if(lua_gettop(lua) >= 1)
1594     {
1595         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1596         if(ent)
1597         {
1598             lua_pushinteger(lua, ((ent->trigger_layout & ENTITY_TLAYOUT_SSTATUS) >> 7));
1599             return 1;
1600         }
1601     }
1602 
1603     return 0;
1604 }
1605 
1606 
lua_SetEntitySectorStatus(lua_State * lua)1607 int lua_SetEntitySectorStatus(lua_State *lua)
1608 {
1609     if(lua_gettop(lua) >= 2)
1610     {
1611         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1612         if(ent)
1613         {
1614             uint8_t trigger_layout = ent->trigger_layout;
1615             trigger_layout &= ~(uint8_t)(ENTITY_TLAYOUT_SSTATUS);
1616             trigger_layout ^=  ((uint8_t)lua_tointeger(lua, 2)) << 7;   // sector_status  - 10000000
1617             ent->trigger_layout = trigger_layout;
1618         }
1619     }
1620 
1621     return 0;
1622 }
1623 
1624 
lua_GetEntityOCB(lua_State * lua)1625 int lua_GetEntityOCB(lua_State * lua)
1626 {
1627     if(lua_gettop(lua) >= 1)
1628     {
1629         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1630         if(ent)
1631         {
1632             lua_pushinteger(lua, ent->OCB);
1633             return 1;
1634         }
1635     }
1636 
1637     return 0;   // No entity found - return.
1638 }
1639 
1640 
lua_SetEntityOCB(lua_State * lua)1641 int lua_SetEntityOCB(lua_State * lua)
1642 {
1643     if(lua_gettop(lua) >= 2)
1644     {
1645         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1646         if(ent)
1647         {
1648             ent->OCB = lua_tointeger(lua, 2);
1649         }
1650     }
1651 
1652     return 0;
1653 }
1654 
1655 
lua_GetEntityFlags(lua_State * lua)1656 int lua_GetEntityFlags(lua_State * lua)
1657 {
1658     if(lua_gettop(lua) >= 1)
1659     {
1660         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1661         if(ent)
1662         {
1663             lua_pushinteger(lua, ent->state_flags);
1664             lua_pushinteger(lua, ent->type_flags);
1665             lua_pushinteger(lua, ent->callback_flags);
1666             return 3;
1667         }
1668         else
1669         {
1670             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1671         }
1672     }
1673     else
1674     {
1675         Con_Warning("getEntityFlags: expecting arguments (entity_id)");
1676     }
1677 
1678     return 0;
1679 }
1680 
1681 
lua_SetEntityFlags(lua_State * lua)1682 int lua_SetEntityFlags(lua_State * lua)
1683 {
1684     if(lua_gettop(lua) >= 4)
1685     {
1686         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1687         if(ent)
1688         {
1689             if(!lua_isnil(lua, 2))
1690             {
1691                 ent->state_flags = lua_tointeger(lua, 2);
1692                 if(ent->state_flags & ENTITY_STATE_COLLIDABLE)
1693                 {
1694                     Entity_EnableCollision(ent);
1695                 }
1696                 else
1697                 {
1698                     Entity_DisableCollision(ent);
1699                 }
1700             }
1701             if(!lua_isnil(lua, 3))
1702             {
1703                 ent->type_flags = lua_tointeger(lua, 3);
1704             }
1705             if(!lua_isnil(lua, 4))
1706             {
1707                 ent->callback_flags = lua_tointeger(lua, 4);
1708             }
1709         }
1710         else
1711         {
1712             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1713         }
1714     }
1715     else
1716     {
1717         Con_Warning("setEntityFlags: expecting arguments (entity_id, state_flags, type_flags, callback_flags)");
1718     }
1719 
1720     return 0;
1721 }
1722 
1723 
lua_GetEntityTypeFlag(lua_State * lua)1724 int lua_GetEntityTypeFlag(lua_State *lua)
1725 {
1726     int top = lua_gettop(lua);
1727 
1728     if(top >= 1)
1729     {
1730         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1731         if(ent)
1732         {
1733             if(top == 1)
1734             {
1735                 lua_pushinteger(lua, ent->type_flags);
1736             }
1737             else
1738             {
1739                 lua_pushinteger(lua, (ent->type_flags & (uint16_t)(lua_tointeger(lua, 2))));
1740             }
1741             return 1;
1742         }
1743         else
1744         {
1745             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1746         }
1747     }
1748     else
1749     {
1750         Con_Warning("getEntityTypeFlag: expecting arguments (entity_id, (type_flag))");
1751     }
1752 
1753     return 0;
1754 }
1755 
1756 
lua_SetEntityTypeFlag(lua_State * lua)1757 int lua_SetEntityTypeFlag(lua_State *lua)
1758 {
1759     int top = lua_gettop(lua);
1760 
1761     if(top >= 2)
1762     {
1763         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1764         if(ent)
1765         {
1766             if(top == 2)
1767             {
1768                 ent->type_flags ^= (uint16_t)lua_tointeger(lua, 2);
1769             }
1770             else
1771             {
1772                 if(lua_tointeger(lua, 3) == 1)
1773                 {
1774                     ent->type_flags |=  (uint16_t)lua_tointeger(lua, 2);
1775                 }
1776                 else
1777                 {
1778                     ent->type_flags &= ~(uint16_t)lua_tointeger(lua, 2);
1779                 }
1780             }
1781         }
1782         else
1783         {
1784             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1785         }
1786     }
1787     else
1788     {
1789         Con_Warning("setEntityTypeFlag: expecting arguments (entity_id, type_flag, (value))");
1790     }
1791 
1792     return 0;
1793 }
1794 
1795 
lua_GetEntityStateFlag(lua_State * lua)1796 int lua_GetEntityStateFlag(lua_State *lua)
1797 {
1798     int top = lua_gettop(lua);
1799 
1800     if(top >= 1)
1801     {
1802         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1803         if(ent)
1804         {
1805             if(top == 1)
1806             {
1807                 lua_pushinteger(lua, ent->state_flags);
1808             }
1809             else
1810             {
1811                 lua_pushinteger(lua, (ent->state_flags & (uint16_t)(lua_tointeger(lua, 2))));
1812             }
1813             return 1;
1814         }
1815         else
1816         {
1817             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1818         }
1819     }
1820     else
1821     {
1822         Con_Warning("getEntityStateFlag: expecting arguments (entity_id, (state_flag))");
1823     }
1824 
1825     return 0;
1826 }
1827 
1828 
lua_SetEntityStateFlag(lua_State * lua)1829 int lua_SetEntityStateFlag(lua_State *lua)
1830 {
1831     int top = lua_gettop(lua);
1832 
1833     if(top >= 2)
1834     {
1835         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1836         if(ent)
1837         {
1838             if(top == 2)
1839             {
1840                 ent->state_flags ^= (uint16_t)lua_tointeger(lua, 2);
1841             }
1842             else
1843             {
1844                 if(lua_tointeger(lua, 3) == 1)
1845                 {
1846                     ent->state_flags |=  (uint16_t)lua_tointeger(lua, 2);
1847                 }
1848                 else
1849                 {
1850                     ent->state_flags &= ~(uint16_t)lua_tointeger(lua, 2);
1851                 }
1852             }
1853         }
1854         else
1855         {
1856             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1857         }
1858     }
1859     else
1860     {
1861         Con_Warning("setEntityStateFlag: expecting arguments (entity_id, state_flag, (value))");
1862     }
1863 
1864     return 0;
1865 }
1866 
1867 
lua_GetEntityCallbackFlag(lua_State * lua)1868 int lua_GetEntityCallbackFlag(lua_State *lua)
1869 {
1870     int top = lua_gettop(lua);
1871 
1872     if(top >= 1)
1873     {
1874         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1875         if(ent)
1876         {
1877             if(top == 1)
1878             {
1879                 lua_pushinteger(lua, ent->callback_flags);
1880             }
1881             else
1882             {
1883                 lua_pushinteger(lua, (ent->callback_flags & (uint32_t)(lua_tointeger(lua, 2))));
1884             }
1885             return 1;
1886         }
1887         else
1888         {
1889             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1890         }
1891     }
1892     else
1893     {
1894         Con_Warning("getEntityCallbackFlag: expecting arguments (entity_id, (callback_flag))");
1895     }
1896 
1897     return 0;
1898 }
1899 
1900 
lua_SetEntityCallbackFlag(lua_State * lua)1901 int lua_SetEntityCallbackFlag(lua_State *lua)
1902 {
1903     int top = lua_gettop(lua);
1904 
1905     if(top >= 2)
1906     {
1907         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1908         if(ent)
1909         {
1910             if(top == 2)
1911             {
1912                 ent->callback_flags ^= (uint32_t)lua_tointeger(lua, 2);
1913             }
1914             else
1915             {
1916                 if(lua_tointeger(lua, 3) == 1)
1917                 {
1918                     ent->callback_flags |=  (uint16_t)lua_tointeger(lua, 2);
1919                 }
1920                 else
1921                 {
1922                     ent->callback_flags &= ~(uint32_t)lua_tointeger(lua, 2);
1923                 }
1924             }
1925         }
1926         else
1927         {
1928             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1929         }
1930     }
1931     else
1932     {
1933         Con_Warning("setEntityCallbackFlag: expecting arguments (entity_id, callback_flag, (value))");
1934     }
1935 
1936     return 0;
1937 }
1938 
1939 
lua_GetEntityTimer(lua_State * lua)1940 int lua_GetEntityTimer(lua_State * lua)
1941 {
1942     if(lua_gettop(lua) >= 1)
1943     {
1944         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1945         if(ent)
1946         {
1947             lua_pushnumber(lua, ent->timer);
1948             return 1;
1949         }
1950     }
1951 
1952     return 0;
1953 }
1954 
1955 
lua_SetEntityTimer(lua_State * lua)1956 int lua_SetEntityTimer(lua_State * lua)
1957 {
1958     if(lua_gettop(lua) >= 2)
1959     {
1960         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1961         if(ent)
1962         {
1963             ent->timer = lua_tonumber(lua, 2);
1964         }
1965     }
1966 
1967     return 0;
1968 }
1969 
1970 
lua_GetEntityMoveType(lua_State * lua)1971 int lua_GetEntityMoveType(lua_State * lua)
1972 {
1973     if(lua_gettop(lua) >= 1)
1974     {
1975         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
1976         if(ent)
1977         {
1978             lua_pushinteger(lua, ent->move_type);
1979             return 1;
1980         }
1981         else
1982         {
1983             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
1984         }
1985     }
1986     else
1987     {
1988         Con_Warning("getEntityMoveType: expecting arguments (entity_id)");
1989     }
1990 
1991     return 0;
1992 }
1993 
1994 
lua_SetEntityMoveType(lua_State * lua)1995 int lua_SetEntityMoveType(lua_State * lua)
1996 {
1997     if(lua_gettop(lua) >= 2)
1998     {
1999         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2000         if(ent)
2001         {
2002             ent->move_type = lua_tointeger(lua, 2);
2003         }
2004     }
2005     else
2006     {
2007         Con_Warning("setEntityMoveType: expecting arguments (entity_id, move_type)");
2008     }
2009 
2010     return 0;
2011 }
2012 
2013 
lua_SetEntityRoomMove(lua_State * lua)2014 int lua_SetEntityRoomMove(lua_State * lua)
2015 {
2016     if(lua_gettop(lua) >= 4)
2017     {
2018         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2019         if(ent)
2020         {
2021             room_p room = NULL;
2022             if(!lua_isnil(lua, 2) && (room = World_GetRoomByID(lua_tointeger(lua, 2))))
2023             {
2024                 if(ent->self->room != room)
2025                 {
2026                     if(ent->self->room != NULL)
2027                     {
2028                         Room_RemoveObject(ent->self->room, ent->self);
2029                     }
2030                     Room_AddObject(room, ent->self);
2031                 }
2032             }
2033             Entity_UpdateRoomPos(ent);
2034 
2035             if(!lua_isnil(lua, 3))
2036             {
2037                 ent->move_type = lua_tointeger(lua, 3);
2038             }
2039             if(!lua_isnil(lua, 4))
2040             {
2041                 ent->dir_flag = lua_tointeger(lua, 4);
2042             }
2043         }
2044         else
2045         {
2046             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2047         }
2048     }
2049     else
2050     {
2051         Con_Warning("setEntityRoomMove: expecting arguments (entity_id, room_id, move_type, dir_flag)");
2052     }
2053 
2054     return 0;
2055 }
2056 
2057 /*
2058  * physics routine
2059  */
lua_SetEntityCollision(lua_State * lua)2060 int lua_SetEntityCollision(lua_State * lua)
2061 {
2062     int top = lua_gettop(lua);
2063 
2064     if(top >= 1)
2065     {
2066         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2067         if(ent)
2068         {
2069             if((top >= 2) && (lua_toboolean(lua, 2)))
2070             {
2071                 Entity_EnableCollision(ent);
2072             }
2073             else
2074             {
2075                 Entity_DisableCollision(ent);
2076             }
2077         }
2078     }
2079     else
2080     {
2081         Con_Warning("setEntityCollision: Expecting arguments (entity_id, val)");
2082     }
2083 
2084     return 0;
2085 }
2086 
2087 
lua_SetEntityBoneCollision(lua_State * lua)2088 int lua_SetEntityBoneCollision(lua_State * lua)
2089 {
2090     int top = lua_gettop(lua);
2091 
2092     if(top >= 3)
2093     {
2094         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2095         if(ent)
2096         {
2097             Physics_SetBoneCollision(ent->physics, lua_tointeger(lua, 2), lua_tointeger(lua, 3));
2098         }
2099     }
2100     else
2101     {
2102         Con_Warning("setEntityBoneCollision: Expecting arguments (entity_id, bone_id, val)");
2103     }
2104 
2105     return 0;
2106 }
2107 
2108 
lua_SetEntityGhostCollisionShape(lua_State * lua)2109 int lua_SetEntityGhostCollisionShape(lua_State * lua)
2110 {
2111     if(lua_gettop(lua) >= 9)
2112     {
2113         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2114         if(ent)
2115         {
2116             uint16_t ghost_index = lua_tointeger(lua, 2);
2117             base_mesh_p mesh = ent->bf->bone_tags[ghost_index].mesh_base;
2118             ghost_shape_t shape;
2119             shape.shape_id = lua_tointeger(lua, 3);
2120             shape.bb_min[0] = (!lua_isnil(lua, 4) || !mesh) ? (lua_tonumber(lua, 4)) : (mesh->bb_min[0]);
2121             shape.bb_min[1] = (!lua_isnil(lua, 5) || !mesh) ? (lua_tonumber(lua, 5)) : (mesh->bb_min[1]);
2122             shape.bb_min[2] = (!lua_isnil(lua, 6) || !mesh) ? (lua_tonumber(lua, 6)) : (mesh->bb_min[2]);
2123             shape.bb_max[0] = (!lua_isnil(lua, 7) || !mesh) ? (lua_tonumber(lua, 7)) : (mesh->bb_max[0]);
2124             shape.bb_max[1] = (!lua_isnil(lua, 8) || !mesh) ? (lua_tonumber(lua, 8)) : (mesh->bb_max[1]);
2125             shape.bb_max[2] = (!lua_isnil(lua, 9) || !mesh) ? (lua_tonumber(lua, 9)) : (mesh->bb_max[2]);
2126             vec3_add(shape.offset, shape.bb_min, shape.bb_max);
2127             shape.offset[0] *= 0.5f;
2128             shape.offset[1] *= 0.5f;
2129             shape.offset[2] *= 0.5f;
2130             Physics_SetGhostCollisionShape(ent->physics, ent->bf, ghost_index, &shape);
2131         }
2132         else
2133         {
2134             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2135         }
2136     }
2137     else
2138     {
2139         Con_Warning("setEntityGhostCollisionShape: expecting arguments (entity_id, shape_index, min_x, min_y, min_z, max_x, max_y, max_z)");
2140     }
2141 
2142     return 0;
2143 }
2144 
2145 
lua_SetEntityCollisionFlags(lua_State * lua)2146 int lua_SetEntityCollisionFlags(lua_State * lua)
2147 {
2148     if(lua_gettop(lua) >= 4)
2149     {
2150         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2151         if(ent)
2152         {
2153             if(!lua_isnil(lua, 2))
2154             {
2155                 ent->self->collision_group = lua_tointeger(lua, 2);
2156             }
2157             if(!lua_isnil(lua, 3))
2158             {
2159                 ent->self->collision_shape = lua_tointeger(lua, 3);
2160             }
2161             if(!lua_isnil(lua, 4))
2162             {
2163                 ent->self->collision_mask = lua_tointeger(lua, 4);
2164             }
2165 
2166             if(Physics_GetBodiesCount(ent->physics) != ent->bf->bone_tag_count)
2167             {
2168                 ent->self->collision_shape = COLLISION_SHAPE_SINGLE_BOX;
2169             }
2170         }
2171         else
2172         {
2173             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2174         }
2175     }
2176     else
2177     {
2178         Con_Warning("setEntityCollisionFlags: expecting arguments (entity_id, collision_group, collision_shape, collision_mask)");
2179     }
2180 
2181     return 0;
2182 }
2183 
2184 
lua_SetEntityCollisionGroupAndMask(lua_State * lua)2185 int lua_SetEntityCollisionGroupAndMask(lua_State * lua)
2186 {
2187     if(lua_gettop(lua) >= 3)
2188     {
2189         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2190         if(ent)
2191         {
2192             if(!lua_isnil(lua, 2))
2193             {
2194                 ent->self->collision_group = lua_tointeger(lua, 2);
2195             }
2196             if(!lua_isnil(lua, 3))
2197             {
2198                 ent->self->collision_mask = lua_tointeger(lua, 3);
2199             }
2200             Physics_SetCollisionGroupAndMask(ent->physics, ent->self->collision_group, ent->self->collision_mask);
2201         }
2202         else
2203         {
2204             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2205         }
2206     }
2207     else
2208     {
2209         Con_Warning("setEntityCollisionGroupAndMask: expecting arguments (entity_id, collision_group, collision_mask)");
2210     }
2211 
2212     return 0;
2213 }
2214 
2215 
lua_ResetRigidBodies(lua_State * lua)2216 int lua_ResetRigidBodies(lua_State * lua)
2217 {
2218     if(lua_gettop(lua) >= 1)
2219     {
2220         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2221         if(ent)
2222         {
2223             Physics_GenRigidBody(ent->physics, ent->bf);
2224         }
2225         else
2226         {
2227             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2228         }
2229     }
2230     else
2231     {
2232         Con_Warning("resetRigidBodies: expecting arguments (entity_id)");
2233     }
2234 
2235     return 0;
2236 }
2237 
2238 
lua_CreateGhosts(lua_State * lua)2239 int lua_CreateGhosts(lua_State * lua)
2240 {
2241     if(lua_gettop(lua) >= 1)
2242     {
2243         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2244         if(ent && !Physics_IsGhostsInited(ent->physics))
2245         {
2246             Physics_CreateGhosts(ent->physics, ent->bf, NULL);
2247             Entity_GhostUpdate(ent);
2248         }
2249         else
2250         {
2251             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2252         }
2253     }
2254     else
2255     {
2256         Con_Warning("createGhosts: expecting arguments (entity_id)");
2257     }
2258 
2259     return 0;
2260 }
2261 
2262 
lua_GetEntityGlobalMove(lua_State * lua)2263 int lua_GetEntityGlobalMove(lua_State * lua)
2264 {
2265     if(lua_gettop(lua) >= 4)
2266     {
2267         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2268         if(ent)
2269         {
2270             float move[3], gmove[3];
2271             move[0] = lua_tonumber(lua, 2);
2272             move[1] = lua_tonumber(lua, 3);
2273             move[2] = lua_tonumber(lua, 4);
2274 
2275             Mat4_vec3_rot_macro(gmove, ent->transform.M4x4, move);
2276 
2277             lua_pushnumber(lua, gmove[0]);
2278             lua_pushnumber(lua, gmove[1]);
2279             lua_pushnumber(lua, gmove[2]);
2280             return 3;
2281         }
2282         else
2283         {
2284             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2285         }
2286     }
2287     else
2288     {
2289         Con_Warning("getEntityGlobalMove: expecting arguments (entity_id, dx, dy, dz)");
2290     }
2291 
2292     return 0;
2293 }
2294 
2295 
lua_GetEntityCollisionFix(lua_State * lua)2296 int lua_GetEntityCollisionFix(lua_State * lua)
2297 {
2298     if(lua_gettop(lua) >= 2)
2299     {
2300         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2301         if(ent)
2302         {
2303             int16_t filter = lua_tointeger(lua, 2);
2304             float reaction[3] = {0.0f, 0.0f, 0.0f};
2305             Entity_GetPenetrationFixVector(ent, NULL, reaction, NULL, filter);
2306 
2307             bool result = (reaction[0] != 0.0f) || (reaction[1] != 0.0f) || (reaction[2] != 0.0f);
2308             lua_pushboolean(lua, result);
2309             lua_pushnumber(lua, reaction[0]);
2310             lua_pushnumber(lua, reaction[1]);
2311             lua_pushnumber(lua, reaction[2]);
2312             return 4;
2313         }
2314         else
2315         {
2316             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2317         }
2318     }
2319     else
2320     {
2321         Con_Warning("getEntityCollisionFix: expecting arguments (entity_id, filter)");
2322     }
2323 
2324     return 0;
2325 }
2326 
2327 
lua_GetEntityMoveCollisionFix(lua_State * lua)2328 int lua_GetEntityMoveCollisionFix(lua_State * lua)
2329 {
2330     if(lua_gettop(lua) >= 5)
2331     {
2332         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2333         if(ent)
2334         {
2335             int16_t filter = lua_tointeger(lua, 2);
2336             float reaction[3] = {0.0f, 0.0f, 0.0f};
2337             float move[3];
2338             move[0] = lua_tonumber(lua, 3);
2339             move[1] = lua_tonumber(lua, 4);
2340             move[2] = lua_tonumber(lua, 5);
2341 
2342             Entity_CheckNextPenetration(ent, NULL, move, reaction, filter);
2343 
2344             bool result = (reaction[0] != 0.0f) || (reaction[1] != 0.0f) || (reaction[2] != 0.0f);
2345             lua_pushboolean(lua, result);
2346             lua_pushnumber(lua, reaction[0]);
2347             lua_pushnumber(lua, reaction[1]);
2348             lua_pushnumber(lua, reaction[2]);
2349             return 4;
2350         }
2351         else
2352         {
2353             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2354         }
2355     }
2356     else
2357     {
2358         Con_Warning("getEntityMoveCollisionFix: expecting arguments (entity_id, filter, dx, dy, dz)");
2359     }
2360 
2361     return 0;
2362 }
2363 
2364 
lua_GetEntityRayTest(lua_State * lua)2365 int lua_GetEntityRayTest(lua_State * lua)
2366 {
2367     int top = lua_gettop(lua);
2368     if(top >= 5)
2369     {
2370         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2371         if(ent)
2372         {
2373             int16_t filter = lua_tointeger(lua, 2);
2374             float from[3], to[3], move[3];
2375             collision_result_t cs;
2376 
2377             vec3_copy(move, ent->bf->centre);
2378             if(top >= 8)
2379             {
2380                 move[0] += lua_tonumber(lua, 6);
2381                 move[1] += lua_tonumber(lua, 7);
2382                 move[2] += lua_tonumber(lua, 8);
2383             }
2384             Mat4_vec3_mul_macro(from, ent->transform.M4x4, move);
2385 
2386             move[0] = lua_tonumber(lua, 3);
2387             move[1] = lua_tonumber(lua, 4);
2388             move[2] = lua_tonumber(lua, 5);
2389             Mat4_vec3_rot_macro(to, ent->transform.M4x4, move);
2390 
2391             to[0] += from[0];
2392             to[1] += from[1];
2393             to[2] += from[2];
2394 
2395             bool result = Physics_RayTestFiltered(&cs, from, to, ent->self, filter);
2396             lua_pushboolean(lua, result);
2397             lua_pushnumber(lua, cs.fraction);
2398             lua_pushnumber(lua, cs.point[0]);
2399             lua_pushnumber(lua, cs.point[1]);
2400             lua_pushnumber(lua, cs.point[2]);
2401             return 5;
2402         }
2403         else
2404         {
2405             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2406         }
2407     }
2408     else
2409     {
2410         Con_Warning("getEntityRayTest: expecting arguments (entity_id, filter, mx, my, mz, (dx, dy, dz))");
2411     }
2412 
2413     return 0;
2414 }
2415 
2416 
lua_GetEntitySphereTest(lua_State * lua)2417 int lua_GetEntitySphereTest(lua_State * lua)
2418 {
2419     int top = lua_gettop(lua);
2420     if(top >= 6)
2421     {
2422         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2423         if(ent)
2424         {
2425             int16_t filter = lua_tointeger(lua, 2);
2426             float r = lua_tointeger(lua, 3);
2427             float from[3], to[3], move[3];
2428             collision_result_t cs;
2429 
2430             vec3_copy(move, ent->bf->centre);
2431             if(top >= 9)
2432             {
2433                 move[0] += lua_tonumber(lua, 7);
2434                 move[1] += lua_tonumber(lua, 8);
2435                 move[2] += lua_tonumber(lua, 9);
2436             }
2437             Mat4_vec3_mul_macro(from, ent->transform.M4x4, move);
2438 
2439             move[0] = lua_tonumber(lua, 4);
2440             move[1] = lua_tonumber(lua, 5);
2441             move[2] = lua_tonumber(lua, 6);
2442             Mat4_vec3_rot_macro(to, ent->transform.M4x4, move);
2443 
2444             to[0] += from[0];
2445             to[1] += from[1];
2446             to[2] += from[2];
2447 
2448             bool result = Physics_SphereTest(&cs, from, to, r, ent->self, filter);
2449             lua_pushboolean(lua, result);
2450             lua_pushnumber(lua, cs.fraction);
2451             lua_pushnumber(lua, cs.point[0]);
2452             lua_pushnumber(lua, cs.point[1]);
2453             lua_pushnumber(lua, cs.point[2]);
2454             return 5;
2455         }
2456         else
2457         {
2458             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2459         }
2460     }
2461     else
2462     {
2463         Con_Warning("getEntitySphereTest: expecting arguments (entity_id, filter, r, mx, my, mz, (dx, dy, dz))");
2464     }
2465 
2466     return 0;
2467 }
2468 
2469 
lua_DropEntity(lua_State * lua)2470 int lua_DropEntity(lua_State * lua)
2471 {
2472     int top = lua_gettop(lua);
2473 
2474     if(top >= 2)
2475     {
2476         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2477         if(ent)
2478         {
2479             bool only_room = (top > 2) ? (lua_toboolean(lua, 3)) : (false);
2480             int16_t filter = ((only_room) ? (COLLISION_GROUP_STATIC_ROOM) : ent->self->collision_mask);
2481             float move[3], g[3], t, time = lua_tonumber(lua, 2);
2482             float from[3], to[3];
2483             collision_result_t cb;
2484 
2485             Physics_GetGravity(g);
2486             vec3_mul_scalar(move, ent->speed, time);
2487             t = 0.5f * time * time;
2488             vec3_add_mul(move, move, g, t);
2489             ent->speed[0] += g[0] * time;
2490             ent->speed[1] += g[1] * time;
2491             ent->speed[2] += g[2] * time;
2492 
2493             Mat4_vec3_mul_macro(from, ent->transform.M4x4, ent->bf->centre);
2494             vec3_add(to, from, move);
2495             from[2] += 32.0f;
2496             to[2] -= (ent->bf->bb_max[2] - ent->bf->bb_min[2]);
2497 
2498             if(Physics_RayTestFiltered(&cb, from, to, ent->self, filter))
2499             {
2500                 lua_pushboolean(lua, ent->transform.M4x4[12 + 2] < cb.point[2] + 1.0f);
2501                 ent->transform.M4x4[12 + 2] = cb.point[2];
2502                 vec3_set_zero(ent->speed);
2503             }
2504             else
2505             {
2506                 vec3_add_to(ent->transform.M4x4 + 12, move);
2507                 lua_pushboolean(lua, false);
2508             }
2509             Entity_UpdateRigidBody(ent, 1);
2510             return 1;
2511         }
2512         else
2513         {
2514             Con_Warning("no entity with id = %d", lua_tointeger(lua, 1));
2515         }
2516     }
2517     else
2518     {
2519         Con_Warning("dropEntity: expecting arguments (entity_id, time, (only_room))");
2520     }
2521 
2522     return 0;
2523 }
2524 
2525 
lua_PushEntityBody(lua_State * lua)2526 int lua_PushEntityBody(lua_State *lua)
2527 {
2528     if(lua_gettop(lua) >= 5)
2529     {
2530         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2531         int body_number = lua_tointeger(lua, 2);
2532         if(ent && (body_number < ent->bf->bone_tag_count) && (ent->type_flags & ENTITY_TYPE_DYNAMIC))
2533         {
2534             float h_force = lua_tonumber(lua, 3);
2535             float t       = ent->transform.angles[0] * M_PI / 180.0;
2536             float speed[3];
2537 
2538             speed[0] = -sinf(t) * h_force;
2539             speed[1] =  cosf(t) * h_force;
2540             speed[2] =  lua_tonumber(lua, 4);
2541 
2542             Physics_PushBody(ent->physics, speed, body_number);
2543         }
2544         else
2545         {
2546             Con_Printf("Can't apply force to entity %d - no entity, body, or entity is not kinematic!", lua_tointeger(lua, 1));
2547         }
2548     }
2549     else
2550     {
2551         Con_Printf("pushEntityBody: expecting arguments (entity_id, body_number, h_force, v_force, reset_flag)");
2552     }
2553 
2554     return 0;
2555 }
2556 
2557 
lua_SetEntityBodyMass(lua_State * lua)2558 int lua_SetEntityBodyMass(lua_State *lua)
2559 {
2560     int top = lua_gettop(lua);
2561 
2562     if(lua_gettop(lua) >= 3)
2563     {
2564         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2565         int body_number = lua_tointeger(lua, 2);
2566         body_number = (body_number < 1) ? (1) : (body_number);
2567 
2568         if(ent && (ent->bf->bone_tag_count >= body_number))
2569         {
2570             uint16_t argn  = 3;
2571             bool dynamic = false;
2572             float mass = 0.0;
2573 
2574             for(int i = 0; i < body_number; i++)
2575             {
2576                 if(top >= argn) mass = lua_tonumber(lua, argn++);
2577                 if(mass > 0.0) dynamic = true;
2578                 Physics_SetBodyMass(ent->physics, mass, i);
2579             }
2580             Entity_UpdateRigidBody(ent, 1);
2581 
2582             if(dynamic)
2583             {
2584                 ent->type_flags |=  ENTITY_TYPE_DYNAMIC;
2585             }
2586             else
2587             {
2588                 ent->type_flags &= ~ENTITY_TYPE_DYNAMIC;
2589             }
2590         }
2591         else
2592         {
2593             Con_Printf("Can't find entity %d or body number is more than %d", lua_tointeger(lua, 1), body_number);
2594         }
2595     }
2596     else
2597     {
2598         Con_Printf("setEntityBodyMass: expecting arguments (entity_id, body_number, (mass / each body mass))");
2599     }
2600 
2601     return 0;
2602 }
2603 
2604 
lua_LockEntityBodyLinearFactor(lua_State * lua)2605 int lua_LockEntityBodyLinearFactor(lua_State *lua)
2606 {
2607     int top = lua_gettop(lua);
2608 
2609     if(top >= 2)
2610     {
2611         entity_p ent = World_GetEntityByID(lua_tointeger(lua, 1));
2612         int body_number = lua_tointeger(lua, 2);
2613         if(ent && (body_number < ent->bf->bone_tag_count) && (ent->type_flags & ENTITY_TYPE_DYNAMIC))
2614         {
2615             float factor[3], t    = ent->transform.angles[0] * M_PI / 180.0;
2616             factor[0] = fabs(sinf(t));
2617             factor[1] = fabs(cosf(t));
2618             factor[2] = 1.0;
2619 
2620             if(top >= 3)
2621             {
2622                 factor[2] = fabs(lua_tonumber(lua, 3));
2623                 factor[2] = (factor[2] > 1.0) ? (1.0) : (factor[2]);
2624             }
2625             Physics_SetLinearFactor(ent->physics, factor, body_number);
2626         }
2627         else
2628         {
2629             Con_Printf("Can't apply force to entity %d - no entity, body, or entity is not dynamic!", lua_tointeger(lua, 1));
2630         }
2631     }
2632     else
2633     {
2634         Con_Printf("lockEntityBodyLinearFactor: expecting arguments (entity_id, body_number, (vertical_factor))");
2635     }
2636 
2637     return 0;
2638 }
2639 
2640 
Script_LuaRegisterEntityFuncs(lua_State * lua)2641 void Script_LuaRegisterEntityFuncs(lua_State *lua)
2642 {
2643     lua_register(lua, "addItem", lua_AddItem);
2644     lua_register(lua, "removeItem", lua_RemoveItem);
2645     lua_register(lua, "removeAllItems", lua_RemoveAllItems);
2646     lua_register(lua, "getItemsCount", lua_GetItemsCount);
2647     lua_register(lua, "getItems", lua_GetItems);
2648 
2649     lua_register(lua, "canTriggerEntity", lua_CanTriggerEntity);
2650     lua_register(lua, "entityRotateToTriggerZ", lua_EntityRotateToTriggerZ);
2651     lua_register(lua, "entityRotateToTrigger", lua_EntityRotateToTrigger);
2652     lua_register(lua, "entityMoveToTriggerActivationPoint", lua_EntityMoveToTriggerActivationPoint);
2653     lua_register(lua, "enableEntity", lua_EnableEntity);
2654     lua_register(lua, "disableEntity", lua_DisableEntity);
2655 
2656     lua_register(lua, "activateEntity", lua_ActivateEntity);
2657     lua_register(lua, "deactivateEntity", lua_DeactivateEntity);
2658     lua_register(lua, "noFixEntityCollision", lua_NoFixEntityCollision);
2659     lua_register(lua, "noEntityMove", lua_NoEntityMove);
2660 
2661     lua_register(lua, "moveEntityGlobal", lua_MoveEntityGlobal);
2662     lua_register(lua, "moveEntityLocal", lua_MoveEntityLocal);
2663     lua_register(lua, "moveEntityToSink", lua_MoveEntityToSink);
2664     lua_register(lua, "moveEntityToEntity", lua_MoveEntityToEntity);
2665     lua_register(lua, "rotateEntity", lua_RotateEntity);
2666 
2667     lua_register(lua, "getEntityVector", lua_GetEntityVector);
2668     lua_register(lua, "getEntityDirDot", lua_GetEntityDirDot);
2669     lua_register(lua, "getEntityDistance", lua_GetEntityDistance);
2670     lua_register(lua, "getEntityRoom", lua_GetEntityRoom);
2671     lua_register(lua, "getEntityPos", lua_GetEntityPosition);
2672     lua_register(lua, "setEntityPos", lua_SetEntityPosition);
2673     lua_register(lua, "getEntityAngles", lua_GetEntityAngles);
2674     lua_register(lua, "setEntityAngles", lua_SetEntityAngles);
2675     lua_register(lua, "getEntityScaling", lua_GetEntityScaling);
2676     lua_register(lua, "setEntityScaling", lua_SetEntityScaling);
2677     lua_register(lua, "getEntitySpeed", lua_GetEntitySpeed);
2678     lua_register(lua, "setEntitySpeed", lua_SetEntitySpeed);
2679     lua_register(lua, "setEntityLinearSpeed", lua_SetEntityLinearSpeed);
2680     lua_register(lua, "getEntitySpeedLinear", lua_GetEntitySpeedLinear);
2681     lua_register(lua, "setEntityBodyPartFlag", lua_SetEntityBodyPartFlag);
2682     lua_register(lua, "getEntityVisibility", lua_GetEntityVisibility);
2683     lua_register(lua, "setEntityVisibility", lua_SetEntityVisibility);
2684     lua_register(lua, "getEntityActivity", lua_GetEntityActivity);
2685     lua_register(lua, "setEntityActivity", lua_SetEntityActivity);
2686     lua_register(lua, "getEntityEnability", lua_GetEntityEnability);
2687     lua_register(lua, "getEntityOCB", lua_GetEntityOCB);
2688     lua_register(lua, "setEntityOCB", lua_SetEntityOCB);
2689     lua_register(lua, "getEntityTimer", lua_GetEntityTimer);
2690     lua_register(lua, "setEntityTimer", lua_SetEntityTimer);
2691     lua_register(lua, "getEntityFlags", lua_GetEntityFlags);
2692     lua_register(lua, "setEntityFlags", lua_SetEntityFlags);
2693     lua_register(lua, "getEntityTypeFlag", lua_GetEntityTypeFlag);
2694     lua_register(lua, "setEntityTypeFlag", lua_SetEntityTypeFlag);
2695     lua_register(lua, "getEntityStateFlag", lua_GetEntityStateFlag);
2696     lua_register(lua, "setEntityStateFlag", lua_SetEntityStateFlag);
2697     lua_register(lua, "getEntityCallbackFlag", lua_GetEntityCallbackFlag);
2698     lua_register(lua, "setEntityCallbackFlag", lua_SetEntityCallbackFlag);
2699     lua_register(lua, "setEntityRoomMove", lua_SetEntityRoomMove);
2700     lua_register(lua, "getEntityMoveType", lua_GetEntityMoveType);
2701     lua_register(lua, "setEntityMoveType", lua_SetEntityMoveType);
2702 
2703     lua_register(lua, "getEntityTriggerLayout", lua_GetEntityTriggerLayout);
2704     lua_register(lua, "setEntityTriggerLayout", lua_SetEntityTriggerLayout);
2705     lua_register(lua, "getEntityMask", lua_GetEntityMask);
2706     lua_register(lua, "setEntityMask", lua_SetEntityMask);
2707     lua_register(lua, "getEntityEvent", lua_GetEntityEvent);
2708     lua_register(lua, "setEntityEvent", lua_SetEntityEvent);
2709     lua_register(lua, "getEntityLock", lua_GetEntityLock);
2710     lua_register(lua, "setEntityLock", lua_SetEntityLock);
2711     lua_register(lua, "getEntitySectorStatus", lua_GetEntitySectorStatus);
2712     lua_register(lua, "setEntitySectorStatus", lua_SetEntitySectorStatus);
2713 
2714     lua_register(lua, "getEntityActivationOffset", lua_GetEntityActivationOffset);
2715     lua_register(lua, "setEntityActivationOffset", lua_SetEntityActivationOffset);
2716     lua_register(lua, "getEntityActivationDirection", lua_GetEntityActivationDirection);
2717     lua_register(lua, "setEntityActivationDirection", lua_SetEntityActivationDirection);
2718     lua_register(lua, "getEntitySectorIndex", lua_GetEntitySectorIndex);
2719     lua_register(lua, "getEntitySectorFlags", lua_GetEntitySectorFlags);
2720     lua_register(lua, "getEntitySectorMaterial", lua_GetEntitySectorMaterial);
2721     lua_register(lua, "getEntityBoxID", lua_GetEntityBoxID);
2722 
2723     lua_register(lua, "setEntityCollision", lua_SetEntityCollision);
2724     lua_register(lua, "setEntityBoneCollision", lua_SetEntityBoneCollision);
2725     lua_register(lua, "setEntityGhostCollisionShape", lua_SetEntityGhostCollisionShape);
2726     lua_register(lua, "setEntityCollisionFlags", lua_SetEntityCollisionFlags);
2727     lua_register(lua, "setEntityCollisionGroupAndMask", lua_SetEntityCollisionGroupAndMask);
2728     lua_register(lua, "resetRigidBodies", lua_ResetRigidBodies);
2729     lua_register(lua, "createGhosts", lua_CreateGhosts);
2730     lua_register(lua, "getEntityGlobalMove", lua_GetEntityGlobalMove);
2731     lua_register(lua, "getEntityCollisionFix", lua_GetEntityCollisionFix);
2732     lua_register(lua, "getEntityMoveCollisionFix", lua_GetEntityMoveCollisionFix);
2733     lua_register(lua, "getEntityRayTest", lua_GetEntityRayTest);
2734     lua_register(lua, "getEntitySphereTest", lua_GetEntitySphereTest);
2735     lua_register(lua, "dropEntity", lua_DropEntity);
2736     lua_register(lua, "setEntityBodyMass", lua_SetEntityBodyMass);
2737     lua_register(lua, "pushEntityBody", lua_PushEntityBody);
2738     lua_register(lua, "lockEntityBodyLinearFactor", lua_LockEntityBodyLinearFactor);
2739 }
2740