Exemplo n.º 1
0
//==========================================
// AI_MoveToGoalEntity
// Set bot to move to it's movetarget. Short range goals
//==========================================
qboolean AI_MoveToGoalEntity(edict_t *self, usercmd_t *ucmd)
{
	if (!self->movetarget || !self->client)
		return false;

	// If a rocket or grenade is around deal with it
	// Simple, but effective (could be rewritten to be more accurate)
	if(!Q_stricmp(self->movetarget->classname,"rocket") ||
	   !Q_stricmp(self->movetarget->classname,"grenade") ||
	   !Q_stricmp(self->movetarget->classname,"hgrenade"))
	{
		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);

		// strafe left/right
		if(rand()%1 && AI_CanMove(self, BOT_MOVE_LEFT))
				ucmd->sidemove = -400;
		else if(AI_CanMove(self, BOT_MOVE_RIGHT))
				ucmd->sidemove = 400;
		return true;

	}

	// Set bot's movement direction
	VectorSubtract (self->movetarget->s.origin, self->s.origin, self->ai.move_vector);
	AI_ChangeAngle(self);
	if(!AI_CanMove(self, BOT_MOVE_FORWARD) ) 
	{
		self->movetarget = NULL;
		ucmd->forwardmove = -400;
		return false;
	}

	//Move
	ucmd->forwardmove = 400;
	return true;
}
Exemplo n.º 2
0
//==========================================
// BOT_DMclass_CombatMovement
//
// NOTE: Very simple for now, just a basic move about avoidance.
//       Change this routine for more advanced attack movement.
//==========================================
void BOT_DMclass_CombatMovement( edict_t *self, usercmd_t *ucmd )
{
	float c;
	float dist;
	bool rocket = false;
	vec3_t away_from_rocket = { 0, 0, 0 };

	if( !self->enemy || self->ai->rush_item )
	{
		BOT_DMclass_Move( self, ucmd );
		return;
	}

	if( self->ai->pers.skillLevel >= 0.25f ) 
		rocket = BOT_DMclass_FindRocket( self, away_from_rocket );

	dist = DistanceFast( self->s.origin, self->enemy->s.origin );
	c = random();

	if( level.time > self->ai->combatmovepush_timeout )
	{
		bool canMOVELEFT, canMOVERIGHT, canMOVEFRONT, canMOVEBACK;

		canMOVELEFT = AI_CanMove( self, BOT_MOVE_LEFT );
		canMOVERIGHT = AI_CanMove( self, BOT_MOVE_RIGHT );
		canMOVEFRONT = AI_CanMove( self, BOT_MOVE_FORWARD );
		canMOVEBACK = AI_CanMove( self, BOT_MOVE_BACK );

		self->ai->combatmovepush_timeout = level.time + AI_COMBATMOVE_TIMEOUT;
		VectorClear( self->ai->combatmovepushes );

		if( rocket )
		{
			//VectorScale(away_from_rocket,1,self->ai->combatmovepushes);
			if( away_from_rocket[0] )
			{
				if( ( away_from_rocket[0] < 0 ) && canMOVEBACK )
					self->ai->combatmovepushes[0] = -1;
				else if( ( away_from_rocket[0] > 0 ) && canMOVEFRONT )
					self->ai->combatmovepushes[0] = 1;
			}
			if( away_from_rocket[1] )
			{
				if( ( away_from_rocket[1] < 0 ) && canMOVELEFT )
					self->ai->combatmovepushes[1] = -1;
				else if( ( away_from_rocket[1] > 0 ) && canMOVERIGHT )
					self->ai->combatmovepushes[1] = 1;
			}

			ucmd->buttons |= BUTTON_SPECIAL;
		}
		else
			if( dist < 150 ) // range = AIWEAP_MELEE_RANGE;
			{
				if( self->s.weapon == WEAP_GUNBLADE ) // go into him!
				{
					ucmd->buttons &= ~BUTTON_ATTACK; // remove pressing fire
					if( canMOVEFRONT )  // move to your enemy
						self->ai->combatmovepushes[0] = 1;
					else if( c <= 0.5 && canMOVELEFT )
						self->ai->combatmovepushes[1] = -1;
					else if( canMOVERIGHT )
						self->ai->combatmovepushes[1] = 1;
				}
				else
				{
					//priorize sides
					if( canMOVELEFT || canMOVERIGHT )
					{
						if( canMOVELEFT && canMOVERIGHT )
						{
							self->ai->combatmovepushes[1] = c < 0.5 ? -1 : 1;
						}
						else if( canMOVELEFT )
						{
							self->ai->combatmovepushes[1] = -1;
						}
						else
						{
							self->ai->combatmovepushes[1] = 1;
						}
					}

					if( c < 0.3 && canMOVEBACK )
						self->ai->combatmovepushes[0] = -1;
				}

			}
			else if( dist < 500 ) //AIWEAP_SHORT_RANGE limit is Grenade Laucher range
			{
				if( canMOVELEFT || canMOVERIGHT )
				{
					if( canMOVELEFT && canMOVERIGHT )
					{
						self->ai->combatmovepushes[1] = c < 0.5 ? -1 : 1;
					}
					else if( canMOVELEFT )
					{
						self->ai->combatmovepushes[1] = -1;
					}
					else
					{
						self->ai->combatmovepushes[1] = 1;
					}
				}

				if( c < 0.3 && canMOVEFRONT )
				{
					self->ai->combatmovepushes[0] = 1;
				}

			}
			else if( dist < 900 )
			{
				if( canMOVELEFT || canMOVERIGHT )
				{
					if( canMOVELEFT && canMOVERIGHT )
					{
						self->ai->combatmovepushes[1] = c < 0.5 ? -1 : 1;
					}
					else if( canMOVELEFT )
					{
						self->ai->combatmovepushes[1] = -1;
					}
					else
					{
						self->ai->combatmovepushes[1] = 1;
					}
				}
			}
			else //range = AIWEAP_LONG_RANGE;
			{
				if( c < 0.75 && ( canMOVELEFT || canMOVERIGHT ) )
				{
					if( canMOVELEFT && canMOVERIGHT )
					{
						self->ai->combatmovepushes[1] = c < 0.5 ? -1 : 1;
					}
					else if( canMOVELEFT )
					{
						self->ai->combatmovepushes[1] = -1;
					}
					else
					{
						self->ai->combatmovepushes[1] = 1;
					}
				}
			}
	}

	if( !rocket && ( self->health < 25 || ( dist >= 500 && c < 0.2 ) || ( dist >= 1000 && c < 0.5 ) ) )
	{
		BOT_DMclass_Move( self, ucmd );
	}

	if( !self->ai->camp_item )
	{
		ucmd->forwardmove = self->ai->combatmovepushes[0];
	}
	ucmd->sidemove = self->ai->combatmovepushes[1];
	ucmd->upmove = self->ai->combatmovepushes[2];
}
Exemplo n.º 3
0
void BOT_DMclass_MoveWander( edict_t *self, usercmd_t *ucmd )
{
	vec3_t temp;

	if( self->deadflag )
		return;
	if( !self->r.client->ps.pmove.stats[PM_STAT_MAXSPEED] ) {
		return;
	}

	// Special check for elevators, stand still until the ride comes to a complete stop.
	if( self->groundentity && self->groundentity->use == Use_Plat )
	{
		if( self->groundentity->moveinfo.state != STATE_UP &&
			self->groundentity->moveinfo.state != STATE_DOWN )
		{
			self->velocity[0] = 0;
			self->velocity[1] = 0;
			self->velocity[2] = 0;
			return;
		}
	}

	// Move To Goal (Short Range Goal, not following paths)
	if( !AI_MoveToShortRangeGoalEntity( self, ucmd ) )
	{
		// Swimming?
		VectorCopy( self->s.origin, temp );
		temp[2] += 24;

		if( G_PointContents( temp ) & MASK_WATER )
		{
			// If drowning and no node, move up
			if( self->r.client && self->r.client->resp.next_drown_time > 0 )
			{
				ucmd->upmove = 1;
				self->s.angles[PITCH] = -45;
			}
			else
				ucmd->upmove = 1;

			ucmd->forwardmove = 1;
		}
		// else self->r.client->next_drown_time = 0; // probably shound not be messing with this, but


		// Lava?
		temp[2] -= 48;
		if( G_PointContents( temp ) & ( CONTENTS_LAVA|CONTENTS_SLIME ) )
		{
			self->s.angles[YAW] += random() * 360 - 180;
			ucmd->forwardmove = 1;
			if( self->groundentity )
				ucmd->upmove = 1;
			else
				ucmd->upmove = 0;
			return;
		}


		// Check for special movement
		if( VectorLengthFast( self->velocity ) < 37 )
		{
			if( random() > 0.1 && AI_SpecialMove( self, ucmd ) )  //jumps, crouches, turns...
				return;

			self->s.angles[YAW] += random() * 180 - 90;

			if( !self->is_step )  // if there is ground continue otherwise wait for next move
				ucmd->forwardmove = 0; //0
			else if( AI_CanMove( self, BOT_MOVE_FORWARD ) )
			{
				ucmd->forwardmove = 1;
				ucmd->buttons |= BUTTON_WALK;
			}

			return;
		}

		// Otherwise move slowly, walking wondering what's going on
		ucmd->buttons |= BUTTON_WALK;
	}

	if( AI_CanMove( self, BOT_MOVE_FORWARD ) )
		ucmd->forwardmove = 1;
	else
		ucmd->forwardmove = -1;
}
Exemplo n.º 4
0
bool AI_FindPath( monsterCharacter_t* monster )
{
	node_t *startNode;							
	node_t *bestNode;							
	node_t newNode;								
	node_t *actualNode;							

	int i;										
	
	monster->ai.searchNumber = 0;



	if( monster->ai.curPos[0] == monster->ai.goalPos[0] && 
		monster->ai.curPos[1] == monster->ai.goalPos[1] ) return( 1 );

	
	if( monster->ai.goalPos[0] == monster->ai.path[0][0] &&
		 monster->ai.goalPos[1] == monster->ai.path[0][1] ) return( 1 );

	
	if( monster->ai.isGoal )
	{
		
		if( monster->ai.totalSearch == 0 )
		{
			startNode = AI_GetNode( monster, monster->ai.curPos );
			
			startNode->onClosed = false;
			startNode->onOpen = true;
			startNode->parent = NULL;
			startNode->cost = 0;
			
			startNode->total = AI_CostFromNodeToNode( monster->ai.curPos, monster->ai.goalPos )  * monster->ai.heruristic;
			
			monster->ai.pathQueue.goal[0] = monster->ai.goalPos[0];
			monster->ai.pathQueue.goal[1] = monster->ai.goalPos[1];
			
			
			AI_PushPriorityQueue( monster->ai.pathQueue.open, startNode );
			
			
			monster->ai.totalSearch = 0;
		}
	}

	while( !AI_IsPriorityQueueEmpty( monster->ai.pathQueue.open ) )
	{
		
		if( monster->ai.searchNumber > NUMBER_OF_PATH_SEARCH )
		{
			monster->ai.totalSearch += monster->ai.searchNumber;
			if( monster->ai.totalSearch > MAX_NUMBER_OF_PATH_SEARCH ) 
				return( false );
			
			monster->ai.isGoal = false;
			return( true );
		}

		
		bestNode = AI_PopPriorityQueue( monster->ai.pathQueue.open );

		
		if( bestNode->pos[0] == monster->ai.pathQueue.goal[0] && 
			bestNode->pos[1] == monster->ai.pathQueue.goal[1] )
		{
			AI_PushPriorityQueue( monster->ai.pathQueue.open, bestNode );
			
			AI_MakePath( monster );
			
			monster->ai.isGoal = true;
			return( true );
		}

		
		for( i = 0; i < 8; i ++ )
		{
			switch( i )
			{
			case 0:
				newNode.pos[0] = bestNode->pos[0] - 1;
				newNode.pos[1] = bestNode->pos[1];
				break;
			case 1:
				newNode.pos[0] = bestNode->pos[0] - 1;
				newNode.pos[1] = bestNode->pos[1] + 1;
				break;
			case 2:
				newNode.pos[0] = bestNode->pos[0];
				newNode.pos[1] = bestNode->pos[1] + 1;
				break;
			case 3:
				newNode.pos[0] = bestNode->pos[0] + 1;
				newNode.pos[1] = bestNode->pos[1] + 1;
				break;
			case 4:
				newNode.pos[0] = bestNode->pos[0] + 1;
				newNode.pos[1] = bestNode->pos[1];
				break;
			case 5:
				newNode.pos[0] = bestNode->pos[0] + 1;
				newNode.pos[1] = bestNode->pos[1] - 1;
				break;
			case 6:
				newNode.pos[0] = bestNode->pos[0];
				newNode.pos[1] = bestNode->pos[1] - 1;
				break;
			case 7:
				newNode.pos[0] = bestNode->pos[0] - 1;
				newNode.pos[1] = bestNode->pos[1] - 1;
				break;
			}
			
			if( !AI_CanMove( monster, newNode.pos, i ) ) continue;

			if( bestNode->parent == NULL || \
				bestNode->parent->pos[0] != newNode.pos[0] || \
				bestNode->parent->pos[1] != newNode.pos[1] )
			{
				newNode.parent = bestNode;
				newNode.cost = bestNode->cost + AI_CostFromNodeToNode( newNode.pos, bestNode->pos );
				newNode.total = newNode.cost + AI_CostFromNodeToNode( newNode.pos, monster->ai.pathQueue.goal ) * monster->ai.heruristic;

				actualNode = AI_GetNode( monster, newNode.pos );
				if( actualNode == NULL ) return( false );

				if( !( actualNode->onOpen && newNode.total > actualNode->total ) && \
					!( actualNode->onClosed && newNode.total > actualNode->total ) )
				{
					actualNode->onClosed = false;
					actualNode->parent = newNode.parent;
					actualNode->cost = newNode.cost;
					actualNode->total = newNode.total;

					if( actualNode->onOpen )
					{
						AI_UpdateNodeOnPriorityQueue( monster->ai.pathQueue.open, actualNode );
					}
					else
					{
						AI_PushPriorityQueue( monster->ai.pathQueue.open, actualNode );
						actualNode->onOpen = true;
					}
					monster->ai.searchNumber ++;
				}
			}
		}
		bestNode->onClosed = true;
	}
	return( false );
}