mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-22 02:42:11 +00:00
jabot: Improve navigation save logic
This commit is contained in:
parent
5d4a2facbd
commit
0fbcbbcdff
22 changed files with 160 additions and 236 deletions
|
@ -528,7 +528,8 @@ SCR_ReadNextAVFrame(void)
|
|||
static qboolean
|
||||
SCR_LoadAVcodec(const char *arg, const char *dot)
|
||||
{
|
||||
char name[MAX_OSPATH], *path = NULL;
|
||||
const char *path = NULL;
|
||||
char name[MAX_OSPATH];
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
|
@ -245,7 +245,7 @@ typedef struct
|
|||
|
||||
// gamedir will be the current directory that generated
|
||||
// files should be stored to, ie: "f:\quake\id1"
|
||||
char *(IMPORT *FS_Gamedir) (void);
|
||||
const char *(IMPORT *FS_Gamedir) (void);
|
||||
|
||||
cvar_t *(IMPORT *Cvar_Get) (const char *name, const char *value, int flags);
|
||||
cvar_t *(IMPORT *Cvar_Set) (const char *name, const char *value);
|
||||
|
|
|
@ -231,27 +231,30 @@ FS_FileLength(FILE *f)
|
|||
* Creates any directories needed to store the given filename.
|
||||
*/
|
||||
void
|
||||
FS_CreatePath(char *path)
|
||||
FS_CreatePath(const char *path)
|
||||
{
|
||||
char *cur; /* Current '/'. */
|
||||
char *old; /* Old '/'. */
|
||||
char dir_path[MAX_OSPATH];
|
||||
|
||||
FS_DPrintf("FS_CreatePath(%s)\n", path);
|
||||
FS_DPrintf("%s(%s)\n", __func__, path);
|
||||
|
||||
if (strstr(path, "..") != NULL)
|
||||
if (strstr(dir_path, "..") != NULL)
|
||||
{
|
||||
Com_Printf("WARNING: refusing to create relative path '%s'.\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
cur = old = path;
|
||||
strncpy(dir_path, path, sizeof(dir_path) - 1);
|
||||
|
||||
cur = old = dir_path;
|
||||
|
||||
while (cur != NULL)
|
||||
{
|
||||
if ((cur - old) > 1)
|
||||
{
|
||||
*cur = '\0';
|
||||
Sys_Mkdir(path);
|
||||
Sys_Mkdir(dir_path);
|
||||
*cur = '/';
|
||||
}
|
||||
|
||||
|
@ -278,7 +281,7 @@ FS_DPrintf(const char *format, ...)
|
|||
Com_Printf("%s", msg);
|
||||
}
|
||||
|
||||
char *
|
||||
const char *
|
||||
FS_Gamedir(void)
|
||||
{
|
||||
return fs_gamedir;
|
||||
|
@ -1460,7 +1463,7 @@ FS_LoadPK3(const char *packPath)
|
|||
/*
|
||||
* Allows enumerating all of the directories in the search path.
|
||||
*/
|
||||
char *
|
||||
const char *
|
||||
FS_NextPath(const char *prevPath)
|
||||
{
|
||||
char *prev;
|
||||
|
@ -2013,7 +2016,7 @@ FS_Dir_f(void)
|
|||
{
|
||||
char **dirnames; /* File list. */
|
||||
char findname[1024]; /* File search path and pattern. */
|
||||
char *path = NULL; /* Search path. */
|
||||
const char *path = NULL; /* Search path. */
|
||||
char *lastsep;
|
||||
char wildcard[1024] = "*.*"; /* File pattern. */
|
||||
int i; /* Loop counter. */
|
||||
|
|
|
@ -743,8 +743,8 @@ void FS_FreeList(char **list, int nfiles);
|
|||
void FS_InitFilesystem(void);
|
||||
void FS_ShutdownFilesystem(void);
|
||||
void FS_BuildGameSpecificSearchPath(const char *dir);
|
||||
char *FS_Gamedir(void);
|
||||
char *FS_NextPath(const char *prevpath);
|
||||
const char *FS_Gamedir(void);
|
||||
const char *FS_NextPath(const char *prevpath);
|
||||
int FS_LoadFile(const char *path, void **buffer);
|
||||
qboolean FS_FileInGamedir(const char *file);
|
||||
qboolean FS_AddPAKFromGamedir(const char *pak);
|
||||
|
@ -757,7 +757,7 @@ char **FS_ListMods(int *nummods);
|
|||
/* properly handles partial reads */
|
||||
|
||||
void FS_FreeFile(void *buffer);
|
||||
void FS_CreatePath(char *path);
|
||||
void FS_CreatePath(const char *path);
|
||||
|
||||
/* MISC */
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ qboolean BOT_DMclass_FindEnemy(edict_t *self)
|
|||
if(bestenemy)
|
||||
{
|
||||
// if (AIDevel.debugChased && bot_showcombat->value && bestenemy->ai.is_bot)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: selected %s as enemy.\n",
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: selected %s as enemy.\n",
|
||||
// self->ai.pers.netname,
|
||||
// bestenemy->ai.pers.netname);
|
||||
|
||||
|
@ -587,7 +587,7 @@ void BOT_DMclass_FireWeapon (edict_t *self, usercmd_t *ucmd)
|
|||
ucmd->buttons = BUTTON_ATTACK;
|
||||
|
||||
//if(AIDevel.debugChased && bot_showcombat->integer)
|
||||
// G_PrintMsg (AIDevel.devguy, PRINT_HIGH, "%s: attacking %s\n",self->bot.pers.netname ,self->enemy->r.client->pers.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: attacking %s\n",self->bot.pers.netname ,self->enemy->r.client->pers.netname);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ void M_default_FireWeapon (edict_t *self)
|
|||
}
|
||||
|
||||
//if(AIDevel.debugMode && bot_debugmonster->integer)
|
||||
// G_PrintMsg (NULL, PRINT_HIGH, "monster: attacking\n");
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "monster: attacking\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef struct
|
|||
qboolean was_falling;
|
||||
int last_node;
|
||||
|
||||
}player_dropping_nodes_t;
|
||||
} player_dropping_nodes_t;
|
||||
player_dropping_nodes_t player;
|
||||
|
||||
|
||||
|
@ -100,24 +100,25 @@ int AI_AddNode( vec3_t origin, int flagsmask )
|
|||
// AI_UpdateNodeEdge
|
||||
// Add/Update node connections (paths)
|
||||
//==========================================
|
||||
void AI_UpdateNodeEdge( int from, int to )
|
||||
void AI_UpdateNodeEdge(int from, int to)
|
||||
{
|
||||
int link;
|
||||
|
||||
if(from == -1 || to == -1 || from == to)
|
||||
{
|
||||
return; // safety
|
||||
|
||||
}
|
||||
|
||||
if(AI_PlinkExists(from, to))
|
||||
{
|
||||
link = AI_PlinkMoveType(from, to);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
link = AI_FindLinkType( from, to );
|
||||
}
|
||||
|
||||
Com_Printf("Link: %d -> %d. ", from, to);
|
||||
|
||||
|
||||
Com_Printf("%s\n", AI_LinkString(link) );
|
||||
Com_Printf("Link: %d -> %d. %s\n", from, to, AI_LinkString(link) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,7 +162,9 @@ void AI_DropLadderNodes( edict_t *self )
|
|||
{
|
||||
VectorCopy( trace.endpos, borigin );
|
||||
|
||||
} else { //it wasn't so easy
|
||||
}
|
||||
else
|
||||
{ //it wasn't so easy
|
||||
|
||||
trace = gi.trace( borigin, tv(-15,-15,-25), tv(15,15,0), borigin, self, MASK_NODESOLID );
|
||||
while( AI_IsLadder( borigin, self->client->ps.viewangles, self->mins, self->maxs, self)
|
||||
|
@ -506,28 +509,38 @@ void AITools_InitMakenodes( void )
|
|||
// save nodes and plinks to file.
|
||||
// Only navigation nodes are saved. Item nodes aren't
|
||||
//==========================================
|
||||
qboolean AI_SavePLKFile( char *mapname )
|
||||
static qboolean
|
||||
AI_SavePLKFile(const char *mapname)
|
||||
{
|
||||
FILE *pOut;
|
||||
char filename[MAX_OSPATH];
|
||||
int i;
|
||||
int version = NAV_FILE_VERSION;
|
||||
|
||||
Com_sprintf (filename, sizeof(filename), "%s/%s/%s.%s", AI_MOD_FOLDER, AI_NODES_FOLDER, mapname, NAV_FILE_EXTENSION );
|
||||
pOut = fopen (filename, "wb");
|
||||
Com_sprintf(filename, sizeof(filename), "%s/%s/%s.%s",
|
||||
gi.FS_Gamedir(), AI_NODES_FOLDER, mapname, NAV_FILE_EXTENSION);
|
||||
gi.FS_CreatePath(filename);
|
||||
pOut = fopen(filename, "wb");
|
||||
if (!pOut)
|
||||
{
|
||||
Com_Printf("Failed to store: %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite(&version,sizeof(int),1,pOut);
|
||||
fwrite(&nav.num_nodes,sizeof(int),1,pOut);
|
||||
fwrite(&version, sizeof(int), 1, pOut);
|
||||
fwrite(&nav.num_nodes, sizeof(int), 1, pOut);
|
||||
|
||||
// write out nodes
|
||||
for(i=0; i<nav.num_nodes;i++)
|
||||
fwrite(&nodes[i],sizeof(nav_node_t),1,pOut);
|
||||
{
|
||||
fwrite(&nodes[i], sizeof(nav_node_t), 1, pOut);
|
||||
}
|
||||
|
||||
// write out plinks array
|
||||
for(i=0; i<nav.num_nodes;i++)
|
||||
fwrite(&pLinks[i],sizeof(nav_plink_t),1,pOut);
|
||||
{
|
||||
fwrite(&pLinks[i], sizeof(nav_plink_t), 1, pOut);
|
||||
}
|
||||
|
||||
fclose(pOut);
|
||||
|
||||
|
@ -550,23 +563,28 @@ void AITools_SaveNodes( void )
|
|||
int newlinks;
|
||||
int jumplinks;
|
||||
|
||||
if( !nav.num_nodes ) {
|
||||
if( !nav.num_nodes )
|
||||
{
|
||||
Com_Printf("CGame AITools: No nodes to save\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//find links
|
||||
newlinks = AI_LinkCloseNodes();
|
||||
Com_Printf (" : Added %i new links\n", newlinks);
|
||||
Com_Printf ("Added %i new links\n", newlinks);
|
||||
|
||||
//find jump links
|
||||
jumplinks = AI_LinkCloseNodes_JumpPass(0);
|
||||
Com_Printf (" : Added %i new jump links\n", jumplinks);
|
||||
Com_Printf ("Added %i new jump links\n", jumplinks);
|
||||
|
||||
if( !AI_SavePLKFile( level.mapname ) )
|
||||
Com_Printf (" : Failed: Couldn't create the nodes file\n");
|
||||
if(!AI_SavePLKFile(level.mapname))
|
||||
{
|
||||
Com_Printf ("Failed: Couldn't create the nodes file\n");
|
||||
}
|
||||
else
|
||||
Com_Printf (" : Nodes files saved\n");
|
||||
{
|
||||
Com_Printf ("Nodes files saved\n");
|
||||
}
|
||||
|
||||
//restart navigation
|
||||
AITools_EraseNodes();
|
||||
|
|
|
@ -274,7 +274,7 @@ float AI_ItemWeight(edict_t *self, edict_t *it)
|
|||
|
||||
//item didn't have a recognizable item flag
|
||||
// if (AIDevel.debugMode)
|
||||
// G_PrintMsg (NULL, PRINT_HIGH, "(AI_ItemWeight) WARNING: Item with unhandled item flag:%s\n", it->classname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "(AI_ItemWeight) WARNING: Item with unhandled item flag:%s\n", it->classname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ qboolean AI_AddLink( int n1, int n2, int linkType )
|
|||
//add the link
|
||||
if (pLinks[n1].numLinks > NODES_MAX_PLINKS)
|
||||
{
|
||||
// G_Printf("MaxPlinks Reached! node:%i numPlinks:%i\n", n1, pLinks[n1].numLinks);
|
||||
// Com_Printf("MaxPlinks Reached! node:%i numPlinks:%i\n", n1, pLinks[n1].numLinks);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ qboolean AI_BotRoamForLRGoal(edict_t *self, int current_node)
|
|||
self->ai.tries = 0; // Reset the count of how many times we tried this goal
|
||||
|
||||
// if(AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: selected a bot roam of weight %f at node %d for LR goal.\n",self->ai.pers.netname, nav.broams[best_broam].weight, goal_node);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: selected a bot roam of weight %f at node %d for LR goal.\n",self->ai.pers.netname, nav.broams[best_broam].weight, goal_node);
|
||||
|
||||
AI_SetGoal(self,goal_node);
|
||||
|
||||
|
@ -209,7 +209,7 @@ void AI_PickLongRangeGoal(edict_t *self)
|
|||
if(current_node == -1) //failed. Go wandering :(
|
||||
{
|
||||
// if (AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: LRGOAL: Closest node not found. Tries:%i\n", self->ai.pers.netname, self->ai.nearest_node_tries);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: LRGOAL: Closest node not found. Tries:%i\n", self->ai.pers.netname, self->ai.nearest_node_tries);
|
||||
// Com_Printf( "%s: LRGOAL: Closest node not found. Tries:%i\n", self->ai.pers.netname, self->ai.nearest_node_tries);
|
||||
|
||||
if( self->ai.state != BOT_STATE_WANDER )
|
||||
|
@ -307,7 +307,7 @@ void AI_PickLongRangeGoal(edict_t *self)
|
|||
self->ai.state = BOT_STATE_WANDER;
|
||||
self->ai.wander_timeout = level.time + 1.0;
|
||||
// if(AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: did not find a LR goal, wandering.\n",self->ai.pers.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: did not find a LR goal, wandering.\n",self->ai.pers.netname);
|
||||
// Com_Printf( "%s: did not find a LR goal, wandering.\n",self->ai.pers.netname);
|
||||
}
|
||||
return; // no path?
|
||||
|
@ -318,7 +318,7 @@ void AI_PickLongRangeGoal(edict_t *self)
|
|||
self->ai.tries = 0; // Reset the count of how many times we tried this goal
|
||||
|
||||
// if(goal_ent != NULL && AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: selected a %s at node %d for LR goal.\n",self->ai.pers.netname, goal_ent->classname, goal_node);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: selected a %s at node %d for LR goal.\n",self->ai.pers.netname, goal_ent->classname, goal_node);
|
||||
// if(goal_ent != NULL )
|
||||
// Com_Printf( "%s: selected a %s at node %d for LR goal.\n",self->ai.pers.netname, goal_ent->classname, goal_node);
|
||||
|
||||
|
@ -356,7 +356,7 @@ void AI_PickShortRangeGoal(edict_t *self)
|
|||
if (self->ai.status.playersWeights[target->owner->s.number-1])
|
||||
{
|
||||
// if(AIDevel.debugChased && bot_showcombat->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: ROCKET ALERT!\n", self->ai.pers.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: ROCKET ALERT!\n", self->ai.pers.netname);
|
||||
|
||||
self->enemy = target->owner; // set who fired the rocket as enemy
|
||||
return;
|
||||
|
@ -387,7 +387,7 @@ void AI_PickShortRangeGoal(edict_t *self)
|
|||
self->movetarget = best;
|
||||
self->goalentity = best;
|
||||
// if(AIDevel.debugChased && bot_showsrgoal->value && (self->goalentity != self->movetarget))
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: selected a %s for SR goal.\n",self->ai.pers.netname, self->movetarget->classname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: selected a %s for SR goal.\n",self->ai.pers.netname, self->movetarget->classname);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ qboolean AI_CanMove(edict_t *self, int direction)
|
|||
if(tr.fraction == 1.0 || tr.contents & (CONTENTS_LAVA|CONTENTS_SLIME))
|
||||
{
|
||||
//if(AIDevel.debugChased) //jal: is too spammy. Temporary disabled
|
||||
// G_PrintMsg (AIDevel.devguy, PRINT_HIGH, "%s: move blocked\n", self->bot.botStatus.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: move blocked\n", self->bot.botStatus.netname);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@ qboolean AI_MoveToGoalEntity(edict_t *self, usercmd_t *ucmd)
|
|||
VectorSubtract (self->movetarget->s.origin, self->s.origin, self->ai.move_vector);
|
||||
AI_ChangeAngle(self);
|
||||
// if(AIDevel.debugChased && bot_showcombat->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: Oh crap a rocket!\n",self->ai.pers.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: Oh crap a rocket!\n",self->ai.pers.netname);
|
||||
|
||||
// strafe left/right
|
||||
if(rand()%1 && AI_CanMove(self, BOT_MOVE_LEFT))
|
||||
|
|
|
@ -144,7 +144,7 @@ void AI_SetGoal(edict_t *self, int goal_node)
|
|||
//-------------------------
|
||||
|
||||
// if(AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: GOAL: new START NODE selected %d\n", self->ai.pers.netname, node);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: GOAL: new START NODE selected %d\n", self->ai.pers.netname, node);
|
||||
|
||||
self->ai.next_node = self->ai.current_node; // make sure we get to the nearest node first
|
||||
self->ai.node_timeout = 0;
|
||||
|
@ -202,7 +202,7 @@ qboolean AI_FollowPath( edict_t *self )
|
|||
if( self->ai.next_node == self->ai.goal_node )
|
||||
{
|
||||
// if(AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: GOAL REACHED!\n", self->ai.pers.netname);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: GOAL REACHED!\n", self->ai.pers.netname);
|
||||
|
||||
//if botroam, setup a timeout for it
|
||||
if( nodes[self->ai.goal_node].flags & NODEFLAGS_BOTROAM )
|
||||
|
@ -213,7 +213,7 @@ qboolean AI_FollowPath( edict_t *self )
|
|||
continue;
|
||||
|
||||
// if(AIDevel.debugChased && bot_showlrgoal->value)
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: BotRoam Time Out set up for node %i\n", self->ai.pers.netname, nav.broams[i].node);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: BotRoam Time Out set up for node %i\n", self->ai.pers.netname, nav.broams[i].node);
|
||||
self->ai.status.broam_timeouts[i] = level.time + 15.0;
|
||||
break;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ qboolean AI_FollowPath( edict_t *self )
|
|||
self->ai.next_node = self->ai.path->nodes[self->ai.path_position++];
|
||||
|
||||
// if(AIDevel.debugChased && bot_showpath->value > 1 )
|
||||
// G_PrintMsg (AIDevel.chaseguy, PRINT_HIGH, "%s: CurrentNode(%i):%s NextNode(%i):%s\n", self->ai.pers.netname, self->ai.current_node, nodeTypeNames[nodes[self->ai.current_node].type], self->ai.next_node, nodeTypeNames[nodes[self->ai.next_node].type]);
|
||||
// gi.cprintf(NULL, PRINT_HIGH, "%s: CurrentNode(%i):%s NextNode(%i):%s\n", self->ai.pers.netname, self->ai.current_node, nodeTypeNames[nodes[self->ai.current_node].type], self->ai.next_node, nodeTypeNames[nodes[self->ai.next_node].type]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ qboolean AI_PredictJumpadDestity( edict_t *ent, vec3_t out )
|
|||
// trap_Trace ( &trace, target_origin, tv(-15, -15, -8), tv(15, 15, 8), floor_target_origin, NULL, MASK_NODESOLID);
|
||||
trace = gi.trace( target_origin, tv(-15, -15, -8), tv(15, 15, 8), floor_target_origin, NULL, MASK_NODESOLID);
|
||||
if ((trace.fraction == 1.0 && trace.startsolid) || (trace.allsolid && trace.startsolid)){
|
||||
// G_Printf("JUMPAD LAND: ERROR: trace was in solid.\n"); //started inside solid (target should never be inside solid, this is a mapper error)
|
||||
// Com_Printf("JUMPAD LAND: ERROR: trace was in solid.\n"); //started inside solid (target should never be inside solid, this is a mapper error)
|
||||
return false;
|
||||
} else if ( trace.fraction == 1.0 ) {
|
||||
|
||||
|
@ -645,7 +645,8 @@ qboolean AI_LoadPLKFile( char *mapname )
|
|||
char filename[MAX_OSPATH];
|
||||
int version;
|
||||
|
||||
Com_sprintf (filename, sizeof(filename), "%s/%s/%s.%s", AI_MOD_FOLDER, AI_NODES_FOLDER, mapname, NAV_FILE_EXTENSION);
|
||||
Com_sprintf (filename, sizeof(filename), "%s/%s/%s.%s",
|
||||
gi.FS_Gamedir(), AI_NODES_FOLDER, mapname, NAV_FILE_EXTENSION);
|
||||
|
||||
pIn = fopen( filename, "rb" );
|
||||
if( pIn == NULL )
|
||||
|
@ -904,12 +905,14 @@ void AI_InitNavigationData(void)
|
|||
//Load nodes from file
|
||||
nav.loaded = AI_LoadPLKFile( level.mapname );
|
||||
if( !nav.loaded ) {
|
||||
Com_Printf( "AI: FAILED to load nodes file.\n");
|
||||
Com_Printf("AI: FAILED to load nodes file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for( linkscount = 0, i = 0; i< nav.num_nodes; i++ )
|
||||
{
|
||||
linkscount += pLinks[i].numLinks;
|
||||
}
|
||||
|
||||
servernodesstart = nav.num_nodes;
|
||||
|
||||
|
@ -918,12 +921,12 @@ void AI_InitNavigationData(void)
|
|||
newlinks = AI_LinkServerNodes( servernodesstart );
|
||||
newjumplinks = AI_LinkCloseNodes_JumpPass( servernodesstart );
|
||||
|
||||
Com_Printf("-------------------------------------\n" );
|
||||
Com_Printf(" : AI: Nodes Initialized.\n" );
|
||||
Com_Printf(" : loaded nodes:%i.\n", servernodesstart );
|
||||
Com_Printf(" : added nodes:%i.\n", nav.num_nodes - servernodesstart );
|
||||
Com_Printf(" : total nodes:%i.\n", nav.num_nodes );
|
||||
Com_Printf(" : loaded links:%i.\n", linkscount );
|
||||
Com_Printf(" : added links:%i.\n", newlinks );
|
||||
Com_Printf(" : added jump links:%i.\n", newjumplinks );
|
||||
Com_Printf("-------------------------------------\n");
|
||||
Com_Printf("AI: Nodes Initialized.\n");
|
||||
Com_Printf("Loaded nodes: %i.\n", servernodesstart);
|
||||
Com_Printf("Added nodes: %i.\n", nav.num_nodes - servernodesstart);
|
||||
Com_Printf("Total nodes: %i.\n", nav.num_nodes);
|
||||
Com_Printf("Loaded links: %i.\n", linkscount);
|
||||
Com_Printf("Added links: %i.\n", newlinks);
|
||||
Com_Printf("Added jump links: %i.\n", newjumplinks);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#define NODES_MAX_PLINKS 16
|
||||
#define NAV_FILE_VERSION 11
|
||||
#define NAV_FILE_EXTENSION "nav"
|
||||
#define AI_MOD_FOLDER "jabot"
|
||||
#define AI_NODES_FOLDER "navigation"
|
||||
|
||||
#define MASK_NODESOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW)
|
||||
|
|
|
@ -39,23 +39,23 @@ void AIDebug_ToogleBotDebug(void)
|
|||
{
|
||||
/* if (AIDevel.debugMode || !sv_cheats->integer )
|
||||
{
|
||||
// G_Printf ("BOT: Debug Mode Off\n");
|
||||
// Com_Printf("BOT: Debug Mode Off\n");
|
||||
AIDevel.debugMode = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//Activate debug mode
|
||||
G_Printf ("\n======================================\n");
|
||||
G_Printf ("--==[ D E B U G ]==--\n");
|
||||
G_Printf ("======================================\n");
|
||||
G_Printf ("'addnode [nodetype]' -- Add [specified] node to players current location\n");
|
||||
G_Printf ("'movenode [node] [x y z]' -- Move [node] to [x y z] coordinates\n");
|
||||
G_Printf ("'findnode' -- Finds closest node\n");
|
||||
G_Printf ("'removelink [node1 node2]' -- Removes link between two nodes\n");
|
||||
G_Printf ("'addlink [node1 node2]' -- Adds a link between two nodes\n");
|
||||
G_Printf ("======================================\n\n");
|
||||
Com_Printf("\n======================================\n");
|
||||
Com_Printf("--==[ D E B U G ]==--\n");
|
||||
Com_Printf("======================================\n");
|
||||
Com_Printf("'addnode [nodetype]' -- Add [specified] node to players current location\n");
|
||||
Com_Printf("'movenode [node] [x y z]' -- Move [node] to [x y z] coordinates\n");
|
||||
Com_Printf("'findnode' -- Finds closest node\n");
|
||||
Com_Printf("'removelink [node1 node2]' -- Removes link between two nodes\n");
|
||||
Com_Printf("'addlink [node1 node2]' -- Adds a link between two nodes\n");
|
||||
Com_Printf("======================================\n\n");
|
||||
|
||||
G_Printf ("BOT: Debug Mode On\n");
|
||||
Com_Printf("BOT: Debug Mode On\n");
|
||||
|
||||
AIDevel.debugMode = true;
|
||||
*/
|
||||
|
|
|
@ -62,7 +62,17 @@ static int goalNode;
|
|||
static int currentNode;
|
||||
|
||||
int ValidLinksMask;
|
||||
#define DEFAULT_MOVETYPES_MASK (LINK_MOVE|LINK_STAIRS|LINK_FALL|LINK_WATER|LINK_WATERJUMP|LINK_JUMPPAD|LINK_PLATFORM|LINK_TELEPORT);
|
||||
|
||||
#define DEFAULT_MOVETYPES_MASK ( \
|
||||
LINK_MOVE | \
|
||||
LINK_STAIRS | \
|
||||
LINK_FALL | \
|
||||
LINK_WATER | \
|
||||
LINK_WATERJUMP | \
|
||||
LINK_JUMPPAD | \
|
||||
LINK_PLATFORM | \
|
||||
LINK_TELEPORT);
|
||||
|
||||
//==========================================
|
||||
//
|
||||
//
|
||||
|
@ -149,13 +159,17 @@ static int Astar_HDist_ManhatanGuess( int node )
|
|||
|
||||
//teleporters are exceptional
|
||||
if( nodes[node].flags & NODEFLAGS_TELEPORTER_IN )
|
||||
{
|
||||
node++; //it's tele out is stored in the next node in the array
|
||||
}
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
DistVec[i] = nodes[goalNode].origin[i] - nodes[node].origin[i];
|
||||
if( DistVec[i] < 0.0f )
|
||||
{
|
||||
DistVec[i] = -DistVec[i]; //use only positive values. We don't care about direction.
|
||||
}
|
||||
}
|
||||
|
||||
HDist = (int)(DistVec[0] + DistVec[1] + DistVec[2]);
|
||||
|
@ -164,7 +178,8 @@ static int Astar_HDist_ManhatanGuess( int node )
|
|||
|
||||
static void AStar_PutInClosed( int node )
|
||||
{
|
||||
if( !astarnodes[node].list ) {
|
||||
if( !astarnodes[node].list )
|
||||
{
|
||||
alist[alist_numNodes] = node;
|
||||
alist_numNodes++;
|
||||
}
|
||||
|
@ -182,17 +197,23 @@ static void AStar_PutAdjacentsInOpen(int node)
|
|||
|
||||
//ignore invalid links
|
||||
if( !(ValidLinksMask & pLinks[node].moveType[i]) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
addnode = pLinks[node].nodes[i];
|
||||
|
||||
//ignore self
|
||||
if( addnode == node )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//ignore if it's already in closed list
|
||||
if( AStar_nodeIsInClosed( addnode ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//if it's already inside open list
|
||||
if( AStar_nodeIsInOpen( addnode ) )
|
||||
|
@ -202,7 +223,7 @@ static void AStar_PutAdjacentsInOpen(int node)
|
|||
plinkDist = AStar_PLinkDistance( node, addnode );
|
||||
if( plinkDist == -1)
|
||||
{
|
||||
//printf("WARNING: AStar_PutAdjacentsInOpen - Couldn't find distance between nodes\n");
|
||||
Com_Printf("WARNING: AStar_PutAdjacentsInOpen - Couldn't find distance between nodes\n");
|
||||
}
|
||||
//compare G distances and choose best parent
|
||||
else if( astarnodes[addnode].G > (astarnodes[node].G + plinkDist) )
|
||||
|
@ -211,7 +232,9 @@ static void AStar_PutAdjacentsInOpen(int node)
|
|||
astarnodes[addnode].G = astarnodes[node].G + plinkDist;
|
||||
}
|
||||
|
||||
} else { //just put it in
|
||||
}
|
||||
else
|
||||
{ //just put it in
|
||||
|
||||
int plinkDist;
|
||||
|
||||
|
@ -220,14 +243,16 @@ static void AStar_PutAdjacentsInOpen(int node)
|
|||
{
|
||||
plinkDist = AStar_PLinkDistance( addnode, node );
|
||||
if( plinkDist == -1)
|
||||
{
|
||||
plinkDist = 999;//jalFIXME
|
||||
}
|
||||
|
||||
//ERROR
|
||||
//printf("WARNING: AStar_PutAdjacentsInOpen - Couldn't find distance between nodes\n");
|
||||
Com_Printf("WARNING: AStar_PutAdjacentsInOpen - Couldn't find distance between nodes\n");
|
||||
}
|
||||
|
||||
//put in global list
|
||||
if( !astarnodes[addnode].list ) {
|
||||
if( !astarnodes[addnode].list )
|
||||
{
|
||||
alist[alist_numNodes] = addnode;
|
||||
alist_numNodes++;
|
||||
}
|
||||
|
@ -251,14 +276,18 @@ static int AStar_FindInOpen_BestF ( void )
|
|||
int node = alist[i];
|
||||
|
||||
if( astarnodes[node].list != OPENLIST )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( bestF == -1 || bestF > (astarnodes[node].G + astarnodes[node].H) ) {
|
||||
if ( bestF == -1 || bestF > (astarnodes[node].G + astarnodes[node].H) )
|
||||
{
|
||||
bestF = astarnodes[node].G + astarnodes[node].H;
|
||||
best = node;
|
||||
}
|
||||
}
|
||||
//printf("BEST:%i\n", best);
|
||||
|
||||
Com_Printf("BEST:%i\n", best);
|
||||
return best;
|
||||
}
|
||||
|
||||
|
@ -301,7 +330,9 @@ int AStar_ResolvePath ( int n1, int n2, int movetypes )
|
|||
{
|
||||
ValidLinksMask = movetypes;
|
||||
if ( !ValidLinksMask )
|
||||
{
|
||||
ValidLinksMask = DEFAULT_MOVETYPES_MASK;
|
||||
}
|
||||
|
||||
AStar_InitLists();
|
||||
|
||||
|
@ -312,12 +343,14 @@ int AStar_ResolvePath ( int n1, int n2, int movetypes )
|
|||
while ( !AStar_nodeIsInOpen(goalNode) )
|
||||
{
|
||||
if( !AStar_FillLists() )
|
||||
{
|
||||
return 0; //failed
|
||||
}
|
||||
}
|
||||
|
||||
AStar_ListsToPath();
|
||||
|
||||
//printf("RESULT:\n Origin:%i\n Goal:%i\n numNodes:%i\n FirstInPath:%i\n LastInPath:%i\n", originNode, goalNode, Apath_numNodes, Apath[0], Apath[Apath_numNodes-1]);
|
||||
Com_Printf("RESULT:\n Origin:%i\n Goal:%i\n numNodes:%i\n FirstInPath:%i\n LastInPath:%i\n", originNode, goalNode, Apath_numNodes, Apath[0], Apath[Apath_numNodes-1]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -327,14 +360,17 @@ int AStar_GetPath( int origin, int goal, int movetypes, struct astarpath_s *path
|
|||
int i;
|
||||
|
||||
if( !AStar_ResolvePath ( origin, goal, movetypes ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
path->numNodes = Apath_numNodes;
|
||||
path->originNode = origin;
|
||||
path->goalNode = goal;
|
||||
for(i=0; i<path->numNodes; i++)
|
||||
{
|
||||
path->nodes[i] = Apath[i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,19 +27,6 @@
|
|||
|
||||
//ACE
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================
|
||||
// BOT_Commands
|
||||
// Special command processor
|
||||
//==========================================
|
||||
qboolean BOT_Commands(edict_t *ent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//==========================================
|
||||
// BOT_ServerCommand
|
||||
// Special server command processor
|
||||
|
@ -59,10 +46,6 @@ qboolean BOT_ServerCommand (void)
|
|||
else // name, skin
|
||||
BOT_SpawnBot ( NULL, gi.argv(2), gi.argv(3), NULL );
|
||||
}
|
||||
// removebot
|
||||
else if( !Q_stricmp (cmd, "removebot") )
|
||||
BOT_RemoveBot(gi.argv(2));
|
||||
|
||||
else if( !Q_stricmp (cmd, "editnodes") )
|
||||
AITools_InitEditnodes();
|
||||
|
||||
|
@ -84,94 +67,6 @@ qboolean BOT_ServerCommand (void)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//==========================================
|
||||
// AI_BotObituary
|
||||
// Bots can't use stock obituaries cause server doesn't print from them
|
||||
//==========================================
|
||||
void AI_BotObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
||||
{
|
||||
/* int mod;
|
||||
char message[64];
|
||||
char message2[64];
|
||||
qboolean ff;
|
||||
|
||||
if (coop->value && attacker->client)
|
||||
meansOfDeath |= MOD_FRIENDLY_FIRE;
|
||||
|
||||
if ( deathmatch->value || coop->value )
|
||||
{
|
||||
ff = meansOfDeath & MOD_FRIENDLY_FIRE;
|
||||
mod = meansOfDeath & ~MOD_FRIENDLY_FIRE;
|
||||
|
||||
GS_Obituary ( self, G_PlayerGender ( self ), attacker, mod, message, message2 );
|
||||
|
||||
// duplicate message at server console for logging
|
||||
if ( attacker && attacker->client )
|
||||
{
|
||||
if ( attacker != self )
|
||||
{ // regular death message
|
||||
if ( deathmatch->value ) {
|
||||
if( ff )
|
||||
attacker->client->resp.score--;
|
||||
else
|
||||
attacker->client->resp.score++;
|
||||
}
|
||||
|
||||
self->enemy = attacker;
|
||||
|
||||
if( dedicated->value )
|
||||
G_Printf ( "%s %s %s%s\n", self->client->pers.netname, message, attacker->client->pers.netname, message2 );
|
||||
else
|
||||
{ //bot
|
||||
G_PrintMsg (NULL, PRINT_HIGH, "%s%s %s %s%s\n",
|
||||
self->client->pers.netname,
|
||||
S_COLOR_WHITE,
|
||||
message,
|
||||
attacker->client->pers.netname,
|
||||
message2);
|
||||
}
|
||||
|
||||
} else { // suicide
|
||||
|
||||
if( deathmatch->value )
|
||||
self->client->resp.score--;
|
||||
|
||||
self->enemy = NULL;
|
||||
|
||||
if( dedicated->value )
|
||||
G_Printf ( "%s %s\n", self->client->pers.netname, message );
|
||||
else
|
||||
{ //bot
|
||||
G_PrintMsg (NULL, PRINT_HIGH, "%s%s %s\n",
|
||||
self->client->pers.netname,
|
||||
S_COLOR_WHITE,
|
||||
message );
|
||||
}
|
||||
}
|
||||
|
||||
} else { // wrong place, suicide, etc.
|
||||
|
||||
if( deathmatch->value )
|
||||
self->client->resp.score--;
|
||||
|
||||
self->enemy = NULL;
|
||||
|
||||
if( dedicated->value )
|
||||
G_Printf( "%s %s\n", self->client->pers.netname, message );
|
||||
else
|
||||
{ //bot
|
||||
G_PrintMsg (NULL, PRINT_HIGH, "%s%s %s\n",
|
||||
self->client->pers.netname,
|
||||
S_COLOR_WHITE,
|
||||
message );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// These routines are bot safe print routines, all id code needs to be
|
||||
// changed to these so the bots do not blow up on messages sent to them.
|
||||
|
@ -185,34 +80,6 @@ void AI_BotObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Debug print, could add a "logging" feature to print to a file
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void debug_printf(char *fmt, ...)
|
||||
{
|
||||
int i;
|
||||
char bigbuffer[0x10000];
|
||||
va_list argptr;
|
||||
edict_t *cl_ent;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsprintf (bigbuffer,fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (dedicated->value)
|
||||
gi.cprintf(NULL, PRINT_MEDIUM, bigbuffer);
|
||||
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
{
|
||||
cl_ent = g_edicts + 1 + i;
|
||||
if (!cl_ent->inuse || cl_ent->ai.is_bot)
|
||||
continue;
|
||||
|
||||
gi.cprintf(cl_ent, PRINT_MEDIUM, bigbuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// botsafe cprintf
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -114,16 +114,6 @@ cvar_t *bot_showsrgoal;
|
|||
cvar_t *bot_showlrgoal;
|
||||
cvar_t *bot_debugmonster;
|
||||
|
||||
/*
|
||||
void ClientThink (edict_t *ent, usercmd_t *cmd);
|
||||
qboolean ClientConnect (edict_t *ent, char *userinfo);
|
||||
void ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
||||
void ClientDisconnect (edict_t *ent);
|
||||
void ClientBegin (edict_t *ent);
|
||||
void ClientCommand (edict_t *ent);
|
||||
void RunEntity (edict_t *ent);
|
||||
void InitGame(void);
|
||||
*/
|
||||
static void G_RunFrame(void);
|
||||
|
||||
/* =================================================================== */
|
||||
|
|
|
@ -353,6 +353,12 @@ ServerCommand(void)
|
|||
{
|
||||
SVCmd_WriteIP_f();
|
||||
}
|
||||
/* JABot[start] */
|
||||
else if(Q_stricmp(cmd, "removebot") == 0)
|
||||
{
|
||||
BOT_RemoveBot(gi.argv(2));
|
||||
}
|
||||
/* [end] */
|
||||
else
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Copyright (C) 2001 Steve Yeager
|
||||
* Copyright (C) 2001-2004 Pat AfterMoon
|
||||
* Copyright (c) ZeniMax Media Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -98,7 +100,6 @@ typedef struct
|
|||
|
||||
|
||||
// bot_cmds.c
|
||||
qboolean BOT_Commands(edict_t *ent);
|
||||
qboolean BOT_ServerCommand(void);
|
||||
|
||||
// ai_main.c
|
||||
|
@ -114,9 +115,6 @@ void BOT_SpawnBot(char *team, char *name, char *skin, char *userinfo);
|
|||
void BOT_RemoveBot(char *name);
|
||||
void BOT_Respawn(edict_t *self);
|
||||
|
||||
//bot_misc.c
|
||||
void AI_BotObituary(edict_t *self, edict_t *inflictor, edict_t *attacker);
|
||||
|
||||
// ai_tools.c
|
||||
void AIDebug_ToogleBotDebug(void);
|
||||
|
||||
|
@ -124,7 +122,6 @@ void AITools_Frame(void);
|
|||
void AITools_DropNodes(edict_t *ent);
|
||||
|
||||
// safe **cough** prints
|
||||
void debug_printf(char *fmt, ...);
|
||||
void safe_cprintf(edict_t *ent, int printlevel, char *fmt, ...);
|
||||
void safe_centerprintf(edict_t *ent, char *fmt, ...);
|
||||
void safe_bprintf(int printlevel, char *fmt, ...);
|
||||
|
|
|
@ -210,8 +210,10 @@ typedef struct
|
|||
or a discrete file from anywhere in the quake search path
|
||||
a -1 return means the file does not exist
|
||||
NULL can be passed for buf to just determine existance */
|
||||
int (*FS_LoadFile) (const char *name, void **buf);
|
||||
void (*FS_FreeFile) (void *buf);
|
||||
int (*FS_LoadFile)(const char *name, void **buf);
|
||||
void (*FS_FreeFile)(void *buf);
|
||||
const char * (*FS_Gamedir)(void);
|
||||
void (*FS_CreatePath)(const char *path);
|
||||
const char * (*get_configstring)(int num);
|
||||
} game_import_t;
|
||||
|
||||
|
|
|
@ -474,6 +474,8 @@ SV_InitGameProgs(void)
|
|||
/* Extension to classic Quake2 API */
|
||||
import.FS_LoadFile = FS_LoadFile;
|
||||
import.FS_FreeFile = FS_FreeFile;
|
||||
import.FS_Gamedir = FS_Gamedir;
|
||||
import.FS_CreatePath = FS_CreatePath;
|
||||
|
||||
ge = (game_export_t *)Sys_GetGameAPI(&import);
|
||||
|
||||
|
|
Loading…
Reference in a new issue