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