mirror of
https://github.com/ENSL/NS.git
synced 2024-11-28 07:12:15 +00:00
2f9f0c732e
git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@277 67975925-1194-0748-b3d5-c16f83f1a3a1
1301 lines
53 KiB
C++
1301 lines
53 KiB
C++
//
|
|
// HPB bot - botman's High Ping Bastard bot
|
|
//
|
|
// (http://planethalflife.com/botman/)
|
|
//
|
|
// bot_combat.cpp
|
|
//
|
|
|
|
#include "extdll.h"
|
|
#include "util.h"
|
|
#include "cbase.h"
|
|
|
|
#include "bot.h"
|
|
#include "bot_func.h"
|
|
#include "bot_weapons.h"
|
|
#include "mod/AvHBasePlayerWeaponConstants.h"
|
|
#include "mod/AvHMarineWeaponConstants.h"
|
|
#include "mod/AvHAlienWeaponConstants.h"
|
|
#include "mod/AvHPlayer.h"
|
|
|
|
extern int mod_id;
|
|
extern bot_weapon_t weapon_defs[MAX_WEAPONS];
|
|
extern bool b_observer_mode;
|
|
extern int team_allies[4];
|
|
extern edict_t *pent_info_ctfdetect;
|
|
extern float is_team_play;
|
|
extern bool checked_teamplay;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
int iId; // the weapon ID value
|
|
char weapon_name[64]; // name of the weapon when selecting it
|
|
int skill_level; // bot skill must be less than or equal to this value
|
|
float primary_min_distance; // 0 = no minimum
|
|
float primary_max_distance; // 9999 = no maximum
|
|
float secondary_min_distance; // 0 = no minimum
|
|
float secondary_max_distance; // 9999 = no maximum
|
|
int use_percent; // times out of 100 to use this weapon when available
|
|
bool can_use_underwater; // can use this weapon underwater
|
|
int primary_fire_percent; // times out of 100 to use primary fire
|
|
int min_primary_ammo; // minimum ammout of primary ammo needed to fire
|
|
int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
|
|
bool primary_fire_hold; // hold down primary fire button to use?
|
|
bool secondary_fire_hold; // hold down secondary fire button to use?
|
|
bool primary_fire_charge; // charge weapon using primary fire?
|
|
bool secondary_fire_charge; // charge weapon using secondary fire?
|
|
float primary_charge_delay; // time to charge weapon
|
|
float secondary_charge_delay; // time to charge weapon
|
|
} bot_weapon_select_t;
|
|
|
|
typedef struct
|
|
{
|
|
int iId;
|
|
float primary_base_delay;
|
|
float primary_min_delay[5];
|
|
float primary_max_delay[5];
|
|
float secondary_base_delay;
|
|
float secondary_min_delay[5];
|
|
float secondary_max_delay[5];
|
|
} bot_fire_delay_t;
|
|
|
|
|
|
// weapons are stored in priority order, most desired weapon should be at
|
|
// the start of the array and least desired should be at the end
|
|
|
|
bot_weapon_select_t valve_weapon_select[] = {
|
|
{VALVE_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
|
|
30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
|
|
50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
|
|
100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
|
|
{VALVE_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
|
|
100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
|
|
100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
|
|
100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{VALVE_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
/* terminator */
|
|
{0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
|
|
};
|
|
|
|
bot_weapon_select_t tfc_weapon_select[] = {
|
|
{TF_WEAPON_AXE, "tf_weapon_axe", 5, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_KNIFE, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_SPANNER, "tf_weapon_knife", 5, 0.0, 40.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_MEDIKIT, "tf_weapon_medikit", 5, 0.0, 40.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_SNIPERRIFLE, "tf_weapon_sniperrifle", 5, 300.0, 2500.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, TRUE, FALSE, 1.0, 0.0},
|
|
{TF_WEAPON_FLAMETHROWER, "tf_weapon_flamethrower", 5, 100.0, 500.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_AC, "tf_weapon_ac", 5, 50.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_GL, "tf_weapon_gl", 5, 300.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_RPG, "tf_weapon_rpg", 5, 300.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_IC, "tf_weapon_ic", 5, 300.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_TRANQ, "tf_weapon_tranq", 5, 40.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_RAILGUN, "tf_weapon_railgun", 5, 40.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_SUPERNAILGUN, "tf_weapon_superng", 5, 40.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_SUPERSHOTGUN, "tf_weapon_supershotgun", 5, 40.0, 500.0, 0.0, 0.0,
|
|
100, TRUE, 100, 2, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_AUTORIFLE, "tf_weapon_autorifle", 5, 0.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_SHOTGUN, "tf_weapon_shotgun", 5, 40.0, 400.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{TF_WEAPON_NAILGUN, "tf_weapon_ng", 5, 40.0, 600.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
/* terminator */
|
|
{0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
|
|
};
|
|
|
|
bot_weapon_select_t cs_weapon_select[] = {
|
|
{CS_WEAPON_KNIFE, "weapon_knife", 5, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{CS_WEAPON_USP, "weapon_usp", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{CS_WEAPON_GLOCK18, "weapon_glock18", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
/* terminator */
|
|
{0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
|
|
};
|
|
|
|
bot_weapon_select_t gearbox_weapon_select[] = {
|
|
{GEARBOX_WEAPON_PIPEWRENCH, "weapon_pipewrench", 3, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_KNIFE, "weapon_knife", 4, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_CROWBAR, "weapon_crowbar", 2, 0.0, 50.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_DISPLACER, "weapon_displacer", 5, 100.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_SPORELAUNCHER, "weapon_sporelauncher", 5, 500.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_SHOCKRIFLE, "weapon_shockrifle", 5, 50.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_SNIPERRIFLE, "weapon_sniperrifle", 5, 50.0, 1500.0, 0.0, 0.0,
|
|
100, FALSE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_HANDGRENADE, "weapon_handgrenade", 5, 250.0, 750.0, 0.0, 0.0,
|
|
30, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_SNARK, "weapon_snark", 5, 150.0, 500.0, 0.0, 0.0,
|
|
50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_EGON, "weapon_egon", 5, 0.0, 9999.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_GAUSS, "weapon_gauss", 5, 0.0, 9999.0, 0.0, 9999.0,
|
|
100, FALSE, 80, 1, 10, FALSE, FALSE, FALSE, TRUE, 0.0, 0.8},
|
|
{GEARBOX_WEAPON_M249, "weapon_m249", 5, 0.0, 400.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_SHOTGUN, "weapon_shotgun", 5, 30.0, 150.0, 30.0, 150.0,
|
|
100, FALSE, 70, 1, 2, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_EAGLE, "weapon_eagle", 5, 0.0, 1200.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_PYTHON, "weapon_357", 5, 30.0, 700.0, 0.0, 0.0,
|
|
100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_HORNETGUN, "weapon_hornetgun", 5, 30.0, 1000.0, 30.0, 1000.0,
|
|
100, TRUE, 50, 1, 4, FALSE, TRUE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_MP5, "weapon_9mmAR", 5, 0.0, 250.0, 300.0, 600.0,
|
|
100, FALSE, 90, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_CROSSBOW, "weapon_crossbow", 5, 100.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_RPG, "weapon_rpg", 5, 300.0, 9999.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{GEARBOX_WEAPON_GLOCK, "weapon_9mmhandgun", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 70, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
/* terminator */
|
|
{0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
|
|
};
|
|
|
|
bot_weapon_select_t frontline_weapon_select[] = {
|
|
{FLF_WEAPON_HEGRENADE, "weapon_hegrenade", 3, 200.0, 1000.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_FLASHBANG, "weapon_flashbang", 3, 100.0, 800.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
// {FLF_WEAPON_KNIFE, "weapon_knife", 3, 0.0, 60.0, 0.0, 0.0,
|
|
// 100, TRUE, 100, 0, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_HK21, "weapon_hk21", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_UMP45, "weapon_ump45", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_FAMAS, "weapon_famas", 5, 0.0, 500.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_MSG90, "weapon_msg90", 5, 0.0, 2500.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_MP5A2, "weapon_mp5a2", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_AK5, "weapon_ak5", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_MP5SD, "weapon_mp5sd", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_M4, "weapon_m4", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_SPAS12, "weapon_spas12", 5, 0.0, 900.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_MAC10, "weapon_mac10", 5, 0.0, 500.0, 0.0, 0.0,
|
|
100, TRUE, 100, 1, 0, TRUE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_BERETTA, "weapon_beretta", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
{FLF_WEAPON_MK23, "weapon_mk23", 5, 0.0, 1200.0, 0.0, 1200.0,
|
|
100, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0},
|
|
/* terminator */
|
|
{0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, TRUE, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, 0.0, 0.0}
|
|
};
|
|
|
|
//int iId; // the weapon ID value
|
|
//char weapon_name[64]; // name of the weapon when selecting it
|
|
//int skill_level; // bot skill must be less than or equal to this value
|
|
//float primary_min_distance; // 0 = no minimum
|
|
//float primary_max_distance; // 9999 = no maximum
|
|
//float secondary_min_distance; // 0 = no minimum
|
|
//float secondary_max_distance; // 9999 = no maximum
|
|
//int use_percent; // times out of 100 to use this weapon when available
|
|
//bool can_use_underwater; // can use this weapon underwater
|
|
//int primary_fire_percent; // times out of 100 to use primary fire
|
|
//int min_primary_ammo; // minimum ammout of primary ammo needed to fire
|
|
//int min_secondary_ammo; // minimum ammout of seconday ammo needed to fire
|
|
//bool primary_fire_hold; // hold down primary fire button to use?
|
|
//bool secondary_fire_hold; // hold down secondary fire button to use?
|
|
//bool primary_fire_charge; // charge weapon using primary fire?
|
|
//bool secondary_fire_charge; // charge weapon using secondary fire?
|
|
//float primary_charge_delay; // time to charge weapon
|
|
//float secondary_charge_delay; // time to charge weapon
|
|
|
|
bot_weapon_select_t ns_weapon_select[] = {
|
|
{AVH_WEAPON_GRENADE_GUN, kwsGrenadeGun, 3, 120, kGGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_SONIC, kwsShotGun, 3, 0.0, kSGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_HMG, kwsHeavyMachineGun, 3, 0.0, kHMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_MG, kwsMachineGun, 3, 0.0, kMGRange, 0.0, 0.0, 100, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_PISTOL, kwsPistol, 3, 0.0, kHGRange, 0.0, 0.0, 75, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_KNIFE, kwsKnife, 3, 0.0, kKNRange, 0.0, 0.0, 50, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
|
|
// Base alien abilities
|
|
{AVH_WEAPON_PRIMALSCREAM, kwsPrimalScream, 3, 0.0, 300, 0.0, 0.0, 20, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_SWIPE, kwsSwipe, 3, 0.0, kSwipeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_SPORES, kwsSporeGun, 3, 0.0, kSporeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_SPIT, kwsSpitGun, 3, 0.0, kSpitGRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_CLAWS, kwsClaws, 3, 0.0, kClawsRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_BITE, kwsBiteGun, 3, 0.0, 60, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_ABILITY_LEAP, kwsLeap, 3, 0.0, 600, 0.0, 0.0, 50, FALSE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
{AVH_WEAPON_SPIKE, kwsSpikeGun, 3, 0.0, kSpikeRange, 0.0, 0.0, 75, TRUE, 100, 1, 0, FALSE, FALSE, FALSE, FALSE, 0.0f, 0.0f},
|
|
};
|
|
|
|
// weapon firing delay based on skill (min and max delay for each weapon)
|
|
// THESE MUST MATCH THE SAME ORDER AS THE WEAPON SELECT ARRAY!!!
|
|
|
|
bot_fire_delay_t valve_fire_delay[] = {
|
|
{VALVE_WEAPON_CROWBAR,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_HANDGRENADE,
|
|
0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_SNARK,
|
|
0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_EGON,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_GAUSS,
|
|
0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
|
|
1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
|
|
{VALVE_WEAPON_SHOTGUN,
|
|
0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
|
|
1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
|
|
{VALVE_WEAPON_PYTHON,
|
|
0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_HORNETGUN,
|
|
0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_MP5,
|
|
0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
|
|
1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
|
|
{VALVE_WEAPON_CROSSBOW,
|
|
0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_RPG,
|
|
1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{VALVE_WEAPON_GLOCK,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
|
|
/* terminator */
|
|
{0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
|
|
bot_fire_delay_t tfc_fire_delay[] = {
|
|
{TF_WEAPON_AXE,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_KNIFE,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_SPANNER,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_MEDIKIT,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_SNIPERRIFLE,
|
|
1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_FLAMETHROWER,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_AC,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_GL,
|
|
0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_RPG,
|
|
0.5, {0.0, 0.1, 0.3, 0.6, 1.0}, {0.1, 0.2, 0.7, 1.0, 2.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_IC,
|
|
2.0, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_TRANQ,
|
|
1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_RAILGUN,
|
|
0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_SUPERNAILGUN,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_SUPERSHOTGUN,
|
|
0.6, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_AUTORIFLE,
|
|
0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_SHOTGUN,
|
|
0.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{TF_WEAPON_NAILGUN,
|
|
0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
/* terminator */
|
|
{0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
|
|
bot_fire_delay_t cs_fire_delay[] = {
|
|
{CS_WEAPON_KNIFE,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{CS_WEAPON_USP,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
|
|
{CS_WEAPON_GLOCK18,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
|
|
/* terminator */
|
|
{0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
|
|
bot_fire_delay_t gearbox_fire_delay[] = {
|
|
{GEARBOX_WEAPON_PIPEWRENCH,
|
|
0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_KNIFE,
|
|
0.4, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_CROWBAR,
|
|
0.3, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_DISPLACER,
|
|
5.0, {0.0, 0.5, 0.8, 1.6, 2.5}, {0.3, 0.8, 1.4, 2.2, 3.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_SPORELAUNCHER,
|
|
0.5, {0.0, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.3, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_SHOCKRIFLE,
|
|
0.1, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_SNIPERRIFLE,
|
|
1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_HANDGRENADE,
|
|
0.1, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_SNARK,
|
|
0.1, {0.0, 0.1, 0.2, 0.4, 0.6}, {0.1, 0.2, 0.5, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_EGON,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_GAUSS,
|
|
0.2, {0.0, 0.2, 0.3, 0.5, 1.0}, {0.1, 0.3, 0.5, 0.8, 1.2},
|
|
1.0, {0.2, 0.3, 0.5, 0.8, 1.2}, {0.5, 0.7, 1.0, 1.5, 2.0}},
|
|
{GEARBOX_WEAPON_M249,
|
|
0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_SHOTGUN,
|
|
0.75, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0},
|
|
1.5, {0.0, 0.2, 0.4, 0.6, 0.8}, {0.25, 0.5, 0.8, 1.2, 2.0}},
|
|
{GEARBOX_WEAPON_EAGLE,
|
|
0.25, {0.0, 0.1, 0.2, 0.3, 0.5}, {0.1, 0.25, 0.4, 0.7, 1.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_PYTHON,
|
|
0.75, {0.0, 0.2, 0.4, 1.0, 1.5}, {0.25, 0.5, 0.8, 1.3, 2.2},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_HORNETGUN,
|
|
0.25, {0.0, 0.25, 0.4, 0.6, 1.0}, {0.1, 0.4, 0.7, 1.0, 1.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_MP5,
|
|
0.1, {0.0, 0.1, 0.25, 0.4, 0.5}, {0.1, 0.3, 0.45, 0.65, 0.8},
|
|
1.0, {0.0, 0.4, 0.7, 1.0, 1.4}, {0.3, 0.7, 1.0, 1.6, 2.0}},
|
|
{GEARBOX_WEAPON_CROSSBOW,
|
|
0.75, {0.0, 0.2, 0.5, 0.8, 1.0}, {0.25, 0.4, 0.7, 1.0, 1.3},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_RPG,
|
|
1.5, {1.0, 2.0, 3.0, 4.0, 5.0}, {3.0, 4.0, 5.0, 6.0, 7.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{GEARBOX_WEAPON_GLOCK,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
|
|
/* terminator */
|
|
{0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
|
|
bot_fire_delay_t frontline_fire_delay[] = {
|
|
{FLF_WEAPON_HEGRENADE,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_FLASHBANG,
|
|
0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
// {FLF_WEAPON_KNIFE,
|
|
// 0.3, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
// 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}},
|
|
{FLF_WEAPON_HK21,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_UMP45,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_FAMAS,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_MSG90,
|
|
1.2, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_MP5A2,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_AK5,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_MP5SD,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_M4,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_SPAS12,
|
|
0.9, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_MAC10,
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_BERETTA,
|
|
0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{FLF_WEAPON_MK23,
|
|
0.4, {0.0, 0.1, 0.2, 0.3, 0.4}, {0.1, 0.2, 0.3, 0.4, 0.5},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
/* terminator */
|
|
{0, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0},
|
|
0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
bot_fire_delay_t ns_fire_delay[] = {
|
|
{AVH_WEAPON_GRENADE_GUN, 0.3f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.2, 0.3, 0.4, 0.5, 1.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_SONIC, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_HMG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_MG, 0.0f, {0.0, 0.0, 0.0, 0.1, 0.3}, {0.0, 0.0, 0.0, 0.2, 0.6}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_PISTOL, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.1, 0.15, 0.2, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_KNIFE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
|
|
{AVH_WEAPON_PRIMALSCREAM, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_SWIPE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_SPORES, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_SPIT, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_CLAWS, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.4, 0.5}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_BITE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_ABILITY_LEAP, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}},
|
|
{AVH_WEAPON_SPIKE, 0.0f, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}
|
|
};
|
|
|
|
void BotCheckTeamplay(void)
|
|
{
|
|
// is this TFC or Counter-Strike or OpFor teamplay or FrontLineForce?
|
|
if ((mod_id == TFC_DLL) || (mod_id == CSTRIKE_DLL) ||
|
|
((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) ||
|
|
(mod_id == FRONTLINE_DLL) ||
|
|
(mod_id == AVH_DLL) )
|
|
is_team_play = 1.0;
|
|
else
|
|
is_team_play = CVAR_GET_FLOAT("mp_teamplay"); // teamplay enabled?
|
|
|
|
checked_teamplay = TRUE;
|
|
}
|
|
|
|
|
|
edict_t *BotFindEnemy( bot_t *pBot )
|
|
{
|
|
Vector vecEnd;
|
|
static bool flag=TRUE;
|
|
edict_t *pent = NULL;
|
|
edict_t *pNewEnemy;
|
|
float nearestdistance;
|
|
int i;
|
|
|
|
edict_t *pEdict = pBot->pEdict;
|
|
|
|
if(pBot->mBotPlayMode != PLAYMODE_PLAYING)
|
|
{
|
|
pBot->pBotEnemy = NULL;
|
|
}
|
|
|
|
if (pBot->pBotEnemy != NULL) // does the bot already have an enemy?
|
|
{
|
|
vecEnd = pBot->pBotEnemy->v.origin + pBot->pBotEnemy->v.view_ofs;
|
|
|
|
// if the enemy is dead?
|
|
if (!IsAlive(pBot->pBotEnemy)) // is the enemy dead?, assume bot killed it
|
|
{
|
|
// the enemy is dead, jump for joy about 10% of the time
|
|
if (RANDOM_LONG(1, 100) <= 10)
|
|
pEdict->v.button |= IN_JUMP;
|
|
|
|
// Taunt sometimes after a kill
|
|
if(RANDOM_LONG(1, 5) == 1)
|
|
{
|
|
pBot->mTimeOfNextTaunt = gpGlobals->time + RANDOM_FLOAT(.3f, 4.0f);
|
|
}
|
|
|
|
// don't have an enemy anymore so null out the pointer...
|
|
pBot->pBotEnemy = NULL;
|
|
}
|
|
else if (FInViewCone( &vecEnd, pEdict ) &&
|
|
FVisible( vecEnd, pEdict ))
|
|
{
|
|
if ((mod_id == TFC_DLL) &&
|
|
(pEdict->v.playerclass == TFC_CLASS_MEDIC))
|
|
{
|
|
if (pBot->pBotEnemy->v.health >= pBot->pBotEnemy->v.max_health)
|
|
{
|
|
pBot->pBotEnemy = NULL; // player is healed, null out pointer
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if enemy is still visible and in field of view, keep it
|
|
|
|
// face the enemy
|
|
Vector v_enemy = pBot->pBotEnemy->v.origin - pEdict->v.origin;
|
|
Vector bot_angles = UTIL_VecToAngles( v_enemy );
|
|
|
|
pEdict->v.ideal_yaw = bot_angles.y;
|
|
|
|
BotFixIdealYaw(pEdict);
|
|
|
|
// keep track of when we last saw an enemy
|
|
pBot->f_bot_see_enemy_time = gpGlobals->time;
|
|
|
|
return (pBot->pBotEnemy);
|
|
}
|
|
}
|
|
}
|
|
|
|
pent = NULL;
|
|
pNewEnemy = NULL;
|
|
nearestdistance = 1000;
|
|
|
|
if (mod_id == TFC_DLL)
|
|
{
|
|
if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
|
|
{
|
|
// search the world for players...
|
|
for (i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
edict_t *pPlayer = INDEXENT(i);
|
|
|
|
// skip invalid players and skip self (i.e. this bot)
|
|
if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict))
|
|
{
|
|
// skip this player if not alive (i.e. dead or dying)
|
|
if (!IsAlive(pPlayer))
|
|
continue;
|
|
|
|
if ((b_observer_mode) && !(pPlayer->v.flags & FL_FAKECLIENT))
|
|
continue;
|
|
|
|
int player_team = UTIL_GetTeam(pPlayer);
|
|
int bot_team = UTIL_GetTeam(pEdict);
|
|
|
|
// don't target your enemies...
|
|
if ((bot_team != player_team) &&
|
|
!(team_allies[bot_team] & (1<<player_team)))
|
|
continue;
|
|
|
|
// check if player needs to be healed...
|
|
if ((pPlayer->v.health / pPlayer->v.max_health) > 0.50)
|
|
continue; // health greater than 50% so ignore
|
|
|
|
vecEnd = pPlayer->v.origin + pPlayer->v.view_ofs;
|
|
|
|
// see if bot can see the player...
|
|
if (FInViewCone( &vecEnd, pEdict ) &&
|
|
FVisible( vecEnd, pEdict ))
|
|
{
|
|
float distance = (pPlayer->v.origin - pEdict->v.origin).Length();
|
|
|
|
if (distance < nearestdistance)
|
|
{
|
|
nearestdistance = distance;
|
|
pNewEnemy = pPlayer;
|
|
|
|
pBot->pBotUser = NULL; // don't follow user when enemy found
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pNewEnemy == NULL)
|
|
{
|
|
while ((pent = UTIL_FindEntityByClassname( pent, "building_sentrygun" )) != NULL)
|
|
{
|
|
int sentry_team = -1;
|
|
int bot_team = UTIL_GetTeam(pEdict);
|
|
|
|
if (pent->v.colormap == 0xA096)
|
|
sentry_team = 0; // blue team's sentry
|
|
else if (pent->v.colormap == 0x04FA)
|
|
sentry_team = 1; // red team's sentry
|
|
else if (pent->v.colormap == 0x372D)
|
|
sentry_team = 2; // yellow team's sentry
|
|
else if (pent->v.colormap == 0x6E64)
|
|
sentry_team = 3; // green team's sentry
|
|
|
|
// don't target your own team's sentry guns...
|
|
if (bot_team == sentry_team)
|
|
continue;
|
|
|
|
// don't target your allie's sentry guns either...
|
|
if (team_allies[bot_team] & (1<<sentry_team))
|
|
continue;
|
|
|
|
vecEnd = pent->v.origin + pent->v.view_ofs;
|
|
|
|
// is this sentry gun visible?
|
|
if (FInViewCone( &vecEnd, pEdict ) &&
|
|
FVisible( vecEnd, pEdict ))
|
|
{
|
|
float distance = (pent->v.origin - pEdict->v.origin).Length();
|
|
|
|
// is this the closest sentry gun?
|
|
if (distance < nearestdistance)
|
|
{
|
|
nearestdistance = distance;
|
|
pNewEnemy = pent;
|
|
|
|
pBot->pBotUser = NULL; // don't follow user when enemy found
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pNewEnemy == NULL)
|
|
{
|
|
nearestdistance = 2500;
|
|
|
|
// search the world for players...(and enemies)
|
|
//for (i = 1; i <= gpGlobals->maxClients; i++)
|
|
for (i = 1; i <= gpGlobals->maxEntities; i++)
|
|
{
|
|
edict_t *pEntity = INDEXENT(i);
|
|
|
|
// skip invalid players and skip self (i.e. this bot)
|
|
if ((pEntity) && (!pEntity->free) && (pEntity != pEdict) && (FBitSet(pEntity->v.flags, FL_MONSTER) || FBitSet(pEntity->v.flags, FL_CLIENT)))
|
|
{
|
|
// Skip webs?
|
|
const char* theClassName = STRING(pEntity->v.classname);
|
|
|
|
// Skip cloaked players
|
|
// if(pEntity->v.iuser4 & MASK_ALIEN_CLOAKED)
|
|
// continue;
|
|
|
|
// skip this player if not alive (i.e. dead or dying)
|
|
if (!IsAlive(pEntity))
|
|
continue;
|
|
|
|
if ((b_observer_mode) && !(pEntity->v.flags & FL_FAKECLIENT))
|
|
continue;
|
|
|
|
if (!checked_teamplay) // check for team play...
|
|
BotCheckTeamplay();
|
|
|
|
// is team play enabled?
|
|
if (is_team_play > 0.0)
|
|
{
|
|
int player_team = UTIL_GetTeam(pEntity);
|
|
int bot_team = UTIL_GetTeam(pEdict);
|
|
|
|
// don't target your teammates...
|
|
if (bot_team == player_team)
|
|
continue;
|
|
|
|
if (mod_id == TFC_DLL)
|
|
{
|
|
// don't target your allies either...
|
|
if (team_allies[bot_team] & (1<<player_team))
|
|
continue;
|
|
}
|
|
}
|
|
|
|
vecEnd = pEntity->v.origin + pEntity->v.view_ofs;
|
|
|
|
float theDistance = (pEdict->v.origin - pEntity->v.origin).Length();
|
|
|
|
// see if bot can see the player...
|
|
if ((FInViewCone( &vecEnd, pEdict ) &&
|
|
FVisible( vecEnd, pEdict )) || (theDistance < 32))
|
|
{
|
|
float distance = (pEntity->v.origin - pEdict->v.origin).Length();
|
|
if (distance < nearestdistance)
|
|
{
|
|
nearestdistance = distance;
|
|
pNewEnemy = pEntity;
|
|
|
|
pBot->pBotUser = NULL; // don't follow user when enemy found
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pNewEnemy)
|
|
{
|
|
// face the enemy
|
|
Vector v_enemy = pNewEnemy->v.origin - pEdict->v.origin;
|
|
Vector bot_angles = UTIL_VecToAngles( v_enemy );
|
|
|
|
pEdict->v.ideal_yaw = bot_angles.y;
|
|
|
|
BotFixIdealYaw(pEdict);
|
|
|
|
// keep track of when we last saw an enemy
|
|
pBot->f_bot_see_enemy_time = gpGlobals->time;
|
|
}
|
|
|
|
// has the bot NOT seen an ememy for at least 5 seconds (time to reload)?
|
|
if ((pBot->f_bot_see_enemy_time > 0) &&
|
|
((pBot->f_bot_see_enemy_time + 5.0) <= gpGlobals->time))
|
|
{
|
|
pBot->f_bot_see_enemy_time = -1; // so we won't keep reloading
|
|
|
|
if ((mod_id == VALVE_DLL) || (mod_id == GEARBOX_DLL) || (mod_id == AVH_DLL))
|
|
{
|
|
pEdict->v.button |= IN_RELOAD; // press reload button
|
|
}
|
|
}
|
|
|
|
return (pNewEnemy);
|
|
}
|
|
|
|
|
|
Vector BotBodyTarget( edict_t *pBotEnemy, bot_t *pBot )
|
|
{
|
|
Vector target;
|
|
float f_distance;
|
|
float f_scale;
|
|
int d_x = 0;
|
|
int d_y = 0;
|
|
int d_z = 0;
|
|
|
|
edict_t *pEdict = pBot->pEdict;
|
|
|
|
f_distance = (pBotEnemy->v.origin - pEdict->v.origin).Length();
|
|
|
|
if (f_distance > 1000)
|
|
f_scale = 1.0;
|
|
else if (f_distance > 100)
|
|
f_scale = f_distance / 1000.0;
|
|
else
|
|
f_scale = 0.1;
|
|
|
|
switch (pBot->bot_skill)
|
|
{
|
|
case 0:
|
|
// VERY GOOD, same as from CBasePlayer::BodyTarget (in player.h)
|
|
target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs * RANDOM_FLOAT( 0.5, 1.1 );
|
|
d_x = 0; // no offset
|
|
d_y = 0;
|
|
d_z = 0;
|
|
break;
|
|
case 1:
|
|
// GOOD, offset a little for x, y, and z
|
|
target = pBotEnemy->v.origin + pBotEnemy->v.view_ofs; // aim for the head (if you can find it)
|
|
d_x = RANDOM_FLOAT(-5, 5) * f_scale;
|
|
d_y = RANDOM_FLOAT(-5, 5) * f_scale;
|
|
d_z = RANDOM_FLOAT(-10, 10) * f_scale;
|
|
break;
|
|
case 2:
|
|
// FAIR, offset somewhat for x, y, and z
|
|
target = pBotEnemy->v.origin; // aim for the body
|
|
d_x = RANDOM_FLOAT(-10, 10) * f_scale;
|
|
d_y = RANDOM_FLOAT(-10, 10) * f_scale;
|
|
d_z = RANDOM_FLOAT(-18, 18) * f_scale;
|
|
break;
|
|
case 3:
|
|
// POOR, offset for x, y, and z
|
|
target = pBotEnemy->v.origin; // aim for the body
|
|
d_x = RANDOM_FLOAT(-20, 20) * f_scale;
|
|
d_y = RANDOM_FLOAT(-20, 20) * f_scale;
|
|
d_z = RANDOM_FLOAT(-32, 32) * f_scale;
|
|
break;
|
|
case 4:
|
|
// BAD, offset lots for x, y, and z
|
|
target = pBotEnemy->v.origin; // aim for the body
|
|
d_x = RANDOM_FLOAT(-35, 35) * f_scale;
|
|
d_y = RANDOM_FLOAT(-35, 35) * f_scale;
|
|
d_z = RANDOM_FLOAT(-50, 50) * f_scale;
|
|
break;
|
|
}
|
|
|
|
target = target + Vector(d_x, d_y, d_z);
|
|
|
|
return target;
|
|
}
|
|
|
|
|
|
// specifing a weapon_choice allows you to choose the weapon the bot will
|
|
// use (assuming enough ammo exists for that weapon)
|
|
// BotFireWeapon will return TRUE if weapon was fired, FALSE otherwise
|
|
|
|
bool BotFireWeapon( Vector v_enemy, bot_t *pBot, int weapon_choice)
|
|
{
|
|
bot_weapon_select_t *pSelect = NULL;
|
|
bot_fire_delay_t *pDelay = NULL;
|
|
int select_index;
|
|
int iId;
|
|
bool use_primary;
|
|
bool use_secondary;
|
|
int use_percent;
|
|
int primary_percent;
|
|
|
|
edict_t *pEdict = pBot->pEdict;
|
|
|
|
float distance = v_enemy.Length(); // how far away is the enemy?
|
|
|
|
if (mod_id == VALVE_DLL)
|
|
{
|
|
pSelect = &valve_weapon_select[0];
|
|
pDelay = &valve_fire_delay[0];
|
|
}
|
|
else if (mod_id == TFC_DLL)
|
|
{
|
|
pSelect = &tfc_weapon_select[0];
|
|
pDelay = &tfc_fire_delay[0];
|
|
}
|
|
else if (mod_id == CSTRIKE_DLL)
|
|
{
|
|
pSelect = &cs_weapon_select[0];
|
|
pDelay = &cs_fire_delay[0];
|
|
}
|
|
else if (mod_id == GEARBOX_DLL)
|
|
{
|
|
pSelect = &gearbox_weapon_select[0];
|
|
pDelay = &gearbox_fire_delay[0];
|
|
}
|
|
else if (mod_id == FRONTLINE_DLL)
|
|
{
|
|
pSelect = &frontline_weapon_select[0];
|
|
pDelay = &frontline_fire_delay[0];
|
|
}
|
|
else if (mod_id == AVH_DLL)
|
|
{
|
|
pSelect = &ns_weapon_select[0];
|
|
pDelay = &ns_fire_delay[0];
|
|
}
|
|
|
|
if (pSelect)
|
|
{
|
|
// are we charging the primary fire?
|
|
if (pBot->f_primary_charging > 0)
|
|
{
|
|
iId = pBot->charging_weapon_id;
|
|
|
|
if (mod_id == TFC_DLL)
|
|
{
|
|
if (iId == TF_WEAPON_SNIPERRIFLE)
|
|
{
|
|
pBot->f_move_speed = 0; // don't move while using sniper rifle
|
|
}
|
|
}
|
|
|
|
// is it time to fire the charged weapon?
|
|
if (pBot->f_primary_charging <= gpGlobals->time)
|
|
{
|
|
// we DON'T set pEdict->v.button here to release the
|
|
// fire button which will fire the charged weapon
|
|
|
|
pBot->f_primary_charging = -1; // -1 means not charging
|
|
|
|
// find the correct fire delay for this weapon
|
|
select_index = 0;
|
|
|
|
while ((pSelect[select_index].iId) &&
|
|
(pSelect[select_index].iId != iId))
|
|
select_index++;
|
|
|
|
// set next time to shoot
|
|
int skill = pBot->bot_skill;
|
|
float base_delay, min_delay, max_delay;
|
|
|
|
base_delay = pDelay[select_index].primary_base_delay;
|
|
min_delay = pDelay[select_index].primary_min_delay[skill];
|
|
max_delay = pDelay[select_index].primary_max_delay[skill];
|
|
|
|
pBot->f_shoot_time = gpGlobals->time + base_delay +
|
|
RANDOM_FLOAT(min_delay, max_delay);
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEdict->v.button |= IN_ATTACK; // charge the weapon
|
|
pBot->f_shoot_time = gpGlobals->time; // keep charging
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// are we charging the secondary fire?
|
|
if (pBot->f_secondary_charging > 0)
|
|
{
|
|
iId = pBot->charging_weapon_id;
|
|
|
|
// is it time to fire the charged weapon?
|
|
if (pBot->f_secondary_charging <= gpGlobals->time)
|
|
{
|
|
// we DON'T set pEdict->v.button here to release the
|
|
// fire button which will fire the charged weapon
|
|
|
|
pBot->f_secondary_charging = -1; // -1 means not charging
|
|
|
|
// find the correct fire delay for this weapon
|
|
select_index = 0;
|
|
|
|
while ((pSelect[select_index].iId) &&
|
|
(pSelect[select_index].iId != iId))
|
|
select_index++;
|
|
|
|
// set next time to shoot
|
|
int skill = pBot->bot_skill;
|
|
float base_delay, min_delay, max_delay;
|
|
|
|
base_delay = pDelay[select_index].secondary_base_delay;
|
|
min_delay = pDelay[select_index].secondary_min_delay[skill];
|
|
max_delay = pDelay[select_index].secondary_max_delay[skill];
|
|
|
|
pBot->f_shoot_time = gpGlobals->time + base_delay +
|
|
RANDOM_FLOAT(min_delay, max_delay);
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEdict->v.button |= IN_ATTACK2; // charge the weapon
|
|
pBot->f_shoot_time = gpGlobals->time; // keep charging
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
select_index = 0;
|
|
|
|
// loop through all the weapons until terminator is found...
|
|
while (pSelect[select_index].iId)
|
|
{
|
|
// was a weapon choice specified? (and if so do they NOT match?)
|
|
if ((weapon_choice != 0) &&
|
|
(weapon_choice != pSelect[select_index].iId))
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
// is the bot NOT carrying this weapon?
|
|
if (!(pBot->bot_weapons & (1<<pSelect[select_index].iId)))
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
// is the bot NOT skilled enough to use this weapon?
|
|
if ((pBot->bot_skill+1) > pSelect[select_index].skill_level)
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
// is the bot underwater and does this weapon NOT work under water?
|
|
if ((pEdict->v.waterlevel == 3) &&
|
|
!(pSelect[select_index].can_use_underwater))
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
use_percent = RANDOM_LONG(1, 100);
|
|
|
|
// is use percent greater than weapon use percent?
|
|
if (use_percent > pSelect[select_index].use_percent)
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
iId = pSelect[select_index].iId;
|
|
use_primary = FALSE;
|
|
use_secondary = FALSE;
|
|
primary_percent = RANDOM_LONG(1, 100);
|
|
|
|
// is primary percent less than weapon primary percent AND
|
|
// no ammo required for this weapon OR
|
|
// enough ammo available to fire AND
|
|
// the bot is far enough away to use primary fire AND
|
|
// the bot is close enough to the enemy to use primary fire
|
|
|
|
if ((primary_percent <= pSelect[select_index].primary_fire_percent) &&
|
|
((weapon_defs[iId].iAmmo1 == -1) ||
|
|
(pBot->m_rgAmmo[weapon_defs[iId].iAmmo1] >=
|
|
pSelect[select_index].min_primary_ammo)) &&
|
|
(distance >= pSelect[select_index].primary_min_distance) &&
|
|
(distance <= pSelect[select_index].primary_max_distance))
|
|
{
|
|
use_primary = TRUE;
|
|
}
|
|
|
|
// otherwise see if there is enough secondary ammo AND
|
|
// the bot is far enough away to use secondary fire AND
|
|
// the bot is close enough to the enemy to use secondary fire
|
|
|
|
else if (((weapon_defs[iId].iAmmo2 == -1) ||
|
|
(pBot->m_rgAmmo[weapon_defs[iId].iAmmo2] >=
|
|
pSelect[select_index].min_secondary_ammo)) &&
|
|
(distance >= pSelect[select_index].secondary_min_distance) &&
|
|
(distance <= pSelect[select_index].secondary_max_distance))
|
|
{
|
|
use_secondary = TRUE;
|
|
}
|
|
|
|
// see if there wasn't enough ammo to fire the weapon...
|
|
if ((use_primary == FALSE) && (use_secondary == FALSE))
|
|
{
|
|
select_index++; // skip to next weapon
|
|
continue;
|
|
}
|
|
|
|
// select this weapon if it isn't already selected
|
|
if (pBot->current_weapon.iId != iId)
|
|
UTIL_SelectItem(pEdict, pSelect[select_index].weapon_name);
|
|
|
|
if (pDelay[select_index].iId != iId)
|
|
{
|
|
char msg[80];
|
|
sprintf(msg, "fire_delay mismatch for weapon id=%d\n",iId);
|
|
ALERT(at_console, msg);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (mod_id == TFC_DLL)
|
|
{
|
|
if (iId == TF_WEAPON_SNIPERRIFLE)
|
|
{
|
|
pBot->f_move_speed = 0; // don't move while using sniper rifle
|
|
|
|
if (pEdict->v.velocity.Length() > 50)
|
|
{
|
|
return FALSE; // don't press attack key until velocity is < 50
|
|
}
|
|
}
|
|
|
|
if (pEdict->v.playerclass == TFC_CLASS_MEDIC)
|
|
{
|
|
int player_team = UTIL_GetTeam(pBot->pBotEnemy);
|
|
int bot_team = UTIL_GetTeam(pEdict);
|
|
|
|
// only heal your teammates or allies...
|
|
if (((bot_team == player_team) ||
|
|
(team_allies[bot_team] & (1<<player_team))) &&
|
|
(iId != TF_WEAPON_MEDIKIT))
|
|
{
|
|
return FALSE; // don't "fire" unless weapon is medikit
|
|
}
|
|
}
|
|
}
|
|
|
|
if (use_primary)
|
|
{
|
|
pEdict->v.button |= IN_ATTACK; // use primary attack
|
|
|
|
if (pSelect[select_index].primary_fire_charge)
|
|
{
|
|
pBot->charging_weapon_id = iId;
|
|
|
|
// release primary fire after the appropriate delay...
|
|
pBot->f_primary_charging = gpGlobals->time +
|
|
pSelect[select_index].primary_charge_delay;
|
|
|
|
pBot->f_shoot_time = gpGlobals->time; // keep charging
|
|
}
|
|
else
|
|
{
|
|
// set next time to shoot
|
|
if (pSelect[select_index].primary_fire_hold)
|
|
pBot->f_shoot_time = gpGlobals->time; // don't let button up
|
|
else
|
|
{
|
|
int skill = pBot->bot_skill;
|
|
float base_delay, min_delay, max_delay;
|
|
|
|
base_delay = pDelay[select_index].primary_base_delay;
|
|
min_delay = pDelay[select_index].primary_min_delay[skill];
|
|
max_delay = pDelay[select_index].primary_max_delay[skill];
|
|
|
|
pBot->f_shoot_time = gpGlobals->time + base_delay +
|
|
RANDOM_FLOAT(min_delay, max_delay);
|
|
}
|
|
}
|
|
}
|
|
else // MUST be use_secondary...
|
|
{
|
|
pEdict->v.button |= IN_ATTACK2; // use secondary attack
|
|
|
|
if (pSelect[select_index].secondary_fire_charge)
|
|
{
|
|
pBot->charging_weapon_id = iId;
|
|
|
|
// release secondary fire after the appropriate delay...
|
|
pBot->f_secondary_charging = gpGlobals->time +
|
|
pSelect[select_index].secondary_charge_delay;
|
|
|
|
pBot->f_shoot_time = gpGlobals->time; // keep charging
|
|
}
|
|
else
|
|
{
|
|
// set next time to shoot
|
|
if (pSelect[select_index].secondary_fire_hold)
|
|
pBot->f_shoot_time = gpGlobals->time; // don't let button up
|
|
else
|
|
{
|
|
int skill = pBot->bot_skill;
|
|
float base_delay, min_delay, max_delay;
|
|
|
|
base_delay = pDelay[select_index].secondary_base_delay;
|
|
min_delay = pDelay[select_index].secondary_min_delay[skill];
|
|
max_delay = pDelay[select_index].secondary_max_delay[skill];
|
|
|
|
pBot->f_shoot_time = gpGlobals->time + base_delay +
|
|
RANDOM_FLOAT(min_delay, max_delay);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE; // weapon was fired
|
|
}
|
|
}
|
|
|
|
// didn't have any available weapons or ammo, return FALSE
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void BotShootAtEnemy( bot_t *pBot )
|
|
{
|
|
float f_distance;
|
|
|
|
edict_t *pEdict = pBot->pEdict;
|
|
|
|
// aim for the head and/or body
|
|
Vector v_enemy = BotBodyTarget( pBot->pBotEnemy, pBot ) - GetGunPosition(pEdict);
|
|
|
|
pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
|
|
|
|
if (pEdict->v.v_angle.y > 180)
|
|
pEdict->v.v_angle.y -=360;
|
|
|
|
// Paulo-La-Frite - START bot aiming bug fix
|
|
if (pEdict->v.v_angle.x > 180)
|
|
pEdict->v.v_angle.x -=360;
|
|
|
|
// set the body angles to point the gun correctly
|
|
pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
|
|
pEdict->v.angles.y = pEdict->v.v_angle.y;
|
|
pEdict->v.angles.z = 0;
|
|
|
|
// adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
|
|
pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
|
|
// Paulo-La-Frite - END
|
|
|
|
float x = pEdict->v.v_angle.y;
|
|
if (x > 180) x -= 360;
|
|
if (abs(pEdict->v.ideal_yaw - x) > 2.0)
|
|
fp = NULL;
|
|
|
|
pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
|
|
|
|
BotFixIdealYaw(pEdict);
|
|
|
|
|
|
v_enemy.z = 0; // ignore z component (up & down)
|
|
|
|
f_distance = v_enemy.Length(); // how far away is the enemy scum?
|
|
|
|
if (f_distance > 200) // run if distance to enemy is far
|
|
pBot->f_move_speed = pBot->f_max_speed;
|
|
else if (f_distance > 20) // walk if distance is closer
|
|
pBot->f_move_speed = pBot->f_max_speed / 2;
|
|
else // don't move if close enough
|
|
pBot->f_move_speed = 0.0;
|
|
|
|
|
|
// is it time to shoot yet?
|
|
if (pBot->f_shoot_time <= gpGlobals->time)
|
|
{
|
|
// select the best weapon to use at this distance and fire...
|
|
BotFireWeapon(v_enemy, pBot, 0);
|
|
}
|
|
}
|
|
|
|
|
|
bool BotShootTripmine( bot_t *pBot )
|
|
{
|
|
edict_t *pEdict = pBot->pEdict;
|
|
|
|
if (pBot->b_shoot_tripmine != TRUE)
|
|
return FALSE;
|
|
|
|
// aim at the tripmine and fire the glock...
|
|
|
|
Vector v_enemy = pBot->v_tripmine - GetGunPosition( pEdict );
|
|
|
|
pEdict->v.v_angle = UTIL_VecToAngles( v_enemy );
|
|
|
|
if (pEdict->v.v_angle.y > 180)
|
|
pEdict->v.v_angle.y -=360;
|
|
|
|
// Paulo-La-Frite - START bot aiming bug fix
|
|
if (pEdict->v.v_angle.x > 180)
|
|
pEdict->v.v_angle.x -=360;
|
|
|
|
// set the body angles to point the gun correctly
|
|
pEdict->v.angles.x = pEdict->v.v_angle.x / 3;
|
|
pEdict->v.angles.y = pEdict->v.v_angle.y;
|
|
pEdict->v.angles.z = 0;
|
|
|
|
// adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff)
|
|
pEdict->v.v_angle.x = -pEdict->v.v_angle.x;
|
|
// Paulo-La-Frite - END
|
|
|
|
pEdict->v.ideal_yaw = pEdict->v.v_angle.y;
|
|
|
|
BotFixIdealYaw(pEdict);
|
|
|
|
return (BotFireWeapon( v_enemy, pBot, VALVE_WEAPON_GLOCK ));
|
|
}
|
|
|