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