be_aas_entity.c (12947B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 /***************************************************************************** 24 * name: be_aas_entity.c 25 * 26 * desc: AAS entities 27 * 28 * $Archive: /MissionPack/code/botlib/be_aas_entity.c $ 29 * 30 *****************************************************************************/ 31 32 #include "../game/q_shared.h" 33 #include "l_memory.h" 34 #include "l_script.h" 35 #include "l_precomp.h" 36 #include "l_struct.h" 37 #include "l_utils.h" 38 #include "l_log.h" 39 #include "aasfile.h" 40 #include "../game/botlib.h" 41 #include "../game/be_aas.h" 42 #include "be_aas_funcs.h" 43 #include "be_interface.h" 44 #include "be_aas_def.h" 45 46 #define MASK_SOLID CONTENTS_PLAYERCLIP 47 48 //FIXME: these might change 49 enum { 50 ET_GENERAL, 51 ET_PLAYER, 52 ET_ITEM, 53 ET_MISSILE, 54 ET_MOVER 55 }; 56 57 //=========================================================================== 58 // 59 // Parameter: - 60 // Returns: - 61 // Changes Globals: - 62 //=========================================================================== 63 int AAS_UpdateEntity(int entnum, bot_entitystate_t *state) 64 { 65 int relink; 66 aas_entity_t *ent; 67 vec3_t absmins, absmaxs; 68 69 if (!aasworld.loaded) 70 { 71 botimport.Print(PRT_MESSAGE, "AAS_UpdateEntity: not loaded\n"); 72 return BLERR_NOAASFILE; 73 } //end if 74 75 ent = &aasworld.entities[entnum]; 76 77 if (!state) { 78 //unlink the entity 79 AAS_UnlinkFromAreas(ent->areas); 80 //unlink the entity from the BSP leaves 81 AAS_UnlinkFromBSPLeaves(ent->leaves); 82 // 83 ent->areas = NULL; 84 // 85 ent->leaves = NULL; 86 return BLERR_NOERROR; 87 } 88 89 ent->i.update_time = AAS_Time() - ent->i.ltime; 90 ent->i.type = state->type; 91 ent->i.flags = state->flags; 92 ent->i.ltime = AAS_Time(); 93 VectorCopy(ent->i.origin, ent->i.lastvisorigin); 94 VectorCopy(state->old_origin, ent->i.old_origin); 95 ent->i.solid = state->solid; 96 ent->i.groundent = state->groundent; 97 ent->i.modelindex = state->modelindex; 98 ent->i.modelindex2 = state->modelindex2; 99 ent->i.frame = state->frame; 100 ent->i.event = state->event; 101 ent->i.eventParm = state->eventParm; 102 ent->i.powerups = state->powerups; 103 ent->i.weapon = state->weapon; 104 ent->i.legsAnim = state->legsAnim; 105 ent->i.torsoAnim = state->torsoAnim; 106 //number of the entity 107 ent->i.number = entnum; 108 //updated so set valid flag 109 ent->i.valid = qtrue; 110 //link everything the first frame 111 if (aasworld.numframes == 1) relink = qtrue; 112 else relink = qfalse; 113 // 114 if (ent->i.solid == SOLID_BSP) 115 { 116 //if the angles of the model changed 117 if (!VectorCompare(state->angles, ent->i.angles)) 118 { 119 VectorCopy(state->angles, ent->i.angles); 120 relink = qtrue; 121 } //end if 122 //get the mins and maxs of the model 123 //FIXME: rotate mins and maxs 124 AAS_BSPModelMinsMaxsOrigin(ent->i.modelindex, ent->i.angles, ent->i.mins, ent->i.maxs, NULL); 125 } //end if 126 else if (ent->i.solid == SOLID_BBOX) 127 { 128 //if the bounding box size changed 129 if (!VectorCompare(state->mins, ent->i.mins) || 130 !VectorCompare(state->maxs, ent->i.maxs)) 131 { 132 VectorCopy(state->mins, ent->i.mins); 133 VectorCopy(state->maxs, ent->i.maxs); 134 relink = qtrue; 135 } //end if 136 VectorCopy(state->angles, ent->i.angles); 137 } //end if 138 //if the origin changed 139 if (!VectorCompare(state->origin, ent->i.origin)) 140 { 141 VectorCopy(state->origin, ent->i.origin); 142 relink = qtrue; 143 } //end if 144 //if the entity should be relinked 145 if (relink) 146 { 147 //don't link the world model 148 if (entnum != ENTITYNUM_WORLD) 149 { 150 //absolute mins and maxs 151 VectorAdd(ent->i.mins, ent->i.origin, absmins); 152 VectorAdd(ent->i.maxs, ent->i.origin, absmaxs); 153 //unlink the entity 154 AAS_UnlinkFromAreas(ent->areas); 155 //relink the entity to the AAS areas (use the larges bbox) 156 ent->areas = AAS_LinkEntityClientBBox(absmins, absmaxs, entnum, PRESENCE_NORMAL); 157 //unlink the entity from the BSP leaves 158 AAS_UnlinkFromBSPLeaves(ent->leaves); 159 //link the entity to the world BSP tree 160 ent->leaves = AAS_BSPLinkEntity(absmins, absmaxs, entnum, 0); 161 } //end if 162 } //end if 163 return BLERR_NOERROR; 164 } //end of the function AAS_UpdateEntity 165 //=========================================================================== 166 // 167 // Parameter: - 168 // Returns: - 169 // Changes Globals: - 170 //=========================================================================== 171 void AAS_EntityInfo(int entnum, aas_entityinfo_t *info) 172 { 173 if (!aasworld.initialized) 174 { 175 botimport.Print(PRT_FATAL, "AAS_EntityInfo: aasworld not initialized\n"); 176 Com_Memset(info, 0, sizeof(aas_entityinfo_t)); 177 return; 178 } //end if 179 180 if (entnum < 0 || entnum >= aasworld.maxentities) 181 { 182 botimport.Print(PRT_FATAL, "AAS_EntityInfo: entnum %d out of range\n", entnum); 183 Com_Memset(info, 0, sizeof(aas_entityinfo_t)); 184 return; 185 } //end if 186 187 Com_Memcpy(info, &aasworld.entities[entnum].i, sizeof(aas_entityinfo_t)); 188 } //end of the function AAS_EntityInfo 189 //=========================================================================== 190 // 191 // Parameter: - 192 // Returns: - 193 // Changes Globals: - 194 //=========================================================================== 195 void AAS_EntityOrigin(int entnum, vec3_t origin) 196 { 197 if (entnum < 0 || entnum >= aasworld.maxentities) 198 { 199 botimport.Print(PRT_FATAL, "AAS_EntityOrigin: entnum %d out of range\n", entnum); 200 VectorClear(origin); 201 return; 202 } //end if 203 204 VectorCopy(aasworld.entities[entnum].i.origin, origin); 205 } //end of the function AAS_EntityOrigin 206 //=========================================================================== 207 // 208 // Parameter: - 209 // Returns: - 210 // Changes Globals: - 211 //=========================================================================== 212 int AAS_EntityModelindex(int entnum) 213 { 214 if (entnum < 0 || entnum >= aasworld.maxentities) 215 { 216 botimport.Print(PRT_FATAL, "AAS_EntityModelindex: entnum %d out of range\n", entnum); 217 return 0; 218 } //end if 219 return aasworld.entities[entnum].i.modelindex; 220 } //end of the function AAS_EntityModelindex 221 //=========================================================================== 222 // 223 // Parameter: - 224 // Returns: - 225 // Changes Globals: - 226 //=========================================================================== 227 int AAS_EntityType(int entnum) 228 { 229 if (!aasworld.initialized) return 0; 230 231 if (entnum < 0 || entnum >= aasworld.maxentities) 232 { 233 botimport.Print(PRT_FATAL, "AAS_EntityType: entnum %d out of range\n", entnum); 234 return 0; 235 } //end if 236 return aasworld.entities[entnum].i.type; 237 } //end of the AAS_EntityType 238 //=========================================================================== 239 // 240 // Parameter: - 241 // Returns: - 242 // Changes Globals: - 243 //=========================================================================== 244 int AAS_EntityModelNum(int entnum) 245 { 246 if (!aasworld.initialized) return 0; 247 248 if (entnum < 0 || entnum >= aasworld.maxentities) 249 { 250 botimport.Print(PRT_FATAL, "AAS_EntityModelNum: entnum %d out of range\n", entnum); 251 return 0; 252 } //end if 253 return aasworld.entities[entnum].i.modelindex; 254 } //end of the function AAS_EntityModelNum 255 //=========================================================================== 256 // 257 // Parameter: - 258 // Returns: - 259 // Changes Globals: - 260 //=========================================================================== 261 int AAS_OriginOfMoverWithModelNum(int modelnum, vec3_t origin) 262 { 263 int i; 264 aas_entity_t *ent; 265 266 for (i = 0; i < aasworld.maxentities; i++) 267 { 268 ent = &aasworld.entities[i]; 269 if (ent->i.type == ET_MOVER) 270 { 271 if (ent->i.modelindex == modelnum) 272 { 273 VectorCopy(ent->i.origin, origin); 274 return qtrue; 275 } //end if 276 } //end if 277 } //end for 278 return qfalse; 279 } //end of the function AAS_OriginOfMoverWithModelNum 280 //=========================================================================== 281 // 282 // Parameter: - 283 // Returns: - 284 // Changes Globals: - 285 //=========================================================================== 286 void AAS_EntitySize(int entnum, vec3_t mins, vec3_t maxs) 287 { 288 aas_entity_t *ent; 289 290 if (!aasworld.initialized) return; 291 292 if (entnum < 0 || entnum >= aasworld.maxentities) 293 { 294 botimport.Print(PRT_FATAL, "AAS_EntitySize: entnum %d out of range\n", entnum); 295 return; 296 } //end if 297 298 ent = &aasworld.entities[entnum]; 299 VectorCopy(ent->i.mins, mins); 300 VectorCopy(ent->i.maxs, maxs); 301 } //end of the function AAS_EntitySize 302 //=========================================================================== 303 // 304 // Parameter: - 305 // Returns: - 306 // Changes Globals: - 307 //=========================================================================== 308 void AAS_EntityBSPData(int entnum, bsp_entdata_t *entdata) 309 { 310 aas_entity_t *ent; 311 312 ent = &aasworld.entities[entnum]; 313 VectorCopy(ent->i.origin, entdata->origin); 314 VectorCopy(ent->i.angles, entdata->angles); 315 VectorAdd(ent->i.origin, ent->i.mins, entdata->absmins); 316 VectorAdd(ent->i.origin, ent->i.maxs, entdata->absmaxs); 317 entdata->solid = ent->i.solid; 318 entdata->modelnum = ent->i.modelindex - 1; 319 } //end of the function AAS_EntityBSPData 320 //=========================================================================== 321 // 322 // Parameter: - 323 // Returns: - 324 // Changes Globals: - 325 //=========================================================================== 326 void AAS_ResetEntityLinks(void) 327 { 328 int i; 329 for (i = 0; i < aasworld.maxentities; i++) 330 { 331 aasworld.entities[i].areas = NULL; 332 aasworld.entities[i].leaves = NULL; 333 } //end for 334 } //end of the function AAS_ResetEntityLinks 335 //=========================================================================== 336 // 337 // Parameter: - 338 // Returns: - 339 // Changes Globals: - 340 //=========================================================================== 341 void AAS_InvalidateEntities(void) 342 { 343 int i; 344 for (i = 0; i < aasworld.maxentities; i++) 345 { 346 aasworld.entities[i].i.valid = qfalse; 347 aasworld.entities[i].i.number = i; 348 } //end for 349 } //end of the function AAS_InvalidateEntities 350 //=========================================================================== 351 // 352 // Parameter: - 353 // Returns: - 354 // Changes Globals: - 355 //=========================================================================== 356 void AAS_UnlinkInvalidEntities(void) 357 { 358 int i; 359 aas_entity_t *ent; 360 361 for (i = 0; i < aasworld.maxentities; i++) 362 { 363 ent = &aasworld.entities[i]; 364 if (!ent->i.valid) 365 { 366 AAS_UnlinkFromAreas( ent->areas ); 367 ent->areas = NULL; 368 AAS_UnlinkFromBSPLeaves( ent->leaves ); 369 ent->leaves = NULL; 370 } //end for 371 } //end for 372 } //end of the function AAS_UnlinkInvalidEntities 373 //=========================================================================== 374 // 375 // Parameter: - 376 // Returns: - 377 // Changes Globals: - 378 //=========================================================================== 379 int AAS_NearestEntity(vec3_t origin, int modelindex) 380 { 381 int i, bestentnum; 382 float dist, bestdist; 383 aas_entity_t *ent; 384 vec3_t dir; 385 386 bestentnum = 0; 387 bestdist = 99999; 388 for (i = 0; i < aasworld.maxentities; i++) 389 { 390 ent = &aasworld.entities[i]; 391 if (ent->i.modelindex != modelindex) continue; 392 VectorSubtract(ent->i.origin, origin, dir); 393 if (abs(dir[0]) < 40) 394 { 395 if (abs(dir[1]) < 40) 396 { 397 dist = VectorLength(dir); 398 if (dist < bestdist) 399 { 400 bestdist = dist; 401 bestentnum = i; 402 } //end if 403 } //end if 404 } //end if 405 } //end for 406 return bestentnum; 407 } //end of the function AAS_NearestEntity 408 //=========================================================================== 409 // 410 // Parameter: - 411 // Returns: - 412 // Changes Globals: - 413 //=========================================================================== 414 int AAS_BestReachableEntityArea(int entnum) 415 { 416 aas_entity_t *ent; 417 418 ent = &aasworld.entities[entnum]; 419 return AAS_BestReachableLinkArea(ent->areas); 420 } //end of the function AAS_BestReachableEntityArea 421 //=========================================================================== 422 // 423 // Parameter: - 424 // Returns: - 425 // Changes Globals: - 426 //=========================================================================== 427 int AAS_NextEntity(int entnum) 428 { 429 if (!aasworld.loaded) return 0; 430 431 if (entnum < 0) entnum = -1; 432 while(++entnum < aasworld.maxentities) 433 { 434 if (aasworld.entities[entnum].i.valid) return entnum; 435 } //end while 436 return 0; 437 } //end of the function AAS_NextEntity