Esempio n. 1
0
/*
AddToFullPack

Return 1 if the entity state has been filled in for the ent and the entity will be propagated to the client, 0 otherwise

state is the server maintained copy of the state info that is transmitted to the client
a MOD could alter values copied into state to send the "host" a different look for a particular entity update, etc.
e and ent are the entity that is being added to the update, if 1 is returned
host is the player's edict of the player whom we are sending the update to
player is 1 if the ent/e is a player and 0 otherwise
pSet is either the PAS or PVS that we previous set up.  We can use it to ask the engine to filter the entity against the PAS or PVS.
we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to.  Caching the value is valid in that case, but still only for the current frame
*/
int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet )
{
	int					i;

	// don't send if flagged for NODRAW and it's not the host getting the message
	if ( ( ent->v.effects == EF_NODRAW ) &&
		 ( ent != host ) )
		return 0;

	// Ignore ents without valid / visible models
	if ( !ent->v.modelindex || !STRING( ent->v.model ) )
		return 0;

	// Don't send spectators to other players
	if ( ( ent->v.flags & FL_SPECTATOR ) && ( ent != host ) )
	{
		return 0;
	}

	// Ignore if not the host and not touching a PVS/PAS leaf
	// If pSet is NULL, then the test will always succeed and the entity will be added to the update
	if ( ent != host )
	{
		if ( !ENGINE_CHECK_VISIBILITY( (const struct edict_s *)ent, pSet ) )
		{
			// env_sky is visible always
			if( !FClassnameIs( ent, "env_sky" ))
			{
				return 0;
			}
		}
	}


	// Don't send entity to local client if the client says it's predicting the entity itself.
	if ( ent->v.flags & FL_SKIPLOCALHOST )
	{
		if ( hostflags & 4 ) return 0; // it's a portal pass
		if ( ( hostflags & 1 ) && ( ent->v.owner == host ) )
			return 0;
	}
	
	if ( host->v.groupinfo )
	{
		UTIL_SetGroupTrace( host->v.groupinfo, GROUP_OP_AND );

		// Should always be set, of course
		if ( ent->v.groupinfo )
		{
			if ( g_groupop == GROUP_OP_AND )
			{
				if ( !(ent->v.groupinfo & host->v.groupinfo ) )
					return 0;
			}
			else if ( g_groupop == GROUP_OP_NAND )
			{
				if ( ent->v.groupinfo & host->v.groupinfo )
					return 0;
			}
		}

		UTIL_UnsetGroupTrace();
	}

	memset( state, 0, sizeof( *state ) );

	// Assign index so we can track this entity from frame to frame and
	//  delta from it.
	state->number	  = e;
	state->entityType = ENTITY_NORMAL;
	
	// Flag custom entities.
	if ( ent->v.flags & FL_CUSTOMENTITY )
	{
		state->entityType = ENTITY_BEAM;
	}

	// 
	// Copy state data
	//

	// Round animtime to nearest millisecond
	state->animtime   = (int)(1000.0 * ent->v.animtime ) / 1000.0;

	memcpy( state->origin, ent->v.origin, 3 * sizeof( float ) );
	memcpy( state->angles, ent->v.angles, 3 * sizeof( float ) );
	memcpy( state->mins, ent->v.mins, 3 * sizeof( float ) );
	memcpy( state->maxs, ent->v.maxs, 3 * sizeof( float ) );

	memcpy( state->startpos, ent->v.startpos, 3 * sizeof( float ) );
	memcpy( state->endpos, ent->v.endpos, 3 * sizeof( float ) );
	memcpy( state->velocity, ent->v.velocity, 3 * sizeof( float ) );

	state->impacttime = ent->v.impacttime;
	state->starttime = ent->v.starttime;

	state->modelindex = ent->v.modelindex;
		
	state->frame      = ent->v.frame;

	state->skin       = ent->v.skin;
	state->effects    = ent->v.effects;

	// This non-player entity is being moved by the game .dll and not the physics simulation system
	//  make sure that we interpolate it's position on the client if it moves
	if ( !player &&
		 ent->v.animtime &&
		 ent->v.velocity[ 0 ] == 0 && 
		 ent->v.velocity[ 1 ] == 0 && 
		 ent->v.velocity[ 2 ] == 0 )
	{
		state->eflags |= EFLAG_SLERP;
	}

	state->scale	  = ent->v.scale;
	state->solid	  = ent->v.solid;
	state->colormap   = ent->v.colormap;

	state->movetype   = ent->v.movetype;
	state->sequence   = ent->v.sequence;
	state->framerate  = ent->v.framerate;
	state->body       = ent->v.body;

	for (i = 0; i < 4; i++)
	{
		state->controller[i] = ent->v.controller[i];
	}

	for (i = 0; i < 2; i++)
	{
		state->blending[i]   = ent->v.blending[i];
	}

	state->rendermode    = ent->v.rendermode;
	state->renderamt     = ent->v.renderamt; 
	state->renderfx      = ent->v.renderfx;
	state->rendercolor.r = ent->v.rendercolor.x;
	state->rendercolor.g = ent->v.rendercolor.y;
	state->rendercolor.b = ent->v.rendercolor.z;

	state->aiment = 0;
	if ( ent->v.aiment )
	{
		state->aiment = ENTINDEX( ent->v.aiment );
	}

	state->owner = 0;
	if ( ent->v.owner )
	{
		int owner = ENTINDEX( ent->v.owner );
		
		// Only care if owned by a player
		if ( owner >= 1 && owner <= gpGlobals->maxClients )
		{
			state->owner = owner;	
		}
	}

	state->onground = 0;
	if ( ent->v.groundentity )
	{
		state->onground = ENTINDEX( ent->v.groundentity );
	}

	// HACK:  Somewhat...
	// Class is overridden for non-players to signify a breakable glass object ( sort of a class? )
	if ( !player )
	{
		state->playerclass  = ent->v.playerclass;
	}

	// Special stuff for players only
	if ( player )
	{
		memcpy( state->basevelocity, ent->v.basevelocity, 3 * sizeof( float ) );

		state->weaponmodel  = MODEL_INDEX( STRING( ent->v.weaponmodel ) );
		state->gaitsequence = ent->v.gaitsequence;
		state->spectator = ent->v.flags & FL_SPECTATOR;
		state->friction     = ent->v.friction;

		state->gravity      = ent->v.gravity;
//		state->team			= ent->v.team;
//		
		state->usehull      = ( ent->v.flags & FL_DUCKING ) ? 1 : 0;
		state->health		= ent->v.health;
	}

	return 1;
}
Esempio n. 2
0
bool Bot::LookupEnemy (void)
{
   // this function tries to find the best suitable enemy for the bot
   m_visibility = 0;

   // SyPB Pro P.1
   if (m_enemy != null && (GetTeam (GetEntity ()) == GetTeam (m_enemy) || Attack_Invisible(m_enemy)))
   {
   	   m_enemy = null;
   	   return false;
   }

   // SyPB Pro P.4
   if (GetEnemyEntity ())
   	   return true;

   // do not search for enemies while we're blinded, or shooting disabled by user
   if (m_blindTime > engine->GetTime () || sypb_noshots.GetBool ())
      return false;

   // do not check for new enemy too fast
   if (!FNullEnt (m_enemy) && m_enemyUpdateTime > engine->GetTime () && !(m_states & STATE_SUSPECTENEMY))
   {
      m_aimFlags |= AIM_ENEMY;
      return true;
   }
   edict_t *player, *newEnemy = null;

   float nearestDistance = m_viewDistance;
   int i, team = GetTeam (GetEntity ());

   // setup potentially visible set for this bot
   Vector potentialVisibility = EyePosition ();

   if (pev->flags & FL_DUCKING)
      potentialVisibility = potentialVisibility + (VEC_HULL_MIN - VEC_DUCK_HULL_MIN);

   uint8_t *pvs = ENGINE_SET_PVS (reinterpret_cast <float *> (&potentialVisibility));

   // clear suspected flag
   if (m_seeEnemyTime + 4.0f < engine->GetTime ())
      m_states &= ~STATE_SUSPECTENEMY;

   if (!FNullEnt (m_enemy))
   {
      player = m_enemy;

      // is player is alive
      if (IsAlive (player) && IsEnemyViewable (player))
         newEnemy = player;
   }

   // the old enemy is no longer visible or
   if (FNullEnt (newEnemy))
   {
      m_enemyUpdateTime = engine->GetTime () + 0.25f;

      // some shield stuff
      Array <edict_t *> enemies;

      // search the world for players...
      for (i = 0; i < engine->GetMaxClients (); i++)
      {
         if (!(g_clients[i].flags & CFLAG_USED) || !(g_clients[i].flags & CFLAG_ALIVE) || (g_clients[i].team == team) || (g_clients[i].ent == GetEntity ()))
            continue;

         player = g_clients[i].ent;

         // let the engine check if this player is potentially visible
         if (!ENGINE_CHECK_VISIBILITY (player, pvs))
            continue;

         // skip glowed players, in free for all mode, we can't hit them
         if (player->v.renderfx == kRenderFxGlowShell && GetGameMod() == 1)
            continue;

         // do some blind by smoke grenade
         if (IsBehindSmokeClouds (player) && m_blindRecognizeTime < engine->GetTime ())
            m_blindRecognizeTime = engine->GetTime () + engine->RandomFloat (2.0, 3.0f);

         if (player->v.button & (IN_ATTACK | IN_ATTACK2))
            m_blindRecognizeTime = engine->GetTime () - 0.1f;

         // see if bot can see the player...
         if (m_blindRecognizeTime < engine->GetTime () && IsEnemyViewable (player))
         {
            float distance = (player->v.origin - pev->origin).GetLength ();

            if (distance < nearestDistance)
            {
               enemies.Push (player);

               if (IsEnemyProtectedByShield (player))
                  continue;

               nearestDistance = distance;
               newEnemy = player;

               // aim VIP first on AS maps...
               if ((g_mapType & MAP_AS) && *(INFOKEY_VALUE (GET_INFOKEYBUFFER (player), "model")) == 'v')
                  break;
            }
         }
      }

      // if we got no enemies with no shield, and got enemies with target them
      if (enemies.GetElementNumber () != 0 && !IsValidPlayer (newEnemy))
         newEnemy = enemies[0];
   }

   if (IsValidPlayer (newEnemy))
   {
      g_botsCanPause = true;
      m_aimFlags |= AIM_ENEMY;

      if (newEnemy == m_enemy)
      {
         // if enemy is still visible and in field of view, keep it keep track of when we last saw an enemy
         m_seeEnemyTime = engine->GetTime ();

         // zero out reaction time
         m_actualReactionTime = 0.0f;
         m_lastEnemy = newEnemy;
         m_lastEnemyOrigin = newEnemy->v.origin;
         
         m_GetNewEnemyTimer =  engine->GetTime () + 0.8;

         return true;
      }
      else
      {
         if (m_seeEnemyTime + 3.0f < engine->GetTime () && (pev->weapons & (1 << WEAPON_C4) || HasHostage () || !FNullEnt (m_targetEntity)))
            RadioMessage (Radio_EnemySpotted);

         m_targetEntity = null; // stop following when we see an enemy...

         if (engine->RandomInt (0, 100) < m_skill)
            m_enemySurpriseTime = engine->GetTime () + (m_actualReactionTime / 3);
         else
            m_enemySurpriseTime = engine->GetTime () + m_actualReactionTime;

         // zero out reaction time
         m_actualReactionTime = 0.0f;
         m_enemy = newEnemy;
         m_lastEnemy = newEnemy;
         m_lastEnemyOrigin = newEnemy->v.origin;
         m_enemyReachableTimer = 0.0f;

         // keep track of when we last saw an enemy
         m_seeEnemyTime = engine->GetTime ();

         // now alarm all teammates who see this bot & don't have an actual enemy of the bots enemy should simulate human players seeing a teammate firing
         for (int j = 0; j < engine->GetMaxClients (); j++)
         {
            if (!(g_clients[j].flags & CFLAG_USED) || !(g_clients[j].flags & CFLAG_ALIVE) || g_clients[j].team != team || g_clients[j].ent == GetEntity ())
               continue;

            Bot *friendBot = g_botManager->GetBot (g_clients[j].ent);

            if (friendBot != null)
            {
               if (friendBot->m_seeEnemyTime + 2.0f < engine->GetTime () || FNullEnt (friendBot->m_lastEnemy))
               {
                  if (IsVisible (pev->origin, ENT (friendBot->pev)))
                  {
                     friendBot->m_lastEnemy = newEnemy;
                     friendBot->m_lastEnemyOrigin = m_lastEnemyOrigin;
                     friendBot->m_seeEnemyTime = engine->GetTime ();
                  }
               }
            }
         }
         m_GetNewEnemyTimer =  engine->GetTime () + 1.6;
         return true;
      }
   }
   else if (!FNullEnt (m_enemy))
   {
      newEnemy = m_enemy;
      m_lastEnemy = newEnemy;
      m_GetNewEnemyTimer =  engine->GetTime () + 0.8;

      if (!IsAlive (newEnemy))
      {
         m_enemy = null;

         // shoot at dying players if no new enemy to give some more human-like illusion
         if (m_seeEnemyTime + 0.1 > engine->GetTime ())
         {
            if (!UsesSniper ())
            {
               m_shootAtDeadTime = engine->GetTime () + 0.2f;
               m_actualReactionTime = 0.0f;
               m_states |= STATE_SUSPECTENEMY;

               return true;
            }
            return false;
         }
         else if (m_shootAtDeadTime > engine->GetTime ())
         {
            m_actualReactionTime = 0.0f;
            m_states |= STATE_SUSPECTENEMY;

            return true;
         }
         return false;
      }

      // if no enemy visible check if last one shoot able through wall
      if (sypb_thruwalls.GetBool () && engine->RandomInt (1, 100) < g_skillTab[m_skill / 20].seenShootThruProb)
      {
         if (IsShootableThruObstacle (newEnemy->v.origin))
         {
            m_seeEnemyTime = engine->GetTime () - 0.2f;

            m_states |= STATE_SUSPECTENEMY;
            m_aimFlags |= AIM_LASTENEMY;

            m_enemy = newEnemy;
            m_lastEnemy = newEnemy;
            m_lastEnemyOrigin = newEnemy->v.origin;

            return true;
         }
      }
   }

   // check if bots should reload...
   if ((m_aimFlags <= AIM_PREDICTENEMY && m_seeEnemyTime + 4.0f < engine->GetTime () &&  !(m_states & (STATE_SEEINGENEMY | STATE_HEARENEMY)) && FNullEnt (m_lastEnemy) && FNullEnt (m_enemy) && GetCurrentTask ()->taskID != TASK_DESTROYBREAKABLE && GetCurrentTask ()->taskID != TASK_PLANTBOMB && GetCurrentTask ()->taskID != TASK_DEFUSEBOMB) || g_roundEnded)
   {
      if (!m_reloadState)
         m_reloadState = RSTATE_PRIMARY;
   }

   // is the bot using a sniper rifle or a zoomable rifle?
   if ((UsesSniper () || UsesZoomableRifle ()) && m_zoomCheckTime + 1.0f < engine->GetTime ())
   {
      if (pev->fov < 90) // let the bot zoom out
         pev->button |= IN_ATTACK2;
      else
         m_zoomCheckTime = 0.0f;
   }
   return false;
}