[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