//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ShowReachableAreas(int areanum) { aas_areasettings_t *settings; static aas_reachability_t reach; static int index, lastareanum; static float lasttime; if (areanum != lastareanum) { index = 0; lastareanum = areanum; } //end if settings = &aasworld.areasettings[areanum]; // if (!settings->numreachableareas) return; // if (index >= settings->numreachableareas) index = 0; // if (AAS_Time() - lasttime > 1.5) { Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t)); index++; lasttime = AAS_Time(); AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK); botimport.Print(PRT_MESSAGE, "\n"); } //end if AAS_ShowReachability(&reach); } //end of the function ShowReachableAreas
float BotAvoidGoalTime( int goalstate, int number ) { bot_goalstate_t* gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return 0; } for ( int i = 0; i < MAX_AVOIDGOALS; i++ ) { if ( gs->avoidgoals[ i ] == number && gs->avoidgoaltimes[ i ] >= AAS_Time() ) { return gs->avoidgoaltimes[ i ] - AAS_Time(); } } return 0; }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void BotAddToAvoidGoals( bot_goalstate_t *gs, int number, float avoidtime ) { int i; for ( i = 0; i < MAX_AVOIDGOALS; i++ ) { //if this avoid goal has expired if ( gs->avoidgoaltimes[i] < AAS_Time() ) { gs->avoidgoals[i] = number; gs->avoidgoaltimes[i] = AAS_Time() + avoidtime; return; } //end if } //end for } //end of the function BotAddToAvoidGoals
void BotDumpAvoidGoals( int goalstate ) { bot_goalstate_t* gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return; } for ( int i = 0; i < MAX_AVOIDGOALS; i++ ) { if ( gs->avoidgoaltimes[ i ] >= AAS_Time() ) { char name[ 32 ]; BotGoalName( gs->avoidgoals[ i ], name, 32 ); Log_Write( "avoid goal %s, number %d for %f seconds", name, gs->avoidgoals[ i ], gs->avoidgoaltimes[ i ] - AAS_Time() ); } } }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int BotItemGoalInVisButNotVisible( int viewer, vec3_t eye, vec3_t viewangles, bot_goal_t *goal ) { aas_entityinfo_t entinfo; bsp_trace_t trace; vec3_t middle; if ( !( goal->flags & GFL_ITEM ) ) { return qfalse; } // VectorAdd( goal->mins, goal->mins, middle ); VectorScale( middle, 0.5, middle ); VectorAdd( goal->origin, middle, middle ); // trace = AAS_Trace( eye, NULL, NULL, middle, viewer, CONTENTS_SOLID ); //if the goal middle point is visible if ( trace.fraction >= 1 ) { //the goal entity number doesn't have to be valid //just assume it's valid if ( goal->entitynum <= 0 ) { return qfalse; } // //if the entity data isn't valid AAS_EntityInfo( goal->entitynum, &entinfo ); //NOTE: for some wacko reason entities are sometimes // not updated //if (!entinfo.valid) return qtrue; if ( entinfo.ltime < AAS_Time() - 0.5 ) { return qtrue; } } //end if return qfalse; } //end of the function BotItemGoalInVisButNotVisible
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== float BotAvoidGoalTime( int goalstate, int number ) { int i; bot_goalstate_t *gs; gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return 0; } //don't use the goals the bot wants to avoid for ( i = 0; i < MAX_AVOIDGOALS; i++ ) { if ( gs->avoidgoals[i] == number && gs->avoidgoaltimes[i] >= AAS_Time() ) { return gs->avoidgoaltimes[i] - AAS_Time(); } //end if } //end for return 0; } //end of the function BotAvoidGoalTime
static void BotAddToAvoidGoals( bot_goalstate_t* gs, int number, float avoidtime ) { for ( int i = 0; i < MAX_AVOIDGOALS; i++ ) { //if the avoid goal is already stored if ( gs->avoidgoals[ i ] == number ) { gs->avoidgoals[ i ] = number; gs->avoidgoaltimes[ i ] = AAS_Time() + avoidtime; return; } } for ( int i = 0; i < MAX_AVOIDGOALS; i++ ) { //if this avoid goal has expired if ( gs->avoidgoaltimes[ i ] < AAS_Time() ) { gs->avoidgoals[ i ] = number; gs->avoidgoaltimes[ i ] = AAS_Time() + avoidtime; return; } } }
void BotRemoveFromAvoidGoals( int goalstate, int number ) { bot_goalstate_t* gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return; } for ( int i = 0; i < MAX_AVOIDGOALS; i++ ) { if ( gs->avoidgoals[ i ] == number && gs->avoidgoaltimes[ i ] >= AAS_Time() ) { gs->avoidgoaltimes[ i ] = 0; return; } } }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_UpdateEntity(int entnum, bot_entitystate_t *state) { int relink; aas_entity_t *ent; vec3_t absmins, absmaxs; if (!aasworld.loaded) { botimport.Print(PRT_MESSAGE, "AAS_UpdateEntity: not loaded\n"); return BLERR_NOAASFILE; } //end if ent = &aasworld.entities[entnum]; if (!state) { //unlink the entity AAS_UnlinkFromAreas(ent->areas); //unlink the entity from the BSP leaves AAS_UnlinkFromBSPLeaves(ent->leaves); // ent->areas = NULL; // ent->leaves = NULL; return BLERR_NOERROR; } ent->i.update_time = AAS_Time() - ent->i.ltime; ent->i.type = state->type; ent->i.flags = state->flags; ent->i.ltime = AAS_Time(); VectorCopy(ent->i.origin, ent->i.lastvisorigin); VectorCopy(state->old_origin, ent->i.old_origin); ent->i.solid = state->solid; ent->i.groundent = state->groundent; ent->i.modelindex = state->modelindex; ent->i.modelindex2 = state->modelindex2; ent->i.frame = state->frame; ent->i.event = state->event; ent->i.eventParm = state->eventParm; ent->i.powerups = state->powerups; ent->i.weapon = state->weapon; ent->i.legsAnim = state->legsAnim; ent->i.torsoAnim = state->torsoAnim; //number of the entity ent->i.number = entnum; //updated so set valid flag ent->i.valid = qtrue; //link everything the first frame if (aasworld.numframes == 1) relink = qtrue; else relink = qfalse; // if (ent->i.solid == SOLID_BSP) { //if the angles of the model changed if (!VectorCompare(state->angles, ent->i.angles)) { VectorCopy(state->angles, ent->i.angles); relink = qtrue; } //end if //get the mins and maxs of the model //FIXME: rotate mins and maxs AAS_BSPModelMinsMaxsOrigin(ent->i.modelindex, ent->i.angles, ent->i.mins, ent->i.maxs, NULL); } //end if else if (ent->i.solid == SOLID_BBOX) { //if the bounding box size changed if (!VectorCompare(state->mins, ent->i.mins) || !VectorCompare(state->maxs, ent->i.maxs)) { VectorCopy(state->mins, ent->i.mins); VectorCopy(state->maxs, ent->i.maxs); relink = qtrue; } //end if VectorCopy(state->angles, ent->i.angles); } //end if //if the origin changed if (!VectorCompare(state->origin, ent->i.origin)) { VectorCopy(state->origin, ent->i.origin); relink = qtrue; } //end if //if the entity should be relinked if (relink) { //don't link the world model if (entnum != ENTITYNUM_WORLD) { //absolute mins and maxs VectorAdd(ent->i.mins, ent->i.origin, absmins); VectorAdd(ent->i.maxs, ent->i.origin, absmaxs); //unlink the entity AAS_UnlinkFromAreas(ent->areas); //relink the entity to the AAS areas (use the larges bbox) ent->areas = AAS_LinkEntityClientBBox(absmins, absmaxs, entnum, PRESENCE_NORMAL); //unlink the entity from the BSP leaves AAS_UnlinkFromBSPLeaves(ent->leaves); //link the entity to the world BSP tree ent->leaves = AAS_BSPLinkEntity(absmins, absmaxs, entnum, 0); } //end if } //end if return BLERR_NOERROR; } //end of the function AAS_UpdateEntity
void BotUpdateEntityItems( void ) { int ent, i, modelindex; vec3_t dir; levelitem_t *li, *nextli; aas_entityinfo_t entinfo; itemconfig_t *ic; //timeout current entity items if necessary for ( li = levelitems; li; li = nextli ) { nextli = li->next; //if it is a item that will time out if ( li->timeout ) { //timeout the item if ( li->timeout < AAS_Time() ) { RemoveLevelItemFromList( li ); FreeLevelItem( li ); } //end if } //end if } //end for //find new entity items ic = itemconfig; if ( !itemconfig ) { return; } // for ( ent = AAS_NextEntity( 0 ); ent; ent = AAS_NextEntity( ent ) ) { if ( AAS_EntityType( ent ) != ET_ITEM ) { continue; } //get the model index of the entity modelindex = AAS_EntityModelindex( ent ); // if ( !modelindex ) { continue; } //get info about the entity AAS_EntityInfo( ent, &entinfo ); //FIXME: don't do this //skip all floating items for now if ( entinfo.groundent != ENTITYNUM_WORLD ) { continue; } //if the entity is still moving if ( entinfo.origin[0] != entinfo.lastvisorigin[0] || entinfo.origin[1] != entinfo.lastvisorigin[1] || entinfo.origin[2] != entinfo.lastvisorigin[2] ) { continue; } //check if the level item isn't already stored for ( li = levelitems; li; li = li->next ) { //if the model of the level item and the entity are different if ( ic->iteminfo[li->iteminfo].modelindex != modelindex ) { continue; } //if the level item is linked to an entity if ( li->entitynum ) { if ( li->entitynum == ent ) { VectorCopy( entinfo.origin, li->origin ); break; } //end if } //end if else { //check if the entity is very close VectorSubtract( li->origin, entinfo.origin, dir ); if ( VectorLength( dir ) < 30 ) { //found an entity for this level item li->entitynum = ent; //keep updating the entity origin VectorCopy( entinfo.origin, li->origin ); //also update the goal area number li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[li->iteminfo].mins, ic->iteminfo[li->iteminfo].maxs, li->goalorigin ); //Log_Write("found item %s entity", ic->iteminfo[li->iteminfo].classname); break; } //end if //else botimport.Print(PRT_MESSAGE, "item %s has no attached entity\n", // ic->iteminfo[li->iteminfo].name); } //end else } //end for if ( li ) { continue; } //check if the model is from a known item for ( i = 0; i < ic->numiteminfo; i++ ) { if ( ic->iteminfo[i].modelindex == modelindex ) { break; } //end if } //end for //if the model is not from a known item if ( i >= ic->numiteminfo ) { continue; } //allocate a new level item li = AllocLevelItem(); // if ( !li ) { continue; } //entity number of the level item li->entitynum = ent; //number for the level item li->number = numlevelitems + ent; //set the item info index for the level item li->iteminfo = i; //origin of the item VectorCopy( entinfo.origin, li->origin ); //get the item goal area and goal origin li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[i].mins, ic->iteminfo[i].maxs, li->goalorigin ); // if ( AAS_AreaJumpPad( li->goalareanum ) ) { FreeLevelItem( li ); continue; } //end if //time this item out after 30 seconds //dropped items disappear after 30 seconds li->timeout = AAS_Time() + 30; //add the level item to the list AddLevelItemToList( li ); //botimport.Print(PRT_MESSAGE, "found new level item %s\n", ic->iteminfo[i].classname); } //end for } //end of the function BotUpdateEntityItems
void BotUpdateEntityItems() { int ent, i, modelindex; vec3_t dir; levelitem_t* li, * nextli; aas_entityinfo_t entinfo; itemconfig_t* ic; //timeout current entity items if necessary for ( li = levelitems; li; li = nextli ) { nextli = li->next; //if it is a item that will time out if ( li->timeout ) { //timeout the item if ( li->timeout < AAS_Time() ) { RemoveLevelItemFromList( li ); FreeLevelItem( li ); } //end if } //end if } //end for //find new entity items ic = itemconfig; if ( !itemconfig ) { return; } // for ( ent = AAS_NextEntity( 0 ); ent; ent = AAS_NextEntity( ent ) ) { if ( AAS_EntityType( ent ) != Q3ET_ITEM ) { continue; } //get the model index of the entity modelindex = AAS_EntityModelindex( ent ); // if ( !modelindex ) { continue; } //get info about the entity AAS_EntityInfo( ent, &entinfo ); //FIXME: don't do this //skip all floating items for now if ( !( GGameType & GAME_Quake3 ) && entinfo.groundent != Q3ENTITYNUM_WORLD ) { continue; } //if the entity is still moving if ( entinfo.origin[ 0 ] != entinfo.lastvisorigin[ 0 ] || entinfo.origin[ 1 ] != entinfo.lastvisorigin[ 1 ] || entinfo.origin[ 2 ] != entinfo.lastvisorigin[ 2 ] ) { continue; } //check if the entity is already stored as a level item for ( li = levelitems; li; li = li->next ) { if ( GGameType & GAME_Quake3 ) { //if the level item is linked to an entity if ( li->entitynum && li->entitynum == ent ) { //the entity is re-used if the models are different if ( ic->iteminfo[ li->iteminfo ].modelindex != modelindex ) { //remove this level item RemoveLevelItemFromList( li ); FreeLevelItem( li ); li = NULL; break; } else { if ( entinfo.origin[ 0 ] != li->origin[ 0 ] || entinfo.origin[ 1 ] != li->origin[ 1 ] || entinfo.origin[ 2 ] != li->origin[ 2 ] ) { VectorCopy( entinfo.origin, li->origin ); //also update the goal area number li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs, li->goalorigin ); } break; } } } else { //if the model of the level item and the entity are different if ( ic->iteminfo[ li->iteminfo ].modelindex != modelindex ) { continue; } //if the level item is linked to an entity if ( li->entitynum ) { if ( li->entitynum == ent ) { VectorCopy( entinfo.origin, li->origin ); break; } //end if } //end if else { //check if the entity is very close VectorSubtract( li->origin, entinfo.origin, dir ); if ( VectorLength( dir ) < 30 ) { //found an entity for this level item li->entitynum = ent; //keep updating the entity origin VectorCopy( entinfo.origin, li->origin ); //also update the goal area number li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs, li->goalorigin ); //Log_Write("found item %s entity", ic->iteminfo[li->iteminfo].classname); break; } //end if //else BotImport_Print(PRT_MESSAGE, "item %s has no attached entity\n", // ic->iteminfo[li->iteminfo].name); } //end else } } //end for if ( li ) { continue; } if ( GGameType & GAME_Quake3 ) { //try to link the entity to a level item for ( li = levelitems; li; li = li->next ) { //if this level item is already linked if ( li->entitynum ) { continue; } if ( g_gametype == Q3GT_SINGLE_PLAYER ) { if ( li->flags & IFL_NOTSINGLE ) { continue; } } else if ( g_gametype >= Q3GT_TEAM ) { if ( li->flags & IFL_NOTTEAM ) { continue; } } else { if ( li->flags & IFL_NOTFREE ) { continue; } } //if the model of the level item and the entity are the same if ( ic->iteminfo[ li->iteminfo ].modelindex == modelindex ) { //check if the entity is very close VectorSubtract( li->origin, entinfo.origin, dir ); if ( VectorLength( dir ) < 30 ) { //found an entity for this level item li->entitynum = ent; //if the origin is different if ( entinfo.origin[ 0 ] != li->origin[ 0 ] || entinfo.origin[ 1 ] != li->origin[ 1 ] || entinfo.origin[ 2 ] != li->origin[ 2 ] ) { //update the level item origin VectorCopy( entinfo.origin, li->origin ); //also update the goal area number li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs, li->goalorigin ); } #ifdef DEBUG Log_Write( "linked item %s to an entity", ic->iteminfo[ li->iteminfo ].classname ); #endif break; } } } if ( li ) { continue; } } //check if the model is from a known item for ( i = 0; i < ic->numiteminfo; i++ ) { if ( ic->iteminfo[ i ].modelindex == modelindex ) { break; } //end if } //end for //if the model is not from a known item if ( i >= ic->numiteminfo ) { continue; } //allocate a new level item li = AllocLevelItem(); // if ( !li ) { continue; } //entity number of the level item li->entitynum = ent; //number for the level item li->number = numlevelitems + ent; //set the item info index for the level item li->iteminfo = i; //origin of the item VectorCopy( entinfo.origin, li->origin ); //get the item goal area and goal origin li->goalareanum = AAS_BestReachableArea( li->origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs, li->goalorigin ); //never go for items dropped into jumppads if ( AAS_AreaJumpPad( li->goalareanum ) ) { FreeLevelItem( li ); continue; } //end if //time this item out after 30 seconds //dropped items disappear after 30 seconds li->timeout = AAS_Time() + 30; //add the level item to the list AddLevelItemToList( li ); } }