Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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