00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "g_local.h"
00026
00031 qboolean G_FrustumVis (const edict_t *from, const vec3_t point)
00032 {
00033 return FrustumVis(from->origin, from->dir, point);
00034 }
00035
00042 static qboolean G_LineVis (const vec3_t from, const vec3_t to)
00043 {
00044 return G_TestLineWithEnts(from, to);
00045 }
00046
00063 float G_ActorVis (const vec3_t from, const edict_t *check, qboolean full)
00064 {
00065 vec3_t test, dir;
00066 float delta;
00067 int i, n;
00068
00069
00070 VectorCopy(check->origin, test);
00071 if (G_IsDead(check)) {
00072 test[2] += PLAYER_DEAD;
00073 delta = 0;
00074 } else if (G_IsCrouched(check)) {
00075 test[2] += PLAYER_CROUCH - 2;
00076 delta = (PLAYER_CROUCH - PLAYER_MIN) / 2 - 2;
00077 } else {
00078 test[2] += PLAYER_STAND;
00079 delta = (PLAYER_STAND - PLAYER_MIN) / 2 - 2;
00080 }
00081
00082
00083 dir[0] = from[1] - check->origin[1];
00084 dir[1] = check->origin[0] - from[0];
00085 dir[2] = 0;
00086 VectorNormalize(dir);
00087 VectorMA(test, -7, dir, test);
00088
00089
00090 n = 0;
00091 for (i = 0; i < 3; i++) {
00092 if (!G_LineVis(from, test)) {
00093 if (full)
00094 n++;
00095 else
00096 return ACTOR_VIS_100;
00097 }
00098
00099
00100 if (!delta) {
00101 if (n > 0)
00102 return ACTOR_VIS_100;
00103 else
00104 return ACTOR_VIS_0;
00105 }
00106 VectorMA(test, 7, dir, test);
00107 test[2] -= delta;
00108 }
00109
00110
00111 switch (n) {
00112 case 0:
00113 return ACTOR_VIS_0;
00114 case 1:
00115 return ACTOR_VIS_10;
00116 case 2:
00117 return ACTOR_VIS_50;
00118 default:
00119 return ACTOR_VIS_100;
00120 }
00121 }
00122
00132 float G_Vis (const int team, const edict_t *from, const edict_t *check, int flags)
00133 {
00134 vec3_t eye;
00135
00136
00137 if (!from->inuse || !check->inuse)
00138 return ACTOR_VIS_0;
00139
00140
00141 if (!G_IsLivingActor(from))
00142 return ACTOR_VIS_0;
00143
00144
00145 if (team >= 0 && check->team == team && !G_IsDead(check))
00146 return ACTOR_VIS_100;
00147
00148
00149 if (team >= 0 && from->team != team)
00150 return ACTOR_VIS_0;
00151
00152
00153 if (team < 0 && (from->team == -team || G_IsCivilian(from) || check->team != -team))
00154 return ACTOR_VIS_0;
00155
00156
00157 if (VectorCompare(from->pos, check->pos))
00158 return ACTOR_VIS_100;
00159
00160 if (!G_IsVisibleOnBattlefield(check))
00161 return ACTOR_VIS_0;
00162
00163
00164 if (VectorDistSqr(from->origin, check->origin) > MAX_SPOT_DIST * MAX_SPOT_DIST)
00165 return ACTOR_VIS_0;
00166
00167
00168 if (!(flags & VT_NOFRUSTUM) && !G_FrustumVis(from, check->origin))
00169 return ACTOR_VIS_0;
00170
00171
00172 VectorCopy(from->origin, eye);
00173 if (G_IsCrouched(from) || G_IsPaniced(from))
00174 eye[2] += EYE_CROUCH;
00175 else
00176 eye[2] += EYE_STAND;
00177
00178
00179 switch (check->type) {
00180 case ET_ACTOR:
00181 case ET_ACTOR2x2:
00182 return G_ActorVis(eye, check, qfalse);
00183 case ET_ITEM:
00184 case ET_PARTICLE:
00185 return !G_LineVis(eye, check->origin);
00186 default:
00187 return ACTOR_VIS_0;
00188 }
00189 }
00190
00205 int G_TestVis (const int team, edict_t * check, int flags)
00206 {
00207 edict_t *from = NULL;
00208
00209 const int old = G_IsVisibleForTeam(check, team) ? 1 : 0;
00210
00211 if (g_aidebug->integer)
00212 return VIS_YES | !old;
00213
00214 if (!(flags & VT_PERISH) && old)
00215 return VIS_YES;
00216
00217
00218 while ((from = G_EdictsGetNextInUse(from)))
00219 if (G_Vis(team, from, check, flags))
00220
00221 return VIS_YES | !old;
00222
00223
00224 return old;
00225 }
00226
00227 static qboolean G_VisShouldStop (const edict_t *ent)
00228 {
00229 return G_IsLivingActor(ent) && !G_IsCivilian(ent);
00230 }
00231
00232 static int G_DoTestVis (const int team, edict_t * check, qboolean perish, int playerMask, const edict_t *ent)
00233 {
00234 int status = 0;
00235 const int visFlags = perish ? VT_PERISH : 0;
00236 const int vis = G_TestVis(team, check, visFlags);
00237
00238
00239 if (vis & VIS_CHANGE) {
00240
00241 check->visflags ^= G_TeamToVisMask(team);
00242 G_AppearPerishEvent(playerMask, vis & VIS_YES, check, ent);
00243
00244
00245 if (vis & VIS_YES) {
00246 status |= VIS_APPEAR;
00247 if (G_VisShouldStop(check))
00248 status |= VIS_STOP;
00249 } else
00250 status |= VIS_PERISH;
00251 }
00252 return status;
00253 }
00254
00261 int G_CheckVisPlayer (player_t* player, qboolean perish)
00262 {
00263 int status = 0;
00264 edict_t* ent = NULL;
00265
00266
00267 while ((ent = G_EdictsGetNextInUse(ent))) {
00268
00269 status |= G_DoTestVis(player->pers.team, ent, perish, G_PlayerToPM(player), NULL);
00270 }
00271
00272 return status;
00273 }
00274
00298 int G_CheckVisTeam (const int team, edict_t *check, qboolean perish, const edict_t *ent)
00299 {
00300 int status = 0;
00301
00302
00303 if (check->inuse) {
00304
00305 status |= G_DoTestVis(team, check, perish, G_TeamToPM(team), ent);
00306 }
00307
00308 return status;
00309 }
00310
00314 int G_CheckVisTeamAll (const int team, qboolean perish, const edict_t *ent)
00315 {
00316 edict_t *chk = NULL;
00317 int status = 0;
00318
00319 while ((chk = G_EdictsGetNextInUse(chk))) {
00320 status |= G_CheckVisTeam(team, chk, perish, ent);
00321 }
00322 return status;
00323 }
00324
00334 int G_CheckVis (edict_t * check, qboolean perish)
00335 {
00336 int team;
00337 int status;
00338
00339 status = 0;
00340 for (team = 0; team < MAX_TEAMS; team++)
00341 if (level.num_alive[team]) {
00342 if (!check)
00343 status |= G_CheckVisTeamAll(team, perish, NULL);
00344 else
00345 status |= G_CheckVisTeam(team, check, perish, NULL);
00346 }
00347
00348 return status;
00349 }
00350
00355 void G_ClearVisFlags (int team)
00356 {
00357 edict_t *ent = NULL;
00358 int mask;
00359
00360 mask = ~G_TeamToVisMask(team);
00361 while ((ent = G_EdictsGetNextInUse(ent)))
00362 ent->visflags &= mask;
00363 }