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 Quake III Arena source code; 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 "../qcommon/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 "botlib.h"
41 #include "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 //===========================================================================
AAS_UpdateEntity(int entnum,bot_entitystate_t * state)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 //===========================================================================
AAS_EntityInfo(int entnum,aas_entityinfo_t * info)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 //===========================================================================
AAS_EntityOrigin(int entnum,vec3_t origin)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 //===========================================================================
AAS_EntityModelindex(int entnum)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 //===========================================================================
AAS_EntityType(int entnum)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 //===========================================================================
AAS_EntityModelNum(int entnum)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 //===========================================================================
AAS_OriginOfMoverWithModelNum(int modelnum,vec3_t origin)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 //===========================================================================
AAS_EntitySize(int entnum,vec3_t mins,vec3_t maxs)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 //===========================================================================
AAS_EntityBSPData(int entnum,bsp_entdata_t * entdata)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 //===========================================================================
AAS_ResetEntityLinks(void)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 //===========================================================================
AAS_InvalidateEntities(void)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 //===========================================================================
AAS_UnlinkInvalidEntities(void)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 //===========================================================================
AAS_NearestEntity(vec3_t origin,int modelindex)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 //===========================================================================
AAS_BestReachableEntityArea(int entnum)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 //===========================================================================
AAS_NextEntity(int entnum)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
438