Пример #1
0
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Refire)
{
	PARAM_ACTION_PROLOGUE;
	PARAM_BOOL_OPT(ignoremissile)	{ ignoremissile = false; }

	if (self->target == NULL || self->target->health <= 0)
	{
		if (self->MissileState && pr_m_refire() < 160)
		{ // Look for a new target most of the time
			if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self))
			{ // Found somebody new and in range, so don't stop shooting
				return 0;
			}
		}
		self->SetState (self->state + 1);
		return 0;
	}
	if (((ignoremissile || self->MissileState == NULL) && !self->CheckMeleeRange ()) ||
		!P_CheckSight (self, self->target) ||
		pr_m_refire() < 4)	// Small chance of stopping even when target not dead
	{
		self->SetState (self->state + 1);
	}
	return 0;
}
Пример #2
0
DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire)
{
	// keep firing unless target got out of sight
	A_FaceTarget (self);

	// [BC] Client chaingunners continue to fire until told by the server to stop.
	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
		( CLIENTDEMO_IsPlaying( )))
	{
		return;
	}

	if (pr_cposrefire() < 40)
		return;

	if (!self->target
		|| P_HitFriend (self)
		|| self->target->health <= 0
		|| !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
	{
		// [BC] If we're the server, tell clients to update this thing's state.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
			SERVERCOMMANDS_SetThingState( self, STATE_SEE );

		self->SetState (self->SeeState);
	}
}
Пример #3
0
//
// A_SpidRefire
//
// Spider Mastermind line-of-sight checking.
//
void A_SpidRefire(actionargs_t *actionargs)
{
   Mobj *actor = actionargs->actor;

   // keep firing unless target got out of sight
   A_FaceTarget(actionargs);
   
   // killough 12/98: Stop firing if a friend has gotten in the way
   if(actor->flags & MF_FRIEND && P_HitFriend(actor))
   {
      P_SetMobjState(actor, actor->info->seestate);
      return;
   }
   
   if(P_Random(pr_spidrefire) < 10)
      return;

   // killough 11/98: prevent refiring on friends continuously
   if(!actor->target || actor->target->health <= 0    ||
      actor->flags & actor->target->flags & MF_FRIEND ||
      !P_CheckSight(actor, actor->target))
   {
      P_SetMobjState(actor, actor->info->seestate);
   }
}
Пример #4
0
DEFINE_ACTION_FUNCTION(AActor, A_TurretLook)
{
	AActor *target;

	if (self->flags5 & MF5_INCONVERSATION)
		return;

	self->threshold = 0;
	target = self->LastHeard;
	if (target != NULL &&
		target->health > 0 &&
		target->flags & MF_SHOOTABLE &&
		(self->flags & MF_FRIENDLY) != (target->flags & MF_FRIENDLY))
	{
		self->target = target;
		if ((self->flags & MF_AMBUSH) && !P_CheckSight (self, target))
		{
			return;
		}
		if (self->SeeSound != 0)
		{
			S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
		}
		self->LastHeard = NULL;
		self->threshold = 10;
		self->SetState (self->SeeState);
	}
}
Пример #5
0
void DBot::Set_enemy ()
{
	AActor *oldenemy;

	if (enemy
		&& enemy->health > 0
		&& P_CheckSight (player->mo, enemy))
	{
		oldenemy = enemy;
	}
	else
	{
		oldenemy = NULL;
	}

	// [RH] Don't even bother looking for a different enemy if this is not deathmatch
	// and we already have an existing enemy.
	if (deathmatch || !enemy)
	{
		allround = !!enemy;
		enemy = Find_enemy();
		if (!enemy)
			enemy = oldenemy; //Try go for last (it will be NULL if there wasn't anyone)
	}
	//Verify that that enemy is really something alive that bot can kill.
	if (enemy && ((enemy->health < 0 || !(enemy->flags&MF_SHOOTABLE)) || player->mo->IsFriend(enemy)))
		enemy = NULL;
}
Пример #6
0
bool InquisitorCheckDistance (AActor *self)
{
	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
	{
		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
	}
	return false;
}
Пример #7
0
bool Sys_1ed64 (AActor *self)
{
	if (P_CheckSight (self, self->target) && self->reactiontime == 0)
	{
		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
	}
	return false;
}
Пример #8
0
static bool CrusaderCheckRange (AActor *self)
{
	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
	{
		return self->AproxDistance (self->target) < 264*FRACUNIT;
	}
	return false;
}
Пример #9
0
angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
{
	fixed_t dist;
	angle_t ang;
	AActor *actor;
	int m;

	bglobal.SetBodyAt (player->mo->X() + FixedMul(player->mo->velx, 5*FRACUNIT),
					   player->mo->Y() + FixedMul(player->mo->vely, 5*FRACUNIT),
					   player->mo->Z() + (player->mo->height / 2), 2);

	actor = bglobal.body2;

	dist = actor->AproxDistance (enemy);
	if (dist < SAFE_SELF_MISDIST)
		return 0;
	//Predict.
	m = (((dist+1)/FRACUNIT) / GetDefaultByName("Rocket")->Speed);

	bglobal.SetBodyAt (enemy->X() + FixedMul(enemy->velx, (m+2*FRACUNIT)),
					   enemy->Y() + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
	
	//try the predicted location
	if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
	{
		FCheckPosition tm;
		if (bglobal.SafeCheckPosition (player->mo, actor->X(), actor->Y(), tm))
		{
			if (bglobal.FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
			{
				ang = actor->AngleTo(bglobal.body1);
				return ang;
			}
		}
	}
	//Try fire straight.
	if (P_CheckSight (actor, enemy, 0))
	{
		if (bglobal.FakeFire (player->mo, enemy, cmd) >= SAFE_SELF_MISDIST)
		{
			ang = player->mo->AngleTo(enemy);
			return ang;
		}
	}
	return 0;
}
Пример #10
0
bool InquisitorCheckDistance (AActor *self)
{
	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
	{
		return self->Distance2D (self->target) < 264.;
	}
	return false;
}
Пример #11
0
angle_t DCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
{
	fixed_t dist;
	angle_t ang;
	AActor *actor;
	int m;

	SetBodyAt (bot->x + FixedMul(bot->momx, 5*FRACUNIT),
			   bot->y + FixedMul(bot->momy, 5*FRACUNIT),
			   bot->z + (bot->height / 2), 2);

	actor = bglobal.body2;

	dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y);
	if (dist < SAFE_SELF_MISDIST)
		return 0;
	//Predict.
	m = (((dist+1)/FRACUNIT) / GetDefault<ARocket>()->Speed);

	SetBodyAt (enemy->x + FixedMul (enemy->momx, (m+2*FRACUNIT)),
			   enemy->y + FixedMul(enemy->momy, (m+2*FRACUNIT)), ONFLOORZ, 1);
	dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y);
	//try the predicted location
	if (P_CheckSight (actor, bglobal.body1, 1)) //See the predicted location, so give a test missile
	{
		if (SafeCheckPosition (bot, actor->x, actor->y))
		{
			if (FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
			{
				ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y);
				return ang;
			}
		}
	}
	//Try fire straight.
	if (P_CheckSight (actor, enemy, 0))
	{
		if (FakeFire (bot, enemy, cmd) >= SAFE_SELF_MISDIST)
		{
			ang = R_PointToAngle2(bot->x, bot->y, enemy->x, enemy->y);
			return ang;
		}
	}
	return 0;
}
Пример #12
0
DEFINE_ACTION_FUNCTION(AActor, A_CrusaderRefire)
{
	if (self->target == NULL ||
		self->target->health <= 0 ||
		!P_CheckSight (self, self->target))
	{
		self->SetState (self->SeeState);
	}
}
Пример #13
0
//doesnt check LOS, checks visibility with a set view angle.
//B_Checksight checks LOS (straight line)
//----------------------------------------------------------------------
//Check if mo1 has free line to mo2
//and if mo2 is within mo1 viewangle (vangle) given with normal degrees.
//if these conditions are true, the function returns true.
//GOOD TO KNOW is that the player's view angle
//in doom is 90 degrees infront.
bool DCajunMaster::Check_LOS (AActor *from, AActor *to, angle_t vangle)
{
	if (!P_CheckSight (from, to, 2))
		return false; // out of sight
	if (vangle == ANGLE_MAX)
		return true;
	if (vangle == 0)
		return false; //Looker seems to be blind.

	return abs (R_PointToAngle2 (from->x, from->y, to->x, to->y) - from->angle) <= vangle/2;
}
Пример #14
0
//doesnt check LOS, checks visibility with a set view angle.
//B_Checksight checks LOS (straight line)
//----------------------------------------------------------------------
//Check if mo1 has free line to mo2
//and if mo2 is within mo1 viewangle (vangle) given with normal degrees.
//if these conditions are true, the function returns true.
//GOOD TO KNOW is that the player's view angle
//in doom is 90 degrees infront.
bool DBot::Check_LOS (AActor *to, angle_t vangle)
{
	if (!P_CheckSight (player->mo, to, SF_SEEPASTBLOCKEVERYTHING))
		return false; // out of sight
	if (vangle == ANGLE_MAX)
		return true;
	if (vangle == 0)
		return false; //Looker seems to be blind.

	return absangle(player->mo->AngleTo(to) - player->mo->angle) <= vangle/2;
}
Пример #15
0
DEFINE_ACTION_FUNCTION(AActor, A_CrusaderRefire)
{
	PARAM_ACTION_PROLOGUE;

	if (self->target == NULL ||
		self->target->health <= 0 ||
		!P_CheckSight (self, self->target))
	{
		self->SetState (self->SeeState);
	}
	return 0;
}
Пример #16
0
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
{		
	ACTION_PARAM_START(7);
	ACTION_PARAM_SOUND(snd,0);
	ACTION_PARAM_INT(dmg,1);
	ACTION_PARAM_INT(blastdmg,2);
	ACTION_PARAM_INT(blastrad,3);
	ACTION_PARAM_FIXED(thrust,4);
	ACTION_PARAM_NAME(dmgtype,5);
	ACTION_PARAM_INT(flags,6);

	AActor *fire, *target;
	angle_t an;
		
	if (NULL == (target = self->target))
		return;
	
	A_FaceTarget (self);

	if (!P_CheckSight (self, target, 0) )
		return;

	S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM);

	int newdam;

	if (flags & VAF_DMGTYPEAPPLYTODIRECT)
		newdam = P_DamageMobj (target, self, self, dmg, dmgtype);

	else
		newdam = P_DamageMobj (target, self, self, dmg, NAME_None);

	P_TraceBleed (newdam > 0 ? newdam : dmg, target);
		
	an = self->angle >> ANGLETOFINESHIFT;
	fire = self->tracer;

	if (fire != NULL)
	{
		// move the fire between the vile and the player
		fire->SetOrigin (target->x - FixedMul (24*FRACUNIT, finecosine[an]),
						 target->y - FixedMul (24*FRACUNIT, finesine[an]),
						 target->z);
		
		P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0);
	}
	if (!(target->flags7 & MF7_DONTTHRUST))
		target->velz = Scale(thrust, 1000, target->Mass);
}
Пример #17
0
void A_Fire(AActor *self, int height)
{
	AActor *dest;
				
	dest = self->tracer;
	if (dest == NULL || self->target == NULL)
		return;
				
	// don't move it if the vile lost sight
	if (!P_CheckSight (self->target, dest, 0) )
		return;

	fixedvec3 newpos = dest->Vec3Angle(24 * FRACUNIT, dest->angle, height);
	self->SetOrigin(newpos, true);
}
Пример #18
0
//
// P_CheckMissileRange
//
boolean P_CheckMissileRange (mobj_t* actor)
{
    fixed_t	dist;
	
    if (! P_CheckSight (actor, actor->target) )
	return false;
	
    if ( actor->flags & MF_JUSTHIT )
    {
	// the target just hit the enemy,
	// so fight back!
	actor->flags &= ~MF_JUSTHIT;
	return true;
    }
	
    if (actor->reactiontime)
	return false;	// do not attack yet
		
    // OPTIMIZE: get this from a global checksight
    dist = P_AproxDistance ( actor->x-actor->target->x,
			     actor->y-actor->target->y) - 64*FRACUNIT;
    
    if (!actor->info->meleestate)
	dist -= 128*FRACUNIT;	// no melee attack, so fire more

    dist >>= 16;

    if (actor->type == MT_VILE)
    {
	if (dist > 14*64)	
	    return false;	// too far away
    }
	

    if (actor->type == MT_UNDEAD)
    {
	if (dist < 196)	
	    return false;	// close for fist attack
	dist >>= 1;
    }
	

    if (actor->type == MT_CYBORG
	|| actor->type == MT_SPIDER
	|| actor->type == MT_SKULL)
    {
	dist >>= 1;
    }
Пример #19
0
DEFINE_ACTION_FUNCTION(AActor, A_CPosRefire)
{
    // keep firing unless target got out of sight
    A_FaceTarget (self);

    if (pr_cposrefire() < 40)
        return;

    if (!self->target
            || P_HitFriend (self)
            || self->target->health <= 0
            || !P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
    {
        self->SetState (self->SeeState);
    }
}
Пример #20
0
DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck)
{
	int i;

	for(i = 0; i < MAXPLAYERS; i++)
	{
		if (playeringame[i])
		{
			AActor *pmo = players[i].mo;
			if (P_CheckSight (self, pmo) && (abs (R_PointToAngle2 (pmo->x,
				pmo->y, self->x, self->y) - pmo->angle) <= ANGLE_45))
			{ // Previous state (pottery bit waiting state)
				self->SetState (self->state - 1);
				return;
			}
		}
	}		
}
Пример #21
0
//
// P_CheckMeleeRange
//
boolean P_CheckMeleeRange (mobj_t*	actor)
{
    mobj_t*	pl;
    fixed_t	dist;
	
    if (!actor->target)
	return false;
		
    pl = actor->target;
    dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);

    if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
	return false;
	
    if (! P_CheckSight (actor, actor->target) )
	return false;
							
    return true;		
}
Пример #22
0
void A_Fire(AActor *self, int height)
{
	AActor *dest;
	angle_t an;
				
	dest = self->tracer;
	if (dest == NULL || self->target == NULL)
		return;
				
	// don't move it if the vile lost sight
	if (!P_CheckSight (self->target, dest, 0) )
		return;

	an = dest->angle >> ANGLETOFINESHIFT;

	self->SetOrigin (dest->x + FixedMul (24*FRACUNIT, finecosine[an]),
					 dest->y + FixedMul (24*FRACUNIT, finesine[an]),
					 dest->z + height);
}
Пример #23
0
DEFINE_ACTION_FUNCTION(AActor, A_SentinelRefire)
{
	PARAM_ACTION_PROLOGUE;

	A_FaceTarget (self);

	if (pr_sentinelrefire() >= 30)
	{
		if (self->target == NULL ||
			self->target->health <= 0 ||
			!P_CheckSight (self, self->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES) ||
			P_HitFriend(self) ||
			(self->MissileState == NULL && !self->CheckMeleeRange()) ||
			pr_sentinelrefire() < 40)
		{
			self->SetState (self->SeeState);
		}
	}
	return 0;
}
Пример #24
0
//
// ACS_funcCheckSight
//
static void ACS_funcCheckSight(ACS_FUNCARG)
{
   int32_t tid1 = args[0];
   int32_t tid2 = args[1];
   Mobj   *mo1  = NULL;
   Mobj   *mo2  = NULL;

   while((mo1 = P_FindMobjFromTID(tid1, mo1, thread->trigger)))
   {
      while((mo2 = P_FindMobjFromTID(tid2, mo2, thread->trigger)))
      {
         if(P_CheckSight(mo1, mo2))
         {
            *retn++ = 1;
            return;
         }
      }
   }

   *retn++ = 0;
}
Пример #25
0
DEFINE_ACTION_FUNCTION(AActor, A_M_Refire)
{
	// [BC] Let the server do this.
	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
		( CLIENTDEMO_IsPlaying( )))
	{
		return;
	}

	if (self->target == NULL || self->target->health <= 0)
	{
		if (self->MissileState && pr_m_refire() < 160)
		{ // Look for a new target most of the time
			if (P_LookForPlayers (self, true) && P_CheckMissileRange (self))
			{ // Found somebody new and in range, so don't stop shooting
				return;
			}
		}

		// [BC] Update the thing's state.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
			SERVERCOMMANDS_SetThingFrame( self, self->state + 1 );

		self->SetState (self->state + 1);
		return;
	}
	if ((self->MissileState == NULL && !self->CheckMeleeRange ()) ||
		!P_CheckSight (self, self->target) ||
		pr_m_refire() < 4)	// Small chance of stopping even when target not dead
	{
		// [BC] Update the thing's state.
		if ( NETWORK_GetState( ) == NETSTATE_SERVER )
			SERVERCOMMANDS_SetThingFrame( self, self->state + 1 );

		self->SetState (self->state + 1);
	}
}
Пример #26
0
bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr)
{
	AActor *ref = COPY_AAPTR(self, ptr);

	// We need these to check out.
	if (!ref || !classname || distance <= 0)
		return false;
	
	int counter = 0;
	bool result = false;
	double closer = distance, farther = 0, current = distance;
	const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER));
	const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST));

	TThinkerIterator<AActor> it;
	AActor *mo, *dist = nullptr;

	// [MC] Process of elimination, I think, will get through this as quickly and 
	// efficiently as possible. 
	while ((mo = it.Next()))
	{
		if (mo == ref) //Don't count self.
			continue;

		// no unmorphed versions of currently morphed players.
		if (mo->flags & MF_UNMORPHED)
			continue;

		// Check inheritance for the classname. Taken partly from CheckClass DECORATE function.
		if (flags & CPXF_ANCESTOR)
		{
			if (!(mo->IsKindOf(classname)))
				continue;
		}
		// Otherwise, just check for the regular class name.
		else if (classname != mo->GetClass())
			continue;

		// [MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use
		// Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly.
		// Ripped from sphere checking in A_RadiusGive (along with a number of things).
		if ((ref->Distance2D(mo) < distance &&
			((flags & CPXF_NOZ) ||
			((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) ||
				(ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance)))))
		{
			if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)))
				continue;

			if (ptrWillChange)
			{
				current = ref->Distance2D(mo);

				if ((flags & CPXF_CLOSEST) && (current < closer))
				{
					dist = mo;
					closer = current; // This actor's closer. Set the new standard.
				}
				else if ((flags & CPXF_FARTHEST) && (current > farther))
				{
					dist = mo;
					farther = current;
				}
				else if (!dist)
					dist = mo; // Just get the first one and call it quits if there's nothing selected.
			}
			if (mo->flags6 & MF6_KILLED)
			{
				if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY)))
					continue;
				counter++;
			}
			else
			{
				if (flags & CPXF_DEADONLY)
					continue;
				counter++;
			}

			// Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal.
			if (counter > count)
			{
				result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true;

				// However, if we have one SET* flag and either the closest or farthest flags, keep the function going.
				if (ptrWillChange && ptrDistPref)
					continue;
				else
					break;
			}
		}
	}

	if (ptrWillChange && dist != 0)
	{
		if (flags & CPXF_SETONPTR)
		{
			if (flags & CPXF_SETTARGET)		ref->target = dist;
			if (flags & CPXF_SETMASTER)		ref->master = dist;
			if (flags & CPXF_SETTRACER)		ref->tracer = dist;
		}
		else
		{
			if (flags & CPXF_SETTARGET)		self->target = dist;
			if (flags & CPXF_SETMASTER)		self->master = dist;
			if (flags & CPXF_SETTRACER)		self->tracer = dist;
		}
	}

	if (counter == count)
		result = true;
	else if (counter < count)
		result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT));

	return result;
}
Пример #27
0
//This function is called every
//tick (for each bot) to set
//the mate (teammate coop mate).
AActor *DBot::Choose_Mate ()
{
	int count;
	fixed_t closest_dist, test;
	AActor *target;
	AActor *observer;

	//is mate alive?
	if (mate)
	{
		if (mate->health <= 0)
			mate = NULL;
		else
			last_mate = mate;
	}
	if (mate) //Still is..
		return mate;

	//Check old_mates status.
	if (last_mate)
		if (last_mate->health <= 0)
			last_mate = NULL;

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

	//Check for player friends
	for (count = 0; count < MAXPLAYERS; count++)
	{
		player_t *client = &players[count];

		if (playeringame[count]
			&& client->mo
			&& player->mo != client->mo
			&& (player->mo->IsTeammate (client->mo) || !deathmatch)
			&& client->mo->health > 0
			&& client->mo != observer
			&& ((player->mo->health/2) <= client->mo->health || !deathmatch)
			&& !bglobal.IsLeader(client)) //taken?
		{
			if (P_CheckSight (player->mo, client->mo, SF_IGNOREVISIBILITY))
			{
				test = client->mo->AproxDistance(player->mo);

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

/*
	//Make a introducing to mate.
	if(target && target!=last_mate)
	{
		if((P_Random()%(200*bglobal.botnum))<3)
		{
			chat = c_teamup;
			if(target->bot)
					strcpy(c_target, botsingame[target->bot_id]);
						else if(target->player)
					strcpy(c_target, player_names[target->play_id]);
		}
	}
*/

	return target;

}
Пример #28
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();
}
Пример #29
0
//This function is called every
//tick (for each bot) to set
//the mate (teammate coop mate).
AActor *DCajunMaster::Choose_Mate (AActor *bot)
{
	int count;
	int count2;
	fixed_t closest_dist, test;
	AActor *target;
	AActor *observer;
	bool p_leader[MAXPLAYERS];

	//is mate alive?
	if (bot->player->mate)
	{
		if (bot->player->mate->health <= 0)
			bot->player->mate = NULL;
		else
			bot->player->last_mate = bot->player->mate;
	}
	if (bot->player->mate) //Still is..
		return bot->player->mate;

	//Check old_mates status.
	if (bot->player->last_mate)
		if (bot->player->last_mate->health <= 0)
			bot->player->last_mate = NULL;

	for (count = 0; count < MAXPLAYERS; count++)
	{
		if (!playeringame[count])
			continue;
		p_leader[count] = false;
		for (count2 = 0; count2 < MAXPLAYERS; count2++)
		{
			if (players[count].isbot
				&& players[count2].mate == players[count].mo)
			{
				p_leader[count] = true;
				break;
			}
		}
	}

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

	//Check for player friends
	for (count = 0; count < MAXPLAYERS; count++)
	{
		player_t *client = &players[count];

		if (playeringame[count]
			&& client->mo
			&& bot != client->mo
			&& (bot->IsTeammate (client->mo) || !deathmatch)
			&& client->mo->health > 0
			&& client->mo != observer
			&& ((bot->health/2) <= client->mo->health || !deathmatch)
			&& !p_leader[count]) //taken?
		{

			if (P_CheckSight (bot, client->mo, 1))
			{
				test = P_AproxDistance (client->mo->x - bot->x,
										client->mo->y - bot->y);

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

/*
	//Make a introducing to mate.
	if(target && target!=bot->player->last_mate)
	{
		if((P_Random()%(200*bglobal.botnum))<3)
		{
			bot->player->chat = c_teamup;
			if(target->bot)
					strcpy(bot->player->c_target, botsingame[target->bot_id]);
						else if(target->player)
					strcpy(bot->player->c_target, player_names[target->play_id]);
		}
	}
*/

	return target;

}
Пример #30
0
dd_bool Mobj_LookForPlayers(mobj_t *mo, dd_bool allAround)
{
    int const playerCount = P_CountPlayersInGame();

    // Nobody to target?
    if(!playerCount) return false;

    int const from = mo->lastLook % MAXPLAYERS;
    int const to   = (from + MAXPLAYERS - 1) % MAXPLAYERS;

    int cand         = from;
    int tries        = 0;
    bool foundTarget = false;
    for(; cand != to; cand = (cand < (MAXPLAYERS - 1)? cand + 1 : 0))
    {
        player_t *player = players + cand;

        // Is player in the game?
        if(!player->plr->inGame) continue;

        mobj_t *plrmo = player->plr->mo;
        if(!plrmo) continue;

        // Do not target camera players.
        if(P_MobjIsCamera(plrmo)) continue;

        // Only look ahead a fixed number of times.
        if(tries++ == 2) break;

        // Do not target dead players.
        if(player->health <= 0) continue;

        // Within sight?
        if(!P_CheckSight(mo, plrmo)) continue;

        if(!allAround)
        {
            angle_t an = M_PointToAngle2(mo->origin, plrmo->origin);
            an -= mo->angle;

            if(an > ANG90 && an < ANG270)
            {
                // If real close, react anyway.
                coord_t dist = M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX],
                                                plrmo->origin[VY] - mo->origin[VY]);
                // Behind us?
                if(dist > MELEERANGE) continue;
            }
        }

#if __JHERETIC__ || __JHEXEN__
        // If player is invisible we may not detect if too far or randomly.
        if(plrmo->flags & MF_SHADOW)
        {
            if((M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX],
                                 plrmo->origin[VY] - mo->origin[VY]) > 2 * MELEERANGE) &&
               M_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) < 5)
            {
                // Too far; can't detect.
                continue;
            }

            // Randomly overlook the player regardless.
            if(P_Random() < 225) continue;
        }
#endif

#if __JHEXEN__
        // Minotaurs do not target their master.
        if(mo->type == MT_MINOTAUR && mo->tracer &&
           mo->tracer->player == player) continue;
#endif

        // Found our quarry.
        mo->target = plrmo;
        foundTarget = true;
    }

    // Start looking from here next time.
    mo->lastLook = cand;
    return foundTarget;
}