/** * @brief test if @c check is visible by team (or if visibility changed?) * @sa G_CheckVisTeam * @param[in] team the team the edict may become visible for or perish from * their view * @param[in] check the edict we are talking about - which may become visible * or perish * @param[in] flags if you want to check whether the edict may also perish from * other players view, you should use the @c VT_PERISH bits * @note If the edict is already visible and flags doesn't contain the * bits of @c VT_PERISH, no further checks are performed - only the * @c VIS_YES bits are returned */ int G_TestVis (const int team, edict_t * check, int flags) { edict_t *from = NULL; /* store old flag */ const int old = G_IsVisibleForTeam(check, team) ? VIS_CHANGE : 0; if (g_aidebug->integer) return VIS_YES | !old; if (!(flags & VT_PERISH) && old) return VIS_YES; /* test if check is visible */ while ((from = G_EdictsGetNextInUse(from))) if (G_Vis(team, from, check, flags)) /* visible */ return VIS_YES | !old; /* just return the old state */ return old; }
/** * @brief test if @c check is visible by team (or if visibility changed?) * @sa G_CheckVisTeam * @param[in] team the team the edict may become visible for or perish from * their view * @param[in] check the edict we are talking about - which may become visible * or perish * @param[in] flags if you want to check whether the edict may also perish from * other players view, you should use the @c VT_PERISHCHK bits * @note If the edict is already visible and flags doesn't contain the * bits of @c VT_PERISHCHK, no further checks are performed - only the * @c VS_YES bits are returned * @return VS_CHANGE is added to the bit mask if the edict flipped its visibility * (invisible to visible or vice versa) VS_YES means the edict is visible for the * given team */ int G_TestVis (const int team, Edict* check, const vischeckflags_t flags) { /* store old flag */ const int old = G_IsVisibleForTeam(check, team) ? VS_CHANGE : 0; if (g_aidebug->integer) return VS_YES | !old; if (!(flags & VT_PERISHCHK) && old) return VS_YES; /* test if check is visible */ Edict* from = nullptr; while ((from = G_EdictsGetNextInUse(from))) if (G_Vis(team, from, check, flags)) /* visible */ return VS_YES | !old; /* just return the old state */ return old; }
/** * @brief Returns what the actor can see. */ static int AIL_see (lua_State *L) { int vision, team; int i, j, k, n, cur; edict_t *check = NULL; aiActor_t target; edict_t *sorted[MAX_EDICTS], *unsorted[MAX_EDICTS]; float distLookup[MAX_EDICTS]; /* Defaults. */ team = TEAM_ALL; vision = 0; /* Handle parameters. */ if ((lua_gettop(L) > 0)) { /* Get what to "see" with. */ if (lua_isstring(L, 1)) { const char *s = lua_tostring(L, 1); /** @todo Properly implement at edict level, get rid of magic numbers. * These are only "placeholders". */ if (Q_streq(s, "all")) vision = 0; else if (Q_streq(s, "sight")) vision = 1; else if (Q_streq(s, "psionic")) vision = 2; else if (Q_streq(s, "infrared")) vision = 3; else AIL_invalidparameter(1); } else AIL_invalidparameter(1); /* We now check for different teams. */ if ((lua_gettop(L) > 1)) { if (lua_isstring(L, 2)) { const char *s = lua_tostring(L, 2); team = AIL_toTeamInt(s); } else AIL_invalidparameter(2); } } n = 0; /* Get visible things. */ while ((check = G_EdictsGetNextLivingActor(check))) { if (AIL_ent == check) continue; if (vision == 0 && (team == TEAM_ALL || check->team == team) /* Check for team match if needed. */ && G_Vis(AIL_ent->team, AIL_ent, check, VT_NOFRUSTUM)) { distLookup[n] = VectorDistSqr(AIL_ent->pos, check->pos); unsorted[n++] = check; } } /* Sort by distance - nearest first. */ for (i = 0; i < n; i++) { /* Until we fill sorted */ cur = -1; for (j = 0; j < n; j++) { /* Check for closest */ /* Is shorter then current minimum? */ if (cur < 0 || distLookup[j] < distLookup[cur]) { /* Check if not already in sorted. */ for (k = 0; k < i; k++) if (sorted[k] == unsorted[j]) break; /* Not already sorted and is new minimum. */ if (k == i) cur = j; } } sorted[i] = unsorted[cur]; } /* Now save it in a Lua table. */ lua_newtable(L); for (i = 0; i < n; i++) { lua_pushnumber(L, i + 1); /* index, starts with 1 */ target.ent = sorted[i]; lua_pushactor(L, &target); /* value */ lua_rawset(L, -3); /* store the value in the table */ } return 1; /* Returns the table of actors. */ }