Skip to content
This repository has been archived by the owner on Jul 19, 2024. It is now read-only.

4. Implementing

Iván Bravo Bravo edited this page Aug 23, 2017 · 7 revisions

The modifications to the base code have been made, now you can implement the Bots system to work with your Player Class, this depends on your mod. You may have created your own Player Class or continue using the default:

If you are doing a multiplayer mod then it should be: CHL2MP_Player (hl2mp_player.h)

If you are doing a singleplayer mod then it should be: CHL2_Player (hl2_player.h)

In this tutorial we will use the source code for the multiplayer version (CHL2MP_Player) but you can use the same code for other versions.

Implementing

Open the file hl2mp_player.h and inside the class CHL2MP_Player, place the following:

protected:
    IBot *m_pBotController;
    CAI_Senses *m_pSenses;

public:
    // Bot
    virtual IBot *GetBotController() {
        return m_pBotController;
    }

    virtual void SetBotController( IBot *pBot );
    virtual void SetUpBot();

    // Senses
    virtual CAI_Senses *GetSenses() {
        return m_pSenses;
    }

    virtual const CAI_Senses *GetSenses() const {
        return m_pSenses;
    }

    virtual void CreateSenses();

    virtual void SetDistLook( float flDistLook );

    virtual int GetSoundInterests();
    virtual int GetSoundPriority( CSound *pSound );

    virtual bool QueryHearSound( CSound *pSound );
    virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );

    virtual void OnLooked( int iDistance );
    virtual void OnListened();

    virtual CSound *GetLoudestSoundOfType( int iType );
    virtual bool SoundIsVisible( CSound *pSound );

    virtual CSound *GetBestSound( int validTypes = ALL_SOUNDS );
    virtual CSound *GetBestScent( void );

Now open the file hl2mp_player.cpp and in the first lines put:

#include "bots\bot.h"

And at the end of the file:

//================================================================================
//================================================================================
void CHL2MP_Player::SetBotController( IBot * pBot )
{
    if ( m_pBotController ) {
        delete m_pBotController;
        m_pBotController = NULL;
    }

    m_pBotController = pBot;
}

//================================================================================
//================================================================================
void CHL2MP_Player::SetUpBot()
{
    CreateSenses();
    SetBotController( new CBot( this ) );
}

//================================================================================
//================================================================================
void CHL2MP_Player::CreateSenses()
{
    m_pSenses = new CAI_Senses;
    m_pSenses->SetOuter( this );
}

//================================================================================
//================================================================================
void CHL2MP_Player::SetDistLook( float flDistLook )
{
    if ( GetSenses() ) {
        GetSenses()->SetDistLook( flDistLook );
    }
}

//================================================================================
//================================================================================
int CHL2MP_Player::GetSoundInterests()
{
    return SOUND_DANGER | SOUND_COMBAT | SOUND_PLAYER | SOUND_CARCASS | SOUND_MEAT | SOUND_GARBAGE;
}

//================================================================================
//================================================================================
int CHL2MP_Player::GetSoundPriority( CSound *pSound )
{
    if ( pSound->IsSoundType( SOUND_COMBAT ) ) {
        return SOUND_PRIORITY_HIGH;
    }

    if ( pSound->IsSoundType( SOUND_DANGER ) ) {
        if ( pSound->IsSoundType( SOUND_CONTEXT_FROM_SNIPER | SOUND_CONTEXT_EXPLOSION ) ) {
            return SOUND_PRIORITY_HIGHEST;
        }
        else if ( pSound->IsSoundType( SOUND_CONTEXT_GUNFIRE | SOUND_BULLET_IMPACT ) ) {
            return SOUND_PRIORITY_VERY_HIGH;
        }

        return SOUND_PRIORITY_HIGH;
    }

    if ( pSound->IsSoundType( SOUND_CARCASS | SOUND_MEAT | SOUND_GARBAGE ) ) {
        return SOUND_PRIORITY_VERY_LOW;
    }

    return SOUND_PRIORITY_NORMAL;
}

//================================================================================
//================================================================================
bool CHL2MP_Player::QueryHearSound( CSound *pSound )
{
    CBaseEntity *pOwner = pSound->m_hOwner.Get();

    if ( pOwner == this )
        return false;

    if ( pSound->IsSoundType( SOUND_PLAYER ) && !pOwner ) {
        return false;
    }

    if ( pSound->IsSoundType( SOUND_CONTEXT_ALLIES_ONLY ) ) {
        if ( Classify() != CLASS_PLAYER_ALLY && Classify() != CLASS_PLAYER_ALLY_VITAL ) {
            return false;
        }
    }

    if ( pOwner ) {
        // Solo escuchemos sonidos provocados por nuestros aliados si son de combate.
        if ( TheGameRules->PlayerRelationship( this, pOwner ) == GR_ALLY ) {
            if ( pSound->IsSoundType( SOUND_COMBAT ) && !pSound->IsSoundType( SOUND_CONTEXT_GUNFIRE ) ) {
                return true;
            }

            return false;
        }
    }

    if ( ShouldIgnoreSound( pSound ) ) {
        return false;
    }

    return true;
}

//================================================================================
//================================================================================
bool CHL2MP_Player::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFear )
{
    if ( bOnlyHateOrFear ) {
        if ( HL2MPRules()->PlayerRelationship( this, pEntity ) == GR_NOTTEAMMATE )
            return true;

        Disposition_t disposition = IRelationType( pEntity );
        return (disposition == D_HT || disposition == D_FR);
    }

    return true;
}

//================================================================================
//================================================================================
void CHL2MP_Player::OnLooked( int iDistance )
{
    if ( GetBotController() ) {
        GetBotController()->OnLooked( iDistance );
    }
}

//================================================================================
//================================================================================
void CHL2MP_Player::OnListened()
{
    if ( GetBotController() ) {
        GetBotController()->OnListened();
    }
}

//================================================================================
//================================================================================
CSound *CHL2MP_Player::GetLoudestSoundOfType( int iType )
{
    return CSoundEnt::GetLoudestSoundOfType( iType, EarPosition() );
}

//================================================================================
// Devuelve si podemos ver el origen del sonido
//================================================================================
bool CHL2MP_Player::SoundIsVisible( CSound *pSound )
{
    return (FVisible( pSound->GetSoundReactOrigin() ) && IsInFieldOfView( pSound->GetSoundReactOrigin() ));
}

//================================================================================
//================================================================================
CSound* CHL2MP_Player::GetBestSound( int validTypes )
{
    CSound *pResult = GetSenses()->GetClosestSound( false, validTypes );

    if ( pResult == NULL ) {
        DevMsg( "NULL Return from GetBestSound\n" );
    }

    return pResult;
}

//================================================================================
//================================================================================
CSound* CHL2MP_Player::GetBestScent()
{
    CSound *pResult = GetSenses()->GetClosestSound( true );

    if ( pResult == NULL ) {
        DevMsg( "NULL Return from GetBestScent\n" );
    }

    return pResult;
}

Now look for the function void CHL2MP_Player::Spawn(void) and at the end of the function put:

if ( GetBotController() ) {
    GetBotController()->Spawn();
}

The same with the function void CHL2MP_Player::Event_Killed( const CTakeDamageInfo &info ), at the end put:

if ( GetBotController() ) {
    GetBotController()->OnDeath( info );
}

The same with the function int CHL2MP_Player::OnTakeDamage( const CTakeDamageInfo &inputInfo ) before the last line put:

if ( GetBotController() ) {
    GetBotController()->OnTakeDamage( inputInfo );
}

Now open the file hl2mp_gamerules.cpp and comment everything from the code block that starts at line 956 so that it looks like this:

/*
void Bot_f()
{		
    // Look at -count.
    int count = 1;
    count = clamp( count, 1, 16 );

    int iTeam = TEAM_COMBINE;
			
    // Look at -frozen.
    bool bFrozen = false;
		
    // Ok, spawn all the bots.
    while ( --count >= 0 )
    {
	    BotPutInServer( bFrozen, iTeam );
    }
}


ConCommand cc_Bot( "bot", Bot_f, "Add a bot.", FCVAR_CHEAT );
*/

And that's it! Compile your project, create a server, and use the bot_add command to add generic Bots.


Make sure you have a Navigation Mesh, to generate it use the command nav_generate

To make Bots move around the map, use the command bot_debug_drive_random

Clone this wiki locally