mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 08:10:32 +02:00
Bot fixes.
This commit is contained in:
+112
-103
@@ -398,49 +398,50 @@ itemconfig_t* idBotGoalManager::LoadItemConfig( char* filename )
|
||||
idBotGoalManager::ItemWeightIndex
|
||||
========================
|
||||
*/
|
||||
/*
|
||||
================
|
||||
Bot_ItemWeightAlias
|
||||
|
||||
Some itemconfig entries come from Quake 3 / Team Arena style bot data, but the
|
||||
Doom 3 weight config usually does not contain every one of those classnames.
|
||||
|
||||
The item weight index must still point at a valid fuzzy weight, so we alias
|
||||
unsupported / missing items to the closest useful existing Doom 3 weight.
|
||||
================
|
||||
*/
|
||||
static const char* Bot_ItemWeightAlias(const char* classname) {
|
||||
if (!classname || !classname[0]) {
|
||||
static const char* Bot_ItemWeightAlias( const char* classname )
|
||||
{
|
||||
if( classname == NULL || classname[0] == '\0' )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct itemWeightAlias_t {
|
||||
struct itemWeightAlias_t
|
||||
{
|
||||
const char* missingName;
|
||||
const char* fallbackName;
|
||||
};
|
||||
|
||||
static const itemWeightAlias_t aliases[] = {
|
||||
// Missing weapon names commonly seen in Q3 bot item configs.
|
||||
{ "weapon_fists", "weapon_pistol" },
|
||||
{ "weapon_grapplinghook", "weapon_chainsaw" },
|
||||
{ "weapon_grenadelauncher", "weapon_rocketlauncher" },
|
||||
{ "weapon_lightning", "weapon_plasmagun" },
|
||||
{ "weapon_machinegun", "weapon_machinegun" },
|
||||
{ "weapon_railgun", "weapon_rocketlauncher" },
|
||||
{ "weapon_nailgun", "weapon_chaingun" },
|
||||
{ "weapon_prox_launcher", "weapon_rocketlauncher" },
|
||||
static const itemWeightAlias_t aliases[] =
|
||||
{
|
||||
{ "weapon_machinegun_mp", "weapon_machinegun" },
|
||||
{ "weapon_shotgun_mp", "weapon_shotgun" },
|
||||
{ "weapon_rocketlauncher_mp", "weapon_rocketlauncher" },
|
||||
{ "weapon_plasmagun_mp", "weapon_plasmagun" },
|
||||
{ "weapon_bfg_mp", "weapon_bfg" },
|
||||
{ "weapon_grenadelauncher", "weapon_rocketlauncher" },
|
||||
{ "weapon_grenadelauncher_mp", "weapon_rocketlauncher" },
|
||||
{ "weapon_lightning", "weapon_plasmagun" },
|
||||
{ "weapon_lightning_mp", "weapon_plasmagun" },
|
||||
{ "weapon_railgun", "weapon_rocketlauncher" },
|
||||
{ "weapon_railgun_mp", "weapon_rocketlauncher" },
|
||||
{ "weapon_fists", "weapon_pistol" },
|
||||
{ "weapon_grapplinghook", "weapon_chainsaw" },
|
||||
{ "weapon_nailgun", "weapon_chaingun" },
|
||||
{ "weapon_nailgun_mp", "weapon_chaingun" },
|
||||
{ "weapon_prox_launcher", "weapon_rocketlauncher" },
|
||||
{ "weapon_prox_launcher_mp", "weapon_rocketlauncher" },
|
||||
|
||||
// Team Arena / CTF objective entities. These are not normal pickup goals.
|
||||
// Give them a valid low-risk fallback so the index is never invalid.
|
||||
{ "team_redobelisk", "item_armor_shard" },
|
||||
{ "team_blueobelisk", "item_armor_shard" },
|
||||
{ "team_neutralobelisk", "item_armor_shard" },
|
||||
{ "team_redobelisk", "item_armor_shard" },
|
||||
{ "team_blueobelisk", "item_armor_shard" },
|
||||
{ "team_neutralobelisk", "item_armor_shard" },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
for (int i = 0; aliases[i].missingName != NULL; i++) {
|
||||
if (idStr::Icmp(classname, aliases[i].missingName) == 0) {
|
||||
for( int i = 0; aliases[i].missingName != NULL; i++ )
|
||||
{
|
||||
if( idStr::Icmp( classname, aliases[i].missingName ) == 0 )
|
||||
{
|
||||
return aliases[i].fallbackName;
|
||||
}
|
||||
}
|
||||
@@ -448,81 +449,84 @@ static const char* Bot_ItemWeightAlias(const char* classname) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idBotGoalManager::ItemWeightIndex
|
||||
================
|
||||
*/
|
||||
int* idBotGoalManager::ItemWeightIndex(weightconfig_t* iwc, itemconfig_t* ic) {
|
||||
int* index;
|
||||
int i;
|
||||
|
||||
if (iwc == NULL || ic == NULL || ic->numiteminfo <= 0) {
|
||||
return NULL;
|
||||
static bool Bot_ItemClassnamesMatch( const char* entityClassname, const char* itemClassname )
|
||||
{
|
||||
if( entityClassname == NULL || itemClassname == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( idStr::Icmp( entityClassname, itemClassname ) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// initialize item weight index
|
||||
index = new int[ic->numiteminfo]; // jmarshall: Get this off of the heap!
|
||||
|
||||
for (i = 0; i < ic->numiteminfo; i++) {
|
||||
const char* classname = ic->iteminfo[i].classname.c_str();
|
||||
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight(iwc, (char*)classname);
|
||||
|
||||
if (index[i] < 0) {
|
||||
const char* aliasName = Bot_ItemWeightAlias(classname);
|
||||
|
||||
if (aliasName != NULL) {
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight(iwc, (char*)aliasName);
|
||||
|
||||
if (index[i] >= 0) {
|
||||
common->Printf(
|
||||
"Bot item weight alias: item info %d \"%s\" using \"%s\"\n",
|
||||
i,
|
||||
classname,
|
||||
aliasName
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Last-resort fallback. This keeps the bot goal system from storing
|
||||
// invalid fuzzy weight indexes even if the expected alias is missing.
|
||||
static const char* safeFallbacks[] = {
|
||||
"item_armor_shard",
|
||||
"item_armor",
|
||||
"ammo_clip",
|
||||
"weapon_pistol",
|
||||
"weapon_shotgun",
|
||||
"weapon_machinegun",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (int j = 0; safeFallbacks[j] != NULL; j++) {
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight(iwc, (char*)safeFallbacks[j]);
|
||||
if (index[i] >= 0) {
|
||||
common->Printf(
|
||||
"Bot item weight fallback: item info %d \"%s\" using \"%s\"\n",
|
||||
i,
|
||||
classname,
|
||||
safeFallbacks[j]
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index[i] < 0) {
|
||||
common->Warning(
|
||||
"item info %d \"%s\" has no fuzzy weight and no fallback weight\r\n",
|
||||
i,
|
||||
classname
|
||||
);
|
||||
}
|
||||
idStr normalizedItem = itemClassname;
|
||||
if( idStr::Icmp( normalizedItem.Right( 3 ).c_str(), "_mp" ) == 0 )
|
||||
{
|
||||
normalizedItem.StripTrailing( "_mp" );
|
||||
if( idStr::Icmp( entityClassname, normalizedItem.c_str() ) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const char* aliasName = Bot_ItemWeightAlias( itemClassname );
|
||||
return aliasName != NULL && idStr::Icmp( entityClassname, aliasName ) == 0;
|
||||
}
|
||||
|
||||
int* idBotGoalManager::ItemWeightIndex( weightconfig_t* iwc, itemconfig_t* ic )
|
||||
{
|
||||
int* index;
|
||||
|
||||
if( iwc == NULL || ic == NULL || ic->numiteminfo <= 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//initialize item weight index
|
||||
index = new int[ic->numiteminfo]; // jmarshall: Get this off of the heap!
|
||||
|
||||
for( int i = 0; i < ic->numiteminfo; i++ )
|
||||
{
|
||||
const char* classname = ic->iteminfo[i].classname.c_str();
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight( iwc, ( char* )classname );
|
||||
if( index[i] < 0 )
|
||||
{
|
||||
const char* aliasName = Bot_ItemWeightAlias( classname );
|
||||
if( aliasName != NULL )
|
||||
{
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight( iwc, ( char* )aliasName );
|
||||
}
|
||||
}
|
||||
if( index[i] < 0 )
|
||||
{
|
||||
static const char* safeFallbacks[] =
|
||||
{
|
||||
"item_armor_shard",
|
||||
"item_armor",
|
||||
"ammo_clip",
|
||||
"weapon_machinegun",
|
||||
"weapon_shotgun",
|
||||
NULL
|
||||
};
|
||||
|
||||
for( int j = 0; safeFallbacks[j] != NULL; j++ )
|
||||
{
|
||||
index[i] = botFuzzyWeightManager.FindFuzzyWeight( iwc, ( char* )safeFallbacks[j] );
|
||||
if( index[i] >= 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( index[i] < 0 )
|
||||
{
|
||||
common->Warning( "item info %d \"%s\" has no fuzzy weight\r\n", i, classname );
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotGoalManager::InitLevelItemHeap
|
||||
@@ -552,7 +556,7 @@ levelitem_t* idBotGoalManager::AllocLevelItem( void )
|
||||
li = freelevelitems;
|
||||
if( !li )
|
||||
{
|
||||
gameLocal.Error( "out of level items\n" );
|
||||
gameLocal.Warning( "out of bot level items, increase MAX_BOT_LEVEL_ITEMS\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -751,7 +755,7 @@ void idBotGoalManager::InitLevelItems( void )
|
||||
|
||||
for( i = 0; i < ic->numiteminfo; i++ )
|
||||
{
|
||||
if( !strcmp( classname, ic->iteminfo[i].classname ) )
|
||||
if( Bot_ItemClassnamesMatch( classname.c_str(), ic->iteminfo[i].classname.c_str() ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1517,11 +1521,16 @@ void idBotGoalManager::BotPushGoal( int goalstate, bot_goal_t* goal )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( gs->goalstacktop > 0 && gs->goalstack[gs->goalstacktop].number == goal->number )
|
||||
{
|
||||
gs->goalstack[gs->goalstacktop] = *goal;
|
||||
return;
|
||||
}
|
||||
if( gs->goalstacktop >= MAX_GOALSTACK - 1 )
|
||||
{
|
||||
gameLocal.Error( "goal heap overflow\n" );
|
||||
gameLocal.Warning( "bot goal stack overflow, clearing stale goals\n" );
|
||||
BotDumpGoalStack( goalstate );
|
||||
return;
|
||||
gs->goalstacktop = 0;
|
||||
}
|
||||
gs->goalstacktop++;
|
||||
gs->goalstack[gs->goalstacktop] = *goal;
|
||||
|
||||
Reference in New Issue
Block a user