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 BotInitLevelItems() { //initialize the map locations and camp spots BotInitInfoEntities(); //initialize the level item heap InitLevelItemHeap(); levelitems = NULL; numlevelitems = 0; itemconfig_t* ic = itemconfig; if ( !ic ) { return; } //if there's no AAS file loaded if ( !AAS_Loaded() ) { return; } //update the modelindexes of the item info for ( int i = 0; i < ic->numiteminfo; i++ ) { if ( !ic->iteminfo[ i ].modelindex ) { Log_Write( "item %s has modelindex 0", ic->iteminfo[ i ].classname ); } } for ( int ent = AAS_NextBSPEntity( 0 ); ent; ent = AAS_NextBSPEntity( ent ) ) { char classname[ MAX_EPAIRKEY ]; if ( !AAS_ValueForBSPEpairKey( ent, "classname", classname, MAX_EPAIRKEY ) ) { continue; } int spawnflags = 0; AAS_IntForBSPEpairKey( ent, "spawnflags", &spawnflags ); int i; for ( i = 0; i < ic->numiteminfo; i++ ) { if ( !String::Cmp( classname, ic->iteminfo[ i ].classname ) ) { break; } } if ( i >= ic->numiteminfo ) { Log_Write( "entity %s unknown item\r\n", classname ); continue; } //get the origin of the item vec3_t origin; if ( !AAS_VectorForBSPEpairKey( ent, "origin", origin ) ) { BotImport_Print( PRT_ERROR, "item %s without origin\n", classname ); continue; } int goalareanum = 0; //if it is a floating item if ( spawnflags & 1 ) { if ( !( GGameType & GAME_Quake3 ) ) { continue; } //if the item is not floating in water if ( !( AAS_PointContents( origin ) & BSP46CONTENTS_WATER ) ) { vec3_t end; VectorCopy( origin, end ); end[ 2 ] -= 32; bsp_trace_t trace = AAS_Trace( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs, end, -1, BSP46CONTENTS_SOLID | BSP46CONTENTS_PLAYERCLIP ); //if the item not near the ground if ( trace.fraction >= 1 ) { //if the item is not reachable from a jumppad goalareanum = AAS_BestReachableFromJumpPadArea( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs ); Log_Write( "item %s reachable from jumppad area %d\r\n", ic->iteminfo[ i ].classname, goalareanum ); if ( !goalareanum ) { continue; } } } } levelitem_t* li = AllocLevelItem(); if ( !li ) { return; } li->number = ++numlevelitems; li->timeout = 0; li->entitynum = 0; li->flags = 0; int value; AAS_IntForBSPEpairKey( ent, "notfree", &value ); if ( value ) { li->flags |= IFL_NOTFREE; } AAS_IntForBSPEpairKey( ent, "notteam", &value ); if ( value ) { li->flags |= IFL_NOTTEAM; } AAS_IntForBSPEpairKey( ent, "notsingle", &value ); if ( value ) { li->flags |= IFL_NOTSINGLE; } if ( GGameType & GAME_Quake3 ) { AAS_IntForBSPEpairKey( ent, "notbot", &value ); if ( value ) { li->flags |= IFL_NOTBOT; } if ( !String::Cmp( classname, "item_botroam" ) ) { li->flags |= IFL_ROAM; AAS_FloatForBSPEpairKey( ent, "weight", &li->weight ); } } //if not a stationary item if ( !( spawnflags & 1 ) ) { if ( !AAS_DropToFloor( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs ) ) { BotImport_Print( PRT_MESSAGE, "%s in solid at (%1.1f %1.1f %1.1f)\n", classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] ); } } //item info of the level item li->iteminfo = i; //origin of the item VectorCopy( origin, li->origin ); if ( goalareanum ) { li->goalareanum = goalareanum; VectorCopy( origin, li->goalorigin ); } else { //get the item goal area and goal origin li->goalareanum = AAS_BestReachableArea( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs, li->goalorigin ); if ( !li->goalareanum ) { BotImport_Print( PRT_MESSAGE, "%s not reachable for bots at (%1.1f %1.1f %1.1f)\n", classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] ); } } AddLevelItemToList( li ); } BotImport_Print( PRT_MESSAGE, "found %d level items\n", numlevelitems ); }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void BotInitLevelItems( void ) { int i, spawnflags; char classname[MAX_EPAIRKEY]; vec3_t origin; int ent; itemconfig_t *ic; levelitem_t *li; //initialize the map locations and camp spots BotInitInfoEntities(); //initialize the level item heap InitLevelItemHeap(); levelitems = NULL; numlevelitems = 0; // ic = itemconfig; if ( !ic ) { return; } //if there's no AAS file loaded if ( !AAS_Loaded() ) { return; } //update the modelindexes of the item info for ( i = 0; i < ic->numiteminfo; i++ ) { //ic->iteminfo[i].modelindex = AAS_IndexFromModel(ic->iteminfo[i].model); if ( !ic->iteminfo[i].modelindex ) { Log_Write( "item %s has modelindex 0", ic->iteminfo[i].classname ); } //end if } //end for for ( ent = AAS_NextBSPEntity( 0 ); ent; ent = AAS_NextBSPEntity( ent ) ) { if ( !AAS_ValueForBSPEpairKey( ent, "classname", classname, MAX_EPAIRKEY ) ) { continue; } // spawnflags = 0; AAS_IntForBSPEpairKey( ent, "spawnflags", &spawnflags ); //FIXME: don't do this // for now skip all floating entities if ( spawnflags & 1 ) { continue; } // for ( i = 0; i < ic->numiteminfo; i++ ) { if ( !strcmp( classname, ic->iteminfo[i].classname ) ) { //get the origin of the item if ( AAS_VectorForBSPEpairKey( ent, "origin", origin ) ) { li = AllocLevelItem(); if ( !li ) { return; } // li->number = ++numlevelitems; li->timeout = 0; li->entitynum = 0; // AAS_IntForBSPEpairKey( ent, "notfree", &li->notfree ); AAS_IntForBSPEpairKey( ent, "notteam", &li->notteam ); AAS_IntForBSPEpairKey( ent, "notsingle", &li->notsingle ); //if not a stationary item if ( !( spawnflags & 1 ) ) { if ( !AAS_DropToFloor( origin, ic->iteminfo[i].mins, ic->iteminfo[i].maxs ) ) { botimport.Print( PRT_MESSAGE, "%s in solid at (%1.1f %1.1f %1.1f)\n", classname, origin[0], origin[1], origin[2] ); } //end if } //end if //item info of the level item li->iteminfo = i; //origin of the item VectorCopy( origin, li->origin ); //get the item goal area and goal origin li->goalareanum = AAS_BestReachableArea( origin, ic->iteminfo[i].mins, ic->iteminfo[i].maxs, li->goalorigin ); // AddLevelItemToList( li ); } //end if else { botimport.Print( PRT_ERROR, "item %s without origin\n", classname ); } //end else break; } //end if } //end for if ( i >= ic->numiteminfo ) { Log_Write( "entity %s unknown item\r\n", classname ); } //end if } //end for botimport.Print( PRT_MESSAGE, "found %d level items\n", numlevelitems ); } //end of the function BotInitLevelItems
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 ); } }