r5241 - trunk/data/qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Tue Dec 16 08:43:41 EST 2008
Author: div0
Date: 2008-12-16 08:43:41 -0500 (Tue, 16 Dec 2008)
New Revision: 5241
Modified:
trunk/data/qcsrc/server/bots.qc
trunk/data/qcsrc/server/havocbot.qc
Log:
bots: combos; custom weapon priorities
Modified: trunk/data/qcsrc/server/bots.qc
===================================================================
--- trunk/data/qcsrc/server/bots.qc 2008-12-16 13:34:27 UTC (rev 5240)
+++ trunk/data/qcsrc/server/bots.qc 2008-12-16 13:43:41 UTC (rev 5241)
@@ -1499,6 +1499,89 @@
self.netname = name;
};
+float bot_custom_weapon;
+float bot_distance_far;
+float bot_distance_close;
+
+float bot_weapons_far[WEP_LAST];
+float bot_weapons_mid[WEP_LAST];
+float bot_weapons_close[WEP_LAST];
+
+void bot_custom_weapon_priority_setup()
+{
+ local float tokens, i, c, w;
+
+ bot_custom_weapon = FALSE;
+
+ if( cvar_string("bot_ai_custom_weapon_priority_far") == "" ||
+ cvar_string("bot_ai_custom_weapon_priority_mid") == "" ||
+ cvar_string("bot_ai_custom_weapon_priority_close") == "" ||
+ cvar_string("bot_ai_custom_weapon_priority_distances") == ""
+ )
+ return;
+
+ // Parse distances
+ tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_distances")," ");
+
+ if (tokens!=2)
+ return;
+
+ bot_distance_far = stof(argv(0));
+ bot_distance_close = stof(argv(1));
+
+ if(bot_distance_far < bot_distance_close){
+ bot_distance_far = stof(argv(1));
+ bot_distance_close = stof(argv(0));
+ }
+
+ // Initialize list of weapons
+ bot_weapons_far[0] = -1;
+ bot_weapons_mid[0] = -1;
+ bot_weapons_close[0] = -1;
+
+ // Parse far distance weapon priorities
+ tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_far")," ");
+
+ c = 0;
+ for(i=0; i < tokens && i < WEP_LAST; ++i){
+ w = stof(argv(i));
+ if ( w >= WEP_FIRST && w <= WEP_LAST) {
+ bot_weapons_far[c] = w;
+ ++c;
+ }
+ }
+ bot_weapons_far[c] = -1;
+
+ // Parse mid distance weapon priorities
+ tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_mid")," ");
+
+ c = 0;
+ for(i=0; i < tokens && i < WEP_LAST; ++i){
+ w = stof(argv(i));
+ if ( w >= WEP_FIRST && w <= WEP_LAST) {
+ bot_weapons_mid[c] = w;
+ ++c;
+ }
+ }
+ bot_weapons_mid[c] = -1;
+
+ // Parse close distance weapon priorities
+ tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_close")," ");
+
+ c = 0;
+ for(i=0; i < tokens && i < WEP_LAST; ++i){
+ w = stof(argv(i));
+ if ( w >= WEP_FIRST && w <= WEP_LAST) {
+ bot_weapons_close[c] = w;
+ ++c;
+ }
+ }
+ bot_weapons_close[c] = -1;
+
+ bot_custom_weapon = TRUE;
+};
+
+
void bot_endgame()
{
local entity e;
@@ -2169,6 +2252,7 @@
head.totalfrags_lastcheck = head.totalfrags;
}
+float bot_cvar_nextthink;
void bot_serverframe()
{
float realplayers, bots, activerealplayers;
@@ -2288,4 +2372,11 @@
if (cvar("g_waypointeditor"))
botframe_showwaypointlinks();
+
+ if(time > bot_cvar_nextthink)
+ {
+ if(currentbots>1)
+ bot_custom_weapon_priority_setup();
+ bot_cvar_nextthink = time + 5;
+ }
};
Modified: trunk/data/qcsrc/server/havocbot.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot.qc 2008-12-16 13:34:27 UTC (rev 5240)
+++ trunk/data/qcsrc/server/havocbot.qc 2008-12-16 13:43:41 UTC (rev 5241)
@@ -320,6 +320,7 @@
self.havocbot_stickenemy = 1;
};
+.float bot_chooseweapontime;
float(entity e) w_getbestweapon;
void havocbot_chooseweapon()
{
@@ -350,6 +351,62 @@
local float distancefromfloor;
traceline(self.enemy.origin,self.enemy.origin-'0 0 1000',TRUE,world);
distancefromfloor = self.enemy.origin_z - trace_endpos_z;
+
+ // Custom weapon list based on distance to the enemy
+ local float i; i = 0;
+ if(bot_custom_weapon){
+
+ // Choose weapons for far distance
+ if ( distance > bot_distance_far ) {
+ for(i=0; i < WEP_LAST && bot_weapons_far[i] != -1 ; ++i){
+ w = bot_weapons_far[i];
+ if ( client_hasweapon(self, w, TRUE, FALSE) ){
+ if ( self.weapon == w){
+ if( cvar("bot_ai_weapon_combo") &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold"))
+ continue;
+ } else {
+ self.switchweapon = w;
+ }
+ return;
+ }
+ }
+ }
+
+ // Choose weapons for mid distance
+ if ( distance > bot_distance_close ) {
+ for(i=0; i < WEP_LAST && bot_weapons_mid[i] != -1 ; ++i){
+ w = bot_weapons_mid[i];
+ if ( client_hasweapon(self, w, TRUE, FALSE) ){
+ if ( self.weapon == w){
+ if( cvar("bot_ai_weapon_combo") &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold"))
+ continue;
+ } else {
+ self.switchweapon = w;
+ }
+ return;
+ }
+ }
+ }
+
+ // Choose weapons for close distance
+ for(i=0; i < WEP_LAST && bot_weapons_close[i] != -1 ; ++i){
+ w = bot_weapons_close[i];
+ if ( client_hasweapon(self, w, TRUE, FALSE) ){
+ if ( self.weapon == w){
+ if( cvar("bot_ai_weapon_combo") &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold"))
+ continue;
+ } else {
+ self.switchweapon = w;
+ }
+ return;
+ }
+ }
+ // If now weapon was chosen by this system fall back to the previous one
+ }
+
// Formula:
// (Damage/Sec * Weapon spefic change to get that damage)
// *(Time to get to target * weapon specfic hitchange bonus) / (in a time of maxdelaytime)
@@ -359,33 +416,71 @@
if (client_hasweapon(self, WEP_MINSTANEX, TRUE, FALSE))
minstanex = (1000/cvar("g_balance_minstanex_refire")*1.0)
* (0.5);
- if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE) &&
+ !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_ROCKET_LAUNCHER &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
rocket = (cvar("g_balance_rocketlauncher_damage")/cvar("g_balance_rocketlauncher_refire")*0.75)
* bound(0,(cvar("g_balance_rocketlauncher_speed")/distance*maxdelaytime),1)*1.5;
- if (client_hasweapon(self, WEP_NEX, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_NEX, TRUE, FALSE) &&
+ !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_NEX &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
nex = (cvar("g_balance_nex_damage")/cvar("g_balance_nex_refire")*1.0)
* (0.5);
- if (client_hasweapon(self, WEP_HAGAR, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_HAGAR, TRUE, FALSE) ) // &&
+ // !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_HAGAR && time < self.bot_lastshot + cvar("g_balance_hagar_primary_refire") ))
hagar = (cvar("g_balance_hagar_primary_damage")/cvar("g_balance_hagar_primary_refire")*1.0)
* bound(0,(cvar("g_balance_hagar_primary_speed")/distance*maxdelaytime),1)*0.2;
- if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE, FALSE) &&
+ !(
+ cvar("bot_ai_weapon_combo") && self.weapon == WEP_GRENADE_LAUNCHER &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
grenade = (cvar("g_balance_grenadelauncher_primary_damage")/cvar("g_balance_grenadelauncher_primary_refire")*1.0)
* bound(0,(cvar("g_balance_grenadelauncher_primary_speed")/distance*maxdelaytime),1)*1.1;
- if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE) &&
+ !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_ELECTRO &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
electro = (cvar("g_balance_electro_primary_damage")/cvar("g_balance_electro_primary_refire")*0.75)
* bound(0,(cvar("g_balance_electro_primary_speed")/distance*maxdelaytime),1)*1.0;
- if (client_hasweapon(self, WEP_CRYLINK, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_CRYLINK, TRUE, FALSE) ) // &&
+ // !( self.weapon == WEP_CRYLINK && time < self.bot_lastshot + cvar("g_balance_crylink_primary_refire") ))
crylink = (cvar("g_balance_crylink_primary_damage")/cvar("g_balance_crylink_primary_refire")*1.0)
* bound(0,(cvar("g_balance_crylink_primary_speed")/distance*maxdelaytime),1)*(64/(32+cvar("g_balance_crylink_primary_spread")*distance))*1.0;
- if (client_hasweapon(self, WEP_UZI, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_UZI, TRUE, FALSE) ) // &&
+ // !( self.weapon == WEP_UZI && time < self.bot_lastshot + cvar("g_balance_uzi_sustained_refire") ))
uzi = (cvar("g_balance_uzi_sustained_damage")/cvar("g_balance_uzi_sustained_refire")*1.0)
* bound(0,32/(32+cvar("g_balance_uzi_sustained_spread")*distance),1);
- if (client_hasweapon(self, WEP_SHOTGUN, TRUE, FALSE))
+
+ if (client_hasweapon(self, WEP_SHOTGUN, TRUE, FALSE) &&
+ !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_SHOTGUN &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
shotgun = (cvar("g_balance_shotgun_primary_damage")*cvar("g_balance_shotgun_primary_bullets")/cvar("g_balance_shotgun_primary_refire")*1.0)
* bound(0,32/(32+cvar("g_balance_shotgun_primary_spread")*distance),1);
- if (client_hasweapon(self, WEP_LASER, FALSE, FALSE))
+
+ if (client_hasweapon(self, WEP_LASER, FALSE, FALSE) &&
+ !( cvar("bot_ai_weapon_combo") && self.weapon == WEP_LASER &&
+ ATTACK_FINISHED(self) > time + cvar("bot_ai_weapon_combo_threshold")
+ )
+ )
laser = (cvar("g_balance_laser_primary_damage")/cvar("g_balance_laser_primary_refire")*1.0)
* bound(0,cvar("g_balance_laser_primary_speed")/distance*maxdelaytime,1);
+
if((self.enemy.flags & FL_ONGROUND)==FALSE){
rocket = rocket * (1.5-bound(0, distancefromfloor/cvar("g_balance_rocketlauncher_radius" ),0.9)); //slight bigger change
grenade = grenade * (1.5-bound(0,distancefromfloor/cvar("g_balance_grenadelauncher_primary_radius"),0.95));
@@ -417,8 +512,13 @@
w = WEP_LASER ;s = laser ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
// switch if the best weapon would provide a significant damage increase
- if (bestscore > currentscore*1.5)
+ if (bestscore > currentscore*1.5){
self.switchweapon = bestweapon;
+
+ // buys time for detonating the rocket. not tested yet
+ if ( cvar("bot_ai_weapon_combo") && bestweapon == WEP_ROCKET_LAUNCHER )
+ self.bot_chooseweapontime += (distance / cvar("g_balance_rocketlauncher_speed"));
+ }
};
.float nextaim;
@@ -442,7 +542,6 @@
lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, self.goalcurrent.origin, '0 0 0');
};
-.float bot_chooseweapontime;
void havocbot_ai()
{
if (bot_strategytoken == self)
@@ -453,7 +552,7 @@
bot_strategytoken_taken = TRUE;
}
havocbot_chooseenemy();
- if (self.bot_chooseweapontime < time)
+ if (self.bot_chooseweapontime < time )
{
self.bot_chooseweapontime = time + cvar("bot_ai_chooseweaponinterval");
havocbot_chooseweapon();
More information about the nexuiz-commits
mailing list