ZBot implementation for Half-Life 1 Created 1 year ago2023-02-22 10:23:30 UTC by Napoleon321 Napoleon321

Created 1 year ago2023-02-22 10:23:30 UTC by Napoleon321 Napoleon321

Posted 1 year ago2023-02-22 10:23:30 UTC Post #347361
Hello Community,

I hope you're doing good.
I've been trying to port the Zbots from the reversed engineered CS DS from here:

https://github.com/FWGS/hlsdk-portable/tree/hlzbot-clean

to Half-Life 1.

I successfully ported the bots to SDK 2.3 (the one from GitHub, note the link above is for Android/Xash). The bots work fine, they don't crash, the waypoints are also generating fine
The main pros for porting them is that the bots are way better of what we already have and they use the weapons, strife, gather items, claimb on ladders... they will actively hunt you... and many more... I even got the bot to fire the nuke on crossfire...

I however have 1 problem, it more of an inconvenience... that a real problems, but still, I taught some of you, or maybe Solokiller... can help me out with this one...

So here's description of the problem that I would like to find solution to:

The bots use just 1 player model: gordon, and I can't make them to use any other model...

So I was looking at the code for the bot profiles:

https://github.com/FWGS/hlsdk-portable/blob/hlzbot-random-weapons/dlls/bot/manager/bot_profile.cpp

It should be able to use the player models in the models/player/ foldesr, if I understand correctly this piece of code:

const char *decoratedName = GetDecoratedSkinName(skinName, filename);
bool skinExists = GetCustomSkinIndex(decoratedName) > 0;
if (m_nextSkin < NumCustomSkins && !skinExists)
{
// decorate the name
m_skins[ m_nextSkin ] = CloneString(decoratedName);

// construct the model filename
m_skinModelnames[ m_nextSkin ] = CloneString(token);
m_skinFilenames[ m_nextSkin ] = new char[ Q_strlen(token) * 2 + Q_strlen("models/player//.mdl") + 1 ];
Q_sprintf(m_skinFilenames[ m_nextSkin ], "models/player/%s/%s.mdl", token, token);
++m_nextSkin;
}

What I don't completely understand is this:

"models/player/%s/%s.mdl"

Does it suppose to load models/player/ <model fodler> / <model_name>.mdl ?

Additionally I have attached the BotProfile.db (as .txt file, it's a simple renamed .txt to .db file). If you look there you can see this:

Link to BotProfile.db: https://www.dropbox.com/s/7fjnxpdatjqtgow/BotProfile.db?dl=0
Link to BotProfile.txt (renamed .db to .txt): https://www.dropbox.com/s/j4qsibu2nmwt7kj/BotProfile.txt?dl=0

//
// All profiles begin with this data and overwrite their own
//
Default
Skill = 50
Aggression = 50
ReactionTime = 0.3
AttackDelay = 0
Teamwork = 75
WeaponPreference = none
Cost = 0
Difficulty = NORMAL
VoicePitch = 100
Skin = 0
End

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

This is supposed to be responsible for the Default bot profile, and the others are created as derivates from it... but the question is... How to specify the player model?

Any help on this one would be greatly appreciated.

Thanks.
Posted 1 year ago2023-02-22 13:16:32 UTC Post #347362
As I understand it, you need to add something like this:

Skin GmanModel
Model = Gman
End


I'm not entirely sure, but after that you may need to enter the Skin Name as the "Skin" attribute value in the profile.

Edit: I guess there is no code in the bot codes to call the function to change the model of a bot.

If you are modifing bot codes, you can use this function whenever you want to change the model of any bot.
There is an inline function called "SetModel" for CBot.

inline void CBot::SetModel(const char *modelName)
{
SET_CLIENT_KEY_VALUE(entindex(), GET_INFO_BUFFER(edict()), "model", (char *)modelName);
}


Or, you can use this macro directly to change the model of any player whether they are bot or not.
SET_CLIENT_KEY_VALUE(<entityindex>, GET_INFO_BUFFER(<edict()>), "model", <modelname>);
The engine will search for the corresponding Model as "models/player/<modelname>/<modelname>.mdl".

Edit 2: Idk if this will work, but I added the SetModel in CHLBot::Initialize.

bool CHLBot::Initialize(const BotProfile *profile)
{
// extend
CBot::Initialize(profile);

SetModel(TheBotProfiles->GetCustomSkinModelname(profile->GetSkin()));

// CS bot initialization
m_diedLastRound = false;
m_morale = POSITIVE; // starting a new round makes everyone a little happy

m_combatRange = RANDOM_FLOAT(325, 425);

m_navNodeList = NULL;
m_currentNode = NULL;

// set initial safe time guess for this map
m_safeTime = 15.0f + 5.0f * GetProfile()->GetAggression();

m_name[0] = '\0';

ResetValues();
StartNormalProcess();

return true;
}
[-TR-] 3mirG [-TR-] 3mirGThe Turkish Half-Life modder.
Posted 1 year ago2023-02-22 17:46:24 UTC Post #347364
Hello,

Thank you for replying to this thread.

I already tried to put the value for the player model in the .db file with no success.

If I put this line:

SetModel(TheBotProfiles->GetCustomSkinModelname(profile->GetSkin()));

under 'bool CHLBot::Initialize(const BotProfile *profile)" the game just crashes when I try to add a bot, and there's no error in the logs an in the debugger.

I also tried this suggestion:
SET_CLIENT_KEY_VALUE(<entityindex>, GET_INFO_BUFFER(<edict()>), "model", <modelname>);

I tried it like this:
SET_CLIENT_KEY_VALUE(entindex(), GET_INFO_BUFFER(edict()), "model", "models/player/gina/gina.mdl");

and this:
SET_CLIENT_KEY_VALUE(entindex(), GET_INFO_BUFFER(edict()), "model", "gina");
And it did not changed anything, yes the game did not crashed (this time) but the model is still gordon...

Any other ideas?
Posted 1 year ago2023-02-22 18:35:11 UTC Post #347365
Maybe it didn't work because we called it before the ClientPutInServer() call.

Try calling it in CHLBotManager::AddBot.

bool CHLBotManager::AddBot(const BotProfile *profile)
{
CHLBot *pBot = CreateBot<CHLBot>(profile);
if (pBot == NULL)
{
return false;
}

ClientPutInServer(pBot->edict());
SET_CLIENT_KEY_VALUE(pBot->entindex(), GET_INFO_BUFFER(pBot->edict()), "*bot", "1");
SET_CLIENT_KEY_VALUE(pBot->entindex(), GET_INFO_BUFFER(pBot->edict()), "model", "gina");

ALERT( at_console, "Added bot %s to server\n", STRING(pBot->pev->netname));
return true;
}


However, I have not yet understood how to get the model name from the bot profile and use it.
[-TR-] 3mirG [-TR-] 3mirGThe Turkish Half-Life modder.
Posted 1 year ago2023-02-22 19:17:04 UTC Post #347366
I'll try that. If you find me on Discord, we can continue the chat there, and I can also give you access to the private repository with the compiled code on GitHub (basically I need a Git handle to do that).

You can find me on Discord @ Napoleon#3089
Posted 1 year ago2023-02-22 19:25:20 UTC Post #347367
That last suggestion actually worked. Now all the bots use gina.mdl. :)

So the next step is to make them to use random player models. :)

Edit:

Here's the final solution:

#define MAX_SKINS 10

char *bot_skins[MAX_SKINS] =
{
"barney",
"gina",
"gman",
"gordon",
"helmet",
"hgrunt",
"recon",
"robo",
"scientist",
"zombie"
};


bool CHLBotManager::AddBot(const BotProfile *profile)
{
CHLBot *pBot = CreateBot<CHLBot>(profile);
if (pBot == NULL)
{
return false;
}

//int nJoinedTeam;
ClientPutInServer(pBot->edict());
SET_CLIENT_KEY_VALUE(pBot->entindex(), GET_INFO_BUFFER(pBot->edict()), "*bot", "1");

SET_CLIENT_KEY_VALUE(pBot->entindex(), GET_INFO_BUFFER(pBot->edict()), "model", bot_skins[RANDOM_LONG(0, 9)]);

ALERT( at_console, "Added bot %s to server\n", STRING(pBot->pev->netname));
return true;
}

Thanks for your help. :)
Posted 1 year ago2023-02-23 14:11:22 UTC Post #347368
I don't do C++ but it doesn't need to to say I hate hardcoded values. put the list in a config file, perhaps?
Posted 1 year ago2023-02-23 18:32:45 UTC Post #347369
Well, my goal was to make it work... and I guess that was the easiest way. I might at some point try to get the bot to read the models from the .db file, but for now that's good enough for me.

I'll focus on adapting the bots to work properly with teamplay and to get the correct colors (temp colors).

Other than that, I think I'm quite happy with them, and I might release them as dll for the original Half-Life. It will not impair you joining other servers and the bots are only server side, and there are no changes on the client, furthermore the singleplayer works with no issues, unlike some of the other bots that outright disable the singleplayer...
You must be logged in to post a response.