Exemplo n.º 1
0
///////////////////////////////////////////////////////////////////////
// Set bot to move to it's movetarget. (following node path)
///////////////////////////////////////////////////////////////////////
void ACEMV_MoveToGoal(edict_t *self, usercmd_t *ucmd)
{
	// If a rocket or grenade is around deal with it
	// Simple, but effective (could be rewritten to be more accurate)
	if(strcmp(self->movetarget->classname,"rocket")==0 ||
	   strcmp(self->movetarget->classname,"grenade")==0)
	{
		VectorSubtract (self->movetarget->s.origin, self->s.origin, self->move_vector);
		ACEMV_ChangeBotAngle(self);
		if(debug_mode)
			debug_printf("%s: Oh crap a rocket!\n",self->client->pers.netname);
		
		// strafe left/right
		if(rand()%1 && ACEMV_CanMove(self, MOVE_LEFT))
				ucmd->sidemove = -400;
		else if(ACEMV_CanMove(self, MOVE_RIGHT))
				ucmd->sidemove = 400;
		return;

	}
	else
	{
		// Set bot's movement direction
		VectorSubtract (self->movetarget->s.origin, self->s.origin, self->move_vector);
		ACEMV_ChangeBotAngle(self);
		ucmd->forwardmove = 400;
		return;
	}
}
Exemplo n.º 2
0
///////////////////////////////////////////////////////////////////////
// Attack movement routine
//
// NOTE: Very simple for now, just a basic move about avoidance.
//       Change this routine for more advanced attack movement.
///////////////////////////////////////////////////////////////////////
void ACEMV_Attack (edict_t *self, usercmd_t *ucmd)
{
	float c;
	vec3_t  target;
	vec3_t  angles;
	
	// Randomly choose a movement direction
	c = random();
	
	if(c < 0.2 && ACEMV_CanMove(self,MOVE_LEFT))
		ucmd->sidemove -= 300; 
	else if(c < 0.4 && ACEMV_CanMove(self,MOVE_RIGHT))
		ucmd->sidemove += 300; 
		
	if(c < 0.6 && ACEMV_CanMove(self,MOVE_FORWARD))
		ucmd->forwardmove += 300; 
	else if(c < 0.8 && ACEMV_CanMove(self,MOVE_FORWARD))
		ucmd->forwardmove -= 300;

	// random jump
	if(c > 0.95)
		ucmd->upmove += 200;
              
        // Set the attack 
	if(self->client->pers.weapon == FindItem("grenades") && ucmd->buttons == BUTTON_ATTACK)
		ucmd->buttons = 0;
	else
		ucmd->buttons = BUTTON_ATTACK;
	
	// Aim
	VectorCopy(self->enemy->s.origin,target);

	// modify attack angles based on accuracy (mess this up to make the bot's aim not so deadly)
	target[0] += (random()-0.5) * 30;
	target[1] += (random()-0.5) * 30;
	
	// Set direction
	VectorSubtract (target, self->s.origin, self->move_vector);
	vectoangles (self->move_vector, angles);
	VectorCopy(angles,self->s.angles);
	
	//if(debug_mode)
	//	debug_printf("%s attacking %s\n",self->client->pers.netname,self->enemy->classname);
}
Exemplo n.º 3
0
// Set bot to move to it's moveTarget. (following node path)
void ACEMV_MoveToGoal(gentity_t * self)
{
	// if a rocket or grenade is around deal with it
	// simple, but effective (could be rewritten to be more accurate)
	if((strcmp(self->bs.moveTarget->classname, "rocket") == 0 || strcmp(self->bs.moveTarget->classname, "grenade") == 0))
	{
		VectorSubtract(self->bs.moveTarget->s.origin, self->client->ps.origin, self->bs.moveVector);
		ACEMV_ChangeBotAngle(self);

		if(ace_debug.integer)
			trap_SendServerCommand(-1, va("print \"%s: Oh crap a rocket!\n\"", self->client->pers.netname));

		//trap_SendServerCommand(-1, va("%s \"%s%c%c%s\"", mode == SAY_TEAM ? "tchat" : "chat", name, Q_COLOR_ESCAPE, color, message));

		// strafe left/right
		if(rand() % 1 && ACEMV_CanMove(self, MOVE_LEFT))
		{
			self->client->pers.cmd.rightmove = -127;
		}
		else if(ACEMV_CanMove(self, MOVE_RIGHT))
		{
			self->client->pers.cmd.rightmove = 127;
		}
		return;

	}
	else
	{
		// set bot's movement direction
		VectorSubtract(self->bs.moveTarget->s.origin, self->client->ps.origin, self->bs.moveVector);
		ACEMV_ChangeBotAngle(self);

		if(ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove = 127;
		return;
	}
}
Exemplo n.º 4
0
// Handle special cases of crouch/jump
//
// If the move is resolved here, this function returns
// true.
qboolean ACEMV_SpecialMove(gentity_t * self)
{
	vec3_t          dir, forward, right, start, end, offset;
	vec3_t          top;
	trace_t         tr;

	// Get current direction
	VectorCopy(self->client->ps.viewangles, dir);
	dir[YAW] = self->bs.viewAngles[YAW];
	AngleVectors(dir, forward, right, NULL);

	VectorSet(offset, 18, 0, 0);
	G_ProjectSource(self->client->ps.origin, offset, forward, right, start);
	offset[0] += 18;
	G_ProjectSource(self->client->ps.origin, offset, forward, right, end);

	// trace it
	start[2] += 18;				// so they are not jumping all the time
	end[2] += 18;

	//tr = gi.trace(start, self->mins, self->maxs, end, self, MASK_MONSTERSOLID);
	trap_Trace(&tr, start, self->r.mins, self->r.maxs, end, self->s.number, MASK_PLAYERSOLID);

	if(tr.allsolid)
	{
		// check for crouching
		start[2] -= 14;
		end[2] -= 14;

		// set up for crouching check
		VectorCopy(self->r.maxs, top);
		top[2] = 0.0;			// crouching height

		//tr = gi.trace(start, self->mins, top, end, self, MASK_PLAYERSOLID);
		trap_Trace(&tr, start, self->r.mins, self->r.maxs, top, self->s.number, MASK_PLAYERSOLID);

		// crouch
		if(!tr.allsolid)
		{
			if(ACEMV_CanMove(self, MOVE_FORWARD))
				self->client->pers.cmd.forwardmove = 127;
			self->client->pers.cmd.upmove = -127;
			return qtrue;
		}

		// check for jump
		start[2] += 32;
		end[2] += 32;

		//tr = gi.trace(start, self->mins, self->maxs, end, self, MASK_MONSTERSOLID);
		trap_Trace(&tr, start, self->r.mins, self->r.maxs, end, self->s.number, MASK_PLAYERSOLID);

		if(!tr.allsolid)
		{
			if(ACEMV_CanMove(self, MOVE_FORWARD))
				self->client->pers.cmd.forwardmove = 127;
			self->client->pers.cmd.upmove = 127;
			return qtrue;
		}
	}

	return qfalse;				// We did not resolve a move here
}
Exemplo n.º 5
0
// Attack movement routine
//
// NOTE: Very simple for now, just a basic move about avoidance.
//       Change this routine for more advanced attack movement.
void ACEMV_Attack(gentity_t * self)
{
	float           c;
	vec3_t          target, forward, right, up;
	float           distance;
	vec3_t          oldAimVec;
	float           aimTremble[2] = { 0.11f, 0.11f };
	//float           slowness = 0.35;	//lower is slower

	// randomly choose a movement direction
	c = random();

	//if(self->s.groundEntityNum != ENTITYNUM_NONE)
	{
		if(c < 0.2 && ACEMV_CanMove(self, MOVE_LEFT))
			self->client->pers.cmd.rightmove -= 127;
		else if(c < 0.4 && ACEMV_CanMove(self, MOVE_RIGHT))
			self->client->pers.cmd.rightmove += 127;

		if(c < 0.6 && ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove += 127;
		else if(c < 0.8 && ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove -= 127;

		if(c < 0.95)
			self->client->pers.cmd.upmove -= 90;
		else
			self->client->pers.cmd.upmove += 90;
	}

	// aim
	if(self->enemy->client)
		VectorCopy(self->enemy->client->ps.origin, target);
	else
		VectorCopy(self->enemy->s.origin, target);

	// modify attack angles based on accuracy (mess this up to make the bot's aim not so deadly)

	// save the current angles
	VectorCopy(self->bs.moveVector, oldAimVec);
	VectorNormalize(oldAimVec);

	VectorSubtract(target, self->client->ps.origin, forward);
	distance = VectorNormalize(forward);

	PerpendicularVector(up, forward);
	CrossProduct(up, forward, right);

	VectorMA(forward, crandom() * aimTremble[0], up, forward);
	VectorMA(forward, crandom() * aimTremble[1], right, forward);
	VectorNormalize(forward);

	//VectorLerp(oldAimVec, forward, slowness, forward);
	//VectorMA(oldAimVec, slowness, forward, forward);
	//VectorNormalize(forward);

	VectorScale(forward, distance, self->bs.moveVector);
	//ACEMV_ChangeBotAngle(self);
	VectorToAngles(self->bs.moveVector, self->bs.viewAngles);


	// don't attack too much
	if(random() < 0.8 && ACEMV_CheckShot(self, target))
	{
		switch (self->client->pers.cmd.weapon)
		{
			case WP_FLAK_CANNON:
			case WP_ROCKET_LAUNCHER:
				self->client->pers.cmd.buttons = (random() < 0.5) ? BUTTON_ATTACK : BUTTON_ATTACK2;
				break;

			default:
				self->client->pers.cmd.buttons = BUTTON_ATTACK;
				break;
		}
	}

//  if(ace_debug.integer)
//      trap_SendServerCommand(-1, va("print \"%s: attacking %s\n\"", self->client->pers.netname, self->enemy->client->pers.netname));
}
Exemplo n.º 6
0
// Wandering code (based on old ACE movement code)
void ACEMV_Wander(gentity_t * self)
{
	vec3_t          tmp;

	// do not move
	if(self->bs.next_move_time > level.time)
		return;

	// Special check for elevators, stand still until the ride comes to a complete stop.
	/*
	 * FIXME
	 if(self->groundentity != NULL && self->groundentity->use == Use_Plat)
	 if(self->groundentity->moveinfo.state == STATE_UP || self->groundentity->moveinfo.state == STATE_DOWN) // only move when platform not
	 {
	 self->velocity[0] = 0;
	 self->velocity[1] = 0;
	 self->velocity[2] = 0;
	 self->next_move_time = level.time + 500;
	 return;
	 }

	 */

	// touched jumppad last Frame?
	if(self->s.groundEntityNum == ENTITYNUM_NONE)
	{
		if(VectorLength(self->client->ps.velocity) > 120)
		{
			VectorNormalize2(self->client->ps.velocity, tmp);

			if(AngleBetweenVectors(self->bs.moveVector, tmp) >= 120)
			{
				// we might have been knocked back by someone or something ..
				if(!self->bs.moveTarget)
				{
					VectorCopy(tmp, self->bs.moveVector);
					ACEMV_ChangeBotAngle(self);
				}
			}
		}

		//ACEMV_ChangeBotAngle(self);
		//self->client->ps.velocity[0] = self->bs.moveVector[0] * 360;
		//self->client->ps.velocity[1] = self->bs.moveVector[1] * 360;
		//return;
	}

	// is there a target to move to
	if(self->bs.moveTarget)
	{
		ACEMV_MoveToGoal(self);
	}

	// swimming?
	VectorCopy(self->client->ps.origin, tmp);
	tmp[2] += 24;

	if(trap_PointContents(tmp, self->s.number) & MASK_WATER)
	{
		// if drowning and no node, move up
		if(self->client->airOutTime > 0)
		{
			self->client->pers.cmd.upmove = 1;
			self->bs.viewAngles[PITCH] = -45;
		}
		else
			self->client->pers.cmd.upmove = 15;

		self->client->pers.cmd.forwardmove = 100;
	}
	else
	{
		//self->client->airOutTime = 0;    // probably shound not be messing with this, but
	}

	// lava?
	tmp[2] -= 48;
	if(trap_PointContents(tmp, self->s.number) & (CONTENTS_LAVA | CONTENTS_SLIME))
	{
		//  safe_bprintf(PRINT_MEDIUM,"lava jump\n");
		self->bs.viewAngles[YAW] += random() * 360 - 180;
		self->client->pers.cmd.forwardmove = 127;
		self->client->pers.cmd.upmove = 127;
		return;
	}

	// check for special movement if we have a normal move (have to test)
	if(VectorLength(self->client->ps.velocity) < 37)
	{
		//if(random() > 0.1 && ACEMV_SpecialMove(self))
		//  return; //removed this because when wandering, the last thing you want is bots jumping
		//over things and going off ledges.  It's better for them to just bounce around the map.

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

		if(ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove = 127;
		else if(ACEMV_CanMove(self, MOVE_BACK))
			self->client->pers.cmd.forwardmove = -127;

		// if there is ground continue otherwise wait for next move
		if( /*!M_CheckBottom || */ self->s.groundEntityNum != ENTITYNUM_NONE)
		{
			if(ACEMV_CanMove(self, MOVE_FORWARD))
				self->client->pers.cmd.forwardmove = 127;
		}

		return;
	}

	if(ACEMV_CheckEyes(self))
		return;

	if(ACEMV_CanMove(self, MOVE_FORWARD))
		self->client->pers.cmd.forwardmove = 127;
}
Exemplo n.º 7
0
// Main movement code. (following node path)
void ACEMV_Move(gentity_t * self)
{
	int             currentNodeType = -1;
	int             nextNodeType = -1;

	// get current and next node back from nav code.
	if(!ACEND_FollowPath(self))
	{
		self->bs.state = STATE_WANDER;
		self->bs.wander_timeout = level.time + 1000;

		// center view
		//self->bs.viewAngles[PITCH] = 0;   //-self->client->ps.delta_angles[PITCH];
		return;
	}

	currentNodeType = nodes[self->bs.currentNode].type;
	nextNodeType = nodes[self->bs.nextNode].type;

	// move to a selected goal, if any
	if(self->bs.moveTarget)
	{
		ACEMV_MoveToGoal(self);
	}

	// grapple
	/*
	   if(nextNodeType == NODE_GRAPPLE)
	   {
	   ACEMV_ChangeBotAngle(self);
	   ACEIT_ChangeWeapon(self, FindItem("grapple"));
	   self->client->pers.cmd.buttons = BUTTON_ATTACK;
	   return;
	   }
	   // Reset the grapple if hangin on a graple node
	   if(currentNodeType == NODE_GRAPPLE)
	   {
	   CTFPlayerResetGrapple(self);
	   return;
	   }
	 */

#if 0
	// check for platforms
	if(currentNodeType != NODE_PLATFORM && nextNodeType == NODE_PLATFORM)
	{
		// check to see if lift is down?
		for(i = 0; i < num_items; i++)
			if(item_table[i].node == self->bs.nextNode)
				if(item_table[i].ent->moverState != MOVER_POS1)
					return;		// Wait for elevator
	}
#endif

	if(currentNodeType == NODE_PLATFORM && nextNodeType == NODE_PLATFORM)
	{
		// move to the center
		self->bs.moveVector[2] = 0;	// kill z movement

		if(VectorLength(self->bs.moveVector) > 10)
			self->client->pers.cmd.forwardmove = 200;	// walk to center

		ACEMV_ChangeBotAngle(self);

		return;					// No move, riding elevator
	}

	// jumpto nodes
	if(nextNodeType == NODE_JUMP ||
	   (currentNodeType == NODE_JUMP && nextNodeType != NODE_ITEM &&
		nodes[self->bs.nextNode].origin[2] > self->client->ps.origin[2]))
	{
		// set up a jump move
		if(ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove = 127;

		self->client->pers.cmd.upmove = 127;

		ACEMV_ChangeBotAngle(self);

		//VectorCopy(self->bs.moveVector, dist);
		//VectorScale(dist, 127, self->client->ps.velocity);
		return;
	}


	// ladder nodes
	/*
	   if(nextNodeType == NODE_LADDER && nodes[self->nextNode].origin[2] > self->s.origin[2])
	   {
	   // Otherwise move as fast as we can
	   self->client->pers.cmd.forwardmove = 400;
	   self->velocity[2] = 320;

	   ACEMV_ChangeBotAngle(self);

	   return;

	   }
	   // If getting off the ladder
	   if(currentNodeType == NODE_LADDER && nextNodeType != NODE_LADDER && nodes[self->nextNode].origin[2] > self->s.origin[2])
	   {
	   self->client->pers.cmd.forwardmove = 400;
	   self->client->pers.cmd.upmove = 200;
	   self->velocity[2] = 200;
	   ACEMV_ChangeBotAngle(self);
	   return;
	   }
	 */

	// water nodes
	if(currentNodeType == NODE_WATER)
	{
		// we need to be pointed up/down
		ACEMV_ChangeBotAngle(self);

		// ff the next node is not in the water, then move up to get out.
		if(nextNodeType != NODE_WATER && !(trap_PointContents(nodes[self->bs.nextNode].origin, self->s.number) & MASK_WATER))
		{
			// exit water
			self->client->pers.cmd.upmove = 127;
		}

		self->client->pers.cmd.forwardmove = 100;
		return;

	}

	// falling off ledge?
	if(self->s.groundEntityNum == ENTITYNUM_NONE)
	{
		ACEMV_ChangeBotAngle(self);

		//self->client->ps.velocity[0] = self->bs.moveVector[0] * 360;
		//self->client->ps.velocity[1] = self->bs.moveVector[1] * 360;
		return;
	}

	// check to see if stuck, and if so try to free us
	// also handles crouching
	if(VectorLength(self->client->ps.velocity) < 37)
	{
		// keep a random factor just in case....
		if(random() > 0.1 && ACEMV_SpecialMove(self))
			return;

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

		if(ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove = 127;
		else if(ACEMV_CanMove(self, MOVE_BACK))
			self->client->pers.cmd.forwardmove = -127;
		return;
	}

	// otherwise move as fast as we can
	if(ACEMV_CanMove(self, MOVE_FORWARD))
		self->client->pers.cmd.forwardmove = 127;

	ACEMV_ChangeBotAngle(self);
}
Exemplo n.º 8
0
// Checks for obstructions in front of bot
//
// This is a function I created origianlly for ACE that
// tries to help steer the bot around obstructions.
//
// If the move is resolved here, this function returns true.
static qboolean ACEMV_CheckEyes(gentity_t * self)
{
	vec3_t          forward, right;
	vec3_t          leftstart, rightstart, focalpoint;
	vec3_t          upstart, upend;
	vec3_t          dir, offset;

	trace_t         traceRight, traceLeft, traceUp, traceFront;	// for eyesight
	gentity_t      *traceEntity;

	// get current angle and set up "eyes"
	VectorCopy(self->bs.viewAngles, dir);
	AngleVectors(dir, forward, right, NULL);

	// let them move to targets by walls
	if(!self->bs.moveTarget)
		VectorSet(offset, 200, 0, 4);	// focalpoint
	else
		VectorSet(offset, 36, 0, 4);	// focalpoint

	G_ProjectSource(self->client->ps.origin, offset, forward, right, focalpoint);

	// Check from self to focalpoint
	// Ladder code
	VectorSet(offset, 36, 0, 0);	// set as high as possible
	G_ProjectSource(self->client->ps.origin, offset, forward, right, upend);

	trap_Trace(&traceFront, self->client->ps.origin, self->r.mins, self->r.maxs, upend, self->s.number, MASK_PLAYERSOLID);

	/*
	   if(traceFront.contents & CONTENTS_DETAIL)    // using detail brush here cuz sometimes it does not pick up ladders...??
	   {
	   self->client->pers.cmd.upmove = 127;
	   if(ACEMV_CanMove(self, MOVE_FORWARD))
	   self->client->pers.cmd.forwardmove = 127;
	   return qtrue;
	   }
	 */

	// if this check fails we need to continue on with more detailed checks
	if(traceFront.fraction == 1)
	{
		if(ACEMV_CanMove(self, MOVE_FORWARD))
			self->client->pers.cmd.forwardmove = 127;
		return qtrue;
	}

	VectorSet(offset, 0, 18, 4);
	G_ProjectSource(self->client->ps.origin, offset, forward, right, leftstart);

	offset[1] -= 36;			// want to make sure this is correct
	//VectorSet(offset, 0, -18, 4);
	G_ProjectSource(self->client->ps.origin, offset, forward, right, rightstart);

	trap_Trace(&traceRight, rightstart, NULL, NULL, focalpoint, self->s.number, MASK_PLAYERSOLID);
	trap_Trace(&traceLeft, leftstart, NULL, NULL, focalpoint, self->s.number, MASK_PLAYERSOLID);

	// wall checking code, this will degenerate progressivly so the least cost
	// check will be done first.

	// if open space move ok
	if(traceLeft.entityNum != ENTITYNUM_WORLD)
	{
		traceEntity = &g_entities[traceLeft.entityNum];
	}
	else
	{
		traceEntity = NULL;
	}

	if(traceRight.fraction != 1 || traceLeft.fraction != 1)	// || (traceEntity && strcmp(traceEntity->classname, "func_door") != 0))
	{
		// special uppoint logic to check for slopes/stairs/jumping etc.
		VectorSet(offset, 0, 18, 24);
		G_ProjectSource(self->client->ps.origin, offset, forward, right, upstart);

		VectorSet(offset, 0, 0, 200);	// scan for height above head
		G_ProjectSource(self->client->ps.origin, offset, forward, right, upend);
		trap_Trace(&traceUp, upstart, NULL, NULL, upend, self->s.number, MASK_PLAYERSOLID);

		VectorSet(offset, 200, 0, 200 * traceUp.fraction - 5);	// set as high as possible
		G_ProjectSource(self->client->ps.origin, offset, forward, right, upend);
		trap_Trace(&traceUp, upstart, NULL, NULL, upend, self->s.number, MASK_PLAYERSOLID);

		// If the upper trace is not open, we need to turn.
		if(traceUp.fraction != 1)
		{
			if(traceRight.fraction > traceLeft.fraction)
				self->bs.viewAngles[YAW] += (1.0 - traceLeft.fraction) * 45.0;
			else
				self->bs.viewAngles[YAW] += -(1.0 - traceRight.fraction) * 45.0;

			if(ACEMV_CanMove(self, MOVE_FORWARD))
				self->client->pers.cmd.forwardmove = 127;
			return qtrue;
		}
	}

	return qfalse;
}