$$QUERY Objects b:Player is within the [i:Cone=90] degree view cone of [o:Object] at a max distance of [f:Distance] using flags [g:FVIHitFlags=1048585:16269119] qObjCanSeePlayerAdvanced Can object see a player Determines if the specified object can see a player (but allowing some customizability as to what the object can see through) Parameters: Object: The object doing the looking Cone: Angl
| 6220 | $$END |
| 6221 | */ |
| 6222 | bool qObjCanSeePlayerAdvanced(int cone, int handlesrc, float max_distance, int fvi_flags) { |
| 6223 | vector vsource, vtarget, viewvec; |
| 6224 | msafe_struct mstruct; |
| 6225 | matrix orient; |
| 6226 | int sourceroom; |
| 6227 | |
| 6228 | // Get half of the angle that the user specified because they specified a cone, and we want an angle |
| 6229 | double cangle = (double)((double)cone / (double)2); |
| 6230 | double t = cangle * PI / 180; |
| 6231 | double testangle = cos(t); |
| 6232 | |
| 6233 | // Get the viewer position |
| 6234 | mstruct.objhandle = handlesrc; |
| 6235 | MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct); |
| 6236 | vsource = mstruct.pos; |
| 6237 | |
| 6238 | // Get the viewer orientation |
| 6239 | MSafe_GetValue(MSAFE_OBJECT_ORIENT, &mstruct); |
| 6240 | orient = mstruct.orient; |
| 6241 | |
| 6242 | // Get the viewer room |
| 6243 | MSafe_GetValue(MSAFE_OBJECT_ROOMNUM, &mstruct); |
| 6244 | sourceroom = mstruct.roomnum; |
| 6245 | |
| 6246 | // Loop though all possible players |
| 6247 | for (int p = 0; p < MAX_PLAYERS; p++) { |
| 6248 | |
| 6249 | // Get player position |
| 6250 | mstruct.slot = p; |
| 6251 | MSafe_GetValue(MSAFE_OBJECT_PLAYER_HANDLE, &mstruct); |
| 6252 | |
| 6253 | // See if this player active |
| 6254 | if (mstruct.objhandle == OBJECT_HANDLE_NONE) |
| 6255 | continue; |
| 6256 | |
| 6257 | // Get the target position |
| 6258 | MSafe_GetValue(MSAFE_OBJECT_POS, &mstruct); |
| 6259 | vtarget = mstruct.pos; |
| 6260 | |
| 6261 | // Get the normalized vector from the source to the target |
| 6262 | float dist = vm_GetNormalizedDirFast(&viewvec, &vtarget, &vsource); |
| 6263 | |
| 6264 | // Get the angle between the objects |
| 6265 | float dot = vm_DotProduct(&viewvec, &orient.fvec); |
| 6266 | |
| 6267 | // Check angle and distance |
| 6268 | if ((dot > testangle) && (dist < max_distance)) { |
| 6269 | // see if we can cast a ray to the player |
| 6270 | ray_info ray; |
| 6271 | fvi_flags |= (FQ_CHECK_OBJS | FQ_ONLY_PLAYER_OBJ); |
| 6272 | int fate = FVI_RayCast(handlesrc, &vsource, &vtarget, sourceroom, 0.0f, fvi_flags, &ray); |
| 6273 | |
| 6274 | if (fate == HIT_NONE) |
| 6275 | return true; |
| 6276 | |
| 6277 | if (fate == HIT_OBJECT) { |
| 6278 | mstruct.objhandle = ray.hit_object; |
| 6279 | MSafe_GetValue(MSAFE_OBJECT_TYPE, &mstruct); |
no test coverage detected