diff options
Diffstat (limited to 'src/botlib/be_ai_goal.c')
-rw-r--r-- | src/botlib/be_ai_goal.c | 1822 |
1 files changed, 0 insertions, 1822 deletions
diff --git a/src/botlib/be_ai_goal.c b/src/botlib/be_ai_goal.c deleted file mode 100644 index d099080e..00000000 --- a/src/botlib/be_ai_goal.c +++ /dev/null @@ -1,1822 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2006 Tim Angus - -This file is part of Tremulous. - -Tremulous is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Tremulous is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/***************************************************************************** - * name: be_ai_goal.c - * - * desc: goal AI - * - * $Archive: /MissionPack/code/botlib/be_ai_goal.c $ - * - *****************************************************************************/ - -#include "../qcommon/q_shared.h" -#include "l_utils.h" -#include "l_libvar.h" -#include "l_memory.h" -#include "l_log.h" -#include "l_script.h" -#include "l_precomp.h" -#include "l_struct.h" -#include "aasfile.h" -#include "botlib.h" -#include "be_aas.h" -#include "be_aas_funcs.h" -#include "be_interface.h" -#include "be_ai_weight.h" -#include "be_ai_goal.h" -#include "be_ai_move.h" - -//#define DEBUG_AI_GOAL -#ifdef RANDOMIZE -#define UNDECIDEDFUZZY -#endif //RANDOMIZE -#define DROPPEDWEIGHT -//minimum avoid goal time -#define AVOID_MINIMUM_TIME 10 -//default avoid goal time -#define AVOID_DEFAULT_TIME 30 -//avoid dropped goal time -#define AVOID_DROPPED_TIME 10 -// -#define TRAVELTIME_SCALE 0.01 -//item flags -#define IFL_NOTFREE 1 //not in free for all -#define IFL_NOTTEAM 2 //not in team play -#define IFL_NOTSINGLE 4 //not in single player -#define IFL_NOTBOT 8 //bot should never go for this -#define IFL_ROAM 16 //bot roam goal - -//location in the map "target_location" -typedef struct maplocation_s -{ - vec3_t origin; - int areanum; - char name[MAX_EPAIRKEY]; - struct maplocation_s *next; -} maplocation_t; - -//camp spots "info_camp" -typedef struct campspot_s -{ - vec3_t origin; - int areanum; - char name[MAX_EPAIRKEY]; - float range; - float weight; - float wait; - float random; - struct campspot_s *next; -} campspot_t; - -//FIXME: these are game specific -typedef enum { - GT_FFA, // free for all - GT_TOURNAMENT, // one on one tournament - GT_SINGLE_PLAYER, // single player tournament - - //-- team games go after this -- - - GT_TEAM, // team deathmatch - GT_CTF, // capture the flag -#ifdef MISSIONPACK - GT_1FCTF, - GT_OBELISK, - GT_HARVESTER, -#endif - GT_MAX_GAME_TYPE -} gametype_t; - -typedef struct levelitem_s -{ - int number; //number of the level item - int iteminfo; //index into the item info - int flags; //item flags - float weight; //fixed roam weight - vec3_t origin; //origin of the item - int goalareanum; //area the item is in - vec3_t goalorigin; //goal origin within the area - int entitynum; //entity number - float timeout; //item is removed after this time - struct levelitem_s *prev, *next; -} levelitem_t; - -typedef struct iteminfo_s -{ - char classname[32]; //classname of the item - char name[MAX_STRINGFIELD]; //name of the item - char model[MAX_STRINGFIELD]; //model of the item - int modelindex; //model index - int type; //item type - int index; //index in the inventory - float respawntime; //respawn time - vec3_t mins; //mins of the item - vec3_t maxs; //maxs of the item - int number; //number of the item info -} iteminfo_t; - -#define ITEMINFO_OFS(x) (int)&(((iteminfo_t *)0)->x) - -fielddef_t iteminfo_fields[] = -{ -{"name", ITEMINFO_OFS(name), FT_STRING}, -{"model", ITEMINFO_OFS(model), FT_STRING}, -{"modelindex", ITEMINFO_OFS(modelindex), FT_INT}, -{"type", ITEMINFO_OFS(type), FT_INT}, -{"index", ITEMINFO_OFS(index), FT_INT}, -{"respawntime", ITEMINFO_OFS(respawntime), FT_FLOAT}, -{"mins", ITEMINFO_OFS(mins), FT_FLOAT|FT_ARRAY, 3}, -{"maxs", ITEMINFO_OFS(maxs), FT_FLOAT|FT_ARRAY, 3}, -{NULL, 0, 0} -}; - -structdef_t iteminfo_struct = -{ - sizeof(iteminfo_t), iteminfo_fields -}; - -typedef struct itemconfig_s -{ - int numiteminfo; - iteminfo_t *iteminfo; -} itemconfig_t; - -//goal state -typedef struct bot_goalstate_s -{ - struct weightconfig_s *itemweightconfig; //weight config - int *itemweightindex; //index from item to weight - // - int client; //client using this goal state - int lastreachabilityarea; //last area with reachabilities the bot was in - // - bot_goal_t goalstack[MAX_GOALSTACK]; //goal stack - int goalstacktop; //the top of the goal stack - // - int avoidgoals[MAX_AVOIDGOALS]; //goals to avoid - float avoidgoaltimes[MAX_AVOIDGOALS]; //times to avoid the goals -} bot_goalstate_t; - -bot_goalstate_t *botgoalstates[MAX_CLIENTS + 1]; // bk001206 - FIXME: init? -//item configuration -itemconfig_t *itemconfig = NULL; // bk001206 - init -//level items -levelitem_t *levelitemheap = NULL; // bk001206 - init -levelitem_t *freelevelitems = NULL; // bk001206 - init -levelitem_t *levelitems = NULL; // bk001206 - init -int numlevelitems = 0; -//map locations -maplocation_t *maplocations = NULL; // bk001206 - init -//camp spots -campspot_t *campspots = NULL; // bk001206 - init -//the game type -int g_gametype = 0; // bk001206 - init -//additional dropped item weight -libvar_t *droppedweight = NULL; // bk001206 - init - -//======================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//======================================================================== -bot_goalstate_t *BotGoalStateFromHandle(int handle) -{ - if (handle <= 0 || handle > MAX_CLIENTS) - { - botimport.Print(PRT_FATAL, "goal state handle %d out of range\n", handle); - return NULL; - } //end if - if (!botgoalstates[handle]) - { - botimport.Print(PRT_FATAL, "invalid goal state %d\n", handle); - return NULL; - } //end if - return botgoalstates[handle]; -} //end of the function BotGoalStateFromHandle -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotInterbreedGoalFuzzyLogic(int parent1, int parent2, int child) -{ - bot_goalstate_t *p1, *p2, *c; - - p1 = BotGoalStateFromHandle(parent1); - p2 = BotGoalStateFromHandle(parent2); - c = BotGoalStateFromHandle(child); - - InterbreedWeightConfigs(p1->itemweightconfig, p2->itemweightconfig, - c->itemweightconfig); -} //end of the function BotInterbreedingGoalFuzzyLogic -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotSaveGoalFuzzyLogic(int goalstate, char *filename) -{ - bot_goalstate_t *gs; - - gs = BotGoalStateFromHandle(goalstate); - - //WriteWeightConfig(filename, gs->itemweightconfig); -} //end of the function BotSaveGoalFuzzyLogic -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotMutateGoalFuzzyLogic(int goalstate, float range) -{ - bot_goalstate_t *gs; - - gs = BotGoalStateFromHandle(goalstate); - - EvolveWeightConfig(gs->itemweightconfig); -} //end of the function BotMutateGoalFuzzyLogic -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -itemconfig_t *LoadItemConfig(char *filename) -{ - int max_iteminfo; - token_t token; - char path[MAX_PATH]; - source_t *source; - itemconfig_t *ic; - iteminfo_t *ii; - - max_iteminfo = (int) LibVarValue("max_iteminfo", "256"); - if (max_iteminfo < 0) - { - botimport.Print(PRT_ERROR, "max_iteminfo = %d\n", max_iteminfo); - max_iteminfo = 256; - LibVarSet( "max_iteminfo", "256" ); - } - - strncpy( path, filename, MAX_PATH ); - PC_SetBaseFolder(BOTFILESBASEFOLDER); - source = LoadSourceFile( path ); - if( !source ) { - botimport.Print( PRT_ERROR, "counldn't load %s\n", path ); - return NULL; - } //end if - //initialize item config - ic = (itemconfig_t *) GetClearedHunkMemory(sizeof(itemconfig_t) + - max_iteminfo * sizeof(iteminfo_t)); - ic->iteminfo = (iteminfo_t *) ((char *) ic + sizeof(itemconfig_t)); - ic->numiteminfo = 0; - //parse the item config file - while(PC_ReadToken(source, &token)) - { - if (!strcmp(token.string, "iteminfo")) - { - if (ic->numiteminfo >= max_iteminfo) - { - SourceError(source, "more than %d item info defined\n", max_iteminfo); - FreeMemory(ic); - FreeSource(source); - return NULL; - } //end if - ii = &ic->iteminfo[ic->numiteminfo]; - Com_Memset(ii, 0, sizeof(iteminfo_t)); - if (!PC_ExpectTokenType(source, TT_STRING, 0, &token)) - { - FreeMemory(ic); - FreeMemory(source); - return NULL; - } //end if - StripDoubleQuotes(token.string); - strncpy(ii->classname, token.string, sizeof(ii->classname)-1); - if (!ReadStructure(source, &iteminfo_struct, (char *) ii)) - { - FreeMemory(ic); - FreeSource(source); - return NULL; - } //end if - ii->number = ic->numiteminfo; - ic->numiteminfo++; - } //end if - else - { - SourceError(source, "unknown definition %s\n", token.string); - FreeMemory(ic); - FreeSource(source); - return NULL; - } //end else - } //end while - FreeSource(source); - // - if (!ic->numiteminfo) botimport.Print(PRT_WARNING, "no item info loaded\n"); - botimport.Print(PRT_MESSAGE, "loaded %s\n", path); - return ic; -} //end of the function LoadItemConfig -//=========================================================================== -// index to find the weight function of an iteminfo -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int *ItemWeightIndex(weightconfig_t *iwc, itemconfig_t *ic) -{ - int *index, i; - - //initialize item weight index - index = (int *) GetClearedMemory(sizeof(int) * ic->numiteminfo); - - for (i = 0; i < ic->numiteminfo; i++) - { - index[i] = FindFuzzyWeight(iwc, ic->iteminfo[i].classname); - if (index[i] < 0) - { - Log_Write("item info %d \"%s\" has no fuzzy weight\r\n", i, ic->iteminfo[i].classname); - } //end if - } //end for - return index; -} //end of the function ItemWeightIndex -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void InitLevelItemHeap(void) -{ - int i, max_levelitems; - - if (levelitemheap) FreeMemory(levelitemheap); - - max_levelitems = (int) LibVarValue("max_levelitems", "256"); - levelitemheap = (levelitem_t *) GetClearedMemory(max_levelitems * sizeof(levelitem_t)); - - for (i = 0; i < max_levelitems-1; i++) - { - levelitemheap[i].next = &levelitemheap[i + 1]; - } //end for - levelitemheap[max_levelitems-1].next = NULL; - // - freelevelitems = levelitemheap; -} //end of the function InitLevelItemHeap -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -levelitem_t *AllocLevelItem(void) -{ - levelitem_t *li; - - li = freelevelitems; - if (!li) - { - botimport.Print(PRT_FATAL, "out of level items\n"); - return NULL; - } //end if - // - freelevelitems = freelevelitems->next; - Com_Memset(li, 0, sizeof(levelitem_t)); - return li; -} //end of the function AllocLevelItem -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void FreeLevelItem(levelitem_t *li) -{ - li->next = freelevelitems; - freelevelitems = li; -} //end of the function FreeLevelItem -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AddLevelItemToList(levelitem_t *li) -{ - if (levelitems) levelitems->prev = li; - li->prev = NULL; - li->next = levelitems; - levelitems = li; -} //end of the function AddLevelItemToList -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void RemoveLevelItemFromList(levelitem_t *li) -{ - if (li->prev) li->prev->next = li->next; - else levelitems = li->next; - if (li->next) li->next->prev = li->prev; -} //end of the function RemoveLevelItemFromList -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotFreeInfoEntities(void) -{ - maplocation_t *ml, *nextml; - campspot_t *cs, *nextcs; - - for (ml = maplocations; ml; ml = nextml) - { - nextml = ml->next; - FreeMemory(ml); - } //end for - maplocations = NULL; - for (cs = campspots; cs; cs = nextcs) - { - nextcs = cs->next; - FreeMemory(cs); - } //end for - campspots = NULL; -} //end of the function BotFreeInfoEntities -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotInitInfoEntities(void) -{ - char classname[MAX_EPAIRKEY]; - maplocation_t *ml; - campspot_t *cs; - int ent, numlocations, numcampspots; - - BotFreeInfoEntities(); - // - numlocations = 0; - numcampspots = 0; - for (ent = AAS_NextBSPEntity(0); ent; ent = AAS_NextBSPEntity(ent)) - { - if (!AAS_ValueForBSPEpairKey(ent, "classname", classname, MAX_EPAIRKEY)) continue; - - //map locations - if (!strcmp(classname, "target_location")) - { - ml = (maplocation_t *) GetClearedMemory(sizeof(maplocation_t)); - AAS_VectorForBSPEpairKey(ent, "origin", ml->origin); - AAS_ValueForBSPEpairKey(ent, "message", ml->name, sizeof(ml->name)); - ml->areanum = AAS_PointAreaNum(ml->origin); - ml->next = maplocations; - maplocations = ml; - numlocations++; - } //end if - //camp spots - else if (!strcmp(classname, "info_camp")) - { - cs = (campspot_t *) GetClearedMemory(sizeof(campspot_t)); - AAS_VectorForBSPEpairKey(ent, "origin", cs->origin); - //cs->origin[2] += 16; - AAS_ValueForBSPEpairKey(ent, "message", cs->name, sizeof(cs->name)); - AAS_FloatForBSPEpairKey(ent, "range", &cs->range); - AAS_FloatForBSPEpairKey(ent, "weight", &cs->weight); - AAS_FloatForBSPEpairKey(ent, "wait", &cs->wait); - AAS_FloatForBSPEpairKey(ent, "random", &cs->random); - cs->areanum = AAS_PointAreaNum(cs->origin); - if (!cs->areanum) - { - botimport.Print(PRT_MESSAGE, "camp spot at %1.1f %1.1f %1.1f in solid\n", cs->origin[0], cs->origin[1], cs->origin[2]); - FreeMemory(cs); - continue; - } //end if - cs->next = campspots; - campspots = cs; - //AAS_DrawPermanentCross(cs->origin, 4, LINECOLOR_YELLOW); - numcampspots++; - } //end else if - } //end for - if (bot_developer) - { - botimport.Print(PRT_MESSAGE, "%d map locations\n", numlocations); - botimport.Print(PRT_MESSAGE, "%d camp spots\n", numcampspots); - } //end if -} //end of the function BotInitInfoEntities -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotInitLevelItems(void) -{ - int i, spawnflags, value; - char classname[MAX_EPAIRKEY]; - vec3_t origin, end; - int ent, goalareanum; - itemconfig_t *ic; - levelitem_t *li; - bsp_trace_t trace; - - //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); - // - for (i = 0; i < ic->numiteminfo; i++) - { - if (!strcmp(classname, ic->iteminfo[i].classname)) break; - } //end for - if (i >= ic->numiteminfo) - { - Log_Write("entity %s unknown item\r\n", classname); - continue; - } //end if - //get the origin of the item - if (!AAS_VectorForBSPEpairKey(ent, "origin", origin)) - { - botimport.Print(PRT_ERROR, "item %s without origin\n", classname); - continue; - } //end else - // - goalareanum = 0; - //if it is a floating item - if (spawnflags & 1) - { - //if the item is not floating in water - if (!(AAS_PointContents(origin) & CONTENTS_WATER)) - { - VectorCopy(origin, end); - end[2] -= 32; - trace = AAS_Trace(origin, ic->iteminfo[i].mins, ic->iteminfo[i].maxs, end, -1, CONTENTS_SOLID|CONTENTS_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); - //botimport.Print(PRT_MESSAGE, "item %s reachable from jumppad area %d\r\n", ic->iteminfo[i].classname, goalareanum); - if (!goalareanum) continue; - } //end if - } //end if - } //end if - - li = AllocLevelItem(); - if (!li) return; - // - li->number = ++numlevelitems; - li->timeout = 0; - li->entitynum = 0; - // - li->flags = 0; - 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; - AAS_IntForBSPEpairKey(ent, "notbot", &value); - if (value) li->flags |= IFL_NOTBOT; - if (!strcmp(classname, "item_botroam")) - { - li->flags |= IFL_ROAM; - AAS_FloatForBSPEpairKey(ent, "weight", &li->weight); - } //end if - //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); - // - if (goalareanum) - { - li->goalareanum = goalareanum; - VectorCopy(origin, li->goalorigin); - } //end if - 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]); - } //end if - } //end else - // - AddLevelItemToList(li); - } //end for - botimport.Print(PRT_MESSAGE, "found %d level items\n", numlevelitems); -} //end of the function BotInitLevelItems -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotGoalName(int number, char *name, int size) -{ - levelitem_t *li; - - if (!itemconfig) return; - // - for (li = levelitems; li; li = li->next) - { - if (li->number == number) - { - strncpy(name, itemconfig->iteminfo[li->iteminfo].name, size-1); - name[size-1] = '\0'; - return; - } //end for - } //end for - strcpy(name, ""); - return; -} //end of the function BotGoalName -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotResetAvoidGoals(int goalstate) -{ - bot_goalstate_t *gs; - - gs = BotGoalStateFromHandle(goalstate); - if (!gs) return; - Com_Memset(gs->avoidgoals, 0, MAX_AVOIDGOALS * sizeof(int)); - Com_Memset(gs->avoidgoaltimes, 0, MAX_AVOIDGOALS * sizeof(float)); -} //end of the function BotResetAvoidGoals -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotDumpAvoidGoals(int goalstate) -{ - int i; - bot_goalstate_t *gs; - char name[32]; - - gs = BotGoalStateFromHandle(goalstate); - if (!gs) return; - for (i = 0; i < MAX_AVOIDGOALS; i++) - { - if (gs->avoidgoaltimes[i] >= AAS_Time()) - { - 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()); - } //end if - } //end for -} //end of the function BotDumpAvoidGoals -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotAddToAvoidGoals(bot_goalstate_t *gs, int number, float avoidtime) -{ - int i; - - for (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; - } //end if - } //end for - - 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 -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotRemoveFromAvoidGoals(int goalstate, int number) -{ - int i; - bot_goalstate_t *gs; - - gs = BotGoalStateFromHandle(goalstate); - if (!gs) return; - //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()) - { - gs->avoidgoaltimes[i] = 0; - return; - } //end if - } //end for -} //end of the function BotRemoveFromAvoidGoals -//=========================================================================== -// -// 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 -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void BotSetAvoidGoalTime(int goalstate, int number, float avoidtime) -{ - bot_goalstate_t *gs; - levelitem_t *li; - - gs = BotGoalStateFromHandle(goalstate); - if (!gs) - return; - if (avoidtime < 0) - { - if (!itemconfig) - return; - // - for (li = levelitems; li; li = li->next) - { - if (li->number == number) - { - avoidtime = itemconfig->iteminfo[li->iteminfo].respawntime; - if (!avoidtime) - avoidtime = AVOID_DEFAULT_TIME; - if (avoidtime < AVOID_MINIMUM_TIME) - avoidtime = AVOID_MINIMUM_TIME; - BotAddToAvoidGoals(gs, number, avoidtime); - return; - } //end for - } //end for - return; - } //end if - else - { - BotAddToAvoidGoals(gs, number, avoidtime); - } //end else -} //end of the function BotSetAvoidGoalTime -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int BotGetLevelItemGoal(int index, char *name, bot_goal_t *goal) -{ - levelitem_t *li; - - if (!itemconfig) return -1; - li = levelitems; - if (index >= 0) - { - for (; li; li = li->next) - { - if (li->number == index) - { - li = li->next; - break; - } //end if - } //end for - } //end for - for (; 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 (!Q_stricmp(name, itemconfig->iteminfo[li->iteminfo].name)) - { - goal->areanum = li->goalareanum; - VectorCopy(li->goalorigin, goal->origin); - goal->entitynum = li->entitynum; - VectorCopy(itemconfig->iteminfo[li->iteminfo].mins, goal->mins); - VectorCopy(itemconfig->iteminfo[li->iteminfo].maxs, goal->maxs); - goal->number = li->number; - goal->flags = GFL_ITEM; - if (li->timeout) goal->flags |= GFL_DROPPED; - //botimport.Print(PRT_MESSAGE, "found li %s\n", itemconfig->iteminfo[li->iteminfo].name); - return li->number; - } //end if - } //end for - return -1; -} //end of the function BotGetLevelItemGoal -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int BotGetMapLocationGoal(char *name, bot_goal_t *goal) -{ - 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) - { - //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 |