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

3. Installing: Base Modifications

Iván Bravo Bravo edited this page Aug 24, 2017 · 4 revisions

The Bot system is prepared however it is necessary to make some modifications to the base code of your mod to implement the operation of the artificial intelligence.

1. Senses

Bots use the CAI_Senses class to view entities and listen for sounds, and this class inherits from CAI_Component that works only for NPCs (CAI_BaseNPC) so it is necessary to modify it so that it can work with characters (CBaseCombatCharacter)

If you have made modifications to the files:

  • ai_senses.cpp
  • ai_component.h

It is then recommended to apply the modifications on your own, otherwise you can use these versions:

Some of the functions that we have to modify are in ai_basenpc.h so open the file and replace from line 2703 to 2825 by the following (Diff):

inline const Vector &CAI_Component::GetLocalOrigin() const
{
    return GetCharacter()->GetLocalOrigin();
}

//-----------------------------------------------------------------------------

inline void CAI_Component::SetLocalOrigin(const Vector &origin)
{
    GetCharacter()->SetLocalOrigin(origin);
}

//-----------------------------------------------------------------------------

inline const Vector &CAI_Component::GetAbsOrigin() const
{
    return GetCharacter()->GetAbsOrigin();
}

//-----------------------------------------------------------------------------

inline const QAngle &CAI_Component::GetAbsAngles() const
{
    return GetCharacter()->GetAbsAngles();
}

//-----------------------------------------------------------------------------

inline void CAI_Component::SetSolid( SolidType_t val )
{
    GetCharacter()->SetSolid(val);
}

//-----------------------------------------------------------------------------

inline SolidType_t CAI_Component::GetSolid() const
{
    return GetCharacter()->GetSolid();
}

//-----------------------------------------------------------------------------

inline const Vector &CAI_Component::WorldAlignMins() const
{
    return GetCharacter()->WorldAlignMins();
}

//-----------------------------------------------------------------------------

inline const Vector &CAI_Component::WorldAlignMaxs() const
{
    return GetCharacter()->WorldAlignMaxs();
}

//-----------------------------------------------------------------------------

inline CAI_Component::CAI_Component( CAI_BaseNPC * pOuter )
{
    if ( pOuter ) {
        m_pOuter = pOuter->MyCombatCharacterPointer();
    }
}

inline CAI_BaseNPC * CAI_Component::GetOuter()
{
    if ( m_pOuter == NULL )
        return NULL;

    return m_pOuter->MyNPCPointer();
}

inline const CAI_BaseNPC * CAI_Component::GetOuter() const
{
    if ( m_pOuter == NULL )
        return NULL;

    return m_pOuter->MyNPCPointer();
}

inline Hull_t CAI_Component::GetHullType() const
{
    return GetOuter()->GetHullType();
}

//-----------------------------------------------------------------------------

inline Vector CAI_Component::WorldSpaceCenter() const
{
    return GetCharacter()->WorldSpaceCenter();
}

//-----------------------------------------------------------------------------

inline float CAI_Component::GetGravity() const
{
    return GetCharacter()->GetGravity();
}

//-----------------------------------------------------------------------------

inline void CAI_Component::SetGravity( float flGravity )
{
    GetCharacter()->SetGravity( flGravity );
}

//-----------------------------------------------------------------------------

inline float CAI_Component::GetHullWidth() const
{
    return NAI_Hull::Width( GetCharacter()->GetHullType());
}

//-----------------------------------------------------------------------------

inline float CAI_Component::GetHullHeight() const
{
    return NAI_Hull::Height( GetCharacter()->GetHullType());
}

//-----------------------------------------------------------------------------

inline const Vector &CAI_Component::GetHullMins() const
{
    return NAI_Hull::Mins( GetCharacter()->GetHullType());
}

//-----------------------------------------------------------------------------

inline const Vector &CAI_Component::GetHullMaxs() const
{
    return NAI_Hull::Maxs( GetCharacter()->GetHullType());
}

//-----------------------------------------------------------------------------

inline int CAI_Component::GetCollisionGroup() const
{
    return GetCharacter()->GetCollisionGroup();
}

//-----------------------------------------------------------------------------

inline CBaseEntity *CAI_Component::GetEnemy()
{
    return GetCharacter()->GetEnemy();
}

2. CBaseCombatCharacter

Now you need to implement the necessary CAI_Senses functions in CBaseCombatCharacter, so open the file basecombatcharacter.h and in the first few lines write:

#include "soundent.h"

Now somewhere inside the CBaseCombatCharacter class paste the following code block:

//-----------------------------------------------------
//
// Senses
//
//-----------------------------------------------------

virtual void		SetDistLook( float flDistLook ) { }

virtual bool		QueryHearSound( CSound *pSound ) {
    return true;
}

virtual bool		QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ) {
    return true;
}

virtual void		OnLooked( int iDistance ) { }
virtual void		OnListened() { }

virtual void		OnSeeEntity( CBaseEntity *pEntity ) { }

// If true, AI will try to see this entity regardless of distance.
virtual bool		ShouldNotDistanceCull() {
    return false;
}

virtual int			GetSoundInterests( void ) {
    return ALL_SOUNDS;
}
virtual int			GetSoundPriority( CSound *pSound ) {
    return 1;
}

CSound *			GetLoudestSoundOfType( int iType ) {
    return NULL;
}
virtual CSound *	GetBestSound( int validTypes = ALL_SOUNDS ) {
    return NULL;
}
virtual CSound *	GetBestScent( void ) {
    return NULL;
}
virtual float		HearingSensitivity( void ) {
    return 1.0;
}
virtual bool		ShouldIgnoreSound( CSound * ) {
    return false;
}
virtual bool		SoundIsVisible( CSound *pSound ) {
    return false;
}
virtual	bool		OnlySeeAliveEntities( void ) {
    return true;
}

The file will look like this: https://gist.github.com/Kolesias/05fddf175d0dc55476a5fbe05658375e (Diff)

3. CBasePlayer

NOTE: If you have modified 'typedef CBasePlayer CPlayer;' in bot_defs.h by your own player class then incorporate these functions into it.

Now you have to implement the functions that are required by the Bot system in CBasePlayer.

Open the file player.h and in the first lines write:

#include "ai_senses.h"
#include "soundent.h"

Approximately on line 235 you will find this:

private:
    CBasePlayer *m_pParent;
};

class CBasePlayer : public CBaseCombatCharacter 

Change it to:

public:
    CBasePlayer *m_pParent;
};

class IBot;
class CSquad;

class CBasePlayer : public CBaseCombatCharacter 

Now find:

IBotController *GetBotController() { return &m_PlayerInfo; }

Change it to:

virtual IBot *GetBotController() {
    return NULL;
}

virtual void SetBotController( IBot *pBot ) { }
virtual void SetUpBot() { }

virtual CAI_Senses *GetSenses() {
    return NULL;
}

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

virtual CSound *GetBestSound( int validTypes = ALL_SOUNDS ) {
    return NULL;
}

virtual CSound *GetBestScent( void ) {
    return NULL;
}

// Squad
virtual CSquad *GetSquad() {
    return NULL;
}

virtual void SetSquad( CSquad *pSquad ) { }
virtual void SetSquad( const char *name ) { }

virtual void OnNewLeader( CBasePlayer *pMember ) { }
virtual void OnMemberTakeDamage( CBasePlayer *pMember, const CTakeDamageInfo &info ) { }
virtual void OnMemberDeath( CBasePlayer *pMember, const CTakeDamageInfo &info ) { }
virtual void OnMemberReportEnemy( CBasePlayer *pMember, CBaseEntity *pEnemy ) { }

The file will look like this: https://gist.github.com/Kolesias/cdf7eb1a63226c3c22580d6abc3ee773 (Diff)

Functions are self-explanatory, but just in case:

GetBotController(): To obtain the object that processes the Bot Artificial Intelligence.

SetBotController(): Set the Artificial Intelligence that the Bot should use.

SetUpBot(): It should be called when creating a Bot, this is where you have to create the type of Artificial Intelligence you want and set it with SetBotController

4. CPluginBotManager

Open the file playerinfomanager.cpp and in line 102 you will find this:

return pPlayer->GetBotController();

Change it to:

return NULL;

5. IntervalTimer

Open the file util_shared.h and inside IntervalTimer Class put this function:

float GetStartTime() const
{
    return m_timestamp;
}