📄 be_ai_goal.c
字号:
{
maplocation_t *ml;
vec3_t mins = {-8, -8, -8}, maxs = {8, 8, 8};
for (ml = maplocations; ml; ml = ml->next)
{
if (!Q_stricmp(ml->name, name))
{
goal->areanum = ml->areanum;
VectorCopy(ml->origin, goal->origin);
goal->entitynum = 0;
VectorCopy(mins, goal->mins);
VectorCopy(maxs, goal->maxs);
return qtrue;
} //end if
} //end for
return qfalse;
} //end of the function BotGetMapLocationGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotGetNextCampSpotGoal(int num, bot_goal_t *goal)
{
int i;
campspot_t *cs;
vec3_t mins = {-8, -8, -8}, maxs = {8, 8, 8};
if (num < 0) num = 0;
i = num;
for (cs = campspots; cs; cs = cs->next)
{
if (--i < 0)
{
goal->areanum = cs->areanum;
VectorCopy(cs->origin, goal->origin);
goal->entitynum = 0;
VectorCopy(mins, goal->mins);
VectorCopy(maxs, goal->maxs);
return num+1;
} //end if
} //end for
return 0;
} //end of the function BotGetNextCampSpotGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotFindEntityForLevelItem(levelitem_t *li)
{
int ent, modelindex;
itemconfig_t *ic;
aas_entityinfo_t entinfo;
vec3_t dir;
ic = itemconfig;
if (!itemconfig) return;
for (ent = AAS_NextEntity(0); ent; ent = AAS_NextEntity(ent))
{
//get the model index of the entity
modelindex = AAS_EntityModelindex(ent);
//
if (!modelindex) continue;
//get info about the entity
AAS_EntityInfo(ent, &entinfo);
//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;
//
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;
} //end if
} //end if
} //end for
} //end of the function BotFindEntityForLevelItem
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
//NOTE: enum entityType_t in bg_public.h
#define ET_ITEM 2
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 entity is already stored as a level item
for (li = levelitems; li; li = li->next)
{
//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;
} //end if
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);
} //end if
break;
} //end else
} //end if
} //end for
if (li) continue;
//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 == 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 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);
} //end if
#ifdef DEBUG
Log_Write("linked item %s to an entity", ic->iteminfo[li->iteminfo].classname);
#endif //DEBUG
break;
} //end if
} //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);
//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);
//botimport.Print(PRT_MESSAGE, "found new level item %s\n", ic->iteminfo[i].classname);
} //end for
/*
for (li = levelitems; li; li = li->next)
{
if (!li->entitynum)
{
BotFindEntityForLevelItem(li);
} //end if
} //end for*/
} //end of the function BotUpdateEntityItems
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotDumpGoalStack(int goalstate)
{
int i;
bot_goalstate_t *gs;
char name[32];
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
for (i = 1; i <= gs->goalstacktop; i++)
{
BotGoalName(gs->goalstack[i].number, name, 32);
Log_Write("%d: %s", i, name);
} //end for
} //end of the function BotDumpGoalStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotPushGoal(int goalstate, bot_goal_t *goal)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
if (gs->goalstacktop >= MAX_GOALSTACK-1)
{
botimport.Print(PRT_ERROR, "goal heap overflow\n");
BotDumpGoalStack(goalstate);
return;
} //end if
gs->goalstacktop++;
Com_Memcpy(&gs->goalstack[gs->goalstacktop], goal, sizeof(bot_goal_t));
} //end of the function BotPushGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotPopGoal(int goalstate)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
if (gs->goalstacktop > 0) gs->goalstacktop--;
} //end of the function BotPopGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotEmptyGoalStack(int goalstate)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return;
gs->goalstacktop = 0;
} //end of the function BotEmptyGoalStack
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotGetTopGoal(int goalstate, bot_goal_t *goal)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return qfalse;
if (!gs->goalstacktop) return qfalse;
Com_Memcpy(goal, &gs->goalstack[gs->goalstacktop], sizeof(bot_goal_t));
return qtrue;
} //end of the function BotGetTopGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotGetSecondGoal(int goalstate, bot_goal_t *goal)
{
bot_goalstate_t *gs;
gs = BotGoalStateFromHandle(goalstate);
if (!gs) return qfalse;
if (gs->goalstacktop <= 1) return qfalse;
Com_Memcpy(goal, &gs->goalstack[gs->goalstacktop-1], sizeof(bot_goal_t));
return qtrue;
} //end of the function BotGetSecondGoal
//===========================================================================
// pops a new long term goal on the goal stack in the goalstate
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotChooseLTGItem(int goalstate, vec3_t origin, int *inventory, int travelflags)
{
int areanum, t, weightnum;
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;
//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 not 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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -