Ejemplo n.º 1
0
///////////////////////////////////////////////////////////////////////
// Move closer to goal by pointing the bot to the next node
// that is closer to the goal
///////////////////////////////////////////////////////////////////////
qboolean ACEND_FollowPath(edict_t *self)
{
	vec3_t v;
	
	//////////////////////////////////////////
	// Show the path (uncomment for debugging)
//	show_path_from = self->current_node;
//	show_path_to = self->goal_node;
//	ACEND_DrawPath();
	//////////////////////////////////////////

	// Try again?
	if(self->node_timeout ++ > 30)
	{
		if(self->tries++ > 3)
			return false;
		else
			ACEND_SetGoal(self,self->goal_node);
	}
		
	// Are we there yet?
	VectorSubtract(self->s.origin,nodes[self->next_node].origin,v);
	
	if(VectorLength(v) < 32) 
	{
		// reset timeout
		self->node_timeout = 0;

		if(self->next_node == self->goal_node)
		{
			if(debug_mode)
				debug_printf("%s reached goal!\n",self->client->pers.netname);	
			
			ACEAI_PickLongRangeGoal(self); // Pick a new goal
		}
		else
		{
			self->current_node = self->next_node;
			self->next_node = path_table[self->current_node][self->goal_node];
		}
	}
	
	if(self->current_node == -1 || self->next_node ==-1)
		return false;
	
	// Set bot's movement vector
	VectorSubtract (nodes[self->next_node].origin, self->s.origin , self->move_vector);
	
	return true;
}
Ejemplo n.º 2
0
// Move closer to goal by pointing the bot to the next node
// that is closer to the goal
qboolean ACEND_FollowPath(gentity_t * self)
{
	// try again?
	if(self->bs.node_timeout++ > 30)
	{
		if(self->bs.tries++ > 3)
			return qfalse;
		else
			ACEND_SetGoal(self, self->bs.goalNode);
	}

	// are we there yet?

	//if(Distance(self->client->ps.origin, nodes[self->bs.nextNode].origin) < 32)
	if(BoundsIntersectPoint(self->r.absmin, self->r.absmax, nodes[self->bs.nextNode].origin))
	{
		// reset timeout
		self->bs.node_timeout = 0;

		if(self->bs.nextNode == self->bs.goalNode)
		{
			if(ace_debug.integer)
				trap_SendServerCommand(-1, va("print \"%s: reached goal!\n\"", self->client->pers.netname));

			ACEAI_PickLongRangeGoal(self);	// pick a new goal
		}
		else
		{
			self->bs.currentNode = self->bs.nextNode;
			self->bs.nextNode = path_table[self->bs.currentNode][self->bs.goalNode];
		}
	}

	if(self->bs.currentNode == INVALID || self->bs.nextNode == INVALID)
		return qfalse;

	// set bot's movement vector
	VectorSubtract(nodes[self->bs.nextNode].origin, self->client->ps.origin, self->bs.moveVector);

	return qtrue;
}
Ejemplo n.º 3
0
///////////////////////////////////////////////////////////////////////
// Evaluate the best long range goal and send the bot on
// its way. This is a good time waster, so use it sparingly. 
// Do not call it for every think cycle.
///////////////////////////////////////////////////////////////////////
void ACEAI_PickLongRangeGoal(edict_t *self)
{

	int i;
	int node;
	float weight,best_weight=0.0;
	int current_node,goal_node;
	edict_t *goal_ent;
	float cost;
	
	// look for a target 
	current_node = ACEND_FindClosestReachableNode(self,NODE_DENSITY,NODE_ALL);

	self->current_node = current_node;
	
	if(current_node == -1)
	{
		self->state = STATE_WANDER;
		self->wander_timeout = level.time + 1.0;
		self->goal_node = -1;
		return;
	}

	///////////////////////////////////////////////////////
	// Items
	///////////////////////////////////////////////////////
	for (i=0; i<num_items; i++)
	{
		// ignore items that are not there.
		if (!item_table[i].ent || !item_table[i].ent->inuse || item_table[i].ent->solid == SOLID_NOT)
			continue;
		
		cost = ACEND_FindCost(current_node,item_table[i].node);
		
		if (cost == INVALID || cost < 2) // ignore invalid and very short hops
			continue;
	
		weight = ACEIT_ItemNeed(self, item_table[i].item);

		// If I am on team one and I have the flag for the other team....return it
		// Knightmare- rewrote for 3Team CTF
		//if (ctf->value && (item_table[i].item == ITEMLIST_FLAG2 || item_table[i].item == ITEMLIST_FLAG1) &&
		//	(self->client->resp.ctf_team == CTF_TEAM1 && self->client->pers.inventory[ITEMLIST_FLAG2] ||
		//	self->client->resp.ctf_team == CTF_TEAM2 && self->client->pers.inventory[ITEMLIST_FLAG1]))
		if (ctf->value && (
				(item_table[i].item == ITEMLIST_FLAG1 && self->client->resp.ctf_team == CTF_TEAM1 &&
					(self->client->pers.inventory[ITEMLIST_FLAG2] || self->client->pers.inventory[ITEMLIST_FLAG3]) )
				|| (item_table[i].item == ITEMLIST_FLAG2 && self->client->resp.ctf_team == CTF_TEAM2 &&
					(self->client->pers.inventory[ITEMLIST_FLAG1] || self->client->pers.inventory[ITEMLIST_FLAG3]) )
				|| (item_table[i].item == ITEMLIST_FLAG3 && self->client->resp.ctf_team == CTF_TEAM3 &&
					(self->client->pers.inventory[ITEMLIST_FLAG1] || self->client->pers.inventory[ITEMLIST_FLAG2]) )
			))
			weight = 10.0;

		// Knightmare- in 3Team CTF mode, make double captures a lower priority than
		// getting back to base with the flag we already have.
		if (ttctf->value && (
			(self->client->resp.ctf_team == CTF_TEAM1
				&& (self->client->pers.inventory[ITEMLIST_FLAG2] || self->client->pers.inventory[ITEMLIST_FLAG3])
				&& (item_table[i].item == ITEMLIST_FLAG2 || item_table[i].item == ITEMLIST_FLAG3) )
			|| (self->client->resp.ctf_team == CTF_TEAM2
				&& (self->client->pers.inventory[ITEMLIST_FLAG1] || self->client->pers.inventory[ITEMLIST_FLAG3])
				&& (item_table[i].item == ITEMLIST_FLAG1 || item_table[i].item == ITEMLIST_FLAG3) )
			|| (self->client->resp.ctf_team == CTF_TEAM3
				&& (self->client->pers.inventory[ITEMLIST_FLAG1] || self->client->pers.inventory[ITEMLIST_FLAG2])
				&& (item_table[i].item == ITEMLIST_FLAG1 || item_table[i].item == ITEMLIST_FLAG2) )
			))
			weight = 6.5;

		weight *= random(); // Allow random variations
		weight /= cost; // Check against cost of getting there
				
		if (weight > best_weight)
		{
			best_weight = weight;
			goal_node = item_table[i].node;
			goal_ent = item_table[i].ent;
		}
	}

	///////////////////////////////////////////////////////
	// Players
	///////////////////////////////////////////////////////
	// This should be its own function and is for now just
	// finds a player to set as the goal.
	for(i=0;i<num_players;i++)
	{
		if(players[i] == self)
			continue;

		node = ACEND_FindClosestReachableNode(players[i],NODE_DENSITY,NODE_ALL);
		cost = ACEND_FindCost(current_node, node);

		if(cost == INVALID || cost < 3) // ignore invalid and very short hops
			continue;

		// Player carrying the flag?
		if(ctf->value && (players[i]->client->pers.inventory[ITEMLIST_FLAG2] || players[i]->client->pers.inventory[ITEMLIST_FLAG1]))
		  weight = 2.0;
		else
		  weight = 0.3; 
		
		weight *= random(); // Allow random variations
		weight /= cost; // Check against cost of getting there
		
		if(weight > best_weight)
		{		
			best_weight = weight;
			goal_node = node;
			goal_ent = players[i];
		}	
	}

	// If do not find a goal, go wandering....
	if(best_weight == 0.0 || goal_node == INVALID)
	{
		self->goal_node = INVALID;
		self->state = STATE_WANDER;
		self->wander_timeout = level.time + 1.0;
		if(debug_mode)
			debug_printf("%s did not find a LR goal, wandering.\n",self->client->pers.netname);
		return; // no path? 
	}
	
	// OK, everything valid, let's start moving to our goal.
	self->state = STATE_MOVE;
	self->tries = 0; // Reset the count of how many times we tried this goal
	 
	if(goal_ent != NULL && debug_mode)
		debug_printf("%s selected a %s at node %d for LR goal.\n",self->client->pers.netname, goal_ent->classname, goal_node);

	ACEND_SetGoal(self,goal_node);

}