.:: Bots United ::.  
filebase forums discord server github wiki web
cubebot epodbot fritzbot gravebot grogbot hpbbot ivpbot jkbotti joebot
meanmod podbotmm racc rcbot realbot sandbot shrikebot soulfathermaps yapb

Go Back   .:: Bots United ::. > Developer's Farm > SDK Programming discussions > Half-Life 2 SDK
Half-Life 2 SDK For developments focused around the Half-Life 2 engine Half-Life 2

Reply
 
Thread Tools
Custom Interfaces
Old
  (#1)
DrEvil
Member
 
DrEvil's Avatar
 
Status: Offline
Posts: 142
Join Date: Jan 2004
Location: Los Angeles, CA
Default Custom Interfaces - 03-06-2005

So I'm working on a custom interface that I will compile into HL2DM, that should ultimately be exposed and available for server plugins to request and use. Once I get it working and all I hope to convince valve to include it into the SDK and compile it into CS/DOD and such so we can have the functionality we've been asking them to add for some time now.

Here's the code.

in public/dlls/ientityinfo.h
Code:
class IEntityInfo
{
public:
	virtual const char *GetClassName() = 0;
	virtual const QAngle& GetAbsAngles() const = 0;
	virtual const QAngle& GetLocalAngles() const = 0;
	virtual const Vector& GetAbsOrigin() const = 0;
	virtual const Vector& GetLocalOrigin() const = 0;
	virtual const Vector& GetAbsVelocity() const = 0;
	virtual const Vector& GetLocalVelocity() const = 0;
	virtual const QAngle& GetLocalAngularVelocity() const = 0;	
	// add more useful stuff
};

#define INTERFACEVERSION_ENTITYINFOMANAGER "EntityInfoManager001"
class IEntityInfoManager
{
public:
	virtual IEntityInfo *GetEntityInfo( edict_t *pEdict ) = 0;
};
in dlls\EntityInfoManager.h
Code:
#include "dlls/IEntityInfo.h"
#include "dlls/iplayerinfo.h"

class CEntityInfoManager : public IEntityInfoManager
{
public:
	virtual IEntityInfo *GetEntityInfo( edict_t *pEdict );
};

//////////////////////////////////////////////////////////////////////////

class EntityInfo : public IEntityInfo
{
public:
	inline void SetParent( CBaseEntity *_parent ) { m_pParent = _parent; } 

	const char *GetClassName();
	const QAngle& GetAbsAngles() const;
	const QAngle& GetLocalAngles() const;
	const Vector& GetAbsOrigin() const;
	const Vector& GetLocalOrigin() const;
	const Vector& GetAbsVelocity() const;
	const Vector& GetLocalVelocity() const;
	const QAngle& GetLocalAngularVelocity() const;
	IPlayerInfo* GetPlayerInfo() const;

	EntityInfo();
protected:
	CBaseEntity *m_pParent;
};
and in dlls\EntityInfoManager.cpp
Code:
#include "cbase.h"
#include "EntityInfoManager.h"

static CEntityInfoManager s_EntityInfoManager;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEntityInfoManager, IEntityInfoManager, INTERFACEVERSION_ENTITYINFOMANAGER, s_EntityInfoManager);

IEntityInfo *CEntityInfoManager::GetEntityInfo( edict_t *pEdict )
{
	CBaseEntity *pBaseEntity = CBaseEntity::Instance( pEdict );
	return pBaseEntity ? pBaseEntity->GetEntityInfo() : NULL;
}

EntityInfo::EntityInfo() :
	m_pParent(0)
{
}

const char *EntityInfo::GetClassName()
{
	Assert(m_pParent);
	return m_pParent->GetClassName();
}

*snip* implementations of all the rest of those functions, basic accessors
I added this as a member of CBaseEntity
Code:
EntityInfo m_EntityInfo;
I may change this to be completely non-intruesive to CBaseEntity class and rather than getting an EntityInfo from the CBaseEntity, add functions that all take the edict and get the CBaseEntity internally and return the results, like

Code:
 bool CEntityInfoManager::GetEntityAbsVelocity( edict_t *pEdict, Vector &_vel )
{
    CBaseEntity *pBaseEntity = CBaseEntity::Instance( pEdict );
    if(pBaseEntity)
    {
        _vel = pBaseEntity->GetAbsVelocity();
        return true;
    }
     return false;
}
But that doesn't matter at the moment, currently it emulates the same way the IPlayerInfo is set up. It's easy to change once I can figure out whats wrong with actually exporting the interface.

Anyways, this all compiles fine, and best I can tell it's set up exactly like the CPlayerInfoManager and has its interface exposed.

So it all builds fine, I copy the resulting server.dll to source dedicated server\hl2mp\bin and run a HL2DM dedicated server with my plugin that now requests the interface INTERFACEVERSION_ENTITYINFOMANAGER and apparently it's not being found.

Anyone see anything I'm missing from exposing the interface?

best I can tell my use of this
Code:
static CEntityInfoManager s_EntityInfoManager;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEntityInfoManager, IEntityInfoManager, INTERFACEVERSION_ENTITYINFOMANAGER, s_EntityInfoManager);
is exactly the same as how the CPlayerInfoManager is exposed
Code:
static CPlayerInfoManager s_PlayerInfoManager;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CPlayerInfoManager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER, s_PlayerInfoManager);
I don't see anything additional that it does? Am I blind? Anyone got any ideas?

Thanks.


Omni-bot AI framework
http://www.omni-bot.com

Foxbot - for Team Fortress Classic
http://www.foxbot.net



Last edited by DrEvil; 03-06-2005 at 01:52..
  
Reply With Quote
Re: Custom Interfaces
Old
  (#2)
DrEvil
Member
 
DrEvil's Avatar
 
Status: Offline
Posts: 142
Join Date: Jan 2004
Location: Los Angeles, CA
Default Re: Custom Interfaces - 07-06-2005

Ok, so after trying the custom interface in a newly exported mod it loads fine. So it seems like steam is overwriting my server.dll each run if I try loading the interface in HL2DM. They probably overwrite it if it doesn't match what's in the cache file or something. Kinda sucks for testing but it makes sense why they would do it I suppose.

Anyways, I'd like to get any and everyones feedback on everything that you'd like exposed via this custom interface that will be useful to bot coders.

Here's the current list of prototypes for functions that I have so far. Pretty much everything is done retrieved using a CBaseEntity* as the input. This should allow it to be useful for much more than players, like we are currently limited to.

You will also notice some duplicate functionality to what IBotController and/or IPlayerInfo provide. Other than trying to keep it simple and providing most things through a common interface, I believe the implementations of the CPlayerInfoManager and the accessors for some of the properties are less than ideal in terms of efficiency and safety.

For example CPlayerInfoManager::GetPlayerInfo blindly casts the CBaseEntity to a CBasePlayer. Not that it's hard to not call this on non player slots, it seems to demonstrate that these interfaces were likely hastily put together. Why didn't they use CBaseEntity::GetPredictionPlayer or CBaseEntity::GetSimulatingPlayer ?

So what other functionality do you think would be useful through a general IEntityInfoManager interface

Code:
class IEntityInfoManager
{
public:
	virtual const QAngle& GetAbsAngles(const CBaseEntity *_ent) const = 0;
	virtual const QAngle& GetLocalAngles(const CBaseEntity *_ent) const = 0;
	virtual const Vector& GetAbsOrigin(const CBaseEntity *_ent) const = 0;
	virtual const Vector& GetLocalOrigin(const CBaseEntity *_ent) const = 0;
	virtual const Vector& GetAbsVelocity(const CBaseEntity *_ent) const = 0;
	virtual const Vector& GetLocalVelocity(const CBaseEntity *_ent) const = 0;
	virtual const QAngle& GetLocalAngularVelocity(const CBaseEntity *_ent) const = 0;
	virtual const Vector GetEyePosition(const CBaseEntity *_ent) const = 0;
	virtual const Vector GetEarPosition(const CBaseEntity *_ent) const = 0;
};
Regarding the weapon/ammo/player access functionality we're missing, I'm thinking of putting player related functionality in the entityinfo class as well, because I think it's favorable to keep the entity access out of the classes themselves. For example, the current way IPlayerInfo is handled is that there is litterally a CPlayerInfo member in CBasePlayer, and an accessor to it, which is what CPlayerInfoManager::GetPlayerInfo returns the pointer to. This is both intrusive to CBasePlayer class, and adds an extra dependency.

The way CEntityInfoManager is currently set up, a mod can drop 3 files into their project, compile and thats it, no adding stuff to any other classes like CBasePlayer does. No extra dependencies, the CBaseEntity and CBasePlayer know nothing about an interface providing access to some of their members to a server plugin. Plus the drop in & compile should be easier to get mods(and valve) to do than a list of code lines to add to other files.

Anyways, here's the current train of thought for getting player info.

add:
Code:
  virtual const CBasePlayer *GetBasePlayer(const CBaseEntity *_ent) const = 0;
to the EntityInfoManager, and then provide a set of functionality such as:
Code:
 virtual void ChangeTeam( const CBasePlayer *pPlayer, int iTeamNum ) = 0;
virtual void ChangeClass( const CBasePlayer *pPlayer, int iClassNum ) = 0;
...

GetBasePlayer could use CBaseEntity::GetPredictionPlayer or CBaseEntity::GetSimulatingPlayer, assuming one of these functions is available server plugin side(and gives back what we need), or we can figure out another method of getting the CBasePlayer from a CBaseEntity safely.

Pretty much all the necessary things we need as bot authors are provided in CBaseEntity or CBasePlayer. By having the EntityInfoManager act as a wrapper around those function calls I think the result will be a safe and flexible way to expose everything we need for bots.

Anyways, please list any functionality from arbitrary entities or players that you can think of that needs exposed.

Thanks.


Omni-bot AI framework
http://www.omni-bot.com

Foxbot - for Team Fortress Classic
http://www.foxbot.net



Last edited by DrEvil; 07-06-2005 at 16:05..
  
Reply With Quote
Re: Custom Interfaces
Old
  (#3)
botman
Super Moderator
 
Status: Offline
Posts: 280
Join Date: Jan 2004
Location: Plano, TX
Default Re: Custom Interfaces - 07-06-2005

Okay, off the top of my head, here's a list of things that you would need to be available to bots...

Things that I assume are staticly controlled by the bot coder (like what weapons there are in the game, how those weapons are fired, what various "power-ups" do, etc.) These items require NO interface functions because if these were dynamic (defined at run-time) making code to handle them would be a nightmare:

- What weapons are available in the game.
- How those weapons are fired (single shot, auto, semi-auto, charged then fired, etc.).
- What types of ammo is required for each weapon.
- What types of "power-ups" are in the game (health packs, shields, special powers like invisibility/superspeed/longjump, etc.).
- Do the "power-ups" have a time limit or do they stay with you until you are killed.
- What are the game rules (deathmatch, CTF, king-of-the-hill, etc.)
- What types of teams are there and what abilities does each team have (does one team have powers that another team does not) and how are these team chosen by the player in game.
- What types of classes (infantry, medic, sniper, etc.) are available for each team and how are these classes chosen in game.


Things that need to have some interface to access some information at run-time:

- What team is the bot on (even if the bot requests a team, it doesn't mean the bot gets what it asks for in the case of server balanced teams)?
- What class (infantry, medic, sniper) is the bot (again, they might not get what they request)?
- What weapons is the bot currently carrying?
- How much ammo is the bot carrying for each type of weapon that it is carrying (this is needed to intelligently pick which weapon to switch to)?
- How much health does the bot currently have?
- How much shield/money/other does the bot currently have? (this one is difficult because you need some generic interface that basically says "how much 'X' do I have" where X can be unique to each mod. this probably has to be passed as a string "money" and the mod code deciphers the string and returns the int/float value for that item)
- What team/class is some other player on (are they friend or foe)?
- What weapon is some other player carrying (should I attack them or run away)?
- How does the bot get notified when sounds are created?
- How does the bot get notified when visual effects (flashbang) are created?


I'm sure there are plenty of other types of info that bots would need, but this list should be a good starting point.

botman
  
Reply With Quote
Re: Custom Interfaces
Old
  (#4)
DrEvil
Member
 
DrEvil's Avatar
 
Status: Offline
Posts: 142
Join Date: Jan 2004
Location: Los Angeles, CA
Default Re: Custom Interfaces - 07-06-2005

Excellent. Thanks for the list botman.

I haven't researched much into sounds and such, but does anyone know offhand if there is a server side method of intercepting sounds? I thought I had read somewhere that there isn't, and that is the reason why the even system fires events for footsteps and such, and that basically the sound system of a bot would need to be implemented using events as the proxy for sounds. I'm hoping this isn't the case.

botman, do you have any thoughts/feedback on the in-progress implementation ideas posted above?

Also, do you think theres any chance of valve including this in the SDK in the future?

Thanks again.


Omni-bot AI framework
http://www.omni-bot.com

Foxbot - for Team Fortress Classic
http://www.foxbot.net


  
Reply With Quote
Re: Custom Interfaces
Old
  (#5)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: Custom Interfaces - 08-06-2005

Footstep sounds are hookable through game events. Gunshot sounds as well. BUT, it depends on the MOD/GameDLL. When the game DLL allows you to hook these, there you go, when it doesn't, you're fucked :-/

Grab my PMtools and rummage a bit with it.



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote
Re: Custom Interfaces
Old
  (#6)
DrEvil
Member
 
DrEvil's Avatar
 
Status: Offline
Posts: 142
Join Date: Jan 2004
Location: Los Angeles, CA
Default Re: Custom Interfaces - 08-06-2005

Yea that sounds in line with what I read, that the extent of a bot hearing will be entirely dependant on the events that are exposed in a particular mod.


Omni-bot AI framework
http://www.omni-bot.com

Foxbot - for Team Fortress Classic
http://www.foxbot.net


  
Reply With Quote
Re: Custom Interfaces
Old
  (#7)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: Custom Interfaces - 08-06-2005

You can however "simulate" the footstep sounds yourself, by dispatching the right sound to the bot's ears every n milliseconds, depending on the type of surface the player is walking on (use a trace for this). kind of what I'm doing with RACC.

Identically, gunshot sounds can be emulated when a decrease of ammo is detected that is combined with a player's press of the attack button.



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote
Re: Custom Interfaces
Old
  (#8)
DrEvil
Member
 
DrEvil's Avatar
 
Status: Offline
Posts: 142
Join Date: Jan 2004
Location: Los Angeles, CA
Default Re: Custom Interfaces - 08-06-2005

Here's the latest function list.
Code:
const QAngle& GetAbsAngles(const CBaseEntity &_ent) const;
const QAngle& GetLocalAngles(const CBaseEntity &_ent) const;
const Vector& GetAbsOrigin(const CBaseEntity &_ent) const;
const Vector& GetLocalOrigin(const CBaseEntity &_ent) const;
const Vector& GetAbsVelocity(const CBaseEntity &_ent) const;
const Vector& GetLocalVelocity(const CBaseEntity &_ent) const;
const QAngle& GetLocalAngularVelocity(const CBaseEntity &_ent) const;
const Vector GetEyePosition(const CBaseEntity &_ent) const;
const Vector GetEarPosition(const CBaseEntity &_ent) const;
const int GetEntityFlags(const CBaseEntity &_ent) const;
const int GetTeamIndex(const CBaseEntity &_ent) const;

// Player stuff.
const CBasePlayer *GetBasePlayer(CBaseEntity &_ent) const;
const CBaseEntity *GetPlayerVehicle(CBasePlayer &_ent) const;
int GetAmmoCount(CBasePlayer &_ent, int _ammoindex) const;
const char *GetCurrentWeapon(CBasePlayer &_ent) const;
const CBaseEntity *HasItem(CBasePlayer &_ent, const char *_itemname) const;

const char *GetName(CBasePlayer &_ent);
const char *GetNetworkIDString(CBasePlayer &_ent);
void ChangeTeam(CBasePlayer &_ent, int _newteam);
void ChangeClass(CBasePlayer &_ent, int _newclass);
const char *GetClassName(CBasePlayer &_ent);
int	GetFragCount(const CBasePlayer &_ent);
int	GetDeathCount(const CBasePlayer &_ent);
bool IsConnected(const CBasePlayer &_ent);
int	GetArmorValue(const CBasePlayer &_ent);
bool IsHLTV(const CBasePlayer &_ent);
bool IsPlayer(const CBasePlayer &_ent);
bool IsFakeClient(CBasePlayer &_ent);
bool IsDead(const CBasePlayer &_ent);
bool IsInAVehicle(const CBasePlayer &_ent);
bool IsObserver(const CBasePlayer &_ent);
Vector GetPlayerMins(const CBasePlayer &_ent);
Vector GetPlayerMaxs(const CBasePlayer &_ent);
bool IsAllied(CBaseEntity &_ent, CBaseEntity &_ent2);
I think this stuff covers just about all the stuff we need, other than sounds/visual effects which I think there's no way around needing the mod to generate events for.

Anyone see anything missing?

I still want to add some accessors to get more detailed weapon data.

What are ya'lls opinion about getting weapon data. I was thinking one of 2 methods.

Code:
int GetWeaponCount(CBasePlayer &_ent)
{
	return _ent.WeaponCount();
}
CBaseCombatWeapon *GetWeapon(CBasePlayer &_ent, int _index)
{
	return _ent.GetWeapon(_index);
}
int GetWeaponClip1(CBaseCombatWeapon *_weapon)
{
	return _weapon->Clip1();
}
int GetWeaponClip2(CBaseCombatWeapon *_weapon)
{
	return _weapon->Clip2();
}
This basically lets the plugin actually hold the pointer to the weapon and use it in other functions to get data from it. May be confusing though to users who try to call the functions directly and end up with linker errors.

I'm leaning more towards something like this.

Code:
class WeaponInfo
{
public:
	const char *m_WeaponName;
	int	m_Clip1, m_Clip2;

	WeaponInfo()
	{
	}
};
int GetWeaponCount(CBasePlayer &_ent)
{
	return _ent.WeaponCount();
}
const void GetWeaponInfo(CBasePlayer &_ent, int _weaponIndex, WeaponInfo &_wi)
{
	CBaseCombatWeapon *pWeapon = _ent->GetWeapon(_weaponIndex);
	_wi.m_WeaponName = pWeapon->GetName();
	_wi.m_Clip1 = pWeapon->Clip1();
	_wi.m_Clip2 = pWeapon->Clip2();
	//...
}
Any thoughts?


Omni-bot AI framework
http://www.omni-bot.com

Foxbot - for Team Fortress Classic
http://www.foxbot.net



Last edited by DrEvil; 08-06-2005 at 16:40..
  
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 2 (0 members and 2 guests)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
vBulletin Skin developed by: vBStyles.com