/* ================== BotMatch_WhereAreYou ================== */ void BotMatch_WhereAreYou( bot_state_t *bs, bot_match_t *match ) { float dist, bestdist; int i, bestitem, redflagtt, blueflagtt, redtobluett; bot_goal_t goal; char *nearbyitems[] = { "Shotgun", "Grenade Launcher", "Rocket Launcher", "Plasmagun", "Railgun", "Lightning Gun", "BFG10K", "Quad Damage", "Regeneration", "Battle Suit", "Speed", "Invisibility", "Flight", "Armor", "Heavy Armor", "Red Flag", "Blue Flag", NULL }; // if ( !TeamPlayIsOn() ) { return; } //if not addressed to this bot if ( !BotAddressedToBot( bs, match ) ) { return; } bestitem = -1; bestdist = 999999; for ( i = 0; nearbyitems[i]; i++ ) { dist = BotNearestVisibleItem( bs, nearbyitems[i], &goal ); if ( dist < bestdist ) { bestdist = dist; bestitem = i; } } if ( bestitem != -1 ) { if ( gametype == GT_CTF ) { redflagtt = trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, ctf_redflag.areanum, TFL_DEFAULT ); blueflagtt = trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, ctf_blueflag.areanum, TFL_DEFAULT ); redtobluett = trap_AAS_AreaTravelTimeToGoalArea( ctf_redflag.areanum, ctf_redflag.origin, ctf_blueflag.areanum, TFL_DEFAULT ); if ( redflagtt < ( redflagtt + blueflagtt ) * 0.4 ) { BotAI_BotInitialChat( bs, "ctflocation", nearbyitems[bestitem], "red", NULL ); } else if ( blueflagtt < ( redflagtt + blueflagtt ) * 0.4 ) { BotAI_BotInitialChat( bs, "ctflocation", nearbyitems[bestitem], "blue", NULL ); } else { BotAI_BotInitialChat( bs, "location", nearbyitems[bestitem], NULL ); } } else { BotAI_BotInitialChat( bs, "location", nearbyitems[bestitem], NULL ); } trap_BotEnterChat( bs->cs, bs->client, CHAT_TEAM ); } }
int BotTeamCarrierVisible( bot_state_t *bs ) { int i; float vis; aas_entityinfo_t entinfo; gentity_t *ent; float f, alertness; float squaredist; vec3_t dir; int areanum; alertness = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_ALERTNESS, 0, 1 ); for ( i = 0; i < maxclients && i < MAX_CLIENTS; i++ ) { if ( i == bs->client ) continue; ent = &g_entities[ i ]; if ( !ent->inuse || !ent->target_ent ) continue; BotEntityInfo( ent->target_ent->s.number, &entinfo ); if ( !entinfo.valid || !( entinfo.powerups & ( 1 << PW_BATTLESUIT ) ) ) continue; if ( !BotSameTeam( bs, i ) ) continue; VectorSubtract( entinfo.origin, bs->origin, dir ); squaredist = VectorLengthSquared( dir ); if ( squaredist > Square( 900.0 + alertness * 4000.0 ) ) continue; f = 90 + 90 - ( 90 - ( squaredist > Square( 810 ) ? Square( 810 ) : squaredist ) / ( 810 * 9 ) ); vis = BotEntityVisible( bs->entitynum, bs->eye, bs->viewangles, f, entinfo.number ); if ( vis <= 0 ) continue; areanum = BotPointAreaNum( entinfo.origin ); if ( trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, areanum, bs->tfl ) ) { return entinfo.number; } } return -1; }
/* ================== BotClientTravelTimeToGoal ================== */ int BotClientTravelTimeToGoal(int client, bot_goal_t *goal) { playerState_t ps; int areanum; BotAI_GetClientState(client, &ps); areanum = BotPointAreaNum(ps.origin); if (!areanum) return 1; return trap_AAS_AreaTravelTimeToGoalArea(areanum, ps.origin, goal->areanum, TFL_DEFAULT); }
/* ============ AICast_GetAvoid ============ */ qboolean AICast_GetAvoid( cast_state_t *cs, bot_goal_t *goal, vec3_t outpos, qboolean reverse, int blockEnt ) { float yaw, oldyaw, distmoved, bestmoved, bestyaw; vec3_t bestpos; aicast_predictmove_t castmove; usercmd_t ucmd; qboolean enemyVisible; float angleDiff; // TTimo might be used uninitialized int starttraveltime = 0; int besttraveltime, traveltime; int invert; float inc; qboolean averting = qfalse; float maxYaw, simTime; static int lastTime; VectorCopy( vec3_origin, bestpos ); // // if we are in the air, no chance of avoiding if ( cs->bs->cur_ps.groundEntityNum == ENTITYNUM_NONE && g_entities[cs->entityNum].waterlevel <= 1 ) { return qfalse; } // if ( cs->lastAvoid > level.time - rand() % 500 ) { return qfalse; } cs->lastAvoid = level.time + 50 + rand() % 500; // if ( lastTime == level.time ) { return qfalse; } lastTime = level.time; // if they have an enemy, and can currently see them, don't move out of their view enemyVisible = ( cs->bs->enemy >= 0 ) && ( AICast_CheckAttack( cs, cs->bs->enemy, qfalse ) ); // // look for a good direction to move out of the way bestmoved = 0; bestyaw = 360; besttraveltime = 9999999; if ( goal ) { starttraveltime = trap_AAS_AreaTravelTimeToGoalArea( cs->bs->areanum, cs->bs->origin, goal->areanum, cs->travelflags ); } memcpy( &ucmd, &cs->bs->lastucmd, sizeof( usercmd_t ) ); ucmd.forwardmove = 127; ucmd.rightmove = 0; ucmd.upmove = 0; if ( cs->dangerEntity >= 0 && cs->dangerEntityValidTime >= level.time ) { averting = qtrue; } else if ( !goal ) { averting = qtrue; // not heading for a goal, so we must be getting out of someone's way } // maxYaw = 0; simTime = 1.2; // if ( averting ) { // avoiding danger, go anywhere! angleDiff = 300; inc = 60; invert = 1; } else { if ( level.time % 1000 < 500 ) { invert = 1; } else { invert = -1; } angleDiff = 140; inc = 35; } if ( blockEnt > aicast_maxclients ) { maxYaw = angleDiff; simTime = 0.5; } // for ( yaw = -angleDiff * invert; yaw*invert <= maxYaw; yaw += inc * invert ) { if ( !averting && !yaw ) { continue; } oldyaw = cs->bs->cur_ps.viewangles[YAW]; cs->bs->cur_ps.viewangles[YAW] += yaw + reverse * 180; // ucmd.angles[YAW] = ANGLE2SHORT( AngleMod( cs->bs->cur_ps.viewangles[YAW] ) ); // AICast_PredictMovement( cs, 5, 0.4, &castmove, &ucmd, -1 ); // if we have a danger entity, try and get away from it at all costs if ( cs->dangerEntity >= 0 && cs->dangerEntityValidTime >= level.time ) { distmoved = Distance( castmove.endpos, cs->dangerEntityPos ); } else if ( goal ) { //distmoved = 99999 - trap_AAS_AreaTravelTimeToGoalArea( BotPointAreaNum(castmove.endpos), castmove.endpos, goal->areanum, cs->travelflags ); distmoved = 99999 - Distance( castmove.endpos, goal->origin ); } else { distmoved = Distance( castmove.endpos, cs->bs->cur_ps.origin ); } if ( ( distmoved > bestmoved ) //&& ((cs->bs->origin[2] - castmove.endpos[2]) < 64) // allow up, but not down (falling) && ( castmove.groundEntityNum != ENTITYNUM_NONE ) ) { // they all passed, check any other stuff if ( !enemyVisible || AICast_CheckAttackAtPos( cs->entityNum, cs->bs->enemy, castmove.endpos, qfalse, qfalse ) ) { if ( !goal || ( traveltime = trap_AAS_AreaTravelTimeToGoalArea( BotPointAreaNum( castmove.endpos ), castmove.endpos, goal->areanum, cs->travelflags ) ) < ( starttraveltime + 200 ) ) { bestyaw = yaw; bestmoved = distmoved; besttraveltime = traveltime; VectorCopy( castmove.endpos, bestpos ); } } } // cs->bs->cur_ps.viewangles[YAW] = oldyaw; } // if ( bestmoved > 0 ) { VectorCopy( bestpos, outpos ); return qtrue; } else { return qfalse; } //G_Printf("GetAvoid: %i ms\n", -pretime + Sys_MilliSeconds() ); }
void BotTeamSeekGoals( bot_state_t *bs ) { aas_entityinfo_t entinfo; int c; int areanum; if ( bs->ltgtype == LTG_TEAMACCOMPANY && !bs->ordered ) { BotEntityInfo( bs->teammate, &entinfo ); if ( !entinfo.valid || !( entinfo.powerups & ( 1 << PW_BATTLESUIT ) ) ) { bs->ltgtype = 0; return; } areanum = BotPointAreaNum( entinfo.origin ); if ( !trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, areanum, bs->tfl ) ) { bs->ltgtype = 0; } return; } if ( bs->owndecision_time < FloatTime() ) { c = BotTeamCarrierVisible( bs ); if ( c >= 0 && ( bs->ltgtype != LTG_TEAMACCOMPANY || bs->teammate != c ) ) { BotRefuseOrder( bs ); bs->decisionmaker = bs->client; bs->ordered = qfalse; bs->teammate = c; bs->teammatevisible_time = FloatTime(); bs->teammessage_time = 0; bs->arrive_time = 1; bs->teamgoal_time = FloatTime() + 120; bs->ltgtype = LTG_TEAMACCOMPANY; bs->formation_dist = 70; BotSetTeamStatus( bs ); bs->owndecision_time = FloatTime() + 5; return; } } #if 0 if ( BotTeamLeader( bs ) ) { return; } if ( bs->lastgoal_ltgtype ) { bs->teamgoal_time += 60; } if ( !bs->ordered && bs->lastgoal_ltgtype ) { bs->ltgtype = 0; } if ( bs->ltgtype == LTG_TEAMHELP || bs->ltgtype == LTG_TEAMACCOMPANY || bs->ltgtype == LTG_DEFENDKEYAREA || bs->ltgtype == LTG_CAMPORDER || bs->ltgtype == LTG_PATROL || bs->ltgtype == LTG_GETITEM ) { return; } if ( BotSetLastOrderedTask( bs ) ) { return; } if ( bs->owndecision_time > FloatTime() ) { return; } if ( bs->ctfroam_time > FloatTime() ) { return; } if ( BotAggression( bs ) < 50 ) { return; } bs->teammessage_time = FloatTime() + 2 * random(); bs->ltgtype = 0; bs->ctfroam_time = FloatTime() + CTF_ROAM_TIME; BotSetTeamStatus( bs ); bs->owndecision_time = FloatTime() + 5; #endif }
/* ================== BotMatch_WhereAreYou ================== */ void BotMatch_WhereAreYou(bot_state_t *bs, bot_match_t *match) { float dist, bestdist; int i, bestitem, redtt, bluett, client; bot_goal_t goal; char netname[MAX_MESSAGE_SIZE]; char *nearbyitems[] = { "Shotgun", "Grenade Launcher", "Rocket Launcher", "Plasmagun", "Railgun", "Lightning Gun", "BFG10K", "Quad Damage", "Regeneration", "Battle Suit", "Speed", "Invisibility", "Flight", "Armor", "Heavy Armor", "Red Flag", "Blue Flag", #ifdef MISSIONPACK "Nailgun", "Prox Launcher", "Chaingun", "Scout", "Guard", "Doubler", "Ammo Regen", "Neutral Flag", "Red Obelisk", "Blue Obelisk", "Neutral Obelisk", #endif NULL }; // if (!TeamPlayIsOn()) return; //if not addressed to this bot if (!BotAddressedToBot(bs, match)) return; bestitem = -1; bestdist = 999999; for (i = 0; nearbyitems[i]; i++) { dist = BotNearestVisibleItem(bs, nearbyitems[i], &goal); if (dist < bestdist) { bestdist = dist; bestitem = i; } } if (bestitem != -1) { if (gametype == GT_CTF #ifdef MISSIONPACK || gametype == GT_1FCTF #endif ) { redtt = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, ctf_redflag.areanum, TFL_DEFAULT); bluett = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, ctf_blueflag.areanum, TFL_DEFAULT); if (redtt < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, "teamlocation", nearbyitems[bestitem], "red", NULL); } else if (bluett < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, "teamlocation", nearbyitems[bestitem], "blue", NULL); } else { BotAI_BotInitialChat(bs, "location", nearbyitems[bestitem], NULL); } } #ifdef MISSIONPACK else if (gametype == GT_OBELISK || gametype == GT_HARVESTER) { redtt = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, redobelisk.areanum, TFL_DEFAULT); bluett = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, blueobelisk.areanum, TFL_DEFAULT); if (redtt < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, "teamlocation", nearbyitems[bestitem], "red", NULL); } else if (bluett < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, "teamlocation", nearbyitems[bestitem], "blue", NULL); } else { BotAI_BotInitialChat(bs, "location", nearbyitems[bestitem], NULL); } } #endif else { BotAI_BotInitialChat(bs, "location", nearbyitems[bestitem], NULL); } trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname)); client = ClientFromName(netname); trap_BotEnterChat(bs->cs, client, CHAT_TELL); } }
/* ================== BotMatch_WhereAreYou ================== */ void BotMatch_WhereAreYou(bot_state_t *bs, bot_match_t *match) { float dist, bestdist; int i, redtt, bluett, playernum; char *teamlocation; char *bestitemname; bot_goal_t goal; gitem_t *it; char netname[MAX_MESSAGE_SIZE]; char *nearbyitems[] = { #ifdef MISSIONPACK "Red Obelisk", "Blue Obelisk", "Neutral Obelisk", #endif NULL }; // if (!TeamPlayIsOn()) return; //if not addressed to this bot if (!BotAddressedToBot(bs, match)) return; bestitemname = NULL; bestdist = 999999; for (i = 1; i < BG_NumItems(); i++) { it = BG_ItemForItemNum( i ); if ( !it->classname || !*it->classname ) { continue; } //ignore health, ammo, holdables, small armor, and Red Cube and Blue Cube if ( it->giType == IT_HEALTH || it->giType == IT_AMMO || it->giType == IT_HOLDABLE || ( it->giType == IT_ARMOR && it->quantity < 50 ) #ifdef MISSIONPACK || ( it->giType == IT_TEAM && it->giTag == 0 ) #endif ) { continue; } dist = BotNearestVisibleItem(bs, it->pickup_name, &goal); if (dist < bestdist) { bestdist = dist; bestitemname = it->pickup_name; } } for (i = 0; nearbyitems[i]; i++) { dist = BotNearestVisibleItem(bs, nearbyitems[i], &goal); if (dist < bestdist) { bestdist = dist; bestitemname = nearbyitems[i]; } } if (bestitemname) { if (gametype == GT_CTF #ifdef MISSIONPACK || gametype == GT_1FCTF || gametype == GT_OBELISK || gametype == GT_HARVESTER #endif ) { #ifdef MISSIONPACK if (gametype == GT_OBELISK || gametype == GT_HARVESTER) { redtt = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, redobelisk.areanum, TFL_DEFAULT); bluett = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, blueobelisk.areanum, TFL_DEFAULT); } else #endif { redtt = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, ctf_redflag.areanum, TFL_DEFAULT); bluett = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, ctf_blueflag.areanum, TFL_DEFAULT); } // unpatched q3 used 'ctflocation', some games still use it if ( BotNumInitialChats( bs->cs, "teamlocation" ) ) { teamlocation = "teamlocation"; } else { teamlocation = "ctflocation"; } if (redtt < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, teamlocation, bestitemname, "red", NULL); } else if (bluett < (redtt + bluett) * 0.4) { BotAI_BotInitialChat(bs, teamlocation, bestitemname, "blue", NULL); } else { BotAI_BotInitialChat(bs, "location", bestitemname, NULL); } } else { BotAI_BotInitialChat(bs, "location", bestitemname, NULL); } BotMatchVariable(match, NETNAME, netname, sizeof(netname)); playernum = PlayerFromName(netname); BotEnterChat(bs->cs, playernum, CHAT_TELL); } }