void CHudRoundTimer::Paint()
{
	// Update the time.
	C_CSGameRules *pRules = CSGameRules();
	if ( pRules )
	{
		SetDisplayValue( (int)ceil( CSGameRules()->TimeRemaining() ) );
		SetShouldDisplayValue( true );
		BaseClass::Paint();
	}
}
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 );
}
void CWeaponHL2MPBase::Materialize( void )
{
    if ( IsEffectActive( EF_NODRAW ) )
    {
        // changing from invisible state to visible.
        EmitSound( "AlyxEmp.Charge" );

        RemoveEffects( EF_NODRAW );
        DoMuzzleFlash();
    }

    if ( HasSpawnFlags( SF_NORESPAWN ) == false )
    {
        VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false );
        SetMoveType( MOVETYPE_VPHYSICS );

#ifndef CSTRIKE_DLL
        CSGameRules()->AddLevelDesignerPlacedObject( this );
#endif

    }

    if ( HasSpawnFlags( SF_NORESPAWN ) == false )
    {
        if ( GetOriginalSpawnOrigin() == vec3_origin )
        {
            m_vOriginalSpawnOrigin = GetAbsOrigin();
            m_vOriginalSpawnAngles = GetAbsAngles();
        }
    }

    SetPickupTouch();

    SetThink (NULL);
}
Exemple #4
0
void CMapInfo::CheckMapInfo()
{
	bool bCTCantBuy, bTCantBuy;
	switch (m_iBuyingStatus)
	{
	case BUYING_EVERYONE:
		bCTCantBuy = false;
		bTCantBuy = false;

		ALERT(at_console, "EVERYONE CAN BUY!\n");
		break;
	case BUYING_ONLY_CTS:
		bCTCantBuy = false;
		bTCantBuy = true;

		ALERT(at_console, "Only CT's can buy!!\n");
		break;
	case BUYING_ONLY_TERRORISTS:
		bCTCantBuy = true;
		bTCantBuy = false;

		ALERT(at_console, "Only T's can buy!!\n");
		break;
	case BUYING_NO_ONE:
		bCTCantBuy = true;
		bTCantBuy = true;

		ALERT(at_console, "No one can buy!!\n");
		break;
	default:
		bCTCantBuy = false;
		bTCantBuy = false;
		break;
	}

	CSGameRules()->m_flBombRadius = m_flBombRadius;
	CSGameRules()->m_bCTCantBuy = bCTCantBuy;
	CSGameRules()->m_bTCantBuy = bTCantBuy;
}
Exemple #5
0
void CC4::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
	if (m_pPlayer != NULL)
	{
		return;
	}

	CBasePlayer *pPlayer = UTIL_PlayerByIndex(1);

	if (pPlayer != NULL)
	{
		edict_t *m_pentOldCurBombTarget = pPlayer->m_pentCurBombTarget;
		pPlayer->m_pentCurBombTarget = NULL;

		if (pev->speed != 0 && CSGameRules() != NULL)
		{
			CSGameRules()->m_iC4Timer = int(pev->speed);
		}

		EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/c4_plant.wav", VOL_NORM, ATTN_NORM);

		CGrenade::ShootSatchelCharge(m_pPlayer->pev, m_pPlayer->pev->origin, Vector(0, 0, 0));

		CGrenade *pC4 = NULL;
		while ((pC4 = (CGrenade *)UTIL_FindEntityByClassname(pC4, "grenade")) != NULL)
		{
			if (pC4->m_bIsC4 && pC4->m_flNextFreq == gpGlobals->time)
			{
				pC4->pev->target = pev->target;
				pC4->pev->noise1 = pev->noise1;
				break;
			}
		}

		pPlayer->m_pentCurBombTarget = m_pentOldCurBombTarget;
		SUB_Remove();
	}
}
void CC4::PrimaryAttack()
{
	bool	PlaceBomb = false;
	CCSPlayer *pPlayer = GetPlayerOwner();


	int onGround = FBitSet( pPlayer->GetFlags(), FL_ONGROUND );

	if( m_bStartedArming == false )
	{
		if( pPlayer->m_bInBombZone && onGround )
		{
			m_bStartedArming = true;
			m_fArmedTime = gpGlobals->curtime + WEAPON_C4_ARM_TIME;
			m_bBombPlacedAnimation = false;
			//SendWeaponAnim( C4_ARM, UseDecrement() ? 1: 0 );

#if !defined( CLIENT_DLL )			
			// freeze the player in place while planting
			pPlayer->SetMaxSpeed( 1 );

			// player "arming bomb" animation
			pPlayer->SetAnimation( PLAYER_ATTACK1 );

			pPlayer->SetProgressBarTime( 3 );	
#endif
		}
		else
		{
			if ( !pPlayer->m_bInBombZone )
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_At_Bomb_Spot");
			}
			else
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground");
			}

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
			return;
		}
	}
	else
	{
		if ( !onGround || !pPlayer->m_bInBombZone )
		{
			if( !pPlayer->m_bInBombZone )
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Arming_Cancelled" );
			}
			else
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground" );
			}

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.5;
			m_bStartedArming = false;

#if !defined( CLIENT_DLL )
			// release the player from being frozen, we've somehow left the bomb zone
			pPlayer->ResetMaxSpeed();

			pPlayer->SetProgressBarTime( 0 );

			//pPlayer->SetAnimation( PLAYER_HOLDBOMB );

#endif
			/*
			if(m_bBombPlacedAnimation == true) //this means the placement animation is canceled
			{
				SendWeaponAnim( C4_DRAW, UseDecrement() ? 1: 0 );
			}
			else
			{
				SendWeaponAnim( C4_IDLE1, UseDecrement() ? 1: 0 );
			}
			*/
			
			return;
		}
		else
		{
			if( gpGlobals->curtime >= m_fArmedTime ) //the c4 is ready to be armed
			{
				//check to make sure the player is still in the bomb target area
				PlaceBomb = true;
			}
			else if( ( gpGlobals->curtime >= (m_fArmedTime - 0.75) ) && ( !m_bBombPlacedAnimation ) )
			{
				//call the c4 Placement animation 
				m_bBombPlacedAnimation = true;
				//SendWeaponAnim( C4_DROP, UseDecrement() ? 1: 0 );
				
#if !defined( CLIENT_DLL )
				// player "place" animation
				//pPlayer->SetAnimation( PLAYER_HOLDBOMB );
#endif
			}
		}
	}

	if ( PlaceBomb && m_bStartedArming )
	{
		m_bStartedArming = false;
		m_fArmedTime = 0;
		
		if( pPlayer->m_bInBombZone )
		{
#if !defined( CLIENT_DLL )
			//Broadcast("BOMBPL");

			CPlantedC4::ShootSatchelCharge( pPlayer, pPlayer->GetAbsOrigin(), QAngle(0,0,0) );

			// send director message, that something important happened here
			/*
			MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
				WRITE_BYTE ( 9 );	// command length in bytes
				WRITE_BYTE ( DRC_CMD_EVENT ); // bomb placed
				WRITE_SHORT( ENTINDEX(pPlayer->edict()) );
				WRITE_SHORT( 0 );
				WRITE_LONG( 11 | DRC_FLAG_FACEPLAYER );   // eventflags (priority and flags)
			MESSAGE_END();
			*/

			// tell the Ts the bomb has been planted (on radar)
			CTeam *pTeam = GetGlobalTeam( TEAM_TERRORIST );
			for ( int iPlayer=0; iPlayer < pTeam->GetNumPlayers(); iPlayer++ )
			{
				CBasePlayer *pTempPlayer = pTeam->GetPlayer( iPlayer );
				
				if ( pTempPlayer->m_lifeState != LIFE_DEAD )
				{
					/*
					MESSAGE_BEGIN( MSG_ONE, gmsgBombDrop, NULL, pTempPlayer->pev );
						WRITE_COORD( pBomb->pev->origin.x );
						WRITE_COORD( pBomb->pev->origin.y );
						WRITE_COORD( pBomb->pev->origin.z );
						WRITE_BYTE( 1 ); // bomb was planted
					MESSAGE_END();
					*/
				}			
			}

			UTIL_ClientPrintAll( HUD_PRINTCENTER,"#Bomb_Planted" );
			pPlayer->SetProgressBarTime( 0 );

			// tell bots the bomb has been planted
			//g_pBotControl->OnEvent( EVENT_BOMB_PLANTED, pPlayer );

			CSGameRules()->m_bBombDropped = false;

			// Play the plant sound.
			CPASAttenuationFilter filter( this );
			EmitSound( filter, entindex(), "c4.plant" );

			// release the player from being frozen
			pPlayer->ResetMaxSpeed();

			// Remove the C4 icon from the HUD
			//pPlayer->SetBombIcon();

			// No more c4!
			pPlayer->Weapon_Drop( this, NULL, NULL );
			UTIL_Remove( this );
#endif

			return;
		}
		else
		{
			ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Activated_At_Bomb_Spot" );

#if !defined( CLIENT_DLL )
			//pPlayer->SetAnimation( PLAYER_HOLDBOMB );

			// release the player from being frozen
			pPlayer->ResetMaxSpeed();
#endif

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
			return;
		}
	}

	m_flNextPrimaryAttack = gpGlobals->curtime + 0.3;
	m_flTimeWeaponIdle = gpGlobals->curtime + random->RandomFloat ( 10, 15 );
}
	// Regular explosions
	void CPlantedC4::Explode2( trace_t *pTrace, int bitsDamageType )
	{
		float		flRndSound;// sound randomizer
		CCSGameRules *mp = CSGameRules();

		SetSolidFlags( FSOLID_NOT_SOLID );

		m_takedamage = DAMAGE_NO;

		// Shake the ground!!
		//UTIL_ScreenShake( pTrace->endpos, 25.0, 150.0, 1.0, 3000 );

		mp->m_bTargetBombed = true;

		// This variable is checked by the function CheckWinConditions()  to see if the bomb has just detonated.
		m_bJustBlew = true;
		// Check to see if the round is over after the bomb went off...
		mp->CheckWinConditions();


		// Pull out of the wall a bit
		if ( pTrace->fraction != 1.0 )
		{
			SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
		}

		// Fireball sprite and sound!!
		{
			Vector fireballPos = GetAbsOrigin();
			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		{
			Vector fireballPos = GetAbsOrigin() + Vector( 
				random->RandomFloat( -512, 512 ), 
				random->RandomFloat( -512, 512 ),
				random->RandomFloat( -10, 10 ) );

			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		{
			Vector fireballPos = GetAbsOrigin() + Vector( 
				random->RandomFloat( -512, 512 ), 
				random->RandomFloat( -512, 512 ),
				random->RandomFloat( -10, 10 ) );

			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		// Emit a sound effect of the explosion that travels across the entire level!
		CPASAttenuationFilter filter( this );
		EmitSound( filter, entindex(), "c4.explode" );
		
		//EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/c4_explode1.wav", 1.0, 0.25);
		
		SetOwnerEntity( NULL ); // can't traceline attack owner if this is set

		float flBombRadius = 100;
		if ( g_pMapInfo )
			flBombRadius = g_pMapInfo->m_flBombRadius;
		CSGameRules()->RadiusDamage( 
			CTakeDamageInfo( this, GetOwnerEntity(), 1000, bitsDamageType ), GetAbsOrigin(), flBombRadius, CLASS_NONE );

		// send director message, that something important happed here
		/*
		MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
			WRITE_BYTE ( 9 );	// command length in bytes
			WRITE_BYTE ( DRC_CMD_EVENT );	// bomb explode
			WRITE_SHORT( ENTINDEX(this->edict()) );	// index number of primary entity
			WRITE_SHORT( 0 );	// index number of secondary entity
			WRITE_LONG( 15 | DRC_FLAG_FINAL );   // eventflags (priority and flags)
		MESSAGE_END();
		*/

		UTIL_DecalTrace( pTrace, "Scorch" );

		flRndSound = random->RandomFloat( 0 , 1 );


		CPASAttenuationFilter debrisFilter( this );
		EmitSound( debrisFilter, entindex(), "c4.debris" );

		m_fEffects |= EF_NODRAW;
		
		//SetThink( &CPlantedC4::Smoke2 );
		//SetNextThink( gpGlobals->curtime + 0.85 );
	}
	void CPlantedC4::C4Think()
	{
		if (!IsInWorld())
		{
			UTIL_Remove( this );
			return;
		}
		
		SetNextThink( gpGlobals->curtime + 0.12 );
		
		if ( gpGlobals->curtime >= m_flNextFreq )
		{	
			m_flNextFreq = gpGlobals->curtime + m_flNextFreqInterval;
			m_flNextFreqInterval *= 0.9;
			m_iCurWave = clamp( m_iCurWave+1, 0, 5 );
		}

		if ( gpGlobals->curtime >= m_flNextBeep )
		{	
			m_flNextBeep = gpGlobals->curtime + 1.4;

			// Play a beep sound.		
			char soundName[64];
			Q_snprintf( soundName, sizeof( soundName ), "c4.beep%d", m_iCurWave );

			CPASAttenuationFilter filter( this );
			EmitSound( filter, entindex(), soundName );

			// let the bots hear the bomb beeping
			//g_pBotControl->OnEvent( EVENT_BOMB_BEEP, this );
		}

		if(gpGlobals->curtime >= m_flNextBlink)//added by SupraFiend to improve Bomb visibility
		{
			m_flNextBlink = gpGlobals->curtime + BLINK_INTERVAL;

			Vector vPos = GetAbsOrigin();
			vPos.z += 5;
			CPVSFilter filter( GetAbsOrigin() );
			te->GlowSprite( filter, 0, &vPos, g_sModelIndexC4Glow, 1, 0.5, 255 );
		}
		
		// IF the timer has expired ! blow this bomb up!
		if (m_flC4Blow <= gpGlobals->curtime)
		{
			// let the bots hear the bomb exploding
			//g_pBotControl->OnEvent( EVENT_BOMB_EXPLODED );

			// Tell the bomb target brush to trigger its targets
			//MIKETODO: use entity IO?
			/*
			if ( m_pentCurBombTarget )
			{
				CBaseEntity* pBombTarget = CBaseEntity::Instance( m_pentCurBombTarget );
				
				if ( pBombTarget )
					pBombTarget->Use( CBaseEntity::Instance( pev->owner ), this, USE_TOGGLE, 0 );
			}
			*/

			// give the defuser credit for defusing the bomb
			CBasePlayer *pBombOwner = dynamic_cast< CBasePlayer* >( GetOwnerEntity() );
			if ( pBombOwner )
			{
				pBombOwner->IncrementFragCount( 3 );
			}

			CSGameRules()->m_bBombDropped = false;

			if (GetWaterLevel() == 0)
				SetThink ( &CPlantedC4::Detonate2 );
			else
				UTIL_Remove (this); // Get rid of this thing if it's underwater..
		}

		//if the defusing process has started
		if ((m_bStartDefuse == true) && (m_pBombDefuser != NULL))
		{
			//if the defusing process has not ended yet
			if ( m_flDefuseCountDown > gpGlobals->curtime)
			{
				int iOnGround = FBitSet( m_pBombDefuser->GetFlags(), FL_ONGROUND );

				//if the bomb defuser has stopped defusing the bomb
				if( m_fNextDefuse < gpGlobals->curtime || !iOnGround )
				{
					if ( !iOnGround )
						ClientPrint( m_pBombDefuser, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground");

					// release the player from being frozen
					m_pBombDefuser->ResetMaxSpeed();
					m_pBombDefuser->m_bIsDefusing = false;

					//cancel the progress bar
					m_pBombDefuser->SetProgressBarTime( 0 );
					m_pBombDefuser = NULL;
					m_bStartDefuse = false;
					m_flDefuseCountDown = 0;

					// tell the bots someone has aborted defusing
					//g_pBotControl->OnEvent( EVENT_BOMB_DEFUSE_ABORTED );
				}

				return;
			}
			//if the defuse process has ended, kill the c4
			else if ( !m_pBombDefuser->IsDead() )
			{
				// tell the bots the bomb is defused
				//g_pBotControl->OnEvent( EVENT_BOMB_DEFUSED );

				//MIKETODO: spectator
				/*
				// Broadcast to the entire server
				Broadcast( "BOMBDEF" );

				// send director message, that something important happened here
				MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
					WRITE_BYTE ( 9 );
					WRITE_BYTE ( DRC_CMD_EVENT );	// bomb defuse
					WRITE_SHORT( ENTINDEX( m_pBombDefuser->edict() ));	// index number of secondary entity
					WRITE_SHORT( 0 );	// index number of secondary entity
					WRITE_LONG( 15 | DRC_FLAG_DRAMATIC | DRC_FLAG_FINAL | DRC_FLAG_FACEPLAYER );   // eventflags (priority and flags)
				MESSAGE_END();
				*/

				CPASAttenuationFilter filter( this );
				EmitSound( filter, entindex(), "c4.disarmed" );
				
				UTIL_Remove(this);
				
				// The bomb has just been disarmed.. Check to see if the round should end now
				m_bJustBlew = true;

				// release the player from being frozen
				m_pBombDefuser->ResetMaxSpeed();
				m_pBombDefuser->m_bIsDefusing = false;

				CSGameRules()->m_bBombDefused = true;
				CSGameRules()->CheckWinConditions();

				// give the defuser credit for defusing the bomb
				m_pBombDefuser->IncrementFragCount( 3 );

				CSGameRules()->m_bBombDropped = false;
				
				// Clear their progress bar.
				m_pBombDefuser->SetProgressBarTime( 0 );

				m_pBombDefuser = NULL;
				m_bStartDefuse = false;

				return;
			}

			//if it gets here then the previouse defuser has taken off or been killed
			// release the player from being frozen
			m_pBombDefuser->ResetMaxSpeed();
			m_pBombDefuser->m_bIsDefusing = false;
			m_bStartDefuse = false;
			m_pBombDefuser = NULL;

			// tell the bots someone has aborted defusing
			//g_pBotControl->OnEvent( EVENT_BOMB_DEFUSE_ABORTED );
		}
	}
void CC4::PrimaryAttack()
{
	bool	PlaceBomb = false;
	CCSPlayer *pPlayer = GetPlayerOwner();
	if ( !pPlayer )
		return;

	int onGround = FBitSet( pPlayer->GetFlags(), FL_ONGROUND );
	CBaseEntity *groundEntity = (onGround) ? pPlayer->GetGroundEntity() : NULL;
	if ( groundEntity )
	{
		// Don't let us stand on players, breakables, or pushaway physics objects to plant
		if ( groundEntity->IsPlayer() ||
			IsPushableEntity( groundEntity ) ||
#ifndef CLIENT_DLL
			IsBreakableEntity( groundEntity ) ||
#endif // !CLIENT_DLL
			IsPushAwayEntity( groundEntity ) )
		{
			onGround = false;
		}
	}

	if( m_bStartedArming == false && m_bBombPlanted == false )
	{
		if( pPlayer->m_bInBombZone && onGround )
		{
			m_bStartedArming = true;
			m_fArmedTime = gpGlobals->curtime + WEAPON_C4_ARM_TIME;
			m_bBombPlacedAnimation = false;


#if !defined( CLIENT_DLL )			
			// init the beep flags
			int i;
			for( i=0;i<NUM_BEEPS;i++ )
				m_bPlayedArmingBeeps[i] = false;

			// freeze the player in place while planting
			pPlayer->SetMaxSpeed( 1 );

			// player "arming bomb" animation
			pPlayer->SetAnimation( PLAYER_ATTACK1 );
	
			pPlayer->SetNextAttack( gpGlobals->curtime );

			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_beginplant" );
			if( event )
			{
				event->SetInt("userid", pPlayer->GetUserID() );
				event->SetInt("site", pPlayer->m_iBombSiteIndex );
				event->SetInt( "priority", 8 );
				gameeventmanager->FireEvent( event );
			}
#endif

			SendWeaponAnim( ACT_VM_PRIMARYATTACK );

			FX_PlantBomb( pPlayer->entindex(), pPlayer->Weapon_ShootPosition() );
		}
		else
		{
			if ( !pPlayer->m_bInBombZone )
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_At_Bomb_Spot");
			}
			else
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground");
			}

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
			return;
		}
	}
	else
	{
		if ( !onGround || !pPlayer->m_bInBombZone )
		{
			if( !pPlayer->m_bInBombZone )
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Arming_Cancelled" );
			}
			else
			{
				ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground" );
			}

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.5;
			m_bStartedArming = false;

#if !defined( CLIENT_DLL )
			// release the player from being frozen, we've somehow left the bomb zone
			pPlayer->ResetMaxSpeed();

			pPlayer->SetProgressBarTime( 0 );

			//pPlayer->SetAnimation( PLAYER_HOLDBOMB );

			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortplant" );
			if( event )
			{
				event->SetInt("userid", pPlayer->GetUserID() );
				event->SetInt("site", pPlayer->m_iBombSiteIndex );
				event->SetInt( "priority", 8 );
				gameeventmanager->FireEvent( event );
			}

#endif
			if(m_bBombPlacedAnimation == true) //this means the placement animation is canceled
			{
				SendWeaponAnim( ACT_VM_DRAW );
			}
			else
			{
				SendWeaponAnim( ACT_VM_IDLE );
			}
			
			return;
		}
		else
		{
#ifndef CLIENT_DLL
			PlayArmingBeeps();
#endif

			if( gpGlobals->curtime >= m_fArmedTime ) //the c4 is ready to be armed
			{
				//check to make sure the player is still in the bomb target area
				PlaceBomb = true;
			}
			else if( ( gpGlobals->curtime >= (m_fArmedTime - 0.75) ) && ( !m_bBombPlacedAnimation ) )
			{
				//call the c4 Placement animation 
				m_bBombPlacedAnimation = true;

				SendWeaponAnim( ACT_VM_SECONDARYATTACK );
				
#if !defined( CLIENT_DLL )
				// player "place" animation
				//pPlayer->SetAnimation( PLAYER_HOLDBOMB );
#endif
			}
		}
	}

	if ( PlaceBomb && m_bStartedArming )
	{
		m_bStartedArming = false;
		m_fArmedTime = 0;
		
		if( pPlayer->m_bInBombZone )
		{
#if !defined( CLIENT_DLL )

			CPlantedC4 *pC4 = CPlantedC4::ShootSatchelCharge( pPlayer, pPlayer->GetAbsOrigin(), pPlayer->GetAbsAngles() );

			if ( pC4 )
			{
				pC4->SetBombSiteIndex( pPlayer->m_iBombSiteIndex );

				trace_t tr;
				UTIL_TraceEntity( pC4, GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-200), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
				pC4->SetAbsOrigin( tr.endpos );

				CBombTarget *pBombTarget = (CBombTarget*)UTIL_EntityByIndex( pPlayer->m_iBombSiteIndex );
				
				if ( pBombTarget )
				{
					CBaseEntity *pAttachPoint = gEntList.FindEntityByName( NULL, pBombTarget->GetBombMountTarget() );

					if ( pAttachPoint )
					{
						pC4->SetAbsOrigin( pAttachPoint->GetAbsOrigin() );
						pC4->SetAbsAngles( pAttachPoint->GetAbsAngles() );
						pC4->SetParent( pAttachPoint );
					}

					variant_t emptyVariant;
					pBombTarget->AcceptInput( "BombPlanted", pC4, pC4, emptyVariant, 0 );
				}
			}

			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_planted" );
			if( event )
			{
				event->SetInt("userid", pPlayer->GetUserID() );
				event->SetInt("site", pPlayer->m_iBombSiteIndex );
				event->SetInt("posx", pPlayer->GetAbsOrigin().x );
				event->SetInt("posy", pPlayer->GetAbsOrigin().y );
				event->SetInt( "priority", 8 );
				gameeventmanager->FireEvent( event );
			}

			// Fire a beep event also so the bots have a chance to hear the bomb
			event = gameeventmanager->CreateEvent( "bomb_beep" );

			if ( event )
			{
				event->SetInt( "entindex", entindex() );
				gameeventmanager->FireEvent( event );
			}

			pPlayer->SetProgressBarTime( 0 );

			CSGameRules()->m_bBombDropped = false;
			CSGameRules()->m_bBombPlanted = true;

			// Play the plant sound.
			Vector plantPosition = pPlayer->GetAbsOrigin() + Vector( 0, 0, 5 );
			CPASAttenuationFilter filter( plantPosition );
			EmitSound( filter, entindex(), "c4.plant" );

			// release the player from being frozen
			pPlayer->ResetMaxSpeed();

			// No more c4!
			pPlayer->Weapon_Drop( this, NULL, NULL );
			UTIL_Remove( this );
#endif
			//don't allow the planting to start over again next frame.
			m_bBombPlanted = true;

			return;
		}
		else
		{
			ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Activated_At_Bomb_Spot" );

#if !defined( CLIENT_DLL )
			//pPlayer->SetAnimation( PLAYER_HOLDBOMB );

			// release the player from being frozen
			pPlayer->ResetMaxSpeed();

			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortplant" );
			if( event )
			{
				event->SetInt("userid", pPlayer->GetUserID() );
				event->SetInt("site", pPlayer->m_iBombSiteIndex );
				event->SetInt( "priority", 8 );
				gameeventmanager->FireEvent( event );
			}
#endif

			m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
			return;
		}
	}

	m_flNextPrimaryAttack = gpGlobals->curtime + 0.3;
	SetWeaponIdleTime( gpGlobals->curtime + SharedRandomFloat("C4IdleTime", 10, 15 ) );
}
Exemple #10
0
void CC4::__MAKE_VHOOK(PrimaryAttack)()
{
	if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
		return;

	int inBombZone = (m_pPlayer->m_signals.GetState() & SIGNAL_BOMB) == SIGNAL_BOMB;
	int onGround = (m_pPlayer->pev->flags & FL_ONGROUND) == FL_ONGROUND;
	bool bPlaceBomb = (onGround && inBombZone);

	if (!m_bStartedArming)
	{
		if (!inBombZone)
		{
			ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Plant_At_Bomb_Spot");
			m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
			return;
		}

		if (!onGround)
		{
			ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground");
			m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
			return;
		}

		m_bStartedArming = true;
		m_bBombPlacedAnimation = false;
		m_fArmedTime = gpGlobals->time + C4_ARMING_ON_TIME;

		// player "arming bomb" animation
		SendWeaponAnim(C4_ARM, UseDecrement() != FALSE);

		// freeze the player in place while planting
		SET_CLIENT_MAXSPEED(m_pPlayer->edict(), 1.0);

		m_pPlayer->SetAnimation(PLAYER_ATTACK1);
		m_pPlayer->SetProgressBarTime(C4_ARMING_ON_TIME);
	}
	else
	{
		if (bPlaceBomb)
		{
			CBaseEntity *pEntity = NULL;
			CBasePlayer *pTempPlayer = NULL;

			if (m_fArmedTime <= gpGlobals->time)
			{
				if (m_bStartedArming)
				{
					m_bStartedArming = false;
					m_fArmedTime = 0;

					Broadcast("BOMBPL");
					m_pPlayer->m_bHasC4 = false;

					if (pev->speed != 0 && CSGameRules() != NULL)
					{
						CSGameRules()->m_iC4Timer = int(pev->speed);
					}

					CGrenade *pBomb = CGrenade::ShootSatchelCharge(m_pPlayer->pev, m_pPlayer->pev->origin, Vector(0, 0, 0));

					MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
						WRITE_BYTE(9);
						WRITE_BYTE(DRC_CMD_EVENT);
						WRITE_SHORT(m_pPlayer->entindex());
						WRITE_SHORT(0);
						WRITE_LONG(DRC_FLAG_FACEPLAYER | 11);
					MESSAGE_END();

					MESSAGE_BEGIN(MSG_ALL, gmsgBombDrop);
						WRITE_COORD(pBomb->pev->origin.x);
						WRITE_COORD(pBomb->pev->origin.y);
						WRITE_COORD(pBomb->pev->origin.z);
						WRITE_BYTE(1);
					MESSAGE_END();

					UTIL_ClientPrintAll(HUD_PRINTCENTER, "#Bomb_Planted");
					if (TheBots != NULL)
					{
						TheBots->OnEvent(EVENT_BOMB_PLANTED, m_pPlayer, pBomb);
					}

					if (TheCareerTasks != NULL && CSGameRules()->IsCareer() && !m_pPlayer->IsBot())
					{
						TheCareerTasks->HandleEvent(EVENT_BOMB_PLANTED, m_pPlayer);
					}

					UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Planted_The_Bomb\"\n",
						STRING(m_pPlayer->pev->netname),
						GETPLAYERUSERID(m_pPlayer->edict()),
						GETPLAYERAUTHID(m_pPlayer->edict()));

					g_pGameRules->m_bBombDropped = FALSE;

					// Play the plant sound.
					EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/c4_plant.wav", VOL_NORM, ATTN_NORM);

					// hide the backpack in Terrorist's models.
					m_pPlayer->pev->body = 0;

					// release the player from being frozen
					m_pPlayer->ResetMaxSpeed();

					// No more c4!
					m_pPlayer->SetBombIcon(FALSE);

					if (--m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
					{
						RetireWeapon();
						return;
					}
				}
			}
			else
			{
				if (m_fArmedTime - 0.75f <= gpGlobals->time && !m_bBombPlacedAnimation)
				{
					// call the c4 Placement animation
					m_bBombPlacedAnimation = true;
					SendWeaponAnim(C4_DROP, UseDecrement() != FALSE);

					// player "place" animation
					m_pPlayer->SetAnimation(PLAYER_HOLDBOMB);
				}
			}
		}
		else
		{
			if (inBombZone)
				ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground");
			else
				ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Arming_Cancelled");

			m_bStartedArming = false;
			m_flNextPrimaryAttack = GetNextAttackDelay(1.5);

			// release the player from being frozen, we've somehow left the bomb zone
			m_pPlayer->ResetMaxSpeed();
			m_pPlayer->SetProgressBarTime(0);
			m_pPlayer->SetAnimation(PLAYER_HOLDBOMB);

			// this means the placement animation is canceled
			if (m_bBombPlacedAnimation)
				SendWeaponAnim(C4_DRAW, UseDecrement() != FALSE);
			else
				SendWeaponAnim(C4_IDLE1, UseDecrement() != FALSE);

			return;
		}
	}

	m_flNextPrimaryAttack = GetNextAttackDelay(0.3);
	m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT(10, 15);
}
/**
 * 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;
		}
	}
}
Exemple #12
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;
		}
	}
}
Exemple #13
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;
		}
	}
}
void CWeaponCSBase::ItemPostFrame()
{
	CCSPlayer *pPlayer = GetPlayerOwner();


	//GOOSEMAN : Return zoom level back to previous zoom level before we fired a shot. This is used only for the AWP.
	if ( (m_flNextPrimaryAttack <= gpGlobals->curtime) && (pPlayer->m_bResumeZoom == TRUE) )
	{
		#ifndef CLIENT_DLL
			pPlayer->SetFOV( pPlayer->m_iLastZoom );

			if ( pPlayer->GetFOV() == pPlayer->m_iLastZoom )
			{
				// return the fade level in zoom.
				pPlayer->m_bResumeZoom = false;
			}
		#endif
	}

	//GOOSEMAN : Delayed shell ejection code..
	if ( (pPlayer->m_flEjectBrass != 0.0) && (pPlayer->m_flEjectBrass <= gpGlobals->curtime ) )
	{
		pPlayer->m_flEjectBrass = 0.0;
		EjectBrassLate();
	}


	if ((m_bInReload) && (pPlayer->m_flNextAttack <= gpGlobals->curtime))
	{
		// complete the reload. 
		int j = min( GetMaxClip1() - m_iClip1, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) );	

		// Add them to the clip
		m_iClip1 += j;
		pPlayer->RemoveAmmo( j, m_iPrimaryAmmoType );

		m_bInReload = false;
	}

	if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
	{
		if ( m_iClip2 != -1 && !pPlayer->GetAmmoCount( GetSecondaryAmmoType() ) )
		{
			m_bFireOnEmpty = TRUE;
		}
		SecondaryAttack();
		pPlayer->m_nButtons &= ~IN_ATTACK2;
	}
	else if ((pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime ))
	{
		if ( (m_iClip1 == 0/* && pszAmmo1()*/) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) ) )
		{
			m_bFireOnEmpty = TRUE;
		}

		// Can't shoot during the freeze period
		// Ken: Always allow firing in single player
		//---
		if ( !CSGameRules()->IsFreezePeriod() && 
			!pPlayer->m_bIsDefusing &&
			pPlayer->State_Get() == STATE_JOINED
			)
		{
			PrimaryAttack();
		}
		//---
	}
	else if ( pPlayer->m_nButtons & IN_RELOAD && GetMaxClip1() != WEAPON_NOCLIP && !m_bInReload && m_flNextPrimaryAttack < gpGlobals->curtime) 
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.
		
		//MIKETODO: add code for shields...
		//if ( !FBitSet( m_iWeaponState, WPNSTATE_SHIELD_DRAWN ) )
			  Reload();	
	}
	else if ( !(pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ) )
	{
		// no fire buttons down

		// The following code prevents the player from tapping the firebutton repeatedly 
		// to simulate full auto and retaining the single shot accuracy of single fire
		if (m_bDelayFire == TRUE)
		{
			m_bDelayFire = FALSE;
			if (m_iShotsFired > 15)
				m_iShotsFired = 15;
			m_flDecreaseShotsFired = gpGlobals->curtime + 0.4;
		}

		m_bFireOnEmpty = FALSE;

		// if it's a pistol then set the shots fired to 0 after the player releases a button
		if ( IsPistol() )
		{
			m_iShotsFired = 0;
		}
		else
		{
			if ( (m_iShotsFired > 0) && (m_flDecreaseShotsFired < gpGlobals->curtime)	)
			{
				m_flDecreaseShotsFired = gpGlobals->curtime + 0.0225;
				m_iShotsFired--;
			}
		}

		#ifndef CLIENT_DLL
			if ( !IsUseable() && m_flNextPrimaryAttack < gpGlobals->curtime ) 
			{
				// Intentionally blank -- used to switch weapons here
			}
			else
		#endif
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if ( m_iClip1 == 0 && !(GetFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime )
			{
				Reload();
				return;
			}
		}

		WeaponIdle( );
		return;
	}
}
Exemple #15
0
void GameDLL_EndRound_f()
{
	CSGameRules()->EndRoundMessage("#Round_Draw", ROUND_END_DRAW);
	Broadcast("rounddraw");
	CSGameRules()->TerminateRound(5, WINSTATUS_DRAW);
}
//--------------------------------------------------------------------------------------------------------------
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;
		}
	}
}
	void CPlantedC4::C4Think()
	{
		if (!IsInWorld())
		{
			UTIL_Remove( this );
			return;
		}

		//Bomb is dead, don't think anymore
		if( !m_bBombTicking )
		{
			SetThink( NULL );
			return;
		}
				

		SetNextThink( gpGlobals->curtime + 0.12 );

#ifndef CLIENT_DLL
		// let the bots hear the bomb beeping
		// BOTPORT: Emit beep events at same time as client effects
		IGameEvent * event = gameeventmanager->CreateEvent( "bomb_beep" );
		if( event )
		{
			event->SetInt( "entindex", entindex() );
			gameeventmanager->FireEvent( event );
		}
#endif
		
		// IF the timer has expired ! blow this bomb up!
		if (m_flC4Blow <= gpGlobals->curtime)
		{
			// give the defuser credit for defusing the bomb
			CBasePlayer *pBombOwner = dynamic_cast< CBasePlayer* >( GetOwnerEntity() );
			if ( pBombOwner )
			{
				pBombOwner->IncrementFragCount( 3 );
			}

			CSGameRules()->m_bBombDropped = false;

			trace_t tr;
			Vector vecSpot = GetAbsOrigin();
			vecSpot[2] += 8;

			UTIL_TraceLine( vecSpot, vecSpot + Vector ( 0, 0, -40 ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );

			Explode( &tr, DMG_BLAST );

			CSGameRules()->m_bBombPlanted = false;

			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_exploded" );
			if( event )
			{
				event->SetInt( "userid", pBombOwner?pBombOwner->GetUserID():-1 );
				event->SetInt( "site", m_iBombSiteIndex );
				event->SetInt( "priority", 9 );
				gameeventmanager->FireEvent( event );
			}
		}

		//if the defusing process has started
		if ((m_bStartDefuse == true) && (m_pBombDefuser != NULL))
		{
			//if the defusing process has not ended yet
			if ( m_flDefuseCountDown > gpGlobals->curtime)
			{
				int iOnGround = FBitSet( m_pBombDefuser->GetFlags(), FL_ONGROUND );

				//if the bomb defuser has stopped defusing the bomb
				if( m_flNextDefuse < gpGlobals->curtime || !iOnGround )
				{
					if ( !iOnGround && m_pBombDefuser->IsAlive() )
						ClientPrint( m_pBombDefuser, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground");

					// release the player from being frozen
					m_pBombDefuser->ResetMaxSpeed();
					m_pBombDefuser->m_bIsDefusing = false;

#ifndef CLIENT_DLL
					// tell the bots someone has aborted defusing
					IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortdefuse" );
					if( event )
					{
						event->SetInt("userid", m_pBombDefuser->GetUserID() );
						event->SetInt( "priority", 6 );
						gameeventmanager->FireEvent( event );
					}
#endif

					//cancel the progress bar
					m_pBombDefuser->SetProgressBarTime( 0 );
					m_pBombDefuser = NULL;
					m_bStartDefuse = false;
					m_flDefuseCountDown = 0;
					m_flDefuseLength = 0;	//force it to show completely defused
				}

				return;
			}
			//if the defuse process has ended, kill the c4
			else if ( !m_pBombDefuser->IsDead() )
			{
				IGameEvent * event = gameeventmanager->CreateEvent( "bomb_defused" );
				if( event )
				{
					event->SetInt("userid", m_pBombDefuser->GetUserID() );
					event->SetInt("site", m_iBombSiteIndex );
					event->SetInt( "priority", 9 );
					gameeventmanager->FireEvent( event );
				}

			
				Vector soundPosition = m_pBombDefuser->GetAbsOrigin() + Vector( 0, 0, 5 );
				CPASAttenuationFilter filter( soundPosition );

				EmitSound( filter, entindex(), "c4.disarmfinish" );
								
				// The bomb has just been disarmed.. Check to see if the round should end now
				m_bBombTicking = false;

				// release the player from being frozen
				m_pBombDefuser->ResetMaxSpeed();
				m_pBombDefuser->m_bIsDefusing = false;

				CSGameRules()->m_bBombDefused = true;
				CSGameRules()->CheckWinConditions();

				// give the defuser credit for defusing the bomb
				m_pBombDefuser->IncrementFragCount( 3 );

				CSGameRules()->m_bBombDropped = false;
				CSGameRules()->m_bBombPlanted = false;
				
				// Clear their progress bar.
				m_pBombDefuser->SetProgressBarTime( 0 );

				m_pBombDefuser = NULL;
				m_bStartDefuse = false;

				m_flDefuseLength = 10;

				return;
			}

#ifndef CLIENT_DLL
			// tell the bots someone has aborted defusing
			IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortdefuse" );
			if( event )
			{
				event->SetInt("userid", m_pBombDefuser->GetUserID() );
				event->SetInt( "priority", 6 );
				gameeventmanager->FireEvent( event );
			}
#endif

			//if it gets here then the previouse defuser has taken off or been killed
			// release the player from being frozen
			m_pBombDefuser->ResetMaxSpeed();
			m_pBombDefuser->m_bIsDefusing = false;
			m_bStartDefuse = false;
			m_pBombDefuser = NULL;
		}
	}
Exemple #18
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;
	}
}
	// Regular explosions
	void CPlantedC4::Explode( trace_t *pTrace, int bitsDamageType )
	{
		// Check to see if the round is over after the bomb went off...
		CSGameRules()->m_bTargetBombed = true;
		m_bBombTicking = false;
		CSGameRules()->CheckWinConditions();

		// Do the Damage
		float flBombRadius = 500;
		if ( g_pMapInfo )
			flBombRadius = g_pMapInfo->m_flBombRadius;

		// Output to the bomb target ent
		CBaseEntity *pTarget = NULL;
		variant_t emptyVariant;
		while ((pTarget = gEntList.FindEntityByClassname( pTarget, "func_bomb_target" )) != NULL)
		{
			//Adrian - But only to the one we want!
			if ( pTarget->entindex() != m_iBombSiteIndex )
				 continue;
			
			pTarget->AcceptInput( "BombExplode", this, this, emptyVariant, 0 );
				break;
		}	

		// Pull out of the wall a bit
		if ( pTrace->fraction != 1.0 )
		{
			SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) );
		}

		{
			Vector pos = GetAbsOrigin() + Vector( 0,0,8 );

			// add an explosion TE so it affects clientside physics
			CPASFilter filter( pos );
			te->Explosion( filter, 0.0,
				&pos, 
				g_sModelIndexFireball,
				50.0, 
				25,
				TE_EXPLFLAG_NONE,
				flBombRadius * 3.5,
				200 );
		}
		
		// Fireball sprite and sound!!
		{
			Vector fireballPos = GetAbsOrigin();
			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		{
			Vector fireballPos = GetAbsOrigin() + Vector( 
				random->RandomFloat( -512, 512 ), 
				random->RandomFloat( -512, 512 ),
				random->RandomFloat( -10, 10 ) );

			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		{
			Vector fireballPos = GetAbsOrigin() + Vector( 
				random->RandomFloat( -512, 512 ), 
				random->RandomFloat( -512, 512 ),
				random->RandomFloat( -10, 10 ) );

			CPVSFilter filter( fireballPos );
			te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 );
		}

		// Sound! for everyone
		CBroadcastRecipientFilter filter;
		EmitSound( filter, entindex(), "c4.explode" );


		// Decal!
		UTIL_DecalTrace( pTrace, "Scorch" );

		
		// Shake!
		UTIL_ScreenShake( pTrace->endpos, 25.0, 150.0, 1.0, 3000, SHAKE_START );


		SetOwnerEntity( NULL ); // can't traceline attack owner if this is set

		CSGameRules()->RadiusDamage( 
			CTakeDamageInfo( this, GetOwnerEntity(), flBombRadius, bitsDamageType ),
			GetAbsOrigin(),
			flBombRadius * 3.5,	//Matt - don't ask me, this is how CS does it.
			CLASS_NONE,
			true );	// IGNORE THE WORLD!!

		// send director message, that something important happed here
		/*
		MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
			WRITE_BYTE ( 9 );	// command length in bytes
			WRITE_BYTE ( DRC_CMD_EVENT );	// bomb explode
			WRITE_SHORT( ENTINDEX(this->edict()) );	// index number of primary entity
			WRITE_SHORT( 0 );	// index number of secondary entity
			WRITE_LONG( 15 | DRC_FLAG_FINAL );   // eventflags (priority and flags)
		MESSAGE_END();
		*/

		UTIL_Remove( this );
	}