[nexuiz-commits] r6863 - trunk/data/qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Jun 4 22:11:59 EDT 2009


Author: mand1nga
Date: 2009-06-04 22:11:58 -0400 (Thu, 04 Jun 2009)
New Revision: 6863

Added:
   trunk/data/qcsrc/server/havocbot_ctf.qc
Modified:
   trunk/data/qcsrc/server/havocbot_roles.qc
   trunk/data/qcsrc/server/progs.src
Log:
Major rewrite of the CTF ai 
Handle the the deadflag field on all roles
Please test and report


Added: trunk/data/qcsrc/server/havocbot_ctf.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot_ctf.qc	                        (rev 0)
+++ trunk/data/qcsrc/server/havocbot_ctf.qc	2009-06-05 02:11:58 UTC (rev 6863)
@@ -0,0 +1,664 @@
+
+#define HAVOCBOT_ROLE_NONE 		0
+#define HAVOCBOT_CTF_ROLE_DEFENSE	2
+#define HAVOCBOT_CTF_ROLE_MIDDLE	4
+#define HAVOCBOT_CTF_ROLE_OFFENSE	8
+#define HAVOCBOT_CTF_ROLE_CARRIER	16
+#define HAVOCBOT_CTF_ROLE_RETRIEVER	32
+#define HAVOCBOT_CTF_ROLE_ESCORT	64
+
+.void() havocbot_role;
+.void() havocbot_previous_role;
+
+void() havocbot_role_ctf_middle;
+void() havocbot_role_ctf_defense;
+void() havocbot_role_ctf_offense;
+void() havocbot_role_ctf_carrier;
+void() havocbot_role_ctf_retriever;
+void() havocbot_role_ctf_escort;
+
+void(entity bot) havocbot_ctf_reset_role;
+void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
+void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
+
+.float havocbot_cantfindflag;
+.float havocbot_role_timeout;
+.entity ctf_worldflagnext;
+
+vector havocbot_ctf_middlepoint;
+float havocbot_ctf_middlepoint_radius;
+entity ctf_worldflaglist;
+
+entity havocbot_ctf_find_flag(entity bot)
+{
+	entity f;
+	f = ctf_worldflaglist;
+	while (f)
+	{
+		if (bot.team == f.team)
+			return f;
+		f = f.ctf_worldflagnext;
+	}
+	return world;
+};
+
+entity havocbot_ctf_find_enemy_flag(entity bot)
+{
+	entity f;
+	f = ctf_worldflaglist;
+	while (f)
+	{
+		if (bot.team != f.team)
+			return f;
+		f = f.ctf_worldflagnext;
+	}
+	return world;
+};
+
+float havocbot_ctf_teamcount(entity bot, vector org, float radius)
+{
+	if not(teams_matter)
+		return 0;
+
+	float c;
+	entity head;
+
+	FOR_EACH_PLAYER(head)
+	{
+		if(head.team!=bot.team || head.deadflag != DEAD_NO || head == bot)
+			continue;
+
+		if(vlen(head.origin - org) < radius)
+			++c;
+	}
+
+	return c;
+};
+
+void havocbot_goalrating_ctf_ourflag(float ratingscale)
+{
+	local entity head;
+	head = ctf_worldflaglist;
+	while (head)
+	{
+		if (self.team == head.team)
+			break;
+		head = head.ctf_worldflagnext;
+	}
+	if (head)
+		navigation_routerating(head, ratingscale, 10000);
+};
+
+void havocbot_goalrating_ctf_ourbase(float ratingscale)
+{
+	if not(bot_waypoints_for_items)
+	{
+		havocbot_goalrating_ctf_ourflag(ratingscale);
+		return;
+	}
+
+	local entity head;
+	head = ctf_worldflaglist;
+	while (head)
+	{
+		if (self.team == head.team)
+			break;
+		head = head.ctf_worldflagnext;
+	}
+	if not(head)
+		return;
+
+	// dropped_origin is set by ctf code whenever the flag is picked up
+	head = findradius(head.dropped_origin, 100);
+	while(head)
+	{
+		if(head.classname=="waypoint")
+		{
+			navigation_routerating(head, ratingscale, 10000);
+			return;
+		}
+		head=head.chain;
+	}
+};
+
+void havocbot_goalrating_ctf_enemyflag(float ratingscale)
+{
+	local entity head;
+	head = ctf_worldflaglist;
+	while (head)
+	{
+		if (self.team != head.team)
+			break;
+		head = head.ctf_worldflagnext;
+	}
+	if (head)
+		navigation_routerating(head, ratingscale, 10000);
+};
+
+void havocbot_goalrating_ctf_enemybase(float ratingscale)
+{
+	if not(bot_waypoints_for_items)
+	{
+		havocbot_goalrating_ctf_enemyflag(ratingscale);
+		return;
+	}
+
+	local entity head;
+
+	head = havocbot_ctf_find_enemy_flag(self);
+
+	if not(head)
+		return;
+
+	head = findradius(head.dropped_origin, 100);
+	while(head)
+	{
+		if(head.classname=="waypoint")
+		{
+			navigation_routerating(head, ratingscale, 10000);
+			return;
+		}
+		head=head.chain;
+	}
+};
+
+void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
+{
+	local entity mf;
+
+	mf = havocbot_ctf_find_flag(self);
+
+	if(mf.cnt == FLAG_BASE)
+		return;
+
+	navigation_routerating(mf, ratingscale, 10000);
+};
+
+void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float radius)
+{
+	local entity head;
+	head = ctf_worldflaglist;
+	while (head)
+	{
+		// flag is out in the field
+		if(head.cnt != FLAG_BASE)
+		if(head.tag_entity==world)	// dropped
+		{
+			if(radius)
+			{
+				if(vlen(org-head.origin)<radius)
+					navigation_routerating(head, ratingscale, 10000);
+			}
+			else
+				navigation_routerating(head, ratingscale, 10000);
+		}
+
+		head = head.ctf_worldflagnext;
+	}
+};
+
+void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
+{
+	local entity head;
+	local float t;
+	head = findchainfloat(bot_pickup, TRUE);
+	while (head)
+	{
+		// gather health and armor only
+		if (head.solid)
+		if (head.health || head.armorvalue)
+		if (vlen(head.origin - org) < sradius)
+		{
+			// get the value of the item
+			t = head.bot_pickupevalfunc(self, head) * 0.0001;
+			if (t > 0)
+				navigation_routerating(head, t * ratingscale, 500);
+		}
+		head = head.chain;
+	}
+};
+
+void havocbot_role_ctf_setrole(entity bot, float role)
+{
+	dprint(strcat(bot.netname," switched to "));
+	switch(role)
+	{
+		case HAVOCBOT_CTF_ROLE_CARRIER:
+			dprint("carrier");
+			bot.havocbot_role = havocbot_role_ctf_carrier;
+			bot.havocbot_role_timeout = 0;
+			bot.havocbot_cantfindflag = time + 10;
+			break;
+		case HAVOCBOT_CTF_ROLE_DEFENSE:
+			dprint("defense");
+			bot.havocbot_role = havocbot_role_ctf_defense;
+			bot.havocbot_role_timeout = 0;
+			break;
+		case HAVOCBOT_CTF_ROLE_MIDDLE:
+			dprint("middle");
+			bot.havocbot_role = havocbot_role_ctf_middle;
+			bot.havocbot_role_timeout = 0;
+			break;
+		case HAVOCBOT_CTF_ROLE_OFFENSE:
+			dprint("offense");
+			bot.havocbot_role = havocbot_role_ctf_offense;
+			bot.havocbot_role_timeout = 0;
+			break;
+		case HAVOCBOT_CTF_ROLE_RETRIEVER:
+			dprint("retriever");
+			bot.havocbot_previous_role = bot.havocbot_role;
+			bot.havocbot_role = havocbot_role_ctf_retriever;
+			bot.havocbot_role_timeout = time + 10;
+			break;
+		case HAVOCBOT_CTF_ROLE_ESCORT:
+			dprint("escort");
+			bot.havocbot_previous_role = bot.havocbot_role;
+			bot.havocbot_role = havocbot_role_ctf_escort;
+			bot.havocbot_role_timeout = time + 30;
+			break;
+	}
+	dprint("\n");
+};
+
+void havocbot_role_ctf_carrier()
+{
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried == world)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.bot_strategytime < time)
+	{
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_ourbase(50000);
+
+		if(self.health<100)
+			havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
+
+		navigation_goalrating_end();
+
+		if (self.navigation_hasgoals)
+			self.havocbot_cantfindflag = time + 10;
+		else if (time > self.havocbot_cantfindflag)
+		{
+			// Can't navigate to my own base, suicide!
+			// TODO: drop it and wander around
+			Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
+			return;
+		}
+	}
+};
+
+void havocbot_role_ctf_escort()
+{
+	local entity mf, ef;
+
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	// If enemy flag is back on the base switch to previous role
+	ef = havocbot_ctf_find_enemy_flag(self);
+	if(ef.cnt==FLAG_BASE)
+	{
+		self.havocbot_role = self.havocbot_previous_role;
+		self.havocbot_role_timeout = 0;
+		return;
+	}
+
+	// If the flag carrier reached the base switch to defense
+	mf = havocbot_ctf_find_flag(self);
+	if(mf.cnt!=FLAG_BASE)
+	if(vlen(ef.origin - mf.dropped_origin) < 300)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_DEFENSE);
+		return;
+	}
+
+	// Set the role timeout if necessary
+	if (!self.havocbot_role_timeout)
+	{
+		self.havocbot_role_timeout = time + random() * 30 + 60;
+	}
+
+	// If nothing happened just switch to previous role
+	if (time > self.havocbot_role_timeout)
+	{
+		self.havocbot_role = self.havocbot_previous_role;
+		self.havocbot_role_timeout = 0;
+		return;
+	}
+
+	// Chase the flag carrier
+	if (self.bot_strategytime < time)
+	{
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_enemyflag(30000);
+		havocbot_goalrating_ctf_ourstolenflag(40000);
+		havocbot_goalrating_items(10000, self.origin, 10000);
+		navigation_goalrating_end();
+	}
+};
+
+void havocbot_role_ctf_offense()
+{
+	local entity mf, ef;
+	local vector pos;
+
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	// Check flags
+	mf = havocbot_ctf_find_flag(self);
+	ef = havocbot_ctf_find_enemy_flag(self);
+
+	// Own flag stolen
+	if(mf.cnt!=FLAG_BASE)
+	{
+		if(mf.tag_entity)
+			pos = mf.tag_entity.origin;
+		else
+			pos = mf.origin;
+
+		// Try to get it if closer than the enemy base
+		if(vlen(self.origin-ef.dropped_origin)>vlen(self.origin-pos))
+		{
+			havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER);
+			return;
+		}
+	}
+
+	// Escort flag carrier
+	if(ef.cnt!=FLAG_BASE)
+	{
+		if(ef.tag_entity)
+			pos = ef.tag_entity.origin;
+		else
+			pos = ef.origin;
+
+		if(vlen(pos-mf.dropped_origin)>700)
+		{
+			havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_ESCORT);
+			return;
+		}
+	}
+
+	// About to fail, switch to middlefield
+	if(self.health<50)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_MIDDLE);
+		return;
+	}
+
+	// Set the role timeout if necessary
+	if (!self.havocbot_role_timeout)
+		self.havocbot_role_timeout = time + 120;
+
+	if (time > self.havocbot_role_timeout)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.bot_strategytime < time)
+	{
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_ourstolenflag(50000);
+		havocbot_goalrating_ctf_enemybase(20000);
+		havocbot_goalrating_items(5000, self.origin, 1000);
+		havocbot_goalrating_items(1000, self.origin, 10000);
+		navigation_goalrating_end();
+	}
+};
+
+// Retriever (temporary role):
+void havocbot_role_ctf_retriever()
+{
+	local entity mf;
+
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	// If flag is back on the base switch to previous role
+	mf = havocbot_ctf_find_flag(self);
+	if(mf.cnt==FLAG_BASE)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (!self.havocbot_role_timeout)
+		self.havocbot_role_timeout = time + random() * 30 + 60;
+
+	if (time > self.havocbot_role_timeout)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.bot_strategytime < time)
+	{
+		local float radius;
+		radius = 10000;
+
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_ourstolenflag(50000);
+		havocbot_goalrating_ctf_droppedflags(40000, self.origin, radius);
+		havocbot_goalrating_ctf_enemybase(30000);
+		havocbot_goalrating_items(5000, self.origin, radius);
+		navigation_goalrating_end();
+	}
+};
+
+void havocbot_role_ctf_middle()
+{
+	local entity mf;
+
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	mf = havocbot_ctf_find_flag(self);
+	if(mf.cnt!=FLAG_BASE)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER);
+		return;
+	}
+
+	if (!self.havocbot_role_timeout)
+		self.havocbot_role_timeout = time + 10;
+
+	if (time > self.havocbot_role_timeout)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.bot_strategytime < time)
+	{
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_ourstolenflag(50000);
+		havocbot_goalrating_ctf_droppedflags(30000, self.origin, 10000);
+		havocbot_goalrating_enemyplayers(10000, havocbot_ctf_middlepoint, havocbot_ctf_middlepoint_radius * 0.5);
+		havocbot_goalrating_items(5000, havocbot_ctf_middlepoint, havocbot_ctf_middlepoint_radius * 0.5);
+		havocbot_goalrating_items(2500, self.origin, 10000);
+		havocbot_goalrating_ctf_enemybase(2500);
+		navigation_goalrating_end();
+	}
+};
+
+void havocbot_role_ctf_defense()
+{
+	local entity mf;
+
+	if(self.deadflag != DEAD_NO)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	// If own flag was captured
+	mf = havocbot_ctf_find_flag(self);
+	if(mf.cnt!=FLAG_BASE)
+	{
+		// And its located as far as about half the distance between the two bases
+		if(vlen(self.origin-mf.origin)<havocbot_ctf_middlepoint_radius*1.2)
+			havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_RETRIEVER);
+		return;
+	}
+
+	if (!self.havocbot_role_timeout)
+		self.havocbot_role_timeout = time + 30;
+
+	if (time > self.havocbot_role_timeout)
+	{
+		havocbot_ctf_reset_role(self);
+		return;
+	}
+	if (self.bot_strategytime < time)
+	{
+		local float radius;
+		local vector org;
+
+		org = mf.dropped_origin;
+		radius = havocbot_ctf_middlepoint_radius;
+
+		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
+		navigation_goalrating_start();
+		havocbot_goalrating_ctf_ourstolenflag(200000);
+		havocbot_goalrating_ctf_droppedflags(50000, org, radius);
+		havocbot_goalrating_enemyplayers(20000, org, radius);
+		havocbot_goalrating_items(10000, org, radius);
+		navigation_goalrating_end();
+	}
+};
+
+void havocbot_calculate_middlepoint()
+{
+	entity f;
+	vector p1, p2;
+
+	f = ctf_worldflaglist;
+	while (f)
+	{
+		if(p1)
+			p2 = f.origin;
+		else
+			p1 = f.origin;
+
+		f = f.ctf_worldflagnext;
+	}
+	havocbot_ctf_middlepoint = p1 + ((p2-p1) * 0.5);
+	havocbot_ctf_middlepoint_radius	 = vlen(p2-p1) * 0.5;
+};
+
+void havocbot_ctf_reset_role(entity bot)
+{
+	local float cdefense, cmiddle, coffense;
+	local entity mf, ef;
+
+	if(self.deadflag != DEAD_NO)
+		return;
+
+	if(vlen(havocbot_ctf_middlepoint)==0)
+		havocbot_calculate_middlepoint();
+
+	// Check ctf flags
+	if (self.flagcarried)
+	{
+		havocbot_role_ctf_setrole(self, HAVOCBOT_CTF_ROLE_CARRIER);
+		return;
+	}
+
+	mf = havocbot_ctf_find_flag(bot);
+	ef = havocbot_ctf_find_enemy_flag(bot);
+
+	// Retrieve stolen flag
+	if(mf.cnt!=FLAG_BASE)
+	{
+		havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_RETRIEVER);
+		return;
+	}
+
+	// Go to the middle to intercept pursuers
+	if(ef.cnt!=FLAG_BASE)
+	{
+		havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE);
+		return;
+	}
+
+	// Evaluate best position to take
+	// Count mates on middle position
+	cmiddle = havocbot_ctf_teamcount(bot, havocbot_ctf_middlepoint, havocbot_ctf_middlepoint_radius * 0.5);
+
+	// Count mates on defense position
+	cdefense = havocbot_ctf_teamcount(bot, mf.dropped_origin, havocbot_ctf_middlepoint_radius * 0.5);
+
+	// Count mates on offense position
+	coffense = havocbot_ctf_teamcount(bot, ef.dropped_origin, havocbot_ctf_middlepoint_radius);
+
+	if(cdefense<=coffense)
+		havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_DEFENSE);
+	else if(coffense<=cmiddle)
+		havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_OFFENSE);
+	else
+		havocbot_role_ctf_setrole(bot, HAVOCBOT_CTF_ROLE_MIDDLE);
+};
+
+void havocbot_chooserole_ctf()
+{
+	havocbot_ctf_reset_role(self);
+};

Modified: trunk/data/qcsrc/server/havocbot_roles.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot_roles.qc	2009-06-05 02:06:55 UTC (rev 6862)
+++ trunk/data/qcsrc/server/havocbot_roles.qc	2009-06-05 02:11:58 UTC (rev 6863)
@@ -319,471 +319,16 @@
 	}
 };
 
-// Functions for CTF
-
-float canreach(entity e)
-{
-	return vlen(self.origin - e.origin) < 1500;
-}
-
-float teamcount()
-{
-	if not(teams_matter)
-		return 0;
-
-	float c;
-	entity head;
-
-	FOR_EACH_PLAYER(head)
-	if(head.team==self.team)
-		++c;
-
-	return c;
-}
-
-void() havocbot_role_ctf_middle;
-void() havocbot_role_ctf_defense;
-void() havocbot_role_ctf_offense;
-void() havocbot_role_ctf_interceptor;
-
-void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
-{
-	local entity head;
-	local float t;
-	head = findchainfloat(bot_pickup, TRUE);
-	while (head)
-	{
-		// look for health and armor only
-		if (head.solid) // must be possible to pick up (respawning items don't count)
-		if (head.health || head.armorvalue)
-		if (vlen(head.origin - org) < sradius)
-		{
-			// debugging
-			//if (!head.bot_pickupevalfunc || head.model == "")
-			//	eprint(head);
-			// get the value of the item
-			t = head.bot_pickupevalfunc(self, head) * 0.0001;
-			if (t > 0)
-				navigation_routerating(head, t * ratingscale, 500);
-		}
-		head = head.chain;
-	}
-};
-
-entity ctf_worldflaglist;
-.entity ctf_worldflagnext;
-void havocbot_goalrating_ctf_ourflag(float ratingscale)
-{
-	local entity head;
-	head = ctf_worldflaglist;
-	while (head)
-	{
-		if (self.team == head.team)
-			break;
-		head = head.ctf_worldflagnext;
-	}
-	if (head)
-		navigation_routerating(head, ratingscale, 10000);
-};
-
-void havocbot_goalrating_ctf_ourbase(float ratingscale)
-{
-	if not(bot_waypoints_for_items)
-	{
-		havocbot_goalrating_ctf_ourflag(ratingscale);
-		return;
-	}
-
-	local entity head;
-	head = ctf_worldflaglist;
-	while (head)
-	{
-		if (self.team == head.team)
-			break;
-		head = head.ctf_worldflagnext;
-	}
-	if not(head)
-		return;
-
-	head = findradius(head.dropped_origin, 100);
-	while(head)
-	{
-		if(head.classname=="waypoint")
-		{
-			navigation_routerating(head, ratingscale, 10000);
-			return;
-		}
-		head=head.chain;
-	}
-};
-
-void havocbot_goalrating_ctf_enemyflag(float ratingscale)
-{
-	local entity head;
-	head = ctf_worldflaglist;
-	while (head)
-	{
-		if (self.team != head.team)
-			break;
-		head = head.ctf_worldflagnext;
-	}
-	if (head)
-		navigation_routerating(head, ratingscale, 10000);
-};
-
-void havocbot_goalrating_ctf_enemybase(float ratingscale)
-{
-	// div0: needs a change in the CTF code
-};
-
-void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
-{
-	local entity head;
-	head = ctf_worldflaglist;
-	while (head)
-	{
-		if (self.team == head.team)
-			break;
-		head = head.ctf_worldflagnext;
-	}
-	if (head)
-	if (head.cnt != FLAG_BASE)
-		navigation_routerating(head, ratingscale, 10000);
-};
-
-void havocbot_goalrating_ctf_droppedflags(float ratingscale)
-{
-	local entity head;
-	head = ctf_worldflaglist;
-	while (head)
-	{
-		if (head.cnt != FLAG_BASE) // flag is carried or out in the field
-			navigation_routerating(head, ratingscale, 10000);
-		head = head.ctf_worldflagnext;
-	}
-};
-
-// CTF: (always teamplay)
-
-//role rogue: (is this used?)
-//pick up items and dropped flags (with big rating boost to dropped flags)
-void havocbot_role_ctf_rogue()
-{
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_droppedflags(5000);
-		//havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
-		havocbot_goalrating_items(10000, self.origin, 10000);
-		navigation_goalrating_end();
-	}
-}
-
-//role flag carrier:
-//pick up armor and health
-//go to our flag spot
-.float bot_cantfindflag;
-void havocbot_role_ctf_carrier()
-{
-	if (self.flagcarried == world)
-	{
-		dprint("changing role to middle\n");
-		self.havocbot_role = havocbot_role_ctf_middle;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_ourbase(50000);
-		if(self.health<100)
-			havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
-		navigation_goalrating_end();
-
-		if (self.navigation_hasgoals)
-			self.bot_cantfindflag = time + 10;
-		else if (time > self.bot_cantfindflag)
-		{
-			// can't navigate to our own flag :(
-			Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
-			return;
-		}
-	}
-};
-
-//role offense:
-//pick up armor and health
-//if rockets < 25 || health < 100, change role to middle
-//if carrying flag, change role to flag carrier
-//if our flag taken, change role to interceptor
-//(60-90 second timer) change role to middle
-//go to enemy flag
-void havocbot_role_ctf_offense()
-{
-	local entity f;
-	if (self.flagcarried)
-	{
-		dprint("changing role to carrier\n");
-		self.havocbot_role = havocbot_role_ctf_carrier;
-		self.havocbot_role_timeout = 0;
-		self.bot_cantfindflag = time + 10;
-		return;
-	}
-	// check our flag
-	f = ctf_worldflaglist;
-	while (f)
-	{
-		if (self.team == f.team)
-			break;
-		f = f.ctf_worldflagnext;
-	}
-	if (f.cnt != FLAG_BASE && canreach(f))
-	{
-		dprint("changing role to interceptor\n");
-		self.havocbot_previous_role = self.havocbot_role;
-		self.havocbot_role = havocbot_role_ctf_interceptor;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (!self.havocbot_role_timeout)
-		self.havocbot_role_timeout = time + random() * 30 + 60;
-	if (time > self.havocbot_role_timeout)
-	{
-		dprint("changing role to middle\n");
-		self.havocbot_role = havocbot_role_ctf_middle;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_ourstolenflag(50000);
-		havocbot_goalrating_ctf_enemyflag(30000);
-		havocbot_goalrating_ctf_enemybase(20000);
-		havocbot_goalrating_items(10000, self.origin, 10000);
-		navigation_goalrating_end();
-	}
-};
-
-//role interceptor (temporary role):
-//pick up items
-//if carrying flag, change role to flag carrier
-//if our flag is back, change role to previous role
-//follow our flag
-//go to least recently visited area
-void havocbot_role_ctf_interceptor()
-{
-	local entity f;
-	if (self.flagcarried)
-	{
-		dprint("changing role to carrier\n");
-		self.havocbot_role = havocbot_role_ctf_carrier;
-		self.havocbot_role_timeout = 0;
-		self.bot_cantfindflag = time + 10;
-		return;
-	}
-	// check our flag
-	f = ctf_worldflaglist;
-	while (f)
-	{
-		if (self.team == f.team)
-			break;
-		f = f.ctf_worldflagnext;
-	}
-	if (f.cnt == FLAG_BASE)
-	{
-		dprint("changing role back\n");
-		self.havocbot_role = self.havocbot_previous_role;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_ourstolenflag(50000);
-		havocbot_goalrating_ctf_droppedflags(50000);
-		havocbot_goalrating_items(10000, self.origin, 10000);
-		navigation_goalrating_end();
-	}
-};
-
-//role middle:
-//pick up items
-//if carrying flag, change role to flag carrier
-//if our flag taken, change role to interceptor
-//if see flag (of either team) follow it (this has many implications)
-//(10-20 second timer) change role to defense or offense
-//go to least recently visited area
-void havocbot_role_ctf_middle()
-{
-	local entity f;
-	if (self.flagcarried)
-	{
-		dprint("changing role to carrier\n");
-		self.havocbot_role = havocbot_role_ctf_carrier;
-		self.havocbot_role_timeout = 0;
-		self.bot_cantfindflag = time + 10;
-		return;
-	}
-	// check our flag
-	f = ctf_worldflaglist;
-	while (f)
-	{
-		if (self.team == f.team)
-			break;
-		f = f.ctf_worldflagnext;
-	}
-	if (f.cnt != FLAG_BASE && canreach(f))
-	{
-		dprint("changing role to interceptor\n");
-		self.havocbot_previous_role = self.havocbot_role;
-		self.havocbot_role = havocbot_role_ctf_interceptor;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (!self.havocbot_role_timeout)
-		self.havocbot_role_timeout = time + random() * 10 + 10;
-	if (time > self.havocbot_role_timeout)
-	{
-		if (random() < 0.5)
-		{
-			dprint("changing role to offense\n");
-			self.havocbot_role = havocbot_role_ctf_offense;
-		}
-		else
-		{
-			dprint("changing role to defense\n");
-			self.havocbot_role = havocbot_role_ctf_defense;
-		}
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_ourstolenflag(50000);
-		havocbot_goalrating_ctf_droppedflags(30000);
-		//havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
-		havocbot_goalrating_items(10000, self.origin, 10000);
-		navigation_goalrating_end();
-	}
-};
-
-//role defense:
-//if rockets < 25 || health < 100, change role to middle
-//if carrying flag, change role to flag carrier
-//if our flag taken, change role to interceptor
-//(30-50 second timer) change role to middle
-//move to nearest unclaimed defense spot
-void havocbot_role_ctf_defense()
-{
-	local entity f;
-	if (self.flagcarried)
-	{
-		dprint("changing role to carrier\n");
-		self.havocbot_role = havocbot_role_ctf_carrier;
-		self.havocbot_role_timeout = 0;
-		self.bot_cantfindflag = time + 10;
-		return;
-	}
-	// check our flag
-	f = ctf_worldflaglist;
-	while (f)
-	{
-		if (self.team == f.team)
-			break;
-		f = f.ctf_worldflagnext;
-	}
-	if (f.cnt != FLAG_BASE && canreach(f))
-	{
-		dprint("changing role to interceptor\n");
-		self.havocbot_previous_role = self.havocbot_role;
-		self.havocbot_role = havocbot_role_ctf_interceptor;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (!self.havocbot_role_timeout)
-		self.havocbot_role_timeout = time + random() * 20 + 30;
-	if (time > self.havocbot_role_timeout)
-	{
-		dprint("changing role to middle\n");
-		self.havocbot_role = havocbot_role_ctf_middle;
-		self.havocbot_role_timeout = 0;
-		return;
-	}
-	if (self.bot_strategytime < time)
-	{
-		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
-		navigation_goalrating_start();
-		havocbot_goalrating_ctf_ourstolenflag(200000);
-		havocbot_goalrating_ctf_droppedflags(50000);
-		havocbot_goalrating_items(10000, f.origin, 10000);
-		navigation_goalrating_end();
-	}
-	/*
-	// FIXME: place info_ctf_defensepoint entities in CTF maps and use them
-	// change position occasionally
-	if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
-	{
-		self.bot_strategytime = time + random() * 45 + 15;
-		self.goalentity = world;
-		head = findchain(classname, "info_ctf_defensepoint");
-		while (head)
-		{
-			if (time > head.count)
-			{
-				self.goalentity = head;
-				head.chain = world;
-			}
-			head = head.chain;
-		}
-		// if there are no defensepoints defined, switch to middle
-		if (self.goalentity == world)
-		{
-			dprint("changing role to middle\n");
-			self.havocbot_role = havocbot_role_ctf_middle;
-			self.havocbot_role_timeout = 0;
-			return;
-		}
-	}
-	// keep anyone else from taking this spot
-	if (self.goalentity != world)
-		self.goalentity.count = time + 0.5;
-	*/
-};
-
-// CTF:
 // choose a role according to the situation
 void() havocbot_role_dm;
-void havocbot_chooserole_ctf()
-{
-	local float r;
-	dprint("choose CTF role...\n");
-	if (self.team == COLOR_TEAM3 || self.team == COLOR_TEAM4)
-		self.havocbot_role = havocbot_role_ctf_rogue;
-	else
-	{
-		r = random() * 100;
-		if (r < 45)
-			self.havocbot_role = havocbot_role_ctf_offense;
-		else if (r > 75)
-			self.havocbot_role = havocbot_role_ctf_middle;
-		else
-			self.havocbot_role = havocbot_role_ctf_defense;
-	}
-};
 
 //DOM:
 //go to best items, or control points you don't own
 void havocbot_role_dom()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (self.bot_strategytime < time)
 	{
 		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
@@ -800,6 +345,9 @@
 //go to best items
 void havocbot_role_dm()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (self.bot_strategytime < time)
 	{
 		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
@@ -816,6 +364,9 @@
 .float race_checkpoint;
 void havocbot_role_race()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	entity e;
 	if (self.bot_strategytime < time)
 	{
@@ -897,6 +448,9 @@
 void() havocbot_role_kh_freelancer;
 void havocbot_role_kh_carrier()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (!(self.items & IT_KEY1))
 	{
 		dprint("changing role to freelancer\n");
@@ -922,6 +476,9 @@
 
 void havocbot_role_kh_defense()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (self.items & IT_KEY1)
 	{
 		dprint("changing role to carrier\n");
@@ -961,6 +518,9 @@
 
 void havocbot_role_kh_offense()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (self.items & IT_KEY1)
 	{
 		dprint("changing role to carrier\n");
@@ -1001,6 +561,9 @@
 
 void havocbot_role_kh_freelancer()
 {
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	if (self.items & IT_KEY1)
 	{
 		dprint("changing role to carrier\n");
@@ -1050,6 +613,10 @@
 void havocbot_chooserole_kh()
 {
 	local float r;
+
+	if(self.deadflag != DEAD_NO)
+		return;
+
 	r = random() * 3;
 	if (r < 1)
 		self.havocbot_role = havocbot_role_kh_offense;

Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src	2009-06-05 02:06:55 UTC (rev 6862)
+++ trunk/data/qcsrc/server/progs.src	2009-06-05 02:11:58 UTC (rev 6863)
@@ -53,6 +53,7 @@
 
 // LordHavoc's bots
 havocbot.qc
+havocbot_ctf.qc
 havocbot_roles.qc
 
 g_subs.qc



More information about the nexuiz-commits mailing list