📄 be_ai_goal.c
字号:
//if this item won't respawn before we get there
avoidtime = BotAvoidGoalTime(goalstate, li->number);
if (avoidtime - t * 0.009 > 0)
continue;
//
weight /= (float) t * TRAVELTIME_SCALE;
//
if (weight > bestweight)
{
bestweight = weight;
bestitem = li;
} //end if
} //end if
} //end if
} //end for
//if no goal item found
if (!bestitem)
{
/*
//if not in lava or slime
if (!AAS_AreaLava(areanum) && !AAS_AreaSlime(areanum))
{
if (AAS_RandomGoalArea(areanum, travelflags, &goal.areanum, goal.origin))
{
VectorSet(goal.mins, -15, -15, -15);
VectorSet(goal.maxs, 15, 15, 15);
goal.entitynum = 0;
goal.number = 0;
goal.flags = GFL_ROAM;
goal.iteminfo = 0;
//push the goal on the stack
BotPushGoal(goalstate, &goal);
//
#ifdef DEBUG
botimport.Print(PRT_MESSAGE, "chosen roam goal area %d\n", goal.areanum);
#endif //DEBUG
return qtrue;
} //end if
} //end if
*/
return qfalse;
} //end if
//create a bot goal for this item
iteminfo = &ic->iteminfo[bestitem->iteminfo];
VectorCopy(bestitem->goalorigin, goal.origin);
VectorCopy(iteminfo->mins, goal.mins);
VectorCopy(iteminfo->maxs, goal.maxs);
goal.areanum = bestitem->goalareanum;
goal.entitynum = bestitem->entitynum;
goal.number = bestitem->number;
goal.flags = GFL_ITEM;
if (bestitem->timeout)
goal.flags |= GFL_DROPPED;
if (bestitem->flags & IFL_ROAM)
goal.flags |= GFL_ROAM;
goal.iteminfo = bestitem->iteminfo;
//if it's a dropped item
if (bestitem->timeout)
{
avoidtime = AVOID_DROPPED_TIME;
} //end if
else
{
avoidtime = iteminfo->respawntime;
if (!avoidtime)
avoidtime = AVOID_DEFAULT_TIME;
if (avoidtime < AVOID_MINIMUM_TIME)
avoidtime = AVOID_MINIMUM_TIME;
} //end else
//add the chosen goal to the goals to avoid for a while
BotAddToAvoidGoals(gs, bestitem->number, avoidtime);
//push the goal on the stack
BotPushGoal(goalstate, &goal);
//
return qtrue;
} //end of the function BotChooseLTGItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotChooseNBGItem(int goalstate, vec3_t origin, int *inventory, int travelflags,
bot_goal_t *ltg, float maxtime)
{
int areanum, t, weightnum, ltg_time;
float weight, bestweight, avoidtime;
iteminfo_t *iteminfo;
itemconfig_t *ic;
levelitem_t *li, *bestitem;
bot_goal_t goal;
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs)
return qfalse;
if (!gs->itemweightconfig)
return qfalse;
//get the area the bot is in
areanum = BotReachabilityArea(origin, gs->client);
//if the bot is in solid or if the area the bot is in has no reachability links
if (!areanum || !AAS_AreaReachability(areanum))
{
//use the last valid area the bot was in
areanum = gs->lastreachabilityarea;
} //end if
//remember the last area with reachabilities the bot was in
gs->lastreachabilityarea = areanum;
//if still in solid
if (!areanum)
return qfalse;
//
if (ltg) ltg_time = AAS_AreaTravelTimeToGoalArea(areanum, origin, ltg->areanum, travelflags);
else ltg_time = 99999;
//the item configuration
ic = itemconfig;
if (!itemconfig)
return qfalse;
//best weight and item so far
bestweight = 0;
bestitem = NULL;
Com_Memset(&goal, 0, sizeof(bot_goal_t));
//go through the items in the level
for (li = levelitems; li; li = li->next)
{
if (g_gametype == GT_SINGLE_PLAYER) {
if (li->flags & IFL_NOTSINGLE)
continue;
}
else if (g_gametype >= GT_TEAM) {
if (li->flags & IFL_NOTTEAM)
continue;
}
else {
if (li->flags & IFL_NOTFREE)
continue;
}
if (li->flags & IFL_NOTBOT)
continue;
//if the item is in a possible goal area
if (!li->goalareanum)
continue;
//FIXME: is this a good thing? added this for items that never spawned into the game (f.i. CTF flags in obelisk)
if (!li->entitynum && !(li->flags & IFL_ROAM))
continue;
//get the fuzzy weight function for this item
iteminfo = &ic->iteminfo[li->iteminfo];
weightnum = gs->itemweightindex[iteminfo->number];
if (weightnum < 0)
continue;
//
#ifdef UNDECIDEDFUZZY
weight = FuzzyWeightUndecided(inventory, gs->itemweightconfig, weightnum);
#else
weight = FuzzyWeight(inventory, gs->itemweightconfig, weightnum);
#endif //UNDECIDEDFUZZY
#ifdef DROPPEDWEIGHT
//HACK: to make dropped items more attractive
if (li->timeout)
weight += droppedweight->value;
#endif //DROPPEDWEIGHT
//use weight scale for item_botroam
if (li->flags & IFL_ROAM) weight *= li->weight;
//
if (weight > 0)
{
//get the travel time towards the goal area
t = AAS_AreaTravelTimeToGoalArea(areanum, origin, li->goalareanum, travelflags);
//if the goal is reachable
if (t > 0 && t < maxtime)
{
//if this item won't respawn before we get there
avoidtime = BotAvoidGoalTime(goalstate, li->number);
if (avoidtime - t * 0.009 > 0)
continue;
//
weight /= (float) t * TRAVELTIME_SCALE;
//
if (weight > bestweight)
{
t = 0;
if (ltg && !li->timeout)
{
//get the travel time from the goal to the long term goal
t = AAS_AreaTravelTimeToGoalArea(li->goalareanum, li->goalorigin, ltg->areanum, travelflags);
} //end if
//if the travel back is possible and doesn't take too long
if (t <= ltg_time)
{
bestweight = weight;
bestitem = li;
} //end if
} //end if
} //end if
} //end if
} //end for
//if no goal item found
if (!bestitem)
return qfalse;
//create a bot goal for this item
iteminfo = &ic->iteminfo[bestitem->iteminfo];
VectorCopy(bestitem->goalorigin, goal.origin);
VectorCopy(iteminfo->mins, goal.mins);
VectorCopy(iteminfo->maxs, goal.maxs);
goal.areanum = bestitem->goalareanum;
goal.entitynum = bestitem->entitynum;
goal.number = bestitem->number;
goal.flags = GFL_ITEM;
if (bestitem->timeout)
goal.flags |= GFL_DROPPED;
if (bestitem->flags & IFL_ROAM)
goal.flags |= GFL_ROAM;
goal.iteminfo = bestitem->iteminfo;
//if it's a dropped item
if (bestitem->timeout)
{
avoidtime = AVOID_DROPPED_TIME;
} //end if
else
{
avoidtime = iteminfo->respawntime;
if (!avoidtime)
avoidtime = AVOID_DEFAULT_TIME;
if (avoidtime < AVOID_MINIMUM_TIME)
avoidtime = AVOID_MINIMUM_TIME;
} //end else
//add the chosen goal to the goals to avoid for a while
BotAddToAvoidGoals(gs, bestitem->number, avoidtime);
//push the goal on the stack
BotPushGoal(goalstate, &goal);
//
return qtrue;
} //end of the function BotChooseNBGItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotTouchingGoal(vec3_t origin, bot_goal_t *goal)
{
int i;
vec3_t boxmins, boxmaxs;
vec3_t absmins, absmaxs;
vec3_t safety_maxs = {0, 0, 0}; //{4, 4, 10};
vec3_t safety_mins = {0, 0, 0}; //{-4, -4, 0};
AAS_PresenceTypeBoundingBox(PRESENCE_NORMAL, boxmins, boxmaxs);
VectorSubtract(goal->mins, boxmaxs, absmins);
VectorSubtract(goal->maxs, boxmins, absmaxs);
VectorAdd(absmins, goal->origin, absmins);
VectorAdd(absmaxs, goal->origin, absmaxs);
//make the box a little smaller for safety
VectorSubtract(absmaxs, safety_maxs, absmaxs);
VectorSubtract(absmins, safety_mins, absmins);
for (i = 0; i < 3; i++)
{
if (origin[i] < absmins[i] || origin[i] > absmaxs[i]) return qfalse;
} //end for
return qtrue;
} //end of the function BotTouchingGoal
//===========================================================================
//
// 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: -
//===========================================================================
void BotResetGoalState(int goalstate)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
Com_Memset(gs->goalstack, 0, MAX_GOALSTACK * sizeof(bot_goal_t));
gs->goalstacktop = 0;
BotResetAvoidGoals(goalstate);
} //end of the function BotResetGoalState
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadItemWeights(int goalstate, char *filename)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return BLERR_CANNOTLOADITEMWEIGHTS;
//load the weight configuration
gs->itemweightconfig = ReadWeightConfig(filename);
if (!gs->itemweightconfig)
{
botimport.Print(PRT_FATAL, "couldn't load weights\n");
return BLERR_CANNOTLOADITEMWEIGHTS;
} //end if
//if there's no item configuration
if (!itemconfig) return BLERR_CANNOTLOADITEMWEIGHTS;
//create the item weight index
gs->itemweightindex = ItemWeightIndex(gs->itemweightconfig, itemconfig);
//everything went ok
return BLERR_NOERROR;
} //end of the function BotLoadItemWeights
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotFreeItemWeights(int goalstate)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
if (gs->itemweightconfig) FreeWeightConfig(gs->itemweightconfig);
if (gs->itemweightindex) FreeMemory(gs->itemweightindex);
} //end of the function BotFreeItemWeights
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotAllocGoalState(int client)
{
int i;
for (i = 1; i <= MAX_CLIENTS; i++)
{
if (!botgoalstates[i])
{
botgoalstates[i] = GetClearedMemory(sizeof(bot_goalstate_t));
botgoalstates[i]->client = client;
return i;
} //end if
} //end for
return 0;
} //end of the function BotAllocGoalState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeGoalState(int handle)
{
if (handle <= 0 || handle > MAX_CLIENTS)
{
botimport.Print(PRT_FATAL, "goal state handle %d out of range\n", handle);
return;
} //end if
if (!botgoalstates[handle])
{
botimport.Print(PRT_FATAL, "invalid goal state handle %d\n", handle);
return;
} //end if
BotFreeItemWeights(handle);
FreeMemory(botgoalstates[handle]);
botgoalstates[handle] = NULL;
} //end of the function BotFreeGoalState
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotSetupGoalAI(void)
{
char *filename;
//check if teamplay is on
g_gametype = LibVarValue("g_gametype", "0");
//item configuration file
filename = LibVarString("itemconfig", "items.c");
//load the item configuration
itemconfig = LoadItemConfig(filename);
if (!itemconfig)
{
botimport.Print(PRT_FATAL, "couldn't load item config\n");
return BLERR_CANNOTLOADITEMCONFIG;
} //end if
//
droppedweight = LibVar("droppedweight", "1000");
//everything went ok
return BLERR_NOERROR;
} //end of the function BotSetupGoalAI
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotShutdownGoalAI(void)
{
int i;
if (itemconfig) FreeMemory(itemconfig);
itemconfig = NULL;
if (levelitemheap) FreeMemory(levelitemheap);
levelitemheap = NULL;
freelevelitems = NULL;
levelitems = NULL;
numlevelitems = 0;
BotFreeInfoEntities();
for (i = 1; i <= MAX_CLIENTS; i++)
{
if (botgoalstates[i])
{
BotFreeGoalState(i);
} //end if
} //end for
} //end of the function BotShutdownGoalAI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -