jabot: remove botroam functionality

Trust A* heuristic to search path
This commit is contained in:
Denis Pauk 2025-03-22 17:29:08 +02:00
parent 8aea22e6c6
commit 0d8cba6711
13 changed files with 12 additions and 256 deletions

View file

@ -57,8 +57,6 @@ original clients (Vanilla Quake II) commands are still in place.
* **sv savenodes**: Save nodes file
* **sv addbotroam**: Drop a bot roam node
* **sv addbot <team> <name> <skin>**: Spawn a bot (consult ACEbot readme,
it's just the same thing)

View file

@ -437,19 +437,6 @@ AI_PathMap(void)
}
//==========================================
// AI_ClientPathMap
// Clients try to create new nodes while walking the map
//==========================================
void AITools_AddBotRoamNode(void)
{
if( nav.loaded )
return;
AI_AddNode( player.ent->s.origin, NODEFLAGS_BOTROAM );
}
//==========================================
// AI_ClientPathMap
// Clients try to create new nodes while walking the map
@ -478,9 +465,6 @@ void AITools_EraseNodes( void )
nav.num_ents = 0;
memset( nav.ents, 0, sizeof(nav_ents_t) * MAX_EDICTS );
nav.num_broams = 0;
memset( nav.broams, 0, sizeof(nav_broam_t) * MAX_BOT_ROAMS );
nav.num_items = 0;
memset( nav.items, 0, sizeof(nav_item_t) * MAX_EDICTS );
@ -498,9 +482,6 @@ void AITools_InitEditnodes( void )
nav.num_ents = 0;
memset( nav.ents, 0, sizeof(nav_ents_t) * MAX_EDICTS );
nav.num_broams = 0;
memset( nav.broams, 0, sizeof(nav_broam_t) * MAX_BOT_ROAMS );
nav.num_items = 0;
memset( nav.items, 0, sizeof(nav_item_t) * MAX_EDICTS );
nav.loaded = false;

View file

@ -278,29 +278,3 @@ float AI_ItemWeight(edict_t *self, edict_t *it)
return 0;
}
//==========================================
//QUAKED item_botroam
//==========================================
void SP_item_botroam (edict_t *ent)
{
float weight;
//try to convert Q3 weights (doh)
if(st.weight)
{
weight = st.weight;
// item_botroam weights should go between 0 and 100.
// to convert odd weights to this format:
if (weight >= 1000)
weight = 100;
else if (weight >= 100) //include 100, cause some q3 mappers use 100, 200, 300... etc
weight *= 0.1;
}
else
weight = 30; //default value
ent->count = (int)weight;
}

View file

@ -155,8 +155,6 @@ int AI_GravityBoxToLink(int n1, int n2);
//----------------------------------------------------------
qboolean AI_CanPick_Ammo (edict_t *ent, gitem_t *item);
qboolean AI_CanUseArmor (gitem_t *item, edict_t *other);
void AI_BotRoamFinishTimeouts(edict_t *self);
//bot_classes
//----------------------------------------------------------

View file

@ -150,71 +150,9 @@ void AI_ResetNavigation(edict_t *ent)
ent->ai->next_node = INVALID;
VectorSet( ent->ai->move_vector, 0, 0, 0 );
//reset bot_roams timeouts
for( i=0; i<nav.num_broams; i++)
ent->ai->status.broam_timeouts[i] = 0.0;
}
//==========================================
// AI_BotRoamForLRGoal
//
// Try assigning a bot roam node as LR Goal
//==========================================
qboolean AI_BotRoamForLRGoal(edict_t *self, int current_node)
{
int i;
float cost;
float weight, best_weight = 0.0;
int goal_node = INVALID;
// int best_broam = INVALID;
float dist;
if (!nav.num_broams)
return false;
for( i=0; i<nav.num_broams; i++)
{
if( self->ai->status.broam_timeouts[i] > level.time)
continue;
//limit cost finding by distance
dist = AI_Distance( self->s.origin, nodes[nav.broams[i].node].origin );
if( dist > 10000 )
continue;
//find cost
cost = AI_FindCost(current_node, nav.broams[i].node, self->ai->pers.moveTypesMask);
if(cost == INVALID || cost < 3) // ignore invalid and very short hops
continue;
cost *= random(); // Allow random variations for broams
weight = nav.broams[i].weight / cost; // Check against cost of getting there
if(weight > best_weight)
{
best_weight = weight;
goal_node = nav.broams[i].node;
// best_broam = i;
}
}
if(best_weight == 0.0 || goal_node == INVALID)
return false;
//set up the goal
self->ai->state = BOT_STATE_MOVE;
self->ai->tries = 0; // Reset the count of how many times we tried this goal
// if(AIDevel.debugChased && bot_showlrgoal->value)
// gi.cprintf(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);
AI_SetGoal(self,goal_node);
return true;
}
//==========================================
// AI_PickLongRangeGoal
//
@ -332,15 +270,11 @@ void AI_PickLongRangeGoal(edict_t *self)
// If do not find a goal, go wandering....
if(best_weight == 0.0 || goal_node == INVALID)
{
//BOT_ROAMS
if (!AI_BotRoamForLRGoal(self, current_node))
{
self->ai->goal_node = INVALID;
self->ai->state = BOT_STATE_WANDER;
self->ai->wander_timeout = level.time + 1.0;
// if(AIDevel.debugChased && bot_showlrgoal->value)
// gi.cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: did not find a LR goal, wandering.\n",self->ai->pers.netname);
}
self->ai->goal_node = INVALID;
self->ai->state = BOT_STATE_WANDER;
self->ai->wander_timeout = level.time + 1.0;
// if(AIDevel.debugChased && bot_showlrgoal->value)
// gi.cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: did not find a LR goal, wandering.\n",self->ai->pers.netname);
return; // no path?
}

View file

@ -185,22 +185,6 @@ qboolean AI_FollowPath( edict_t *self )
//if(AIDevel.debugChased && bot_showlrgoal->value)
// gi.cprintf(AIDevel.chaseguy, 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 )
{
int i;
for( i=0; i<nav.num_broams; i++) { //find the broam
if( nav.broams[i].node != self->ai->goal_node )
continue;
//if(AIDevel.debugChased && bot_showlrgoal->integer)
// gi.cprintf(AIDevel.chaseguy, PRINT_HIGH, "%s: BotRoam Time Out set up for node %i\n", self->ai->pers.netname, nav.broams[i].node);
//Com_Printf( "%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;
}
}
// Pick a new goal
AI_PickLongRangeGoal(self);
}

View file

@ -486,41 +486,6 @@ int AI_AddNode_Teleporter( edict_t *ent )
}
//==========================================
// AI_AddNode_BotRoam
// add nodes from bot roam entities
//==========================================
int AI_AddNode_BotRoam( edict_t *ent )
{
if( nav.num_nodes + 1 > MAX_NODES )
return INVALID;
nodes[nav.num_nodes].flags = (NODEFLAGS_BOTROAM);//bot roams are not NODEFLAGS_NOWORLD
// Set location
VectorCopy( ent->s.origin, nodes[nav.num_nodes].origin );
if ( ent->spawnflags & 1 ) // floating items
nodes[nav.num_nodes].flags |= NODEFLAGS_FLOAT;
else
if( !AI_DropNodeOriginToFloor( nodes[nav.num_nodes].origin, NULL ) )
return INVALID;//spawned inside solid
nodes[nav.num_nodes].flags |= AI_FlagsForNode( nodes[nav.num_nodes].origin, NULL );
//count into bot_roams table
nav.broams[nav.num_broams].node = nav.num_nodes;
if( ent->count )
nav.broams[nav.num_broams].weight = ent->count * 0.01;//count is a int with a value in between 0 and 100
else
nav.broams[nav.num_broams].weight = 0.3;
nav.num_broams++;
nav.num_nodes++;
return nav.num_nodes-1; // return the node added
}
//==========================================
// AI_AddNode_ItemNode
// Used to add nodes from items
@ -587,62 +552,6 @@ void AI_CreateNodesForEntities ( void )
}
}
// bot roams
nav.num_broams = 0;
memset( nav.broams, 0, sizeof(nav_broam_t) * MAX_BOT_ROAMS );
//visit world nodes first, and put in list what we find in there
for( node=0; node < nav.num_nodes; node++ )
{
if( nodes[node].flags & NODEFLAGS_BOTROAM && nav.num_broams < MAX_BOT_ROAMS)
{
nav.broams[nav.num_broams].node = node;
nav.broams[nav.num_broams].weight = 0.3;
nav.num_broams++;
}
}
//now add bot roams from entities
// for(ent = game.edicts; ent < &game.edicts[game.numentities]; ent++)
for( ent = g_edicts; ent < &g_edicts[game.maxentities]; ent++ )
{
if( !ent->classname )
continue;
if( !strcmp( ent->classname,"item_botroam" ) )
{
//if we have a available node close enough to the item, use it instead of dropping a new node
node = AI_FindClosestReachableNode( ent->s.origin, NULL, 48, NODE_ALL );
if( node != -1 &&
!(nodes[node].flags & NODEFLAGS_SERVERLINK) &&
!(nodes[node].flags & NODEFLAGS_LADDER) )
{
float heightdiff = 0;
heightdiff = ent->s.origin[2] - nodes[node].origin[2];
if( heightdiff < 0 ) heightdiff = -heightdiff;
if( heightdiff < AI_STEPSIZE && nav.num_broams < MAX_BOT_ROAMS ) //near enough
{
nodes[node].flags |= NODEFLAGS_BOTROAM;
//add node to botroam list
if( ent->count )
nav.broams[nav.num_broams].weight = ent->count * 0.01;//count is a int with a value in between 0 and 100
else
nav.broams[nav.num_broams].weight = 0.3; //jalfixme: add cmd to weight (dropped by console cmd, self is player)
nav.broams[nav.num_broams].node = node;
nav.num_broams++;
continue;
}
}
//drop a new node
if( nav.num_broams < MAX_BOT_ROAMS ){
AI_AddNode_BotRoam( ent );
}
}
}
// game items (I want all them on top of the nodes array)
nav.num_items = 0;
memset( nav.items, 0, sizeof(nav_item_t) * MAX_EDICTS );

View file

@ -54,13 +54,6 @@ typedef struct nav_ents_s
} nav_ents_t;
typedef struct nav_botroam_s
{
int node;
float weight;
} nav_broam_t;
typedef struct nav_path_s
{
int next; //next node
@ -82,10 +75,6 @@ typedef struct
int num_ents;
nav_ents_t ents[MAX_EDICTS]; //plats, etc
int num_broams;
nav_broam_t broams[MAX_BOT_ROAMS]; //list of nodes wich are botroams
} ai_navigation_t;
extern ai_navigation_t nav;

View file

@ -53,16 +53,14 @@
#define NODEFLAGS_LADDER 0x00000002
#define NODEFLAGS_SERVERLINK 0x00000004 //plats, doors, teles. Only server can link 2 nodes with this flag
#define NODEFLAGS_FLOAT 0x00000008 //don't drop node to floor ( air & water )
//#define NODEFLAGS_ITEM 0x00000010 //jal remove me
#define NODEFLAGS_BOTROAM 0x00000020
#define NODEFLAGS_JUMPPAD 0x00000040 // jalfixme: add NODEFLAGS_REACHATTOUCH
#define NODEFLAGS_JUMPPAD_LAND 0x00000080
#define NODEFLAGS_PLATFORM 0x00000100
#define NODEFLAGS_TELEPORTER_IN 0x00000200 // jalfixme: add NODEFLAGS_REACHATTOUCH
#define NODEFLAGS_TELEPORTER_OUT 0x00000400
#define NODEFLAGS_REACHATTOUCH 0x00000800
#define NODEFLAGS_JUMPPAD 0x00000010 // jalfixme: add NODEFLAGS_REACHATTOUCH
#define NODEFLAGS_JUMPPAD_LAND 0x00000020
#define NODEFLAGS_PLATFORM 0x00000040
#define NODEFLAGS_TELEPORTER_IN 0x00000080 // jalfixme: add NODEFLAGS_REACHATTOUCH
#define NODEFLAGS_TELEPORTER_OUT 0x00000100
#define NODEFLAGS_REACHATTOUCH 0x00000200
#define NODE_ALL 0x00001000
#define NODE_ALL 0x00000400
// links types (movetypes required to run node links)
#define LINK_MOVE 0x00000001

View file

@ -370,10 +370,6 @@ ServerCommand(void)
{
AITools_SaveNodes();
}
else if (!Q_stricmp (cmd, "addbotroam"))
{
AITools_AddBotRoamNode();
}
else if(Q_stricmp(cmd, "removebot") == 0)
{
BOT_RemoveBot(gi.argv(2));

View file

@ -30,7 +30,6 @@
// declaration of botedict for the game
//----------------------------------------------------------
#define MAX_BOT_ROAMS 128
/* jalToDo: needs dynamic alloc (big terrain maps) */
#define MAX_NODES 2048
@ -49,7 +48,6 @@ typedef struct
float inventoryWeights[MAX_ITEMS];
float playersWeights[MAX_EDICTS];
float broam_timeouts[MAX_BOT_ROAMS]; //revisit bot roams
} ai_status_t;
typedef struct
@ -120,7 +118,6 @@ void AITools_Frame(void);
void AITools_DropNodes(edict_t *ent);
/* ai_dropnodes.c */
void AITools_AddBotRoamNode(void);
void AITools_SaveNodes(void);
void AITools_InitEditnodes(void);
void AITools_InitMakenodes(void);

View file

@ -66,7 +66,6 @@ extern void SP_info_player_deathmatch(edict_t * self);
extern void SP_info_player_intermission ( edict_t * ent ) ;
extern void SP_info_player_start(edict_t * self);
extern void SP_info_teleport_destination(edict_t * self);
extern void SP_item_botroam(edict_t * self);
extern void SP_item_foodcube(edict_t * self);
extern void SP_item_health(edict_t * self);
extern void SP_item_health_large(edict_t * self);

View file

@ -69,7 +69,6 @@
{"info_player_team1", SP_info_player_team1},
{"info_player_team2", SP_info_player_team2},
{"info_teleport_destination", SP_info_teleport_destination},
{"item_botroam", SP_item_botroam},
{"item_health", SP_item_health},
{"item_health_large", SP_item_health_large},
{"item_health_mega", SP_item_health_mega},