r5813 - trunk/data/qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Feb 9 09:58:59 EST 2009


Author: mand1nga
Date: 2009-02-09 09:58:59 -0500 (Mon, 09 Feb 2009)
New Revision: 5813

Modified:
   trunk/data/qcsrc/server/bots.qc
   trunk/data/qcsrc/server/havocbot.qc
   trunk/data/qcsrc/server/havocbot_roles.qc
Log:
Bot improvements:
Use the 2nd best rated goal if something happened to the primary goal (ie: someone picked it up before). This is cheaper than forcing a whole strategy re-think.
Anti lemming behavior workaround
Force strategy re-think upon respawn
Moved keyboard emulation out of movetogoal()
Made them "try" to jump out of lava

Modified: trunk/data/qcsrc/server/bots.qc
===================================================================
--- trunk/data/qcsrc/server/bots.qc	2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/bots.qc	2009-02-09 14:58:59 UTC (rev 5813)
@@ -366,11 +366,12 @@
 // used during navigation_goalrating_begin/end sessions
 float navigation_bestrating;
 entity navigation_bestgoal;
+entity navigation_alternativegoal;
+.entity alternativegoal;
 
 
 
 
-
 /////////////////////////////////////////////////////////////////////////////
 // spawnfunc_waypoint management
 /////////////////////////////////////////////////////////////////////////////
@@ -1252,6 +1253,7 @@
 		//dprint(ftos(f));
 		if (navigation_bestrating < f)
 		{
+			navigation_alternativegoal = navigation_bestgoal;
 			navigation_bestrating = f;
 			navigation_bestgoal = e;
 		}
@@ -1325,6 +1327,7 @@
 {
 	if (self.havocbot_role == havocbot_role_ctf_offense)
 		dprint(navigation_bestgoal.classname, " (with rating ", ftos(navigation_bestrating), ")\n");
+	self.alternativegoal = navigation_alternativegoal;
 	navigation_routetogoal(navigation_bestgoal);
 };
 
@@ -1367,6 +1370,7 @@
 .float(entity player, entity item) bot_pickupevalfunc;
 .float bot_pickupbasevalue;
 .float bot_canfire;
+.float bot_strategytime;
 
 // used for aiming currently
 // FIXME: make the weapon code use these and then replace the calculations here with a call to the weapon code
@@ -1940,10 +1944,13 @@
 	if (self.deadflag)
 	{
 		if (self.deadflag == DEAD_DEAD)
+		{
 			self.BUTTON_JUMP = 1; // press jump to respawn
-		return;
+			self.bot_strategytime = 0;
+			return;
+		}
 	}
-
+	
 	// now call the current bot AI (havocbot for example)
 	self.bot_ai();
 };

Modified: trunk/data/qcsrc/server/havocbot.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot.qc	2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/havocbot.qc	2009-02-09 14:58:59 UTC (rev 5813)
@@ -55,10 +55,82 @@
 	*/
 };
 
-//.float havocbotignoretime;
 .float havocbot_keyboardtime;
 .float havocbot_ducktime;
 .vector havocbot_keyboard;
+void havocbot_keyboard_movement(vector destorg)
+{
+	local vector keyboard;
+	local float blend, maxspeed;
+
+	maxspeed = cvar("sv_maxspeed");	
+
+	if (time < self.havocbot_keyboardtime)
+		return;
+
+	self.havocbot_keyboardtime =
+		max(
+			self.havocbot_keyboardtime
+				+ bound(0,0.05/(skill+self.havocbot_keyboardskill),0.05)
+				+random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
+		, time);
+	keyboard = self.movement * (1.0 / maxspeed);
+
+	local float trigger, trigger1;
+	blend = bound(0,skill*0.1,1);
+	trigger = cvar("bot_ai_keyboard_treshold");
+	trigger1 = 0 - trigger;
+
+	// categorize forward movement
+	// at skill < 1.5 only forward
+	// at skill < 2.5 only individual directions
+	// at skill < 4.5 only individual directions, and forward diagonals
+	// at skill >= 4.5, all cases allowed
+	if (keyboard_x > trigger)
+	{
+		keyboard_x = 1;
+		if (skill < 2.5)
+			keyboard_y = 0;
+	}
+	else if (keyboard_x < trigger1 && skill > 1.5)
+	{
+		keyboard_x = -1;
+		if (skill < 4.5)
+			keyboard_y = 0;
+	}
+	else
+	{
+		keyboard_x = 0;
+		if (skill < 1.5)
+			keyboard_y = 0;
+	}
+	if (skill < 4.5)
+		keyboard_z = 0;
+
+	if (keyboard_y > trigger)
+		keyboard_y = 1;
+	else if (keyboard_y < trigger1)
+		keyboard_y = -1;
+	else
+		keyboard_y = 0;
+
+	if (keyboard_z > trigger)
+		keyboard_z = 1;
+	else if (keyboard_z < trigger1)
+		keyboard_z = -1;
+	else
+		keyboard_z = 0;
+
+	self.havocbot_keyboard = keyboard * maxspeed;
+	if (self.havocbot_ducktime>time) self.BUTTON_CROUCH=TRUE;
+
+	keyboard = self.havocbot_keyboard;
+	blend = bound(0,vlen(destorg-self.origin)/cvar("bot_ai_keyboard_distance"),1); // When getting close move with 360 degree
+	//dprint("movement ", vtos(self.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
+	self.movement = self.movement + (keyboard - self.movement) * blend;
+};
+
+//.float havocbotignoretime;
 //.vector bot_dodgevector;
 //.float bot_dodgevector_time;
 //.float bot_dodgevector_jumpbutton;
@@ -91,13 +163,26 @@
 
 	if (self.goalcurrent == world)
 		return;
+
 	navigation_poptouchedgoals();
 	if (self.goalcurrent == world)
 	{
-		// ran out of goals, rethink strategy as soon as possible
-		self.bot_strategytime = 0;
+		if(self.alternativegoal==world)
+		{
+			// ran out of goals, rethink strategy as soon as possible
+			self.bot_strategytime = 0;
+			return;
+		}
+		// try to use the alternative goal
+		navigation_findnearestwaypoint(self.alternativegoal, TRUE);
+		navigation_routetogoal(self.alternativegoal);
+		self.alternativegoal = world;
 		return;
 	}
+
+//	te_wizspike(self.goalcurrent.origin);
+//	te_lightning2(world, self.origin, self.goalcurrent.origin);
+
 	m1 = self.goalcurrent.origin + self.goalcurrent.mins;
 	m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
 	destorg = self.origin;
@@ -109,23 +194,21 @@
 	dir = normalize(diff);
 	flatdir = diff;flatdir_z = 0;
 	flatdir = normalize(flatdir);
+
 	//if (self.bot_dodgevector_time < time)
 	{
 	//	self.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
 	//	self.bot_dodgevector_jumpbutton = 1;
 		evadeobstacle = '0 0 0';
 		evadelava = '0 0 0';
-		if (!self.waterlevel)
+		if (self.waterlevel)
 		{
-			// Since new update in air contol, we can move in air
-			//if (!(self.flags & FL_ONGROUND))
-			//{
-			//	// prevent goal checks when we can't walk
-			//	if (self.bot_strategytime < time + 0.1)
-			//		self.bot_strategytime = time + 0.1;
-			//	return;
-			//}
-
+			makevectors(self.v_angle);
+			self.BUTTON_JUMP = 1;
+			// TODO: Make them swim up
+		}
+		else
+		{
 			// jump if going toward an obstacle that doesn't look like stairs we
 			// can walk up directly
 			tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.2, FALSE, self);
@@ -144,18 +227,42 @@
 				}
 			}
 
-			traceline(self.origin + self.velocity * 0.3, self.origin + self.velocity * 0.3 + '0 0 -1000', TRUE, world);
-			s = pointcontents(trace_endpos + '0 0 1');
-			if (s == CONTENT_LAVA || s == CONTENT_SLIME)
-				evadelava = normalize(self.velocity) * -1;
+			// avoiding dangers and obstacles
+			// TODO: don't make this check every frame
+			if(self.flags & FL_ONGROUND)
+			{
+				local vector dst_ahead, dst_down;
+				dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.3);
+				dst_down = dst_ahead + '0 0 -1500';				
+				
+				traceline(self.origin + self.view_ofs , dst_ahead, TRUE, world);
+				
+				if(trace_fraction == 1){
+					traceline(dst_ahead , dst_down, TRUE, world);
+				//	te_lightning2(world, self.origin, dst_ahead);	// Draw "ahead" look 
+					if(trace_fraction == 1)
+					{
+						s = pointcontents(trace_endpos + '0 0 1');
+						if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+							evadelava = normalize(self.velocity) * -1;
+						else if (s == CONTENT_SKY)
+							evadeobstacle = normalize(self.velocity) * -1;
+						else if (tracebox_hits_trigger_hurt(dst_ahead, self.mins, self.maxs, trace_endpos))
+						{
+						//	te_lightning2(world, dst_ahead, dst_down);	// Draw "downards" look
+							// TODO: this could be better, but actually it stops lemming behavior
+							evadeobstacle = flatdir * -1;
+						}
+					}
+				}
+			}
 
 			dir = flatdir;
 			evadeobstacle_z = 0;
 			evadelava_z = 0;
 			makevectors(self.v_angle_y * '0 1 0');
 		}
-		else
-			makevectors(self.v_angle);
+
 		dodge = havocbot_dodge();
 		dodge = dodge * bound(0,3+skill*0.1,1);
 		evadelava = evadelava * bound(1,3-skill,3); //Noobs fear lava a lot and take more distance from it
@@ -176,79 +283,13 @@
 	self.movement_y = dir * v_right * maxspeed;
 	self.movement_z = dir * v_up * maxspeed;
 
+	// Emulate keyboard interface
 	if (skill < 10)
-	{
-		// Emulate keyboard interface;
-		local vector keyboard;
-		local float blend;
-		if (time >= self.havocbot_keyboardtime)
-		{
-			self.havocbot_keyboardtime =
-				max(
-					self.havocbot_keyboardtime
-						+ bound(0,0.05/(skill+self.havocbot_keyboardskill),0.05)
-						+random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
-				, time);
-			keyboard = self.movement * (1.0 / maxspeed);
+		havocbot_keyboard_movement(destorg);
 
-			local float trigger, trigger1;
-			blend = bound(0,skill*0.1,1);
-			trigger = cvar("bot_ai_keyboard_treshold");
-			trigger1 = 0 - trigger;
-
-			// categorize forward movement
-			// at skill < 1.5 only forward
-			// at skill < 2.5 only individual directions
-			// at skill < 4.5 only individual directions, and forward diagonals
-			// at skill >= 4.5, all cases allowed
-			if (keyboard_x > trigger)
-			{
-				keyboard_x = 1;
-				if (skill < 2.5)
-					keyboard_y = 0;
-			}
-			else if (keyboard_x < trigger1 && skill > 1.5)
-			{
-				keyboard_x = -1;
-				if (skill < 4.5)
-					keyboard_y = 0;
-			}
-			else
-			{
-				keyboard_x = 0;
-				if (skill < 1.5)
-					keyboard_y = 0;
-			}
-			if (skill < 4.5)
-				keyboard_z = 0;
-
-			if (keyboard_y > trigger)
-				keyboard_y = 1;
-			else if (keyboard_y < trigger1)
-				keyboard_y = -1;
-			else
-				keyboard_y = 0;
-
-			if (keyboard_z > trigger)
-				keyboard_z = 1;
-			else if (keyboard_z < trigger1)
-				keyboard_z = -1;
-			else
-				keyboard_z = 0;
-
-			self.havocbot_keyboard = keyboard * maxspeed;
-			if (self.havocbot_ducktime>time) self.BUTTON_CROUCH=TRUE;
-		}
-		keyboard = self.havocbot_keyboard;
-		blend = bound(0,vlen(destorg-self.origin)/cvar("bot_ai_keyboard_distance"),1); // When getting close move with 360 degree
-		//dprint("movement ", vtos(self.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
-		self.movement = self.movement + (keyboard - self.movement) * blend;
-	}
-
 	if ((dir * v_up) >= cvar("sv_jumpvelocity")*0.5 && (self.flags & FL_ONGROUND)) self.BUTTON_JUMP=1;
 	if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill)*0.1,1)) self.BUTTON_JUMP=TRUE;
 	if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill)*0.1,1)) self.havocbot_ducktime=time+0.3/bound(0.1,skill,10);
-
 };
 
 .float havocbot_chooseenemy_finished;
@@ -559,6 +600,9 @@
 		// token has been used this frame
 		bot_strategytoken_taken = TRUE;
 	}
+	if(self.deadflag)
+		return;
+
 	havocbot_chooseenemy();
 	if (self.bot_chooseweapontime < time )
 	{

Modified: trunk/data/qcsrc/server/havocbot_roles.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot_roles.qc	2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/havocbot_roles.qc	2009-02-09 14:58:59 UTC (rev 5813)
@@ -1,7 +1,6 @@
 
 .float havocbot_role_timeout;
 .void() havocbot_previous_role;
-.float bot_strategytime;
 .void() havocbot_role;
 float bot_ignore_bots;
 
@@ -236,10 +235,28 @@
 		if (self != head)
 		if (head.health > 0)
 		if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
-		if (vlen(head.origin - org) < sradius)
 		{
+			if (vlen(head.origin - org) > sradius)
+				continue;
+				
+			// rate only visible enemies
+			/*
+			traceline(self.origin + self.view_ofs, head.origin, MOVE_NOMONSTERS, self);
+			if (trace_fraction < 1 || trace_ent != head)
+				continue;
+			*/
+			
+			// not falling
+			if(head.flags & FL_ONGROUND == 0)
+			{
+				traceline(head.origin, head.origin + '0 0 -1500', TRUE, world);
+				t = pointcontents(trace_endpos + '0 0 1');
+				if (t != CONTENT_SOLID)
+					continue;
+				// TODO: check for trigger_hurt here
+			}
+			
 			t = (self.health + self.armorvalue ) / (head.health + head.armorvalue );
-		//	clientcommand(self, strcat("say rating ", ftos(t*ratingscale)));
 			navigation_routerating(head, t * ratingscale, 2000);
 		}
 	}




More information about the nexuiz-commits mailing list