Пример #1
0
void CHostageImprov::FaceOutwards()
{
	TraceResult result;
	Vector to;
	float farthestRange = 0.0f;
	int farthest = 0;

	static Vector corner[] =
	{
		Vector(-1000, 1000, 0),
		Vector(1000, 1000, 0),
		Vector(-1000, -1000, 0),
		Vector(1000, -1000, 0)
	};

	const int cornerCount = ARRAYSIZE(corner);

	for (int i = 0; i < cornerCount; ++i)
	{
		to = GetCentroid() + corner[i];

		UTIL_TraceLine(GetCentroid(), to, ignore_monsters, ignore_glass, m_hostage->edict(), &result);

		float_precision range = (result.vecEndPos - GetCentroid()).LengthSquared();

		if (range > farthestRange)
		{
			farthestRange = range;
			farthest = i;
		}
	}

	to = GetCentroid() + corner[farthest];
	FaceTo(to);
}
Пример #2
0
/**
 * Return the closest active player on the given team to the given position.
 * If 'distance' is non-NULL, the distance to the closest player is returned in it.
 */
extern CBasePlayer *UTIL_GetClosestPlayer( const Vector &pos, int team, float *distance )
{
	CBasePlayer *closePlayer = NULL;
	float closeDistSq = 999999999999.9f;

	for ( int i = 1; i <= gpGlobals->maxClients; ++i )
	{
		CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) );

		if (!IsEntityValid( player ))
			continue;

		if (!player->IsAlive())
			continue;

		if (player->GetTeamNumber() != team)
			continue;

		Vector playerOrigin = GetCentroid( player );
		float distSq = (playerOrigin - pos).LengthSqr();
		if (distSq < closeDistSq)
		{
			closeDistSq = distSq;
			closePlayer = static_cast<CBasePlayer *>( player );
		}
	}
	
	if (distance)
		*distance = (float)sqrt( closeDistSq );

	return closePlayer;
}
Пример #3
0
void QueryClusterer::MergeClusters() {
  // Merge two clusters that are within the threshold in similarity
  // Iterate from left to right and merge the left one into right one and mark
  // the left one for deletion
  std::vector<Cluster *> to_delete;
  for (auto i = clusters_.begin(); i != clusters_.end(); i++) {
    for (auto j = i; ++j != clusters_.end();) {
      auto left = *i;
      auto right = *j;
      auto r_centroid = right->GetCentroid();
      auto similarity = left->CosineSimilarity(r_centroid);

      if (similarity > threshold_) {
        auto templates = left->GetTemplates();
        for (auto &fingerprint : templates) {
          right->AddTemplate(fingerprint);
          template_cluster_[fingerprint] = right;
        }
        right->UpdateCentroid(features_);
        to_delete.push_back(left);
        break;
      }
    }
  }

  // Delete the clusters that are empty
  for (auto cluster : to_delete) {
    clusters_.erase(cluster);
    delete cluster;
  }

  // Rebuild the KDTree to account for changed clusters
  kd_tree_.Build(clusters_);
}
Пример #4
0
	FollowTargetCollector( CBasePlayer *player )
	{
		m_player = player;

		Vector playerVel = player->GetAbsVelocity();
		m_forward.x = playerVel.x;
		m_forward.y = playerVel.y;
		float speed = m_forward.NormalizeInPlace();

		Vector playerOrigin = GetCentroid( player );

		const float walkSpeed = 100.0f;
		if (speed < walkSpeed)
		{
			m_cutoff.x = playerOrigin.x;
			m_cutoff.y = playerOrigin.y;
			m_forward.x = 0.0f;
			m_forward.y = 0.0f;
		}
		else
		{
			const float k = 1.5f; // 2.0f;
			float trimSpeed = min( speed, 200.0f );
			m_cutoff.x = playerOrigin.x + k * trimSpeed * m_forward.x;
			m_cutoff.y = playerOrigin.y + k * trimSpeed * m_forward.y;
		}

		m_targetAreaCount = 0;
	}
Пример #5
0
void CHostageImprov::UpdateGrenadeReactions()
{
	if (m_coughTimer.IsElapsed())
	{
		if (TheBots->IsInsideSmokeCloud(&GetCentroid()))
		{
			m_coughTimer.Start(RANDOM_FLOAT(1, 3));
			Chatter(HOSTAGE_CHATTER_COUGH);
			Frighten(SCARED);
		}
	}

	if (m_grenadeTimer.IsElapsed())
	{
		CBaseEntity *entity = NULL;
		const float watchGrenadeRadius = 500.0f;

		m_grenadeTimer.Start(RANDOM_FLOAT(0.4f, 0.6f));

		while ((entity = UTIL_FindEntityInSphere(entity, GetCentroid(), watchGrenadeRadius)) != NULL)
		{
			CGrenade *grenade = static_cast<CGrenade *>(entity);

			if (!FClassnameIs(grenade->pev, "grenade") || grenade->m_SGSmoke > 1)
				continue;

			if (IsVisible(grenade->Center()))
			{
				Chatter(HOSTAGE_CHATTER_SAW_HE_GRENADE);

				if (grenade->pev->dmg > 50.0f)
				{
					m_idleState.OnInjury();
					Frighten(TERRIFIED);
				}
				else
					Frighten(SCARED);

				m_grenadeTimer.Start(10);
				break;
			}
		}
	}
}
Пример #6
0
bool CHostageImprov::CanSeeRescueZone() const
{
	if (TheCSBots() == NULL)
		return false;

	const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(&GetCentroid());

	if (zone != NULL)
		return IsVisible(zone->m_center);

	return false;
}
Пример #7
0
/**
 * Return true if moving from "start" to "finish" will cross a player's line of fire.
 * The path from "start" to "finish" is assumed to be a straight line.
 * "start" and "finish" are assumed to be points on the ground.
 */
bool IsCrossingLineOfFire( const Vector &start, const Vector &finish, CBaseEntity *ignore, int ignoreTeam  )
{
	for ( int p=1; p <= gpGlobals->maxClients; ++p )
	{
		CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( p ) );

		if (!IsEntityValid( player ))
			continue;

		if (player == ignore)
			continue;

		if (!player->IsAlive())
			continue;

		if (ignoreTeam && player->GetTeamNumber() == ignoreTeam)
			continue;

		// compute player's unit aiming vector 
		Vector viewForward;
		AngleVectors( player->EyeAngles() + player->GetPunchAngle(), &viewForward );

		const float longRange = 5000.0f;
		Vector playerOrigin = GetCentroid( player );
		Vector playerTarget = playerOrigin + longRange * viewForward;

		Vector result( 0, 0, 0 );
		if (IsIntersecting2D( start, finish, playerOrigin, playerTarget, &result ))
		{
			// simple check to see if intersection lies in the Z range of the path
			float loZ, hiZ;

			if (start.z < finish.z)
			{
				loZ = start.z;
				hiZ = finish.z;
			}
			else
			{
				loZ = finish.z;
				hiZ = start.z;
			}

			if (result.z >= loZ && result.z <= hiZ + HumanHeight)
				return true;
		}
	}

	return false;
}
Пример #8
0
/**
 * Plant the bomb.
 */
void PlantBombState::OnEnter( CCFBot *me )
{
	me->Crouch();
	me->SetDisposition( CCFBot::SELF_DEFENSE );

	// look at the floor
//	Vector down( myOrigin.x, myOrigin.y, -1000.0f );

	float yaw = me->EyeAngles().y;
	Vector2D dir( BotCOS(yaw), BotSIN(yaw) );
	Vector myOrigin = GetCentroid( me );

	Vector down( myOrigin.x + 10.0f * dir.x, myOrigin.y + 10.0f * dir.y, me->GetFeetZ() );
	me->SetLookAt( "Plant bomb on floor", down, PRIORITY_HIGH );
}
Пример #9
0
/* Find dimensionless coordinates by numerical methods
	input: pos is position in the element
	output: xipos is dimensionless position
	only used in MPM and only here if non-rectangular elements
*/
void ElementBase::GetXiPos(Vector *pos,Vector *xipos) const
{
    double xt,yt,dxxi,dxeta,dyxi,dyeta;
    double deter,dxi,deta,dist;
    double gfn[MaxElNd],gdfnxi[MaxElNd],gdfnet[MaxElNd];
    int numnds=NumberNodes(),i,j;
	
	// initial guess
	GetCentroid(xipos);
	
	// nodal coordinates
	Vector eNode[MaxElNd];
	for(i=0;i<numnds;i++)
	{	eNode[i].x=nd[nodes[i]]->x;
		eNode[i].y=nd[nodes[i]]->y;
	}
    
    /* solve for xipos using Newton-Rapheson (see FEA Notes)
            using shape functions and their derivatives */
    for(j=1;j<=MAXITER;j++)
    {   ShapeFunction(xipos,TRUE,gfn,gdfnxi,gdfnet,NULL,NULL,NULL,NULL);
        xt=-pos->x;
        yt=-pos->y;
        dxxi=0.;
        dxeta=0.;
        dyxi=0.;
        dyeta=0.;
        for(i=0;i<numnds;i++)
        {   xt+=eNode[i].x*gfn[i];
            yt+=eNode[i].y*gfn[i];
            dxxi+=eNode[i].x*gdfnxi[i];
            dxeta+=eNode[i].x*gdfnet[i];
            dyxi+=eNode[i].y*gdfnxi[i];
            dyeta+=eNode[i].y*gdfnet[i];
        }
        deter=dxxi*dyeta-dxeta*dyxi;
        dxi=(-xt*dyeta+yt*dxeta)/deter;
        deta=(xt*dyxi-yt*dxxi)/deter;
        xipos->x+=dxi;
        xipos->y+=deta;
        dist=sqrt(dxi*dxi+deta*deta);
        if(dist<.001) break;
    }
}
Пример #10
0
bool CHostageImprov::__MAKE_VHOOK(IsPlayerLookingAtMe)(CBasePlayer *other, float cosTolerance) const
{
	Vector2D toOther = (other->pev->origin - GetCentroid()).Make2D();
	toOther.NormalizeInPlace();

	UTIL_MakeVectors(other->pev->punchangle + other->pev->v_angle);

	Vector2D otherDir = gpGlobals->v_forward.Make2D();
	otherDir.NormalizeInPlace();

	if (-cosTolerance > DotProduct(toOther, otherDir))
	{
		if (IsVisible(other->EyePosition()))
		{
			return true;
		}
	}

	return false;
}
Пример #11
0
CBasePlayer *CHostageImprov::GetClosestVisiblePlayer(int team)
{
	CBasePlayer *close = NULL;
	float closeRangeSq = 1e8f;

	for (int i = 0; i < m_visiblePlayerCount; ++i)
	{
		CBasePlayer *player = (CBasePlayer *)m_visiblePlayer[i];

		if (player == NULL || (team > 0 && player->m_iTeam != team))
			continue;

		float_precision rangeSq = (GetCentroid() - player->pev->origin).LengthSquared();

		if (rangeSq < closeRangeSq)
		{
			closeRangeSq = rangeSq;
			close = player;
		}
	}

	return close;
}
Пример #12
0
/**
 * Reset internal data to initial state
 */
void CCFBot::ResetValues( void )
{
	m_chatter.Reset();
	m_gameState.Reset();

	m_avoid = NULL;
	m_avoidTimestamp = 0.0f;

	m_hurryTimer.Invalidate();
	m_alertTimer.Invalidate();
	m_sneakTimer.Invalidate();
	m_noiseBendTimer.Invalidate();
	m_bendNoisePositionValid = false;

	m_isStuck = false;
	m_stuckTimestamp = 0.0f;
	m_wiggleTimer.Invalidate();
	m_stuckJumpTimer.Invalidate();

	m_pathLength = 0;
	m_pathIndex = 0;
	m_areaEnteredTimestamp = 0.0f;
	m_currentArea = NULL;
	m_lastKnownArea = NULL;
	m_isStopping = false;

	m_avoidFriendTimer.Invalidate();
	m_isFriendInTheWay = false;
	m_isWaitingBehindFriend = false;
	m_isAvoidingGrenade.Invalidate();

	StopPanicking();

	m_disposition = ENGAGE_AND_INVESTIGATE;

	m_enemy = NULL;

	m_grenadeTossState = NOT_THROWING;
	m_initialEncounterArea = NULL;

	m_wasSafe = true;

	m_nearbyEnemyCount = 0;
	m_enemyPlace = 0;
	m_nearbyFriendCount = 0;
	m_closestVisibleFriend = NULL;
	m_closestVisibleHumanFriend = NULL;
	m_closestVisibleKO = NULL;

	for( int w=0; w<MAX_PLAYERS; ++w )
	{
		m_watchInfo[w].timestamp = 0.0f;
		m_watchInfo[w].isEnemy = false;

		m_playerTravelDistance[ w ] = -1.0f;
	}

	// randomly offset each bot's timer to spread computation out
	m_updateTravelDistanceTimer.Start( RandomFloat( 0.0f, 0.9f ) );
	m_travelDistancePhase = 0;

	m_isEnemyVisible = false;
	m_visibleEnemyParts = VIS_NONE;
	m_lastSawEnemyTimestamp = -999.9f;
	m_firstSawEnemyTimestamp = 0.0f;
	m_currentEnemyAcquireTimestamp = 0.0f;
	m_isLastEnemyDead = true;
	m_attacker = NULL;
	m_attackedTimestamp = 0.0f;
	m_enemyDeathTimestamp = 0.0f;
	m_friendDeathTimestamp = 0.0f;
	m_lastVictimID = 0;
	m_isAimingAtEnemy = false;
	m_fireWeaponTimestamp = 0.0f;
	m_equipTimer.Invalidate();
	m_zoomTimer.Invalidate();

	m_isFollowing = false;
	m_leader = NULL;
	m_followTimestamp = 0.0f;
	m_allowAutoFollowTime = 0.0f;

	m_enemyQueueIndex = 0;
	m_enemyQueueCount = 0;
	m_enemyQueueAttendIndex = 0;
	m_bomber = NULL;

	m_isEnemySniperVisible = false;
	m_sawEnemySniperTimer.Invalidate();

	m_lookAroundStateTimestamp = 0.0f;
	m_inhibitLookAroundTimestamp = 0.0f;

	m_lookPitch = 0.0f;
	m_lookPitchVel = 0.0f;
	m_lookYaw = 0.0f;
	m_lookYawVel = 0.0f;

	m_aimOffsetTimestamp = 0.0f;
	m_aimSpreadTimestamp = 0.0f;
	m_lookAtSpotState = NOT_LOOKING_AT_SPOT;

	for( int p=0; p<MAX_PLAYERS; ++p )
	{
		m_partInfo[p].m_validFrame = 0;
	}

	m_spotEncounter = NULL;
	m_spotCheckTimestamp = 0.0f;
	m_peripheralTimestamp = 0.0f;

	m_avgVelIndex = 0;
	m_avgVelCount = 0;

	m_lastOrigin = GetCentroid();

	m_voiceEndTimestamp = 0.0f;

	m_noisePosition = Vector( 0, 0, 0 );
	m_noiseTimestamp = 0.0f;

	m_stateTimestamp = 0.0f;
	m_task = SEEK_AND_DESTROY;
	m_taskEntity = NULL;

	m_approachPointCount = 0;
	m_approachPointViewPosition.x = 99999999999.9f;
	m_approachPointViewPosition.y = 0.0f;
	m_approachPointViewPosition.z = 0.0f;

	m_checkedHidingSpotCount = 0;

	StandUp();
	Run();
	m_mustRunTimer.Invalidate();
	m_waitTimer.Invalidate();
	m_pathLadder = NULL;

	m_repathTimer.Invalidate();

	m_huntState.ClearHuntArea();
	m_hasVisitedEnemySpawn = false;
	m_stillTimer.Invalidate();

	// adjust morale - if we died, our morale decreased, 
	// but if we live, no adjustement (round win/loss also adjusts morale)
	if (m_diedLastRound)
		DecreaseMorale();

	m_diedLastRound = false;


	// IsRogue() randomly changes this
	m_isRogue = false;	

	m_surpriseTimer.Invalidate();

	// even though these are EHANDLEs, they need to be NULL-ed
	m_goalEntity = NULL;
	m_avoid = NULL;
	m_enemy = NULL;

	for ( int i=0; i<MAX_ENEMY_QUEUE; ++i )
	{
		m_enemyQueue[i].player = NULL;
		m_enemyQueue[i].isReloading = false;
		m_enemyQueue[i].isProtectedByShield = false;
	}

	// start in idle state
	m_isOpeningDoor = false;
	StopAttacking();
	Idle();
}
void DataManager::Initialize(itk::SmartPointer<LabelMapType> labelMap, std::shared_ptr<Coordinates> coordinates, std::shared_ptr<Metadata> metadata)
{
  m_orientationData = coordinates;
  auto spacing      = m_orientationData->GetImageSpacing();
  auto imageorigin  = m_orientationData->GetImageOrigin();
  auto imagesize    = m_orientationData->GetImageSize();

  // insert background label info, initially all voxels are background, we'll subtract later
  auto object = std::make_shared<ObjectInformation>();
  object->scalar   = 0;
  object->centroid = Vector3d((imagesize[0] / 2.0) * spacing[0], (imagesize[1] / 2.0) * spacing[1], (imagesize[2] / 2.0) / spacing[2]);
  object->size     = imagesize[0] * imagesize[1] * imagesize[2];
  object->min      = Vector3ui(0, 0, 0);
  object->max      = Vector3ui(imagesize[0], imagesize[1], imagesize[2]);

  ObjectVector.insert(std::pair<unsigned short, std::shared_ptr<ObjectInformation>>(0, object));

  // evaluate shapelabelobjects to get the centroid of the object
  auto evaluator = itk::ShapeLabelMapFilter<LabelMapType>::New();
  evaluator->SetInput(labelMap);
  evaluator->ComputePerimeterOff();
  evaluator->ComputeFeretDiameterOff();
  evaluator->SetInPlace(true);
  evaluator->Update();

  // get voxel count for each label for statistics and "flatten" the labelmap (make all labels consecutive starting from 1)
  auto labelChanger = ChangeType::New();
  labelChanger->SetInput(evaluator->GetOutput());
  labelChanger->SetInPlace(true);

  ImageRegionType region;
  unsigned short i = 1;
  itk::Point<double, 3> centroid;

  for (int i = 0; i < evaluator->GetOutput()->GetNumberOfLabelObjects(); ++i)
  {
    auto labelObject = evaluator->GetOutput()->GetNthLabelObject(i);
    auto scalar = labelObject->GetLabel();
    centroid = labelObject->GetCentroid();
    region = labelObject->GetBoundingBox();
    auto regionOrigin = region.GetIndex();
    auto regionSize = region.GetSize();

    object = std::make_shared<ObjectInformation>();
    object->scalar   = scalar;
    object->centroid = Vector3d(centroid[0] / spacing[0], centroid[1] / spacing[1], centroid[2] / spacing[2]);
    object->size     = labelObject->Size();
    object->min      = Vector3ui(regionOrigin[0], regionOrigin[1], regionOrigin[2]);
    object->max      = Vector3ui(regionSize[0] + regionOrigin[0], regionSize[1] + regionOrigin[1], regionSize[2] + regionOrigin[2]) - Vector3ui(1, 1, 1);

    ObjectVector.insert(std::pair<unsigned short, std::shared_ptr<ObjectInformation>>(i, object));

    // substract the voxels of this object from the background label
    ObjectVector[0]->size -= labelObject->Size();

    // need to mark object label as used to correct errors in the segmha metadata (defined labels but empty objects)
    metadata->markAsUsed(scalar);

    // flatten label
    labelChanger->SetChange(scalar, i);
  }

  // start entering new labels at the end of the scalar range
  m_firstFreeValue = GetScalarForLabel(GetNumberOfLabels() - 1) + 1;

  // apply all the changes made to labels
  labelChanger->Update();

  m_labelMap = LabelMapType::New();
  m_labelMap = labelChanger->GetOutput();
  m_labelMap->Optimize();
  m_labelMap->Update();

  // generate the initial vtkLookupTable
  m_lookupTable = vtkSmartPointer<vtkLookupTable>::New();
  GenerateLookupTable();
  m_lookupTable->Modified();
}
Пример #14
0
/**--------------------------------------------------------------------------<BR>
C2DPolyArc::RotateToRight <BR>
\brief Rotates the polygon to the right around the centroid.
<P>---------------------------------------------------------------------------*/
void C2DPolyArc::RotateToRight(double dAng)
{
	C2DPolyBase::RotateToRight( dAng, GetCentroid());
}
Пример #15
0
int C_CFPlayer::DrawModel( int flags )
{
	// if local player is spectating this player in first person mode, don't draw it
	C_CFPlayer * pPlayer = GetLocalCFPlayer();

	if (m_bIsDecapitated)
		SetBodygroup(1, 1);
	else if ((!input->CAM_IsThirdPerson() && pPlayer == this)
		|| pPlayer->IsFirstPersonSpectating(this))
		SetBodygroup(1, 1);
	else
		SetBodygroup(1, 0);

	if (IsFuse())
	{
		if ((!input->CAM_IsThirdPerson() && pPlayer == this)
			|| pPlayer->IsFirstPersonSpectating(this))
			SetBodygroup(2, 0);
		else
			SetBodygroup(2, 1);
	}

	// Skip C_BasePlayer::DrawModel() because it has a bunch of logic we don't care for.
	int iResult = C_BaseCombatCharacter::DrawModel( flags );

	if (C_CFPlayer::GetLocalCFPlayer() == this || pPlayer->IsObserver() && pPlayer->GetObserverTarget() && ToCFPlayer(pPlayer->GetObserverTarget()) == this)
		DrawTargets();

	// Put submodels back where they are supposed to be so that shadows and such render them properly.
	SetBodygroup(1, m_bIsDecapitated);
	if (IsFuse())
		SetBodygroup(2, 1);

	if (gpGlobals->curtime - m_flShieldTime < 0.5f)
	{
		Vector vecDmgDirection = m_vecShieldDmgOrigin - GetCentroid();
		QAngle angShield;
		VectorAngles(vecDmgDirection, angShield);
		m_pBarrier->SetAbsAngles(angShield);
		m_pBarrier->SetAbsOrigin(GetAbsOrigin());

		float flAlpha = 0;
		if ((gpGlobals->curtime - m_flShieldTime) < 0.2f)
			flAlpha = RemapVal(gpGlobals->curtime - m_flShieldTime, 0.0f, 0.2f, 0, 255);
		else
			flAlpha = RemapVal(gpGlobals->curtime - m_flShieldTime, 0.2f, 0.5f, 255, 0);

		flAlpha *= m_flShieldStrength;

		if (C_CFPlayer::GetLocalCFPlayer() == this)
			flAlpha /= 2;

		if (flAlpha)
		{
			m_pBarrier->SetBodygroup(0, m_bShieldPhysical);
			m_pBarrier->SetRenderColorA(flAlpha);
			m_pBarrier->DrawModel(flags);
		}
	}

	return iResult;
}
Пример #16
0
void CHostageImprov::__MAKE_VHOOK(OnGameEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{
	switch (event)
	{
	case EVENT_BULLET_IMPACT:
	{
		Vector *impactPos = (Vector *)other;
		const float nearRange = 100.0f;

		if ((GetCentroid() - *impactPos).IsLengthLessThan(nearRange))
		{
			Frighten(TERRIFIED);
		}
		break;
	}
	case EVENT_PLAYER_DIED:
	case EVENT_HOSTAGE_KILLED:
		if (IsVisible(entity->pev->origin, true))
		{
			Frighten(TERRIFIED);

			if (!entity->IsPlayer() || entity->IsPlayer() && ((CBasePlayer *)entity)->m_iTeam != TERRORIST)
			{
				DelayedChatter(RANDOM_FLOAT(0.5f, 0.7f), HOSTAGE_CHATTER_SCARED_OF_MURDER, true);
			}
			if (!entity->IsPlayer())
			{
				m_idleState.OnInjury();
			}
		}
		break;
	case EVENT_HOSTAGE_RESCUED:
		if (m_hostage == other)
		{
			if (!entity)
				return;

			Chatter(HOSTAGE_CHATTER_RESCUED, false);
		}
		break;
	case EVENT_TERRORISTS_WIN:
		Frighten(SCARED);
		m_isDelayedChatterPending = false;
		DelayedChatter(RANDOM_FLOAT(1.0f, 4.0f), HOSTAGE_CHATTER_TERRORISTS_WIN);
		return;
	case EVENT_CTS_WIN:
		m_scaredTimer.Invalidate();
		m_isDelayedChatterPending = false;
		DelayedChatter(RANDOM_FLOAT(1.0f, 4.0f), HOSTAGE_CHATTER_CTS_WIN);
		return;
	}

	float range;
	PriorityType priority;
	bool isHostile;

	if (entity != NULL && IsGameEventAudible(event, entity, other, &range, &priority, &isHostile))
	{
		const float fudge = 0.4f;

		if ((m_hostage->pev->origin - entity->pev->origin).IsLengthLessThan(range * fudge))
		{
			m_lastNoiseTimer.Start();

			if (isHostile)
			{
				Frighten(SCARED);

				switch (event)
				{
				case EVENT_WEAPON_FIRED:
				{
					DelayedChatter(RANDOM_FLOAT(0.3f, 1.0f), HOSTAGE_CHATTER_SCARED_OF_GUNFIRE);
					break;
				}
				case EVENT_HE_GRENADE_EXPLODED:
				case EVENT_SMOKE_GRENADE_EXPLODED:
				case EVENT_BREAK_GLASS:
				case EVENT_BREAK_WOOD:
				case EVENT_BREAK_METAL:
				case EVENT_BREAK_FLESH:
				case EVENT_BREAK_CONCRETE:
					DelayedChatter(RANDOM_FLOAT(0.3f, 1.0f), HOSTAGE_CHATTER_LOOK_OUT);
					break;

				default:
					break;
				}
			}
		}
	}

	if (event == EVENT_FLASHBANG_GRENADE_EXPLODED)
	{
		Vector *impactPos = (Vector *)other;
		const float flashRange = 1000.0f;

		if ((GetEyes() - *impactPos).IsLengthLessThan(flashRange) && IsVisible(*impactPos))
		{
			DelayedChatter(RANDOM_FLOAT(0.0f, 1.0f), HOSTAGE_CHATTER_BLINDED, true);
			Frighten(TERRIFIED);
		}
	}
}
Пример #17
0
/**
 * Follow our leader
 * @todo Clean up this nasty mess
 */
void FollowState::OnUpdate( CDABot *me )
{
	// if we lost our leader, give up
	if (m_leader == NULL || !m_leader->IsAlive())
	{
		me->Idle();
		return;
	}

	// look around
	me->UpdateLookAround();

	// if we are moving, we are not idle
	if (me->IsNotMoving() == false)
		m_idleTimer.Start( RandomFloat( 2.0f, 5.0f ) );

	// compute the leader's speed
	Vector leaderVel = m_leader->GetAbsVelocity();
	float leaderSpeed = Vector2D( leaderVel.x, leaderVel.y ).Length();

	// determine our leader's movement state
	ComputeLeaderMotionState( leaderSpeed );

	// track whether we can see the leader
	bool isLeaderVisible;
	Vector leaderOrigin = GetCentroid( m_leader );
	if (me->IsVisible( leaderOrigin ))
	{
		m_lastSawLeaderTime = gpGlobals->curtime;
		isLeaderVisible = true;
	}
	else
	{
		isLeaderVisible = false;
	}


	// determine whether we should sneak or not
	const float farAwayRange = 750.0f;
	Vector myOrigin = GetCentroid( me );
	if ((leaderOrigin - myOrigin).IsLengthGreaterThan( farAwayRange ))
	{
		// far away from leader - run to catch up
		m_isSneaking = false;
	}
	else if (isLeaderVisible)
	{
		// if we see leader walking and we are nearby, walk
		if (m_leaderMotionState == WALKING)
			m_isSneaking = true;

		// if we are sneaking and our leader starts running, stop sneaking
		if (m_isSneaking && m_leaderMotionState == RUNNING)
			m_isSneaking = false;
	}

	// if we haven't seen the leader for a long time, run
	const float longTime = 20.0f;
	if (gpGlobals->curtime - m_lastSawLeaderTime > longTime)
		m_isSneaking = false;

	if (m_isSneaking)
		me->Walk();
	else
		me->Run();


	bool repath = false;

	// if the leader has stopped, hide nearby
	const float nearLeaderRange = 250.0f;
	if (!me->HasPath() && m_leaderMotionState == STOPPED && m_leaderMotionStateTime.GetElapsedTime() > m_waitTime)
	{
		// throttle how often this check occurs
		m_waitTime += RandomFloat( 1.0f, 3.0f );

		// the leader has stopped - if we are close to him, take up a hiding spot
		if ((leaderOrigin - myOrigin).IsLengthLessThan( nearLeaderRange ))
		{
			const float hideRange = 250.0f;
			if (me->TryToHide( NULL, -1.0f, hideRange, false, USE_NEAREST ))
			{
				me->ResetStuckMonitor();
				return;
			}
		}
	}

	// if we have been idle for awhile, move
	if (m_idleTimer.IsElapsed())
	{
		repath = true;

		// always walk when we move such a short distance
		m_isSneaking = true;
	}

	// if our leader has moved, repath (don't repath if leading is stopping)
	if (leaderSpeed > 100.0f && m_leaderMotionState != STOPPED)
	{
		repath = true;
	}

	// move along our path
	if (me->UpdatePathMovement( NO_SPEED_CHANGE ) != CDABot::PROGRESSING)
	{
		me->DestroyPath();
	}

	// recompute our path if necessary	
	if (repath && m_repathInterval.IsElapsed() && !me->IsOnLadder())
	{
		// recompute our path to keep us near our leader
		m_lastLeaderPos = leaderOrigin;

		me->ResetStuckMonitor();

		const float runSpeed = 200.0f;

		const float collectRange = (leaderSpeed > runSpeed) ? 600.0f : 400.0f;		// 400, 200
		FollowTargetCollector collector( m_leader );
		SearchSurroundingAreas( TheNavMesh->GetNearestNavArea( m_lastLeaderPos ), m_lastLeaderPos, collector, collectRange );

		if (cv_bot_debug.GetBool())
		{
			for( int i=0; i<collector.m_targetAreaCount; ++i )
				collector.m_targetArea[i]->Draw( /*255, 0, 0, 2*/ );		
		}

		// move to one of the collected areas
		if (collector.m_targetAreaCount)
		{
			CNavArea *target = NULL;
			Vector targetPos;

			// if we are idle, pick a random area
			if (m_idleTimer.IsElapsed())
			{
				target = collector.m_targetArea[ RandomInt( 0, collector.m_targetAreaCount-1 ) ];				
				targetPos = target->GetCenter();
				me->PrintIfWatched( "%4.1f: Bored. Repathing to a new nearby area\n", gpGlobals->curtime );
			}
			else
			{
				me->PrintIfWatched( "%4.1f: Repathing to stay with leader.\n", gpGlobals->curtime );

				// find closest area to where we are
				CNavArea *area;
				float closeRangeSq = 9999999999.9f;
				Vector close;

				for( int a=0; a<collector.m_targetAreaCount; ++a )
				{
					area = collector.m_targetArea[a];

					area->GetClosestPointOnArea( myOrigin, &close );

					float rangeSq = (myOrigin - close).LengthSqr();
					if (rangeSq < closeRangeSq)
					{
						target = area;
						targetPos = close;
						closeRangeSq = rangeSq;
					}
				}
			}
						
			if (target == NULL || me->ComputePath( target->GetCenter(), FASTEST_ROUTE ) == NULL)
				me->PrintIfWatched( "Pathfind to leader failed.\n" );

			// throttle how often we repath
			m_repathInterval.Start( 0.5f );

			m_idleTimer.Reset();
		}
	}
}