void FCajunMaster::TurnToAng (AActor *actor)
{
    int maxturn = MAXTURN;

	if (actor->player->ReadyWeapon != NULL)
	{
		if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
		{
			if (actor->player->t_roam && !actor->player->missile)
			{ //Keep angle that where when shot where decided.
				return;
			}
		}


		if(actor->player->enemy)
			if(!actor->player->dest) //happens when running after item in combat situations, or normal, prevents weak turns
				if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
					if(Check_LOS(actor, actor->player->enemy, SHOOTFOV+5*ANGLE_1))
						maxturn = 3;
	}

	int distance = actor->player->angle - actor->angle;

	if (abs (distance) < OKAYRANGE && !actor->player->enemy)
		return;

	distance /= TURNSENS;
	if (abs (distance) > maxturn)
		distance = distance < 0 ? -maxturn : maxturn;

	actor->angle += distance;
}
Exemple #2
0
//MAKEME: Make this a smart decision
AActor *DCajunMaster::Find_enemy (AActor *bot)
{
	int count;
	fixed_t closest_dist, temp; //To target.
	AActor *target;
	angle_t vangle;
	AActor *observer;

	if (!deathmatch)
	{ // [RH] Take advantage of the Heretic/Hexen code to be a little smarter
		return P_RoughMonsterSearch (bot, 20);
	}

	//Note: It's hard to ambush a bot who is not alone
	if (bot->player->allround || bot->player->mate)
		vangle = ANGLE_MAX;
	else
		vangle = ENEMY_SCAN_FOV;
	bot->player->allround = false;

	target = NULL;
	closest_dist = FIXED_MAX;
	if (bot_observer)
		observer = players[consoleplayer].mo;
	else
		observer = NULL;

	for (count = 0; count < MAXPLAYERS; count++)
	{
		player_t *client = &players[count];
		if (playeringame[count]
			&& !bot->IsTeammate (client->mo)
			&& client->mo != observer
			&& client->mo->health > 0
			&& bot != client->mo)
		{
			if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be f****n wierd screded up. 
			//if(P_CheckSight( bot, players[count].mo))
			{
				temp = P_AproxDistance (client->mo->x - bot->x,
										client->mo->y - bot->y);

				//Too dark?
				if (temp > DARK_DIST &&
					client->mo->Sector->lightlevel < WHATS_DARK &&
					bot->player->Powers & PW_INFRARED)
					continue;

				if (temp < closest_dist)
				{
					closest_dist = temp;
					target = client->mo;
				}
			}
		}
	}

	return target;
}
Exemple #3
0
//how the bot moves.
//MAIN movement function.
void DBot::ThinkForMove (ticcmd_t *cmd)
{
	fixed_t dist;
	bool stuck;
	int r;

	stuck = false;
	dist = dest ? player->mo->AproxDistance(dest) : 0;

	if (missile &&
		((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
	{
		sleft = !sleft;
		missile = NULL; //Probably ended its travel.
	}

	if (player->mo->pitch > 0)
		player->mo->pitch -= 80;
	else if (player->mo->pitch <= -60)
		player->mo->pitch += 80;

	//HOW TO MOVE:
	if (missile && (player->mo->AproxDistance(missile)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
	{
		Pitch (missile);
		angle = player->mo->AngleTo(missile);
		cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
		cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.

		if ((player->mo->AproxDistance(oldx, oldy)<50000)
			&& t_strafe<=0)
		{
			t_strafe = 5;
			sleft = !sleft;
		}

		//If able to see enemy while avoiding missile, still fire at enemy.
		if (enemy && Check_LOS (enemy, SHOOTFOV)) 
			Dofire (cmd); //Order bot to fire current weapon
	}
	else if (enemy && P_CheckSight (player->mo, enemy, 0)) //Fight!
	{
		Pitch (enemy);

		//Check if it's more important to get an item than fight.
		if (dest && (dest->flags&MF_SPECIAL)) //Must be an item, that is close enough.
		{
#define is(x) dest->IsKindOf (PClass::FindClass (#x))
			if (
				(
				 (player->mo->health < skill.isp &&
				  (is (Medikit) ||
				   is (Stimpack) ||
				   is (Soulsphere) ||
				   is (Megasphere) ||
				   is (CrystalVial)
				  )
				 ) || (
				  is (Invulnerability) ||
				  is (Invisibility) ||
				  is (Megasphere)
				 ) || 
				 dist < (GETINCOMBAT/4) ||
				 (player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
				)
				&& (dist < GETINCOMBAT || (player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
				&& Reachable (dest))
#undef is
			{
				goto roam; //Pick it up, no matter the situation. All bonuses are nice close up.
			}
		}

		dest = NULL; //To let bot turn right

		if (player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
			player->mo->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.

		if (!(enemy->flags3 & MF3_ISMONSTER))
			t_fight = AFTERTICS;

		if (t_strafe <= 0 &&
			(player->mo->AproxDistance(oldx, oldy)<50000
			|| ((pr_botmove()%30)==10))
			)
		{
			stuck = true;
			t_strafe = 5;
			sleft = !sleft;
		}

		angle = player->mo->AngleTo(enemy);

		if (player->ReadyWeapon == NULL ||
			player->mo->AproxDistance(enemy) >
			player->ReadyWeapon->MoveCombatDist)
		{
			// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
			cmd->ucmd.forwardmove = (enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN;
		}
		else if (!stuck) //Too close, so move away.
		{
			// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
			cmd->ucmd.forwardmove = (enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN;
		}

		//Strafing.
		if (enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool.
		{
			cmd->ucmd.sidemove = sleft ? -SIDEWALK : SIDEWALK;
		}
		else
		{
			cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
		}
		Dofire (cmd); //Order bot to fire current weapon
	}
	else if (mate && !enemy && (!dest || dest==mate)) //Follow mate move.
	{
		fixed_t matedist;

		Pitch (mate);

		if (!Reachable (mate))
		{
			if (mate == dest && pr_botmove.Random() < 32)
			{ // [RH] If the mate is the dest, pick a new dest sometimes
				dest = NULL;
			}
			goto roam;
		}

		angle = player->mo->AngleTo(mate);

		matedist = player->mo->AproxDistance(mate);
		if (matedist > (FRIEND_DIST*2))
			cmd->ucmd.forwardmove = FORWARDRUN;
		else if (matedist > FRIEND_DIST)
			cmd->ucmd.forwardmove = FORWARDWALK; //Walk, when starting to get close.
		else if (matedist < FRIEND_DIST-(FRIEND_DIST/3)) //Got too close, so move away.
			cmd->ucmd.forwardmove = -FORWARDWALK;
	}
	else //Roam after something.
	{
		first_shot = true;

	/////
	roam:
	/////
		if (enemy && Check_LOS (enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it.
			Dofire (cmd); //Order bot to fire current weapon

		if (dest && !(dest->flags&MF_SPECIAL) && dest->health < 0)
		{ //Roaming after something dead.
			dest = NULL;
		}

		if (dest == NULL)
		{
			if (t_fight && enemy) //Enemy/bot has jumped around corner. So what to do?
			{
				if (enemy->player)
				{
					if (((enemy->player->ReadyWeapon != NULL && enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) ||
						(pr_botmove()%100)>skill.isp) && player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
						dest = enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
					else //hide while t_fight, but keep view at enemy.
						angle = player->mo->AngleTo(enemy);
				} //Just a monster, so kill it.
				else
					dest = enemy;

				//VerifFavoritWeapon(player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh.
			}
			else //Choose a distant target. to get things going.
			{
				r = pr_botmove();
				if (r < 128)
				{
					TThinkerIterator<AInventory> it (STAT_INVENTORY, bglobal.firstthing);
					AInventory *item = it.Next();

					if (item != NULL || (item = it.Next()) != NULL)
					{
						r &= 63;	// Only scan up to 64 entries at a time
						while (r)
						{
							--r;
							item = it.Next();
						}
						if (item == NULL)
						{
							item = it.Next();
						}
						bglobal.firstthing = item;
						dest = item;
					}
				}
				else if (mate && (r < 179 || P_CheckSight(player->mo, mate)))
				{
					dest = mate;
				}
				else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0)
				{
					dest = players[(r&(MAXPLAYERS-1))].mo; 
				}
			}

			if (dest)
			{
				t_roam = MAXROAM;
			}
		}
		if (dest)
		{ //Bot has a target so roam after it.
			Roam (cmd);
		}

	} //End of movement main part.

	if (!t_roam && dest)
	{
		prev = dest;
		dest = NULL;
	}

	if (t_fight<(AFTERTICS/2))
		player->mo->flags |= MF_DROPOFF;

	oldx = player->mo->X();
	oldy = player->mo->Y();
}
Exemple #4
0
//-------------------------------------
//Bot_Dofire()
//-------------------------------------
//The bot will check if it's time to fire
//and do so if that is the case.
void DCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
{
	bool no_fire; //used to prevent bot from pumping rockets into nearby walls.
	int aiming_penalty=0; //For shooting at shading target, if screen is red, MAKEME: When screen red.
	int aiming_value; //The final aiming value.
	fixed_t dist;
	angle_t an;
	int m;
	static bool inc[MAXPLAYERS];
	AActor *enemy = actor->player->enemy;

	if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0)
		return;

	if (actor->player->ReadyWeapon == NULL)
		return;

	if (actor->player->damagecount > actor->player->skill.isp)
	{
		actor->player->first_shot = true;
		return;
	}

	//Reaction skill thing.
	if (actor->player->first_shot &&
		!(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
	{
		actor->player->t_react = (100-actor->player->skill.reaction+1)/((pr_botdofire()%3)+3);
	}
	actor->player->first_shot = false;
	if (actor->player->t_react)
		return;

	//MAKEME: Decrease the rocket suicides even more.

	no_fire = true;
	//actor->player->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
	//Distance to enemy.
	dist = P_AproxDistance ((actor->x + actor->momx) - (enemy->x + enemy->momx),
		(actor->y + actor->momy) - (enemy->y + enemy->momy));

	//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
	if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_MELEE)
	{
		if ((actor->player->ReadyWeapon->ProjectileType != NULL))
		{
			if (actor->player->ReadyWeapon->CheckAmmo (AWeapon::PrimaryFire, false, true))
			{
				// This weapon can fire a projectile and has enough ammo to do so
				goto shootmissile;
			}
			else if (!(actor->player->ReadyWeapon->WeaponFlags & WIF_AMMO_OPTIONAL))
			{
				// Ammo is required, so don't shoot. This is for weapons that shoot
				// missiles that die at close range, such as the powered-up Phoneix Rod.
				return;
			}
		}
		else
		{
			//*4 is for atmosphere,  the chainsaws sounding and all..
			no_fire = (dist > (MELEERANGE*4));
		}
	}
	else if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
	{
		//MAKEME: This should be smarter.
		if ((pr_botdofire()%200)<=actor->player->skill.reaction)
			if(Check_LOS(actor, actor->player->enemy, SHOOTFOV))
				no_fire = false;
	}
	else if (actor->player->ReadyWeapon->ProjectileType != NULL)
	{
		if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
		{
			//Special rules for RL
			an = FireRox (actor, enemy, cmd);
			if(an)
			{
				actor->player->angle = an;
				//have to be somewhat precise. to avoid suicide.
				if (abs (actor->player->angle - actor->angle) < 12*ANGLE_1)
				{
					actor->player->t_rocket = 9;
					no_fire = false;
				}
			}
		}
		// prediction aiming
shootmissile:
		dist = P_AproxDistance (actor->x - enemy->x, actor->y - enemy->y);
		m = dist / GetDefaultByType (actor->player->ReadyWeapon->ProjectileType)->Speed;
		SetBodyAt (enemy->x + enemy->momx*m*2, enemy->y + enemy->momy*m*2, enemy->z, 1);
		actor->player->angle = R_PointToAngle2 (actor->x, actor->y, body1->x, body1->y);
		if (Check_LOS (actor, enemy, SHOOTFOV))
			no_fire = false;
	}
	else
	{
		//Other weapons, mostly instant hit stuff.
		actor->player->angle = R_PointToAngle2 (actor->x, actor->y, enemy->x, enemy->y);
		aiming_penalty = 0;
		if (enemy->flags & MF_SHADOW)
			aiming_penalty += (pr_botdofire()%25)+10;
		if (enemy->Sector->lightlevel<WHATS_DARK/* && !(actor->player->powers & PW_INFRARED)*/)
			aiming_penalty += pr_botdofire()%40;//Dark
		if (actor->player->damagecount)
			aiming_penalty += actor->player->damagecount; //Blood in face makes it hard to aim
		aiming_value = actor->player->skill.aiming - aiming_penalty;
		if (aiming_value <= 0)
			aiming_value = 1;
		m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate
		if (m <= 0)
			m = 1; //Prevents lock.

		if (m)
		{
			if (inc[actor->id])
				actor->player->angle += m;
			else
				actor->player->angle -= m;
		}

		if (abs (actor->player->angle - actor->angle) < 4*ANGLE_1)
		{
			inc[actor->id] = !inc[actor->id];
		}

		if (Check_LOS (actor, enemy, (SHOOTFOV/2)))
			no_fire = false;
	}
	if (!no_fire) //If going to fire weapon
	{
		cmd->ucmd.buttons |= BT_ATTACK;
	}
	//Prevents bot from jerking, when firing automatic things with low skill.
	//actor->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
}