00001
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "g_local.h"
00036 #include "g_ai.h"
00037 #include "lua/lauxlib.h"
00038
00039 #define POS3_METATABLE "pos3"
00040 #define ACTOR_METATABLE "actor"
00041 #define AI_METATABLE "ai"
00046 #define luaL_dobuffer(L, b, n, s) \
00047 (luaL_loadbuffer(L, b, n, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
00048 #define AIL_invalidparameter(n) \
00049 gi.DPrintf("AIL: Invalid parameter #%d in '%s'.\n", n, __func__)
00050
00051
00052
00053
00054
00061 static const char *AIL_toTeamString (const int team)
00062 {
00063 const char *teamStr = gi.GetConstVariable("luaaiteam", team);
00064 if (teamStr == NULL)
00065 AIL_invalidparameter(1);
00066 return teamStr;
00067 }
00068
00075 static int AIL_toTeamInt (const char *team)
00076 {
00077 int teamInt = TEAM_DEFAULT;
00078 if (!gi.GetConstIntFromNamespace("luaaiteam", team, &teamInt))
00079 AIL_invalidparameter(1);
00080 return teamInt;
00081 }
00082
00086 typedef struct aiActor_s {
00087 edict_t *ent;
00088 } aiActor_t;
00089
00090
00091
00092
00093
00094 static edict_t *AIL_ent;
00095 static player_t *AIL_player;
00098
00099
00100
00101
00102 static int actorL_register(lua_State *L);
00103 static int lua_isactor(lua_State *L, int index);
00104 static aiActor_t* lua_toactor(lua_State *L, int index);
00105 static aiActor_t* lua_pushactor(lua_State *L, aiActor_t *actor);
00106
00107 static int actorL_tostring(lua_State *L);
00108 static int actorL_pos(lua_State *L);
00109 static int actorL_shoot(lua_State *L);
00110 static int actorL_face(lua_State *L);
00111 static int actorL_team(lua_State *L);
00115 static const luaL_reg actorL_methods[] = {
00116 {"__tostring", actorL_tostring},
00117 {"pos", actorL_pos},
00118 {"shoot", actorL_shoot},
00119 {"face", actorL_face},
00120 {"team", actorL_team},
00121 {NULL, NULL}
00122 };
00123
00124
00128
00129 static int pos3L_register(lua_State *L);
00130 static int lua_ispos3(lua_State *L, int index);
00131 static pos3_t* lua_topos3(lua_State *L, int index);
00132 static pos3_t* lua_pushpos3(lua_State *L, pos3_t *pos);
00133
00134 static int pos3L_tostring(lua_State *L);
00135 static int pos3L_goto(lua_State *L);
00136 static int pos3L_face(lua_State *L);
00140 static const luaL_reg pos3L_methods[] = {
00141 {"__tostring", pos3L_tostring},
00142 {"goto", pos3L_goto},
00143 {"face", pos3L_face},
00144 {NULL, NULL}
00145 };
00146
00147
00151 static int AIL_print(lua_State *L);
00152 static int AIL_see(lua_State *L);
00153 static int AIL_crouch(lua_State *L);
00154 static int AIL_isinjured(lua_State *L);
00155 static int AIL_TU(lua_State *L);
00156 static int AIL_HP(lua_State *L);
00157 static int AIL_morale(lua_State *L);
00158 static int AIL_reactionfire(lua_State *L);
00159 static int AIL_roundsleft(lua_State *L);
00160 static int AIL_canreload(lua_State *L);
00161 static int AIL_reload(lua_State *L);
00162 static int AIL_positionshoot(lua_State *L);
00163 static int AIL_positionhide(lua_State *L);
00164 static int AIL_positionherd(lua_State *L);
00165 static int AIL_distance(lua_State *L);
00169 static const luaL_reg AIL_methods[] = {
00170 {"print", AIL_print},
00171 {"see", AIL_see},
00172 {"crouch", AIL_crouch},
00173 {"isinjured", AIL_isinjured},
00174 {"TU", AIL_TU},
00175 {"HP", AIL_HP},
00176 {"morale", AIL_morale},
00177 {"reactionfire", AIL_reactionfire},
00178 {"roundsleft", AIL_roundsleft},
00179 {"canreload", AIL_canreload},
00180 {"reload", AIL_reload},
00181 {"positionshoot", AIL_positionshoot},
00182 {"positionhide", AIL_positionhide},
00183 {"positionherd", AIL_positionherd},
00184 {"distance", AIL_distance},
00185 {NULL, NULL}
00186 };
00187
00188
00198 static int actorL_register (lua_State *L)
00199 {
00200
00201 luaL_newmetatable(L, ACTOR_METATABLE);
00202
00203
00204 lua_pushvalue(L, -1);
00205 lua_setfield(L, -2, "__index");
00206
00207
00208 luaL_register(L, NULL, actorL_methods);
00209
00210
00211 lua_pop(L, 1);
00212
00213 return 0;
00214 }
00215
00222 static int lua_isactor (lua_State *L, int index)
00223 {
00224 int ret;
00225
00226 if (lua_getmetatable(L, index) == 0)
00227 return 0;
00228 lua_getfield(L, LUA_REGISTRYINDEX, ACTOR_METATABLE);
00229
00230 ret = 0;
00231 if (lua_rawequal(L, -1, -2))
00232 ret = 1;
00233
00234 lua_pop(L, 2);
00235 return ret;
00236 }
00237
00241 static aiActor_t* lua_toactor (lua_State *L, int index)
00242 {
00243 if (lua_isactor(L, index)) {
00244 return (aiActor_t*) lua_touserdata(L, index);
00245 }
00246 luaL_typerror(L, index, ACTOR_METATABLE);
00247 return NULL;
00248 }
00249
00253 static aiActor_t* lua_pushactor (lua_State *L, aiActor_t *actor)
00254 {
00255 aiActor_t *a;
00256 a = (aiActor_t*) lua_newuserdata(L, sizeof(*a));
00257 *a = *actor;
00258 luaL_getmetatable(L, ACTOR_METATABLE);
00259 lua_setmetatable(L, -2);
00260 return a;
00261 }
00262
00266 static int actorL_tostring (lua_State *L)
00267 {
00268 aiActor_t *target;
00269 char buf[MAX_VAR];
00270
00271 assert(lua_isactor(L, 1));
00272
00273 target = lua_toactor(L, 1);
00274 Com_sprintf(buf, sizeof(buf), "Actor( %s )", target->ent->chr.name);
00275
00276 lua_pushstring(L, buf);
00277 return 1;
00278 }
00279
00283 static int actorL_pos (lua_State *L)
00284 {
00285 aiActor_t *target;
00286
00287 assert(lua_isactor(L, 1));
00288
00289 target = lua_toactor(L, 1);
00290 lua_pushpos3(L, &target->ent->pos);
00291 return 1;
00292 }
00293
00297 static int actorL_shoot (lua_State *L)
00298 {
00299 int tu, shots;
00300 shoot_types_t shootType;
00301 aiActor_t *target;
00302 const item_t *item;
00303 const fireDef_t *fdArray;
00304 objDef_t *od;
00305
00306 assert(lua_isactor(L, 1));
00307
00308
00309 target = lua_toactor(L, 1);
00310
00311
00312 if (lua_gettop(L) > 1) {
00313 assert(lua_isnumber(L, 2));
00314
00315 tu = (int) lua_tonumber(L, 2);
00316 } else {
00317 tu = AIL_ent->TU;
00318 }
00319
00320 shootType = ST_RIGHT;
00321 item = AI_GetItemForShootType(shootType, AIL_ent);
00322 if (item == NULL) {
00323 shootType = ST_LEFT;
00324 item = AI_GetItemForShootType(shootType, AIL_ent);
00325 }
00326
00327
00328 if (item == NULL) {
00329 lua_pushboolean(L, 0);
00330 return 1;
00331 }
00332
00334 fdArray = FIRESH_FiredefForWeapon(item);
00335 if (fdArray == NULL) {
00336
00337 lua_pushboolean(L, 0);
00338 return 1;
00339 }
00340
00341 if (!item->m)
00342 od = item->t;
00343 else
00344 od = item->m;
00345
00346 shots = tu / fdArray->time;
00347
00348 while (shots > 0) {
00349 shots--;
00351 G_ClientShoot(AIL_player, AIL_ent, target->ent->pos,
00352 shootType, 0, NULL, qtrue, 0);
00353 }
00354
00355
00356 lua_pushboolean(L, 1);
00357 return 1;
00358 }
00359
00363 static int actorL_face (lua_State *L)
00364 {
00365 aiActor_t *target;
00366
00367 assert(lua_isactor(L, 1));
00368
00369
00370 target = lua_toactor(L, 1);
00371
00372 AI_TurnIntoDirection(AIL_ent, target->ent->pos);
00373
00374
00375 lua_pushboolean(L, 1);
00376 return 1;
00377 }
00378
00382 static int actorL_team (lua_State *L)
00383 {
00384 const aiActor_t *target;
00385 const char *team;
00386
00387 assert(lua_isactor(L, 1));
00388
00389 target = lua_toactor(L, 1);
00390 assert(target != NULL);
00391 team = AIL_toTeamString(target->ent->team);
00392 lua_pushstring(L, team);
00393 return 1;
00394 }
00395
00396
00406 static int pos3L_register (lua_State *L)
00407 {
00408
00409 luaL_newmetatable(L, POS3_METATABLE);
00410
00411
00412 lua_pushvalue(L, -1);
00413 lua_setfield(L, -2, "__index");
00414
00415
00416 luaL_register(L, NULL, pos3L_methods);
00417
00418
00419 lua_pop(L, 1);
00420
00421 return 0;
00422 }
00423
00430 static int lua_ispos3 (lua_State *L, int index)
00431 {
00432 int ret;
00433
00434 if (lua_getmetatable(L, index) == 0)
00435 return 0;
00436 lua_getfield(L, LUA_REGISTRYINDEX, POS3_METATABLE);
00437
00438 ret = 0;
00439 if (lua_rawequal(L, -1, -2))
00440 ret = 1;
00441
00442 lua_pop(L, 2);
00443 return ret;
00444 }
00445
00449 static pos3_t* lua_topos3 (lua_State *L, int index)
00450 {
00451 if (lua_ispos3(L, index)) {
00452 return (pos3_t*) lua_touserdata(L, index);
00453 }
00454 luaL_typerror(L, index, POS3_METATABLE);
00455 return NULL;
00456 }
00457
00461 static pos3_t* lua_pushpos3 (lua_State *L, pos3_t *pos)
00462 {
00463 pos3_t *p;
00464 p = (pos3_t*) lua_newuserdata(L, sizeof(*p));
00465 memcpy(p, pos, sizeof(*p));
00466 luaL_getmetatable(L, POS3_METATABLE);
00467 lua_setmetatable(L, -2);
00468 return p;
00469 }
00470
00474 static int pos3L_tostring (lua_State *L)
00475 {
00476 pos3_t *p;
00477 char buf[MAX_VAR];
00478
00479 assert(lua_ispos3(L, 1));
00480
00481 p = lua_topos3(L, 1);
00482 Com_sprintf(buf, sizeof(buf), "Pos3( x=%d, y=%d, z=%d )", (*p)[0], (*p)[1], (*p)[2]);
00483
00484 lua_pushstring(L, buf);
00485 return 1;
00486 }
00487
00491 static int pos3L_goto (lua_State *L)
00492 {
00493 pos3_t *pos;
00494 const byte crouchingState = G_IsCrouched(AIL_ent) ? 1 : 0;
00495
00496 assert(lua_ispos3(L, 1));
00497
00498
00499 G_MoveCalc(0, AIL_ent, AIL_ent->pos, crouchingState, AIL_ent->TU);
00500 gi.MoveStore(&level.pathingMap);
00501
00502
00503 pos = lua_topos3(L, 1);
00504 G_ClientMove(AIL_player, 0, AIL_ent, *pos);
00505
00506 lua_pushboolean(L, 1);
00507 return 1;
00508 }
00509
00513 static int pos3L_face (lua_State *L)
00514 {
00515 pos3_t *pos;
00516
00517 assert(lua_ispos3(L, 1));
00518
00519 pos = lua_topos3(L, 1);
00520 AI_TurnIntoDirection(AIL_ent, *pos);
00521
00522 lua_pushboolean(L, 1);
00523 return 1;
00524 }
00525
00532 static int AIL_print (lua_State *L)
00533 {
00534 int i;
00535 const int n = lua_gettop(L);
00536
00537 for (i = 1; i <= n; i++) {
00538 const char *s;
00539 qboolean meta = qfalse;
00540
00541 lua_pushvalue(L, i);
00542 if (luaL_callmeta(L, 1, "__tostring")) {
00543 s = lua_tostring(L, -1);
00544 meta = qtrue;
00545 } else {
00546 switch (lua_type(L, -1)) {
00547 case LUA_TNUMBER:
00548 case LUA_TSTRING:
00549 s = lua_tostring(L, -1);
00550 break;
00551 case LUA_TBOOLEAN:
00552 s = lua_toboolean(L, -1) ? "true" : "false";
00553 break;
00554 case LUA_TNIL:
00555 s = "nil";
00556 break;
00557
00558 default:
00559 s = "unknown lua type";
00560 break;
00561 }
00562 }
00563 gi.DPrintf("%s%s", (i > 1) ? "\t" : "", s);
00564 lua_pop(L, 1);
00565 if (meta)
00566 lua_pop(L, 1);
00567 }
00568
00569 gi.DPrintf("\n");
00570 return 0;
00571 }
00572
00576 static int AIL_see (lua_State *L)
00577 {
00578 int vision, team;
00579 int i, j, k, n, cur;
00580 edict_t *check = NULL;
00581 aiActor_t target;
00582 edict_t *sorted[MAX_EDICTS], *unsorted[MAX_EDICTS];
00583 float distLookup[MAX_EDICTS];
00584
00585
00586 team = TEAM_ALL;
00587 vision = 0;
00588
00589
00590 if ((lua_gettop(L) > 0)) {
00591
00592 if (lua_isstring(L, 1)) {
00593 const char *s = lua_tostring(L, 1);
00596 if (strcmp(s, "all") == 0)
00597 vision = 0;
00598 else if (strcmp(s, "sight") == 0)
00599 vision = 1;
00600 else if (strcmp(s, "psionic") == 0)
00601 vision = 2;
00602 else if (strcmp(s, "infrared") == 0)
00603 vision = 3;
00604 else
00605 AIL_invalidparameter(1);
00606 } else
00607 AIL_invalidparameter(1);
00608
00609
00610 if ((lua_gettop(L) > 1)) {
00611 if (lua_isstring(L, 2)) {
00612 const char *s = lua_tostring(L, 2);
00613 team = AIL_toTeamInt(s);
00614 } else
00615 AIL_invalidparameter(2);
00616 }
00617 }
00618
00619 n = 0;
00620
00621 while ((check = G_EdictsGetNextLivingActor(check))) {
00622 if (AIL_ent == check)
00623 continue;
00624 if (vision == 0 && (team == TEAM_ALL || check->team == team)
00625 && G_Vis(AIL_ent->team, AIL_ent, check, VT_NOFRUSTUM)) {
00626 distLookup[n] = VectorDistSqr(AIL_ent->pos, check->pos);
00627 unsorted[n++] = check;
00628 }
00629 }
00630
00631
00632 for (i = 0; i < n; i++) {
00633 cur = -1;
00634 for (j = 0; j < n; j++) {
00635
00636 if (cur < 0 || distLookup[j] < distLookup[cur]) {
00637
00638 for (k = 0; k < i; k++)
00639 if (sorted[k] == unsorted[j])
00640 break;
00641
00642
00643 if (k == i)
00644 cur = j;
00645 }
00646 }
00647
00648 sorted[i] = unsorted[cur];
00649 }
00650
00651
00652 lua_newtable(L);
00653 for (i = 0; i < n; i++) {
00654 lua_pushnumber(L, i + 1);
00655 target.ent = sorted[i];
00656 lua_pushactor(L, &target);
00657 lua_rawset(L, -3);
00658 }
00659 return 1;
00660 }
00661
00665 static int AIL_crouch (lua_State *L)
00666 {
00667 if (lua_gettop(L) > 0) {
00668 if (lua_isboolean(L, 1)) {
00669 const int state = lua_toboolean(L, 1);
00670 G_ClientStateChange(AIL_player, AIL_ent, STATE_CROUCHED,
00671 (state) ? qtrue : qfalse);
00672 } else
00673 AIL_invalidparameter(1);
00674 }
00675
00676 lua_pushboolean(L, G_IsCrouched(AIL_ent));
00677 return 1;
00678 }
00679
00683 static int AIL_isinjured (lua_State *L)
00684 {
00685 lua_pushboolean(L, AIL_ent->HP != AIL_ent->chr.maxHP);
00686 return 1;
00687 }
00688
00692 static int AIL_TU (lua_State *L)
00693 {
00694 lua_pushnumber(L, AIL_ent->TU);
00695 return 1;
00696 }
00697
00701 static int AIL_HP (lua_State *L)
00702 {
00703 lua_pushnumber(L, AIL_ent->HP);
00704 return 1;
00705 }
00706
00710 static int AIL_morale (lua_State *L)
00711 {
00712 lua_pushnumber(L, AIL_ent->morale);
00713 return 1;
00714 }
00715
00719 static int AIL_reactionfire (lua_State *L)
00720 {
00721 int reactionState = 0;
00722 if (lua_gettop(L) > 0) {
00723
00724 if (lua_isstring(L, 1)) {
00725
00726 const char* cmd = lua_tostring(L, 1);
00727 reactionState = !strcmp(cmd, "disable") ? ~STATE_REACTION
00728 : !strcmp(cmd, "once") ? STATE_REACTION_ONCE
00729 : !strcmp(cmd, "many") ? STATE_REACTION_MANY : 0;
00730 }
00731
00732 if (reactionState && lua_gettop(L) > 1 && lua_isboolean(L, 2)) {
00733 const int state = lua_toboolean(L, 2);
00734 G_ClientStateChange(AIL_player, AIL_ent, reactionState,
00735 (state) ? qtrue : qfalse);
00736 } else {
00737 AIL_invalidparameter(reactionState ? 2 : 1);
00738 }
00739 }
00740
00741 lua_pushboolean(L, G_IsReaction(AIL_ent));
00742 return 1;
00743 }
00744
00748 static int AIL_roundsleft (lua_State *L)
00749 {
00750
00751 if (RIGHT(AIL_ent) && RIGHT(AIL_ent)->item.t->reload)
00752 lua_pushnumber(L, RIGHT(AIL_ent)->item.a);
00753 else
00754 lua_pushnil(L);
00755
00756
00757 if (LEFT(AIL_ent) && LEFT(AIL_ent)->item.t->reload)
00758 lua_pushnumber(L, LEFT(AIL_ent)->item.a);
00759 else
00760 lua_pushnil(L);
00761 return 2;
00762 }
00763
00767 static int AIL_canreload (lua_State *L)
00768 {
00769 lua_pushboolean(L, G_ClientCanReload(AIL_ent, gi.csi->idRight));
00770 lua_pushboolean(L, G_ClientCanReload(AIL_ent, gi.csi->idLeft));
00771 return 2;
00772 }
00773
00777 static int AIL_reload (lua_State *L)
00778 {
00779 containerIndex_t container;
00780
00781 if (lua_gettop(L) > 0) {
00782 if (lua_isstring(L, 1)) {
00783 const char *s = lua_tostring(L, 1);
00784
00785 if (!strcmp(s, "right"))
00786 container = gi.csi->idRight;
00787 else if (!strcmp(s, "left"))
00788 container = gi.csi->idLeft;
00789 else
00790 return 0;
00791 } else {
00792 AIL_invalidparameter(1);
00793 return 0;
00794 }
00795 } else
00796 container = gi.csi->idRight;
00797
00798 G_ActorReload(AIL_ent, INVDEF(container));
00799 return 0;
00800 }
00801
00805 static int AIL_positionshoot (lua_State *L)
00806 {
00807 pos3_t to, bestPos;
00808 vec3_t check;
00809 edict_t *ent;
00810 int dist;
00811 int xl, yl, xh, yh;
00812 int min_tu;
00813 aiActor_t *target;
00814 const byte crouchingState = G_IsCrouched(AIL_ent) ? 1 : 0;
00815
00816
00817 assert(lua_isactor(L, 1));
00818 target = lua_toactor(L, 1);
00819
00820
00821 ent = AIL_ent;
00822 dist = ent->TU;
00823
00824
00825 G_MoveCalc(0, ent, ent->pos, crouchingState, ent->TU);
00826 gi.MoveStore(&level.pathingMap);
00827
00828
00829 xl = (int) ent->pos[0] - dist;
00830 if (xl < 0)
00831 xl = 0;
00832 yl = (int) ent->pos[1] - dist;
00833 if (yl < 0)
00834 yl = 0;
00835 xh = (int) ent->pos[0] + dist;
00836 if (xh > PATHFINDING_WIDTH)
00837 xl = PATHFINDING_WIDTH;
00838 yh = (int) ent->pos[1] + dist;
00839 if (yh > PATHFINDING_WIDTH)
00840 yh = PATHFINDING_WIDTH;
00841
00842
00843
00844 min_tu = INT_MAX;
00845 for (to[2] = 0; to[2] < PATHFINDING_HEIGHT; to[2]++)
00846 for (to[1] = yl; to[1] < yh; to[1]++)
00847 for (to[0] = xl; to[0] < xh; to[0]++) {
00848 pos_t tu;
00849
00850 gi.GridPosToVec(gi.routingMap, ent->fieldSize, to, check);
00851 tu = gi.MoveLength(&level.pathingMap, to, G_IsCrouched(ent) ? 1 : 0, qtrue);
00852 if (tu > ent->TU || tu == ROUTING_NOT_REACHABLE)
00853 continue;
00854
00855 if (tu < min_tu) {
00856 if (G_ActorVis(check, target->ent, qtrue) > 0.3) {
00857 VectorCopy(to, bestPos);
00858 min_tu = tu;
00859 }
00860 }
00861 }
00862
00863
00864 if (min_tu > ent->TU) {
00865 lua_pushboolean(L, 0);
00866 return 1;
00867 }
00868
00869
00870 lua_pushpos3(L, &bestPos);
00871 return 1;
00872 }
00873
00879 static int AIL_positionhide (lua_State *L)
00880 {
00881 pos3_t save;
00882 int tus = AIL_ent->TU;
00883 int hidingTeam;
00884
00885 VectorCopy(AIL_ent->pos, save);
00886
00887 hidingTeam = AI_GetHidingTeam(AIL_ent);
00888
00889
00890 if (lua_gettop(L)) {
00891 if (lua_isstring(L, 1)) {
00892 const char* s = lua_tostring(L, 1);
00893 hidingTeam = AIL_toTeamInt(s);
00894 if (hidingTeam == TEAM_ALL)
00895 AIL_invalidparameter(1);
00896 } else {
00897 AIL_invalidparameter(1);
00898 }
00899 }
00900
00901 if (AI_FindHidingLocation(hidingTeam, AIL_ent, AIL_ent->pos, &tus)) {
00902
00903 lua_pushpos3(L, &AIL_ent->pos);
00904 } else {
00905 lua_pushboolean(L, 0);
00906 }
00907 G_EdictSetOrigin(AIL_ent, save);
00908 return 1;
00909 }
00910
00917 static int AIL_positionherd (lua_State *L)
00918 {
00919 pos3_t save;
00920 aiActor_t* target;
00921
00922
00923 if (!(lua_gettop(L) && lua_isactor(L, 1))) {
00924 AIL_invalidparameter(1);
00925 lua_pushboolean(L, 0);
00926 return 1;
00927 }
00928
00929 VectorCopy(AIL_ent->pos, save);
00930 target = lua_toactor(L, 1);
00931 if (AI_FindHerdLocation(AIL_ent, AIL_ent->pos, target->ent->origin, AIL_ent->TU)) {
00932 lua_pushpos3(L, &AIL_ent->pos);
00933 } else {
00934 lua_pushboolean(L, 0);
00935 }
00936 G_EdictSetOrigin(AIL_ent, save);
00937 return 1;
00938 }
00939
00944 static int AIL_distance (lua_State *L)
00945 {
00946 vec_t dist;
00947 aiActor_t* target;
00948
00949
00950 assert(lua_gettop(L) && lua_isactor(L, 1));
00951
00952
00953 target = lua_toactor(L, 1);
00954 dist = VectorDist(AIL_ent->origin, target->ent->origin);
00955 lua_pushnumber(L, dist);
00956 return 1;
00957 }
00958
00968 void AIL_ActorThink (player_t * player, edict_t * ent)
00969 {
00970 lua_State *L;
00971
00972
00973 L = ent->AI.L;
00974
00975
00976 AIL_ent = ent;
00977 AIL_player = player;
00978
00979
00980 lua_getglobal(L, "think");
00981 if (lua_pcall(L, 0, 0, 0)) {
00982 gi.DPrintf("Error while running Lua: %s\n",
00983 lua_isstring(L, -1) ? lua_tostring(L, -1) : "Unknown Error");
00984 }
00985
00986
00987 AIL_ent = NULL;
00988 AIL_player = NULL;
00989 }
00990
00991
00999 int AIL_InitActor (edict_t * ent, char *type, char *subtype)
01000 {
01001 AI_t *AI;
01002 int size;
01003 char path[MAX_VAR];
01004 char *fbuf;
01005
01006
01007 AI = &ent->AI;
01008 Q_strncpyz(AI->type, type, sizeof(AI->type));
01009 Q_strncpyz(AI->subtype, subtype, sizeof(AI->type));
01010
01011
01012 AI->L = luaL_newstate();
01013 if (AI->L == NULL) {
01014 gi.DPrintf("Unable to create Lua state.\n");
01015 return -1;
01016 }
01017
01018
01019 actorL_register(AI->L);
01020 pos3L_register(AI->L);
01021
01022
01023 luaL_register(AI->L, AI_METATABLE, AIL_methods);
01024
01025
01026 Com_sprintf(path, sizeof(path), "ai/%s.lua", type);
01027 size = gi.FS_LoadFile(path, (byte **) &fbuf);
01028 if (size == 0) {
01029 gi.DPrintf("Unable to load Lua file '%s'.\n", path);
01030 return -1;
01031 }
01032 if (luaL_dobuffer(AI->L, fbuf, size, path)) {
01033 gi.DPrintf("Unable to parse Lua file '%s'\n", path);
01034 gi.FS_FreeFile(fbuf);
01035 return -1;
01036 }
01037 gi.FS_FreeFile(fbuf);
01038
01039 return 0;
01040 }
01041
01046 static void AIL_CleanupActor (edict_t * ent)
01047 {
01048 AI_t *AI = &ent->AI;
01049
01050
01051 if (AI->L != NULL) {
01052 lua_close(AI->L);
01053 AI->L = NULL;
01054 }
01055 }
01056
01057 void AIL_Init (void)
01058 {
01059 gi.RegisterConstInt("luaaiteam::phalanx", TEAM_PHALANX);
01060 gi.RegisterConstInt("luaaiteam::civilian", TEAM_CIVILIAN);
01061 gi.RegisterConstInt("luaaiteam::alien", TEAM_ALIEN);
01062 gi.RegisterConstInt("luaaiteam::all", TEAM_ALL);
01063 }
01064
01065 void AIL_Shutdown (void)
01066 {
01067 gi.UnregisterConstVariable("luaaiteam::phalanx");
01068 gi.UnregisterConstVariable("luaaiteam::civilian");
01069 gi.UnregisterConstVariable("luaaiteam::alien");
01070 gi.UnregisterConstVariable("luaaiteam::all");
01071 }
01072
01076 void AIL_Cleanup (void)
01077 {
01078 edict_t *ent = NULL;
01079
01080 while ((ent = G_EdictsGetNextActor(ent)))
01081 AIL_CleanupActor(ent);
01082 }