summaryrefslogtreecommitdiff
path: root/src/botlib/be_ai_goal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/botlib/be_ai_goal.c')
-rw-r--r--src/botlib/be_ai_goal.c1822
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