I make all my weapon pickups/dropping/buying/handling decisions through a BotRateWeapon() function...
Code:
int BotRateWeapon (player_t *pPlayer, weaponspec_t *weapon_spec)
{
// this function returns an integer value describing how much a particular weapon (passed by
// the "weapon" pointer) is interesting for the bot whose player structure is pointed to by
// pPlayer. The more interesting the weapon, the higher the number this function returns.
// FIXME: quick and dirty, empirical. Redo this right.
int score;
// does the bot already have this weapon ?
if (pPlayer->weapons[weapon_spec->index].is_present)
return (0); // then this weapon is of no interest for the bot
// first reset the weapon score
score = 0;
// rate the interest regarding the weapon class
// is weapon primary AND has bot no primary weapon yet ?
if ((weapon_spec->weapon_class == WEAPON_CLASS_PRIMARY)
&& !PlayerHasWeaponOfClass (pPlayer, WEAPON_CLASS_PRIMARY))
score += 500; // then weapon is highly interesting, add 500 in a row
// else is weapon secondary AND has bot no secondary weapon yet ?
else if ((weapon_spec->weapon_class == WEAPON_CLASS_SECONDARY)
&& !PlayerHasWeaponOfClass (pPlayer, WEAPON_CLASS_SECONDARY))
score += 500; // then weapon is highly interesting, add 500 in a row
// else is weapon grenade AND has bot no grenade yet ?
else if ((weapon_spec->weapon_class == WEAPON_CLASS_GRENADE)
&& !PlayerHasWeaponOfClass (pPlayer, WEAPON_CLASS_GRENADE))
score += 500; // then weapon is highly interesting, add 500 in a row
// rate the interest regarding the bot's personal weapon preference
// is this weapon the bot's preferred weapon AND the bot doesn't own that weapon yet ?
if ((strcmp (weapon_spec->classname, pPlayer->Bot.pProfile->preferred_weapon) == 0)
&& !PlayerHasWeapon (pPlayer, weapon_spec))
score += 500; // then weapon is highly interesting, add 500 in a row
// now rate the interest regarding the weapon range
// does this weapon work best in melee AND has bot no melee weapon yet ?
if ((((weapon_spec->primary.range > 0) && (weapon_spec->primary.range == WEAPONRAIL_RANGE_MELEE))
|| ((weapon_spec->secondary.range > 0) && (weapon_spec->secondary.range == WEAPONRAIL_RANGE_MELEE)))
&& !PlayerHasWeaponOfRange (pPlayer, WEAPONRAIL_RANGE_MELEE))
score += 10; // interesting, add 10
// else does this weapon work best at close range AND has bot no close range weapon yet ?
else if ((((weapon_spec->primary.range > 0) && (weapon_spec->primary.range == WEAPONRAIL_RANGE_CLOSE))
|| ((weapon_spec->secondary.range > 0) && (weapon_spec->secondary.range == WEAPONRAIL_RANGE_CLOSE)))
&& !PlayerHasWeaponOfRange (pPlayer, WEAPONRAIL_RANGE_CLOSE))
score += 10; // interesting, add 10
// else does this weapon work best at medium range AND has bot no medium range weapon yet ?
else if ((((weapon_spec->primary.range > 0) && (weapon_spec->primary.range == WEAPONRAIL_RANGE_MEDIUM))
|| ((weapon_spec->secondary.range > 0) && (weapon_spec->secondary.range == WEAPONRAIL_RANGE_MEDIUM)))
&& !PlayerHasWeaponOfRange (pPlayer, WEAPONRAIL_RANGE_MEDIUM))
score += 10; // interesting, add 10
// else does this weapon work best at long range AND has bot no long range weapon yet ?
else if ((((weapon_spec->primary.range > 0) && (weapon_spec->primary.range == WEAPONRAIL_RANGE_FAR))
|| ((weapon_spec->secondary.range > 0) && (weapon_spec->secondary.range == WEAPONRAIL_RANGE_FAR)))
&& !PlayerHasWeaponOfRange (pPlayer, WEAPONRAIL_RANGE_FAR))
score += 10; // interesting, add 10
// now parse each parameter individually
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_DISABLER)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_DISABLER))
score -= 2;
else
score += 11;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_WATERPROOF)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_MISSILE))
score += 1;
else
score += 12;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_LIGHTDAMAGE)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_LIGHTDAMAGE))
score -= 49;
else
score -= 16;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_MEDIUMDAMAGE)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_MEDIUMDAMAGE))
score -= 6;
else
score += 7;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_HEAVYDAMAGE)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_HEAVYDAMAGE))
score += 5;
else
score += 31;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_RADIUSEFFECT)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_RADIUSEFFECT))
score -= 5;
else
score += 15;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_AUTOMATIC)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_AUTOMATIC))
score += 17;
else
score += 33;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_BUCKSHOT)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_BUCKSHOT))
score -= 9;
else
score += 16;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_SCOPED)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_SCOPED))
score += 5;
else
score += 17;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_SNIPER)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_LIGHTDAMAGE))
score -= 22;
else
score += 14;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_SILENCED)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_SILENCED))
score += 10;
else
score += 28;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_MISSILE)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_MISSILE))
score -= 2;
else
score += 10;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_HOMING)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_HOMING))
score += 5;
else
score += 20;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_TOSS)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_TOSS))
score += 2;
else
score += 10;
}
if (weapon_spec->primary.properties & WEAPONRAIL_PROPERTY_PLACE)
{
if (PlayerHasWeaponOfType (pPlayer, WEAPONRAIL_PROPERTY_PLACE))
score -= 5;
else
score += 5;
}
return (score); // return the overall score for this weapon
}