Example #1
0
// Called when enemy seen to adjust safe time for this round
void CCSBot::AdjustSafeTime()
{
	// if we spotted an enemy sooner than we thought possible, adjust our notion of "safe" time
	if (m_safeTime > TheCSBots()->GetElapsedRoundTime())
	{
		// since right now is not safe, adjust safe time to be a few seconds ago
		m_safeTime = TheCSBots()->GetElapsedRoundTime() - 2.0f;
	}
}
Example #2
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;
}
Example #3
0
// Return true if can see the bomb lying on the ground
bool CCSBot::CanSeeLooseBomb() const
{
	if (TheCSBots()->GetScenario() != CCSBotManager::SCENARIO_DEFUSE_BOMB)
		return false;

	CBaseEntity *bomb = TheCSBots()->GetLooseBomb();
	if (bomb)
	{
		if (IsVisible(&bomb->pev->origin, CHECK_FOV))
			return true;
	}

	return false;
}
Example #4
0
// Return true if we noticed the bomb on the ground or on the radar (for T's only)
bool CCSBot::NoticeLooseBomb() const
{
	if (TheCSBots()->GetScenario() != CCSBotManager::SCENARIO_DEFUSE_BOMB)
		return false;

	CBaseEntity *bomb = TheCSBots()->GetLooseBomb();
	if (bomb)
	{
		// T's can always see bomb on their radar
		return true;
	}

	return false;
}
Example #5
0
// Pick a random zone and hide near it
bool CCSBot::GuardRandomZone(float range)
{
	const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone();
	if (zone)
	{
		CNavArea *rescueArea = TheCSBots()->GetRandomAreaInZone(zone);
		if (rescueArea)
		{
			Hide(rescueArea, -1.0f, range);
			return true;
		}
	}

	return false;
}
Example #6
0
// Return true if it is the early, "safe", part of the round
bool CCSBot::IsSafe() const
{
	if (TheCSBots()->GetElapsedRoundTime() < m_safeTime)
		return true;

	return false;
}
Example #7
0
// Return true if it is well past the early, "safe", part of the round
bool CCSBot::IsWellPastSafe() const
{
	if (TheCSBots()->GetElapsedRoundTime() > 1.25f * m_safeTime)
		return true;

	return false;
}
Example #8
0
void CC4::Drop( const Vector &vecVelocity )
{
#if !defined( CLIENT_DLL )

	m_bStartedArming = false; // stop arming sequence

	if ( !CSGameRules()->m_bBombPlanted ) // its not dropped if its planted
	{
		// tell the bots about the dropped bomb
		TheCSBots()->SetLooseBomb( this );

		CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(GetOwnerEntity());
		Assert( pPlayer );
		if ( pPlayer )
		{
			IGameEvent * event = gameeventmanager->CreateEvent("bomb_dropped" );
			if ( event )
			{
				event->SetInt( "userid", pPlayer->GetUserID() );
				event->SetInt( "priority", 6 );
				gameeventmanager->FireEvent( event );
			}
		}
	}
#endif
	BaseClass::Drop( vecVelocity );
}
Example #9
0
// Return true if we are in a hurry
bool CCSBot::IsHurrying() const
{
	if (!m_hurryTimer.IsElapsed())
		return true;

	// if the bomb has been planted, we are in a hurry, CT or T (they could be defusing it!)
	if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB && TheCSBots()->IsBombPlanted())
		return true;

	// if we are a T and hostages are being rescued, we are in a hurry
	if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_RESCUE_HOSTAGES
		&& m_iTeam == TERRORIST
		&& GetGameState()->AreAllHostagesBeingRescued())
		return true;

	return false;
}
Example #10
0
bool CCSBot::IsWellPastSafe() const
{
	CCSBotManager *ctrl = TheCSBots();

	if (ctrl->GetElapsedRoundTime() > 1.25f * m_safeTime)
		return true;

	return false;
}
/**
 * Defuse the bomb
 */
void DefuseBombState::OnUpdate( CCSBot *me )
{
	const Vector *bombPos = me->GetGameState()->GetBombPosition();

	if (bombPos == NULL)
	{
		me->PrintIfWatched( "In Defuse state, but don't know where the bomb is!\n" );
		me->Idle();
		return;
	}

	// look at the bomb
	me->SetLookAt( "Defuse bomb", *bombPos, PRIORITY_HIGH );

	// defuse...
	me->UseEnvironment();

	if (gpGlobals->curtime - me->GetStateTimestamp() > 1.0f)
	{
		// if we missed starting the defuse, give up
		if (TheCSBots()->GetBombDefuser() == NULL)
		{
			me->PrintIfWatched( "Failed to start defuse, giving up\n" );
			me->Idle();
			return;
		}
		else if (TheCSBots()->GetBombDefuser() != me)
		{
			// if someone else got the defuse, give up
			me->PrintIfWatched( "Someone else started defusing, giving up\n" );
			me->Idle();
			return;
		}
	}

	// if bomb has been defused, give up
	if (!TheCSBots()->IsBombPlanted())
	{
		me->Idle();
		return;
	}
}
Example #12
0
CBasePlayer *CCSBot::GetImportantEnemy(bool checkVisibility) const
{
	CCSBotManager *ctrl = TheCSBots();
	CBasePlayer *nearEnemy = NULL;
	float nearDist = 999999999.9f;

	for (int i = 1; i <= gpGlobals->maxClients; ++i)
	{
		CBaseEntity *entity = UTIL_PlayerByIndex(i);

		if (entity == NULL)
			continue;

		if (FNullEnt(entity->pev))
			continue;

		if (FStrEq(STRING(entity->pev->netname), ""))
			continue;

		// is it a player?
		if (!entity->IsPlayer())
			continue;

		CBasePlayer *player = static_cast<CBasePlayer *>(entity);

		// is it alive?
		if (!player->IsAlive())
			continue;

		// skip friends
		if (player->m_iTeam == m_iTeam)
			continue;

		// is it "important"
		if (!ctrl->IsImportantPlayer(player))
			continue;

		// is it closest?
		Vector d = pev->origin - player->pev->origin;

		float distSq = d.x * d.x + d.y * d.y + d.z * d.z;
		if (distSq < nearDist)
		{
			if (checkVisibility && !IsVisible(player, CHECK_FOV))
				continue;

			nearEnemy = player;
			nearDist = distSq;
		}
	}

	return nearEnemy;
}
Example #13
0
void HostageEscapeState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
	const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone();

	if (zone != NULL)
	{
		m_toCoverState.SetRescueGoal(zone->m_center);

		m_behavior.Reset(improv);
		m_behavior.SetState(&m_toCoverState);
	}

	m_canEscape = true;
}
Example #14
0
// Return true if can see the planted bomb
bool CCSBot::CanSeePlantedBomb() const
{
	if (TheCSBots()->GetScenario() != CCSBotManager::SCENARIO_DEFUSE_BOMB)
		return false;

	if (!GetGameState()->IsBombPlanted())
		return false;

	const Vector *bombPos = GetGameState()->GetBombPosition();
	if (bombPos && IsVisible(bombPos, CHECK_FOV))
		return true;

	return false;
}
Example #15
0
// Return the closest "important" enemy for the given scenario (bomb carrier, VIP, hostage escorter)
CBasePlayer *CCSBot::GetImportantEnemy(bool checkVisibility) const
{
	CBasePlayer *nearEnemy = nullptr;
	float nearDist = 999999999.9f;

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

		if (!pPlayer)
			continue;

		if (FNullEnt(pPlayer->pev))
			continue;

		if (FStrEq(STRING(pPlayer->pev->netname), ""))
			continue;

		// is it a player?
		if (!pPlayer->IsPlayer())
			continue;

		// is it alive?
		if (!pPlayer->IsAlive())
			continue;

		// skip friends
		if (BotRelationship(pPlayer) == BOT_TEAMMATE)
			continue;

		// is it "important"
		if (!TheCSBots()->IsImportantPlayer(pPlayer))
			continue;

		// is it closest?
		Vector d = pev->origin - pPlayer->pev->origin;

		float distSq = d.x * d.x + d.y * d.y + d.z * d.z;
		if (distSq < nearDist)
		{
			if (checkVisibility && !IsVisible(pPlayer, CHECK_FOV))
				continue;

			nearEnemy = pPlayer;
			nearDist = distSq;
		}
	}

	return nearEnemy;
}
Example #16
0
/* <3fd284> ../cstrike/dlls/bot/cs_gamestate.cpp:225 */
bool CSGameState::IsAtPlantedBombsite(void) const
{
	if (m_bombState != PLANTED)
		return false;

	CCSBotManager *ctrl = TheCSBots();
	const CCSBotManager::Zone *zone = ctrl->GetClosestZone(&m_owner->pev->origin);

	if (zone != NULL)
	{
		return (m_plantedBombsite == zone->m_index);
	}

	return false;
}
Example #17
0
void CCSBot::SpawnBot()
{
	CCSBotManager *ctrl = TheCSBots();

	ctrl->ValidateMapData();
	ResetValues();

	Q_strcpy(m_name, STRING(pev->netname));

	SetState(&m_buyState);
	SetTouch(&CCSBot::BotTouch);

	if (!TheNavAreaList.Count () && !ctrl->IsLearningMap())
	{
		ctrl->SetLearningMapFlag();
		StartLearnProcess();
	}
}
Example #18
0
// Return true if we are acting like a rogue (not listening to teammates, not doing scenario goals)
// TODO: Account for morale
bool CCSBot::IsRogue() const
{
	if (!TheCSBots()->AllowRogues())
		return false;

	// periodically re-evaluate our rogue status
	if (m_rogueTimer.IsElapsed())
	{
		m_rogueTimer.Start(RANDOM_FLOAT(10, 30));

		// our chance of going rogue is inversely proportional to our teamwork attribute
		const float rogueChance = 100.0f * (1.0f - GetProfile()->GetTeamwork());

		m_isRogue = (RANDOM_FLOAT(0, 100) < rogueChance);
	}

	return m_isRogue;
}
Example #19
0
/* <3fd373> ../cstrike/dlls/bot/cs_gamestate.cpp:313 */
void CSGameState::UpdatePlantedBomb(const Vector *pos)
{
	CCSBotManager *ctrl = TheCSBots();
	const CCSBotManager::Zone *zone = ctrl->GetClosestZone(pos);

	if (zone == NULL)
	{
		CONSOLE_ECHO("ERROR: Bomb planted outside of a zone!\n");
		m_plantedBombsite = UNKNOWN;
	}
	else
	{
		m_plantedBombsite = zone->m_index;
	}

	m_plantedBombPos = *pos;
	m_isPlantedBombPosKnown = true;
	SetBombState(PLANTED);
}
Example #20
0
// Send a radio message
void CCSBot::SendRadioMessage(GameEventType event)
{
	// make sure this is a radio event
	if (event <= EVENT_START_RADIO_1 || event >= EVENT_END_RADIO)
	{
		return;
	}

	PrintIfWatched("%3.1f: SendRadioMessage( %s )\n", gpGlobals->time, GameEventName[event]);

	// note the time the message was sent
	TheCSBots()->SetRadioMessageTimestamp(event, m_iTeam);

	m_lastRadioSentTimestamp = gpGlobals->time;

	char slot[2];
	slot[1] = '\0';

	if (event > EVENT_START_RADIO_1 && event < EVENT_START_RADIO_2)
	{
		slot[0] = event - EVENT_START_RADIO_1;
		ClientCommand("radio1");
		//Radio1(this, event - EVENT_START_RADIO_3);
	}
	else if (event > EVENT_START_RADIO_2 && event < EVENT_START_RADIO_3)
	{
		slot[0] = event - EVENT_START_RADIO_2;
		ClientCommand("radio2");
		//Radio2(this, event - EVENT_START_RADIO_3);
	}
	else
	{
		slot[0] = event - EVENT_START_RADIO_3;
		ClientCommand("radio3");
		//Radio3(this, event - EVENT_START_RADIO_3);
	}

	ClientCommand("menuselect", slot);
	ClientCommand("menuselect", "10");
}
// Move to the bomb on the floor and pick it up
void FetchBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
	if (me->IsCarryingBomb())
	{
		me->PrintIfWatched( "I picked up the bomb\n" );
		me->Idle();
		return;
	}

	CBaseEntity *bomb = TheCSBots()->GetLooseBomb();
	if (bomb != NULL)
	{
		if (!me->HasPath())
		{
			// build a path to the bomb
			if (me->ComputePath(TheNavAreaGrid.GetNavArea(&bomb->pev->origin), &bomb->pev->origin, SAFEST_ROUTE) == false)
			{
				me->PrintIfWatched("Fetch bomb pathfind failed\n");

				// go Hunt instead of Idle to prevent continuous re-pathing to inaccessible bomb
				me->Hunt();
				//return;
			}
		}
	}
	else
	{
		// someone picked up the bomb
		me->PrintIfWatched("Bomb not loose\n");
		me->Idle();
		return;
	}

	// look around
	me->UpdateLookAround();

	if (me->UpdatePathMovement() != CCSBot::PROGRESSING)
		me->Idle();
}
Example #22
0
BOOL CGameRules::CanHavePlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pWeapon)
{
	// only living players can have items
	if (pPlayer->pev->deadflag != DEAD_NO)
	{
		return FALSE;
	}

	CCSBotManager *ctrl = TheCSBots();

	if (pPlayer->IsBot() && ctrl != NULL && !ctrl->IsWeaponUseable(pWeapon))
	{
		return FALSE;
	}

	if (pWeapon->pszAmmo1())
	{
		if (!CanHaveAmmo(pPlayer, pWeapon->pszAmmo1(), pWeapon->iMaxAmmo1()))
		{
			// we can't carry anymore ammo for this gun. We can only
			// have the gun if we aren't already carrying one of this type
			if (pPlayer->HasPlayerItem(pWeapon))
			{
				return FALSE;
			}
		}
	}
	else
	{
		// weapon doesn't use ammo, don't take another if you already have it.
		if (pPlayer->HasPlayerItem(pWeapon))
		{
			return FALSE;
		}
	}

	// note: will fall through to here if GetItemInfo doesn't fill the struct!
	return TRUE;
}
Example #23
0
/* <3fd4f4> ../cstrike/dlls/bot/cs_gamestate.cpp:55 */
void CSGameState::Reset(void)
{
	int i;
	CCSBotManager *ctrl = TheCSBots();

	m_isRoundOver = false;

	// bomb
	m_bombState = MOVING;
	m_lastSawBomber.Invalidate();
	m_lastSawLooseBomb.Invalidate();
	m_bombsiteCount = ctrl->GetZoneCount();

	m_isPlantedBombPosKnown = false;
	m_plantedBombsite = UNKNOWN;

	for (i = 0; i < m_bombsiteCount; ++i)
	{
		m_isBombsiteClear[i] = false;
		m_bombsiteSearchOrder[i] = i;
	}

	// shuffle the bombsite search order
	// allows T's to plant at random site, and TEAM_CT's to search in a random order
	// NOTE: VS6 std::random_shuffle() doesn't work well with an array of two elements (most maps)
	for (i = 0; i < m_bombsiteCount; ++i)
	{
		int swap = m_bombsiteSearchOrder[i];
		int rnd = RANDOM_LONG(i, m_bombsiteCount - 1);

		m_bombsiteSearchOrder[i] = m_bombsiteSearchOrder[rnd];
		m_bombsiteSearchOrder[rnd] = swap;
	}

	m_bombsiteSearchIndex = 0;
	InitializeHostageInfo();
}
Example #24
0
// Return true if we can see the point
bool CCSBot::__MAKE_VHOOK(IsVisible)(const Vector *pos, bool testFOV) const
{
	// we can't see anything if we're blind
	if (IsBlind())
		return false;

	// is it in my general viewcone?
	if (testFOV && !(const_cast<CCSBot *>(this)->FInViewCone(pos)))
		return false;

	// check line of sight against smoke
	if (TheCSBots()->IsLineBlockedBySmoke(&GetEyePosition(), pos))
		return false;

	// check line of sight
	// Must include CONTENTS_MONSTER to pick up all non-brush objects like barrels
	TraceResult result;
	UTIL_TraceLine(GetEyePosition(), *pos, ignore_monsters, ignore_glass, ENT(pev), &result);

	if (result.flFraction != 1.0f)
		return false;

	return true;
}
Example #25
0
void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{
	GetGameState()->OnEvent(event, entity, other);
	GetChatter()->OnEvent(event, entity, other);

	// Morale adjustments happen even for dead players
	switch (event)
	{
	case EVENT_TERRORISTS_WIN:
		if (m_iTeam == CT)
		{
			DecreaseMorale();
		}
		else
		{
			IncreaseMorale();
		}
		break;
	case EVENT_CTS_WIN:
		if (m_iTeam == CT)
		{
			IncreaseMorale();
		}
		else
		{
			DecreaseMorale();
		}
		break;
	}

	if (!IsAlive())
		return;

	CBasePlayer *player = static_cast<CBasePlayer *>(entity);

	// If we just saw a nearby friend die, and we haven't yet acquired an enemy
	// automatically acquire our dead friend's killer
	if (!IsAttacking() && (GetDisposition() == ENGAGE_AND_INVESTIGATE || GetDisposition() == OPPORTUNITY_FIRE))
	{
		if (event == EVENT_PLAYER_DIED)
		{
			if (BotRelationship(player) == BOT_TEAMMATE)
			{
				CBasePlayer *killer = static_cast<CBasePlayer *>(other);

				// check that attacker is an enemy (for friendly fire, etc)
				if (killer != NULL && killer->IsPlayer())
				{
					// check if we saw our friend die - dont check FOV - assume we're aware of our surroundings in combat
					// snipers stay put
					if (!IsSniper() && IsVisible(&player->pev->origin))
					{
						// people are dying - we should hurry
						Hurry(RANDOM_FLOAT(10.0f, 15.0f));

						// if we're hiding with only our knife, be a little more cautious
						const float knifeAmbushChance = 50.0f;
						if (!IsHiding() || !IsUsingKnife() || RANDOM_FLOAT(0, 100) < knifeAmbushChance)
						{
							PrintIfWatched("Attacking our friend's killer!\n");
							Attack(killer);
							return;
						}
					}
				}
			}
		}
	}

	switch (event)
	{
		case EVENT_PLAYER_DIED:
		{
			CBasePlayer *victim = player;
			CBasePlayer *killer = (other != NULL && other->IsPlayer()) ? static_cast<CBasePlayer *>(other) : NULL;

			// if the human player died in the single player game, tell the team
			if (CSGameRules()->IsCareer() && !victim->IsBot() && BotRelationship(victim) == BOT_TEAMMATE)
			{
				GetChatter()->Say("CommanderDown", 20.0f);
			}

			// keep track of the last player we killed
			if (killer == this)
			{
				m_lastVictimID = victim->entindex();
			}

			// react to teammate death
			if (BotRelationship(victim) == BOT_TEAMMATE)
			{
				// chastise friendly fire from humans
				if (killer != NULL && !killer->IsBot() && BotRelationship(killer) == BOT_TEAMMATE && killer != this)
				{
					GetChatter()->KilledFriend();
				}

				if (IsHunting())
				{
					PrintIfWatched("Rethinking hunt due to teammate death\n");
					Idle();
					return;
				}

				if (IsAttacking())
				{
					if (GetTimeSinceLastSawEnemy() > 0.4f)
					{
						PrintIfWatched("Rethinking my attack due to teammate death\n");

						// allow us to sneak past windows, doors, etc
						IgnoreEnemies(1.0f);

						// move to last known position of enemy - this could cause us to flank if 
						// the danger has changed due to our teammate's recent death
						SetTask(MOVE_TO_LAST_KNOWN_ENEMY_POSITION, GetEnemy());
						MoveTo(&GetLastKnownEnemyPosition());
						return;
					}
				}
			}
			// an enemy was killed
			else
			{
				if (killer != NULL && BotRelationship(killer) == BOT_TEAMMATE)
				{
					// only chatter about enemy kills if we see them occur, and they were the last one we see
					if (GetNearbyEnemyCount() <= 1)
					{
						// report if number of enemies left is few and we killed the last one we saw locally
						GetChatter()->EnemiesRemaining();

						if (IsVisible(&victim->pev->origin, CHECK_FOV))
						{						
							// congratulate teammates on their kills
							if (killer != this)
							{
								float delay = RANDOM_FLOAT(2.0f, 3.0f);
								if (killer->IsBot())
								{
									if (RANDOM_FLOAT(0.0f, 100.0f) < 40.0f)
										GetChatter()->Say("NiceShot", 3.0f, delay);
								}
								else
								{
									// humans get the honorific
									if (CSGameRules()->IsCareer())
										GetChatter()->Say("NiceShotCommander", 3.0f, delay);
									else
										GetChatter()->Say("NiceShotSir", 3.0f, delay);
								}
							}
						}
					}
				}
			}
			return;
		}
		case EVENT_TERRORISTS_WIN:
			if (m_iTeam == TERRORIST)
				GetChatter()->CelebrateWin();
			return;
		case EVENT_CTS_WIN:
			if (m_iTeam == CT)
				GetChatter()->CelebrateWin();
			return;
		case EVENT_BOMB_DEFUSED:
			if (m_iTeam == CT && TheCSBots()->GetBombTimeLeft() < 2.0)
				GetChatter()->Say("BarelyDefused");
			return;
		case EVENT_BOMB_PICKED_UP:
		{
			if (m_iTeam == CT && player != NULL)
			{
				// check if we're close enough to hear it
				const float bombPickupHearRangeSq = 1000.0f * 1000.0f;
				if ((pev->origin - player->pev->origin).LengthSquared() < bombPickupHearRangeSq)
				{
					GetChatter()->TheyPickedUpTheBomb();
				}
			}
			return;
		}
		case EVENT_BOMB_BEEP:
		{
			// if we don't know where the bomb is, but heard it beep, we've discovered it
			if (GetGameState()->IsPlantedBombLocationKnown() == false)
			{
				// check if we're close enough to hear it
				const float bombBeepHearRangeSq = 1000.0f * 1000.0f;
				if ((pev->origin - entity->pev->origin).LengthSquared() < bombBeepHearRangeSq)
				{
					// radio the news to our team
					if (m_iTeam == CT && GetGameState()->GetPlantedBombsite() == CSGameState::UNKNOWN)
					{
						const CCSBotManager::Zone *zone = TheCSBots()->GetZone(&entity->pev->origin);
						if (zone != NULL)
							GetChatter()->FoundPlantedBomb(zone->m_index);
					}

					// remember where the bomb is
					GetGameState()->UpdatePlantedBomb(&entity->pev->origin);
				}
			}
			return;
		}
		case EVENT_BOMB_PLANTED:
		{
			// if we're a CT, forget what we're doing and go after the bomb
			if (m_iTeam == CT)
			{
				Idle();
			}

			// if we are following someone, stop following
			if (IsFollowing())
			{
				StopFollowing();
				Idle();
			}

			OnEvent(EVENT_BOMB_BEEP, other);
			return;
		}
		case EVENT_BOMB_DEFUSE_ABORTED:
			PrintIfWatched("BOMB DEFUSE ABORTED\n");
			return;
		case EVENT_WEAPON_FIRED:
		case EVENT_WEAPON_FIRED_ON_EMPTY:
		case EVENT_WEAPON_RELOADED:
		{
			if (m_enemy == entity && IsUsingKnife())
				ForceRun(5.0f);
			break;
		}
		default:
			break;
	}

	// Process radio events from our team
	if (player != NULL && BotRelationship(player) == BOT_TEAMMATE && event > EVENT_START_RADIO_1 && event < EVENT_END_RADIO)
	{
		// TODO: Distinguish between radio commands and responses
		if (event != EVENT_RADIO_AFFIRMATIVE && event != EVENT_RADIO_NEGATIVE && event != EVENT_RADIO_REPORTING_IN)
		{
			m_lastRadioCommand = event;
			m_lastRadioRecievedTimestamp = gpGlobals->time;
			m_radioSubject = player;
			m_radioPosition = player->pev->origin;
		}
	}

	// player_follows needs a player
	if (player == NULL)
		return;

	if (!IsRogue() && event == EVENT_HOSTAGE_CALLED_FOR_HELP && m_iTeam == CT && IsHunting())
	{
		if ((entity->pev->origin - pev->origin).IsLengthGreaterThan(1000.0f))
			return;

		if (IsVisible(&entity->Center()))
		{
			m_task = COLLECT_HOSTAGES;
			m_taskEntity = NULL;

			Run();
			m_goalEntity = entity;

			MoveTo(&entity->pev->origin, m_hostageEscortCount == 0 ? SAFEST_ROUTE : FASTEST_ROUTE);
			PrintIfWatched("I'm fetching a hostage that called out to me\n");

			return;
		}
	}

	// don't pay attention to noise that friends make
	if (!IsEnemy(player))
		return;

	float range;
	PriorityType priority;
	bool isHostile;

	if (IsGameEventAudible(event, entity, other, &range, &priority, &isHostile) == false)
		return;

	if (event == EVENT_HOSTAGE_USED)
	{
		if (m_iTeam == CT)
			return;

		if ((entity->pev->origin - pev->origin).IsLengthGreaterThan(range))
			return;

		GetChatter()->HostagesBeingTaken();

		if (!GetGameState()->GetNearestVisibleFreeHostage() && m_task != GUARD_HOSTAGE_RESCUE_ZONE && GuardRandomZone())
		{
			m_task = GUARD_HOSTAGE_RESCUE_ZONE;
			m_taskEntity = NULL;

			SetDisposition(OPPORTUNITY_FIRE);
			PrintIfWatched("Trying to beat them to an escape zone!\n");
		}
	}

	// check if noise is close enough for us to hear
	const Vector *newNoisePosition = &player->pev->origin;
	float newNoiseDist = (pev->origin - *newNoisePosition).Length();
	if (newNoiseDist < range)
	{
		// we heard the sound
		if ((IsLocalPlayerWatchingMe() && cv_bot_debug.value == 3.0f) || cv_bot_debug.value == 4.0f)
		{
			PrintIfWatched("Heard noise (%s from %s, pri %s, time %3.1f)\n",
				(event == EVENT_WEAPON_FIRED) ? "Weapon fire " : "",
				STRING(player->pev->netname),
				(priority == PRIORITY_HIGH) ? "HIGH" : ((priority == PRIORITY_MEDIUM) ? "MEDIUM" : "LOW"),
				gpGlobals->time);
		}

		if (event == EVENT_PLAYER_FOOTSTEP && IsUsingSniperRifle() && newNoiseDist < 300.0)
			EquipPistol();

		// should we pay attention to it
		// if noise timestamp is zero, there is no prior noise
		if (m_noiseTimestamp > 0.0f)
		{
			// only overwrite recent sound if we are louder (closer), or more important - if old noise was long ago, its faded
			const float shortTermMemoryTime = 3.0f;
			if (gpGlobals->time - m_noiseTimestamp < shortTermMemoryTime)
			{
				// prior noise is more important - ignore new one
				if (priority < m_noisePriority)
					return;

				float oldNoiseDist = (pev->origin - m_noisePosition).Length();
				if (newNoiseDist >= oldNoiseDist)
					return;
			}
		}


		// find the area in which the noise occured
		// TODO: Better handle when noise occurs off the nav mesh
		// TODO: Make sure noise area is not through a wall or ceiling from source of noise
		// TODO: Change GetNavTravelTime to better deal with NULL destination areas
		CNavArea *noiseArea = TheNavAreaGrid.GetNavArea(newNoisePosition);
		if (noiseArea == NULL)
			noiseArea = TheNavAreaGrid.GetNearestNavArea(newNoisePosition);

		if (noiseArea == NULL)
		{
			PrintIfWatched("  *** Noise occurred off the nav mesh - ignoring!\n");
			return;
		}

		m_noiseArea = noiseArea;

		// remember noise priority
		m_noisePriority = priority;

		// randomize noise position in the area a bit - hearing isn't very accurate
		// the closer the noise is, the more accurate our placement
		// TODO: Make sure not to pick a position on the opposite side of ourselves.
		const float maxErrorRadius = 400.0f;
		const float maxHearingRange = 2000.0f;
		float errorRadius = maxErrorRadius * newNoiseDist / maxHearingRange;

		m_noisePosition.x = newNoisePosition->x + RANDOM_FLOAT(-errorRadius, errorRadius);
		m_noisePosition.y = newNoisePosition->y + RANDOM_FLOAT(-errorRadius, errorRadius);

		// make sure noise position remains in the same area
		m_noiseArea->GetClosestPointOnArea(&m_noisePosition, &m_noisePosition);

		m_isNoiseTravelRangeChecked = false;
		// note when we heard the noise
		m_noiseTimestamp = gpGlobals->time;
	}
}
Example #26
0
/**
 * Buy weapons, armor, etc.
 */
void BuyState::OnEnter( CCSBot *me )
{
	m_retries = 0;
	m_prefRetries = 0;
	m_prefIndex = 0;

	const char *cheatWeaponString = bot_loadout.GetString();
	if ( cheatWeaponString && *cheatWeaponString )
	{
		m_doneBuying = false; // we're going to be given weapons - ignore the eco limit
	}
	else
	{
		// check if we are saving money for the next round
		if (me->m_iAccount < cv_bot_eco_limit.GetFloat())
		{
			me->PrintIfWatched( "Saving money for next round.\n" );
			m_doneBuying = true;
		}
		else
		{
			m_doneBuying = false;
		}
	}

	m_isInitialDelay = true;

	// this will force us to stop holding live grenade
	me->EquipBestWeapon( MUST_EQUIP );

	m_buyDefuseKit = false;
	m_buyShield = false;

	if (me->GetTeamNumber() == TEAM_CT)
	{
		if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB)
		{
			// CT's sometimes buy defuse kits in the bomb scenario (except in career mode, where the player should defuse)
			if (CSGameRules()->IsCareer() == false)
			{
				const float buyDefuseKitChance = 100.0f * (me->GetProfile()->GetSkill() + 0.2f);
				if (RandomFloat( 0.0f, 100.0f ) < buyDefuseKitChance)
				{
					m_buyDefuseKit = true;
				}
			}
		}

		// determine if we want a tactical shield
		if (!me->HasPrimaryWeapon() && TheCSBots()->AllowTacticalShield())
		{
			if (me->m_iAccount > 2500)
			{
				if (me->m_iAccount < 4000)
					m_buyShield = (RandomFloat( 0, 100.0f ) < 33.3f) ? true : false;
				else
					m_buyShield = (RandomFloat( 0, 100.0f ) < 10.0f) ? true : false;
			}
		}
	}

	if (TheCSBots()->AllowGrenades())
	{
		m_buyGrenade = (RandomFloat( 0.0f, 100.0f ) < 33.3f) ? true : false;
	}
	else
	{
		m_buyGrenade = false;
	}


	m_buyPistol = false;
	if (TheCSBots()->AllowPistols())
	{
		// check if we have a pistol
		if (me->Weapon_GetSlot( WEAPON_SLOT_PISTOL ))
		{
			// if we have our default pistol, think about buying a different one
			if (HasDefaultPistol( me ))
			{
				// if everything other than pistols is disallowed, buy a pistol
				if (TheCSBots()->AllowShotguns() == false &&
					TheCSBots()->AllowSubMachineGuns() == false &&
					TheCSBots()->AllowRifles() == false &&
					TheCSBots()->AllowMachineGuns() == false &&
					TheCSBots()->AllowTacticalShield() == false &&
					TheCSBots()->AllowSnipers() == false)
				{
					m_buyPistol = (RandomFloat( 0, 100 ) < 75.0f);
				}
				else if (me->m_iAccount < 1000)
				{
					// if we're low on cash, buy a pistol
					m_buyPistol = (RandomFloat( 0, 100 ) < 75.0f);
				}
				else
				{
					m_buyPistol = (RandomFloat( 0, 100 ) < 33.3f);
				}
			}			
		}
		else
		{
			// we dont have a pistol - buy one
			m_buyPistol = true;
		}
	}
}
Example #27
0
//--------------------------------------------------------------------------------------------------------------
void BuyState::OnUpdate( CCSBot *me )
{
	char cmdBuffer[256];

	// wait for a Navigation Mesh
	if (!TheNavMesh->IsLoaded())
		return;

	// apparently we cant buy things in the first few seconds, so wait a bit
	if (m_isInitialDelay)
	{
		const float waitToBuyTime = 0.25f;
		if (gpGlobals->curtime - me->GetStateTimestamp() < waitToBuyTime)
			return;

		m_isInitialDelay = false;
	}

	// if we're done buying and still in the freeze period, wait
	if (m_doneBuying)
	{
		if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod())
		{
			// make sure we're locked and loaded
			me->EquipBestWeapon( MUST_EQUIP );
			me->Reload();
			me->ResetStuckMonitor();
			return;
		}

		me->Idle();
		return;
	}

	// If we're supposed to buy a specific weapon for debugging, do so and then bail
	const char *cheatWeaponString = bot_loadout.GetString();
	if ( cheatWeaponString && *cheatWeaponString )
	{
		CUtlVector<char*, CUtlMemory<char*> > loadout;
		Q_SplitString( cheatWeaponString, " ", loadout );
		for ( int i=0; i<loadout.Count(); ++i )
		{
			const char *item = loadout[i];
			if ( FStrEq( item, "vest" ) )
			{
				me->GiveNamedItem( "item_kevlar" );
			}
			else if ( FStrEq( item, "vesthelm" ) )
			{
				me->GiveNamedItem( "item_assaultsuit" );
			}
			else if ( FStrEq( item, "defuser" ) )
			{
				if ( me->GetTeamNumber() == TEAM_CT )
				{
					me->GiveDefuser();
				}
			}
			else if ( FStrEq( item, "nvgs" ) )
			{
				me->m_bHasNightVision = true;
			}
			else if ( FStrEq( item, "primammo" ) )
			{
				me->AttemptToBuyAmmo( 0 );
			}
			else if ( FStrEq( item, "secammo" ) )
			{
				me->AttemptToBuyAmmo( 1 );
			}
			else
			{
				me->GiveWeapon( item );
			}
		}
		m_doneBuying = true;
		return;
	}


	if (!me->IsInBuyZone())
	{
		m_doneBuying = true;
		CONSOLE_ECHO( "%s bot spawned outside of a buy zone (%d, %d, %d)\n",
						(me->GetTeamNumber() == TEAM_CT) ? "CT" : "Terrorist",
						(int)me->GetAbsOrigin().x,
						(int)me->GetAbsOrigin().y,
						(int)me->GetAbsOrigin().z );
		return;
	}

	// try to buy some weapons
	const float buyInterval = 0.02f;
	if (gpGlobals->curtime - me->GetStateTimestamp() > buyInterval)
	{
		me->m_stateTimestamp = gpGlobals->curtime;

		bool isPreferredAllDisallowed = true;

		// try to buy our preferred weapons first
		if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount() && bot_randombuy.GetBool() == false )
		{
			// need to retry because sometimes first buy fails??
			const int maxPrefRetries = 2;
			if (m_prefRetries >= maxPrefRetries)
			{
				// try to buy next preferred weapon
				++m_prefIndex;
				m_prefRetries = 0;
				return;
			}

			int weaponPreference = me->GetProfile()->GetWeaponPreference( m_prefIndex );

			// don't buy it again if we still have one from last round
			char weaponPreferenceName[32];
			Q_snprintf( weaponPreferenceName, sizeof(weaponPreferenceName), "weapon_%s", me->GetProfile()->GetWeaponPreferenceAsString( m_prefIndex ) );
			if( me->Weapon_OwnsThisType(weaponPreferenceName) )//Prefs and buyalias use the short version, this uses the long
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN)
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			const char *buyAlias = NULL;

			if (weaponPreference == WEAPON_SHIELDGUN)
			{
				if (TheCSBots()->AllowTacticalShield())
					buyAlias = "shield";
			}
			else
			{
				buyAlias = WeaponIDToAlias( weaponPreference );
				WeaponType type = GetWeaponType( buyAlias );
				switch( type )
				{
					case PISTOL:
						if (!TheCSBots()->AllowPistols())
							buyAlias = NULL;
						break;

					case SHOTGUN:
						if (!TheCSBots()->AllowShotguns())
							buyAlias = NULL;
						break;

					case SUB_MACHINE_GUN:
						if (!TheCSBots()->AllowSubMachineGuns())
							buyAlias = NULL;
						break;

					case RIFLE:
						if (!TheCSBots()->AllowRifles())
							buyAlias = NULL;
						break;

					case MACHINE_GUN:
						if (!TheCSBots()->AllowMachineGuns())
							buyAlias = NULL;
						break;

					case SNIPER_RIFLE:
						if (!TheCSBots()->AllowSnipers())
							buyAlias = NULL;
						break;
				}
			}

			if (buyAlias)
			{
				Q_snprintf( cmdBuffer, 256, "buy %s\n", buyAlias );

				CCommand args;
				args.Tokenize( cmdBuffer );
				me->ClientCommand( args );

				me->PrintIfWatched( "Tried to buy preferred weapon %s.\n", buyAlias );
				isPreferredAllDisallowed = false;
			}

			++m_prefRetries;

			// bail out so we dont waste money on other equipment
			// unless everything we prefer has been disallowed, then buy at random
			if (isPreferredAllDisallowed == false)
				return;
		}

		// if we have no preferred primary weapon (or everything we want is disallowed), buy at random
		if (!me->HasPrimaryWeapon() && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference()))
		{
			if (m_buyShield)
			{
				// buy a shield
				CCommand args;
				args.Tokenize( "buy shield" );
				me->ClientCommand( args );

				me->PrintIfWatched( "Tried to buy a shield.\n" );
			}
			else 
			{
				// build list of allowable weapons to buy
				BuyInfo *masterPrimary = (me->GetTeamNumber() == TEAM_TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT;
				BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ];
				int stockPrimaryCount = 0;

				// dont choose sniper rifles as often
				const float sniperRifleChance = 50.0f;
				bool wantSniper = (RandomFloat( 0, 100 ) < sniperRifleChance) ? true : false;

				if ( bot_randombuy.GetBool() )
				{
					wantSniper = true;
				}

				for( int i=0; i<PRIMARY_WEAPON_BUY_COUNT; ++i )
				{
					if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) ||
						(masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) ||
						(masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) ||
						(masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) ||
						(masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns()))
					{
						stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i];
					}
				}
 
				if (stockPrimaryCount)
				{
					// buy primary weapon if we don't have one
					int which;

					// on hard difficulty levels, bots try to buy preferred weapons on the first pass
					if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD && bot_randombuy.GetBool() == false )
					{
						// count up available preferred weapons
						int prefCount = 0;
						for( which=0; which<stockPrimaryCount; ++which )
							if (stockPrimary[which]->preferred)
								++prefCount;

						if (prefCount)
						{
							int whichPref = RandomInt( 0, prefCount-1 );
							for( which=0; which<stockPrimaryCount; ++which )
								if (stockPrimary[which]->preferred && whichPref-- == 0)
									break;
						}
						else
						{
							// no preferred weapons available, just pick randomly
							which = RandomInt( 0, stockPrimaryCount-1 );
						}
					}
					else
					{
						which = RandomInt( 0, stockPrimaryCount-1 );
					}

					Q_snprintf( cmdBuffer, 256, "buy %s\n", stockPrimary[ which ]->buyAlias );

					CCommand args;
					args.Tokenize( cmdBuffer );
					me->ClientCommand( args );

					me->PrintIfWatched( "Tried to buy %s.\n", stockPrimary[ which ]->buyAlias );
				}
			}
		}


		//
		// If we now have a weapon, or have tried for too long, we're done
		//
		if (me->HasPrimaryWeapon() || m_retries++ > 5)
		{
			// primary ammo
			CCommand args;
			if (me->HasPrimaryWeapon())
			{
				args.Tokenize( "buy primammo" );
				me->ClientCommand( args );
			}

			// buy armor last, to make sure we bought a weapon first
			args.Tokenize( "buy vesthelm" );
			me->ClientCommand( args );
			args.Tokenize( "buy vest" );
			me->ClientCommand( args );

			// pistols - if we have no preferred pistol, buy at random
			if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference())
			{
				if (m_buyPistol)
				{
					int which = RandomInt( 0, SECONDARY_WEAPON_BUY_COUNT-1 );
					
					const char *what = NULL;

					if (me->GetTeamNumber() == TEAM_TERRORIST)
						what = secondaryWeaponBuyInfoT[ which ].buyAlias;
					else
						what = secondaryWeaponBuyInfoCT[ which ].buyAlias;

					Q_snprintf( cmdBuffer, 256, "buy %s\n", what );
					args.Tokenize( cmdBuffer );
					me->ClientCommand( args );


					// only buy one pistol
					m_buyPistol = false;
				}

				// make sure we have enough pistol ammo
				args.Tokenize( "buy secammo" );
				me->ClientCommand( args );
			}

			// buy a grenade if we wish, and we don't already have one
			if (m_buyGrenade && !me->HasGrenade())
			{
				if (UTIL_IsTeamAllBots( me->GetTeamNumber() ))
				{
					// only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans)
					float rnd = RandomFloat( 0, 100 );

					if (rnd < 10)
					{
						args.Tokenize( "buy smokegrenade" );
						me->ClientCommand( args );	// smoke grenade
					}
					else if (rnd < 35)
					{
						args.Tokenize( "buy flashbang" );
						me->ClientCommand( args );	// flashbang
					}
					else
					{
						args.Tokenize( "buy hegrenade" );
						me->ClientCommand( args );	// he grenade
					}
				}
				else
				{
					if (RandomFloat( 0, 100 ) < 10)
					{
						args.Tokenize( "buy smokegrenade" );	// smoke grenade
						me->ClientCommand( args );
					}
					else
					{
						args.Tokenize( "buy hegrenade" );	// he grenade
						me->ClientCommand( args );
					}
				}
			}

			if (m_buyDefuseKit)
			{
				args.Tokenize( "buy defuser" );
				me->ClientCommand( args );
			}

			m_doneBuying = true;
		}
	}
}
Example #28
0
/* <43c197> ../cstrike/dlls/hostage/states/hostage_idle.cpp:23 */
void HostageIdleState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
	if (!UTIL_ActivePlayersInGame())
		return;

	if (m_mustFlee || (improv->IsScared() && !improv->IsTerroristNearby() && m_moveState != Moving))
	{
		if (!m_mustFlee && improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
			m_mustFlee = true;

		if ((improv->GetScareIntensity() == CHostageImprov::TERRIFIED || m_mustFlee) || (m_fleeTimer.IsElapsed() && improv->GetScareIntensity() > CHostageImprov::NERVOUS))
		{
			m_fleeTimer.Start(RANDOM_FLOAT(10, 20));

			const float fleeChance = 33.3f;
			const float terroristRecentTime = 5.0f;

			if (!m_mustFlee && improv->GetTimeSinceLastSawPlayer(TERRORIST) > terroristRecentTime && RANDOM_FLOAT(0, 100) < fleeChance)
				m_mustFlee = true;

			if (m_mustFlee)
			{
				m_mustFlee = false;

				const Vector *spot = FindNearbyRetreatSpot(NULL, &improv->GetFeet(), improv->GetLastKnownArea(), 500.0, TERRORIST, false);

				if (spot != NULL)
				{
					improv->MoveTo(*spot);
					improv->Run();

					m_moveState = Moving;

					if (improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
					{
						improv->Frighten(CHostageImprov::SCARED);
					}

					return;
				}
			}
		}
	}

	if (m_moveState && improv->IsAtMoveGoal())
	{
		m_moveState = NotMoving;

		improv->Stop();
		improv->FaceOutwards();
		
		const float crouchChance = 33.3f;
		if (improv->IsScared() && !improv->IsAtHome() && RANDOM_FLOAT(0, 100) <= crouchChance)
		{
			improv->Crouch();
		}

		return;
	}

	if (m_moveState == Moving)
	{
		improv->Run();
		return;
	}

	if (!improv->IsAtMoveGoal(75.0f))
	{
		improv->Walk();
		m_moveState = Moving;
		return;
	}

	CBasePlayer *rescuer = improv->GetClosestVisiblePlayer(CT);
	CBasePlayer *captor = improv->GetClosestVisiblePlayer(TERRORIST);

	if (rescuer != NULL)
	{
		improv->LookAt(rescuer->EyePosition());
		improv->Stop();

		if (captor != NULL)
		{
			const float attentionRange = 700.0f;
			float rangeT = (improv->GetCentroid() - captor->pev->origin).Length();
			
			if (rangeT < attentionRange)
			{
				const float cosTolerance = 0.95f;
				if (improv->IsAnyPlayerLookingAtMe(TERRORIST, cosTolerance))
				{
					improv->LookAt(captor->EyePosition());
				}
				else
				{
					TraceResult result;
					UTIL_TraceLine(rescuer->pev->origin, captor->pev->origin, ignore_monsters, ignore_glass, captor->edict(), &result);

					if (result.flFraction != 1.0f && m_disagreeTimer.IsElapsed())
					{
						improv->Disagree();
						m_disagreeTimer.Start(RANDOM_FLOAT(2, 4));
					}
				}

				return;
			}
		}
		else if (!TheCSBots()->IsRoundOver() && m_askTimer.IsElapsed())
		{
			const float closeRange = 200.0f;
			if ((rescuer->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange))
			{
				if (improv->IsPlayerLookingAtMe(rescuer, 0.99))
				{
					HostageChatterType say;
					if (improv->IsTerroristNearby())
						say = HOSTAGE_CHATTER_WARN_NEARBY;
					else
						say = HOSTAGE_CHATTER_PLEASE_RESCUE_ME;

					improv->Chatter(say, false);
					m_askTimer.Start(RANDOM_FLOAT(3, 10));
				}
			}
		}

		if (m_waveTimer.IsElapsed())
		{
			CHostage *hostage = improv->GetEntity();

			const float waveRange = 250.0f;
			if ((rescuer->pev->origin - hostage->pev->origin).IsLengthGreaterThan(waveRange))
			{
				improv->Stop();
				improv->Wave();

				improv->LookAt(rescuer->EyePosition());
				improv->Chatter(HOSTAGE_CHATTER_CALL_TO_RESCUER, false);

				m_moveState = NotMoving;
				m_waveTimer.Start(RANDOM_FLOAT(10, 20));
			}
		}
	}
	else if (captor != NULL)
	{
		improv->LookAt(captor->EyePosition());
		improv->Stop();

		const float closeRange = 200.0f;
		if ((captor->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange) && improv->IsPlayerLookingAtMe(captor, 0.99))
		{
			if (!m_intimidatedTimer.HasStarted())
			{
				m_intimidatedTimer.Start();
			}

			if (!improv->IsScared())
			{
				improv->Frighten(CHostageImprov::NERVOUS);
			}

			const float minThreatenTime = 1.0f;
			if ((!m_intimidatedTimer.HasStarted() || m_intimidatedTimer.IsGreaterThen(minThreatenTime)) && m_pleadTimer.IsElapsed())
			{
				improv->Chatter(HOSTAGE_CHATTER_INTIMIDATED, true);
				m_pleadTimer.Start(RANDOM_FLOAT(10, 20));
			}

			if (!improv->IsAtHome())
			{
				improv->Chatter(HOSTAGE_CHATTER_RETREAT, true);
				improv->Retreat();
			}
		}
		else
		{
			m_intimidatedTimer.Invalidate();
		}
	}
	else
	{
		improv->ClearLookAt();

		const float pushbackRange = 60.0f;
		if (pushbackRange - improv->GetAggression() * 5.0f < TheCSBots()->GetElapsedRoundTime() && m_escapeTimer.IsElapsed())
		{
			const float stayHomeDuration = 5.0f;
			m_escapeTimer.Start(stayHomeDuration);

			float sightTimeT = improv->GetTimeSinceLastSawPlayer(TERRORIST);
			float sightTimeCT = improv->GetTimeSinceLastSawPlayer(CT);

			const float waitTime = 15.0f - improv->GetAggression() * 3.0f;

			if (sightTimeT > waitTime && sightTimeCT > waitTime)
			{
				if (improv->IsTerroristNearby())
				{
					if (cv_hostage_debug.value > 0.0f)
					{
						CONSOLE_ECHO("Hostage: I want to escape, but a T is nearby\n");
					}

					m_escapeTimer.Start(waitTime);
				}
				else
				{
					improv->Escape();

					if (cv_hostage_debug.value > 0.0f)
					{
						CONSOLE_ECHO("Hostage: I'm escaping!\n");
					}
				}
			}
		}
	}

}
Example #29
0
// Buy weapons, armor, etc.
void BuyState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{
	m_retries = 0;
	m_prefRetries = 0;
	m_prefIndex = 0;

	m_doneBuying = false;
	m_isInitialDelay = true;

	// this will force us to stop holding live grenade
	me->EquipBestWeapon();

	m_buyDefuseKit = false;
	m_buyShield = false;

	if (me->m_iTeam == CT)
	{
		if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB)
		{
			// CT's sometimes buy defuse kits in the bomb scenario (except in career mode, where the player should defuse)
			if (!CSGameRules()->IsCareer())
			{
				const float buyDefuseKitChance = 50.0f;	// 100.0f * (me->GetProfile()->GetSkill() + 0.2f);
				if (RANDOM_FLOAT(0.0f, 100.0f) < buyDefuseKitChance)
				{
					m_buyDefuseKit = true;
				}
			}
		}

		// determine if we want a tactical shield
		if (!me->m_bHasPrimary && TheCSBots()->AllowTacticalShield())
		{
			if (me->m_iAccount > 2500)
			{
				if (me->m_iAccount < 4000)
					m_buyShield = (RANDOM_FLOAT(0, 100.0f) < 33.3f) ? true : false;
				else
					m_buyShield = (RANDOM_FLOAT(0, 100.0f) < 10.0f) ? true : false;
			}
		}
	}

	if (TheCSBots()->AllowGrenades())
	{
		m_buyGrenade = (RANDOM_FLOAT(0.0f, 100.0f) < 33.3f) ? true : false;
	}
	else
	{
		m_buyGrenade = false;
	}

	m_buyPistol = false;

	if (TheCSBots()->AllowPistols())
	{
		CBasePlayerWeapon *pistol = static_cast<CBasePlayerWeapon *>(me->m_rgpPlayerItems[ PISTOL_SLOT ]);

		// check if we have a pistol
		if (pistol != NULL)
		{
			// if we have our default pistol, think about buying a different one
			if (HasDefaultPistol(me))
			{
				// if everything other than pistols is disallowed, buy a pistol
				if (TheCSBots()->AllowShotguns() == false &&
					TheCSBots()->AllowSubMachineGuns() == false &&
					TheCSBots()->AllowRifles() == false &&
					TheCSBots()->AllowMachineGuns() == false &&
					TheCSBots()->AllowTacticalShield() == false &&
					TheCSBots()->AllowSnipers() == false)
				{
					m_buyPistol = (RANDOM_FLOAT(0, 100) < 75.0f);
				}
				else if (me->m_iAccount < 1000)
				{
					// if we're low on cash, buy a pistol
					m_buyPistol = (RANDOM_FLOAT(0, 100) < 75.0f);
				}
				else
				{
					m_buyPistol = (RANDOM_FLOAT(0, 100) < 33.3f);
				}
			}
		}
		else
		{
			// we dont have a pistol - buy one
			m_buyPistol = true;
		}
	}
}
Example #30
0
void BuyState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
	// wait for a Navigation Mesh
	if (!TheNavAreaList.size())
		return;

	// apparently we cant buy things in the first few seconds, so wait a bit
	if (m_isInitialDelay)
	{
		const float waitToBuyTime = 2.0f; // 0.25f;
		if (gpGlobals->time - me->GetStateTimestamp() < waitToBuyTime)
			return;

		m_isInitialDelay = false;
	}

	// if we're done buying and still in the freeze period, wait
	if (m_doneBuying)
	{
		if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod())
		{
#ifdef REGAMEDLL_FIXES
			// make sure we're locked and loaded
			me->EquipBestWeapon(MUST_EQUIP);
			me->Reload();
			me->ResetStuckMonitor();
#endif
			return;
		}

		me->Idle();

#ifdef REGAMEDLL_FIXES
		return;
#endif
	}

	// is the bot spawned outside of a buy zone?
	if (!(me->m_signals.GetState() & SIGNAL_BUY))
	{
		m_doneBuying = true;
		UTIL_DPrintf("%s bot spawned outside of a buy zone (%d, %d, %d)\n", (me->m_iTeam == CT) ? "CT" : "Terrorist", int(me->pev->origin.x), int(me->pev->origin.y), int(me->pev->origin.z));
		return;
	}

	// try to buy some weapons
	const float buyInterval = 0.2f; // 0.02f
	if (gpGlobals->time - me->GetStateTimestamp() > buyInterval)
	{
		me->m_stateTimestamp = gpGlobals->time;

		bool isPreferredAllDisallowed = true;

		// try to buy our preferred weapons first
		if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount())
		{
			// need to retry because sometimes first buy fails??
			const int maxPrefRetries = 2;
			if (m_prefRetries >= maxPrefRetries)
			{
				// try to buy next preferred weapon
				++m_prefIndex;
				m_prefRetries = 0;
				return;
			}

			int weaponPreference = me->GetProfile()->GetWeaponPreference(m_prefIndex);

			// don't buy it again if we still have one from last round
			CBasePlayerWeapon *weapon = me->GetActiveWeapon();
			if (weapon != NULL && weapon->m_iId == weaponPreference)
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN)
			{
				// done with buying preferred weapon
				m_prefIndex = 9999;
				return;
			}

			const char *buyAlias = NULL;

			if (weaponPreference == WEAPON_SHIELDGUN)
			{
				if (TheCSBots()->AllowTacticalShield())
					buyAlias = "shield";
			}
			else
			{
				buyAlias = WeaponIDToAlias(weaponPreference);
				WeaponType type = GetWeaponType(buyAlias);

				switch (type)
				{
				case PISTOL:
					if (!TheCSBots()->AllowPistols())
						buyAlias = NULL;
					break;
				case SHOTGUN:
					if (!TheCSBots()->AllowShotguns())
						buyAlias = NULL;
					break;
				case SUB_MACHINE_GUN:
					if (!TheCSBots()->AllowSubMachineGuns())
						buyAlias = NULL;
					break;
				case RIFLE:
					if (!TheCSBots()->AllowRifles())
						buyAlias = NULL;
					break;
				case MACHINE_GUN:
					if (!TheCSBots()->AllowMachineGuns())
						buyAlias = NULL;
					break;
				case SNIPER_RIFLE:
					if (!TheCSBots()->AllowSnipers())
						buyAlias = NULL;
					break;
				}
			}

			if (buyAlias)
			{
				me->ClientCommand(buyAlias);
				me->PrintIfWatched("Tried to buy preferred weapon %s.\n", buyAlias);

				isPreferredAllDisallowed = false;
			}

			++m_prefRetries;

			// bail out so we dont waste money on other equipment
			// unless everything we prefer has been disallowed, then buy at random
			if (isPreferredAllDisallowed == false)
				return;
		}

		// if we have no preferred primary weapon (or everything we want is disallowed), buy at random
		if (!me->m_bHasPrimary && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference()))
		{
			if (m_buyShield)
			{
				// buy a shield
				me->ClientCommand("shield");
				me->PrintIfWatched("Tried to buy a shield.\n");
			}
			else
			{
				// build list of allowable weapons to buy
				BuyInfo *masterPrimary = (me->m_iTeam == TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT;
				BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ];
				int stockPrimaryCount = 0;

				// dont choose sniper rifles as often
				const float sniperRifleChance = 50.0f;
				bool wantSniper = (RANDOM_FLOAT(0, 100) < sniperRifleChance) ? true : false;

				for (int i = 0; i < PRIMARY_WEAPON_BUY_COUNT; ++i)
				{
					if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) ||
						(masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) ||
						(masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) ||
						(masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) ||
						(masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns()))
					{
						stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i];
					}
				}

				if (stockPrimaryCount)
				{
					// buy primary weapon if we don't have one
					int which;

					// on hard difficulty levels, bots try to buy preferred weapons on the first pass
					if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD)
					{
						// count up available preferred weapons
						int prefCount = 0;
						for (which = 0; which < stockPrimaryCount; ++which)
						{
							if (stockPrimary[which]->preferred)
								++prefCount;
						}

						if (prefCount)
						{
							int whichPref = RANDOM_LONG(0, prefCount - 1);
							for (which = 0; which < stockPrimaryCount; ++which)
							{
								if (stockPrimary[which]->preferred && whichPref-- == 0)
									break;
							}
						}
						else
						{
							// no preferred weapons available, just pick randomly
							which = RANDOM_LONG(0, stockPrimaryCount - 1);
						}
					}
					else
					{
						which = RANDOM_LONG(0, stockPrimaryCount - 1);
					}

					me->ClientCommand(stockPrimary[ which ]->buyAlias);
					me->PrintIfWatched("Tried to buy %s.\n", stockPrimary[ which ]->buyAlias);
				}
			}
		}

		// If we now have a weapon, or have tried for too long, we're done
		if (me->m_bHasPrimary || m_retries++ > 5)
		{
			// primary ammo
			if (me->m_bHasPrimary)
			{
				me->ClientCommand("primammo");
			}

			// buy armor last, to make sure we bought a weapon first
			me->ClientCommand("vesthelm");
			me->ClientCommand("vest");

			// pistols - if we have no preferred pistol, buy at random
			if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference())
			{
				if (m_buyPistol)
				{
					int which = RANDOM_LONG(0, SECONDARY_WEAPON_BUY_COUNT - 1);

					if (me->m_iTeam == TERRORIST)
						me->ClientCommand(secondaryWeaponBuyInfoT[ which ].buyAlias);
					else
						me->ClientCommand(secondaryWeaponBuyInfoCT[ which ].buyAlias);

					// only buy one pistol
					m_buyPistol = false;
				}

				me->ClientCommand("secammo");
			}

			// buy a grenade if we wish, and we don't already have one
			if (m_buyGrenade && !me->HasGrenade())
			{
				if (UTIL_IsTeamAllBots(me->m_iTeam))
				{
					// only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans)
					float rnd = RANDOM_FLOAT(0, 100);

					if (rnd < 10.0f)
					{
						// smoke grenade
						me->ClientCommand("sgren");
					}
					else if (rnd < 35.0f)
					{
						// flashbang
						me->ClientCommand("flash");
					}
					else
					{
						// he grenade
						me->ClientCommand("hegren");
					}
				}
				else
				{
					if (RANDOM_FLOAT(0, 100) < 10.0f)
					{
						// smoke grenade
						me->ClientCommand("sgren");
					}
					else
					{
						// he grenade
						me->ClientCommand("hegren");
					}
				}
			}

			if (m_buyDefuseKit)
			{
				me->ClientCommand("defuser");
			}

			m_doneBuying = true;
		}
	}
}