]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/havocbot_ons.qc
Reverted the changes in tracewalk calls introduced in r6891 as it breaks the CTF...
[divverent/nexuiz.git] / data / qcsrc / server / havocbot_ons.qc
1 #define HAVOCBOT_ONS_ROLE_NONE          0
2 #define HAVOCBOT_ONS_ROLE_DEFENSE       2
3 #define HAVOCBOT_ONS_ROLE_ASSISTANT     4
4 #define HAVOCBOT_ONS_ROLE_OFFENSE       8
5
6 .float havocbot_role_flags;
7 .float havocbot_attack_time;
8
9 .void() havocbot_role;
10 .void() havocbot_previous_role;
11
12 void() havocbot_role_ons_defense;
13 void() havocbot_role_ons_offense;
14 void() havocbot_role_ons_assistant;
15
16 void(entity bot) havocbot_ons_reset_role;
17 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
18 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
19
20 .float isshielded;
21 .float iscaptured;
22 .float islinked;
23 .float isgenneighbor_blue, iscpneighbor_blue;
24 .float isgenneighbor_red, iscpneighbor_red;
25
26 void havocbot_role_ons_setrole(entity bot, float role)
27 {
28         dprint(strcat(bot.netname," switched to "));
29         switch(role)
30         {
31                 case HAVOCBOT_ONS_ROLE_DEFENSE:
32                         dprint("defense");
33                         bot.havocbot_role = havocbot_role_ons_defense;
34                         bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
35                         bot.havocbot_role_timeout = 0;
36                         break;
37                 case HAVOCBOT_ONS_ROLE_ASSISTANT:
38                         dprint("assistant");
39                         bot.havocbot_role = havocbot_role_ons_assistant;
40                         bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
41                         bot.havocbot_role_timeout = 0;
42                         break;
43                 case HAVOCBOT_ONS_ROLE_OFFENSE:
44                         dprint("offense");
45                         bot.havocbot_role = havocbot_role_ons_offense;
46                         bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
47                         bot.havocbot_role_timeout = 0;
48                         break;
49         }
50         dprint("\n");
51 };
52
53 float havocbot_ons_teamcount(entity bot, float role)
54 {
55         local float c;
56         local entity head;
57
58         FOR_EACH_PLAYER(head)
59         if(head.team==self.team)
60         if(head.havocbot_role_flags & role)
61                 ++c;
62
63         return c;
64 };
65
66 float havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
67 {
68         local entity cp, wp, bestwp;
69         local float radius, found, bestcounter;
70
71         for (cp = findchain(classname, "onslaught_controlpoint"); cp; cp = cp.chain)
72         {
73                 if(cp==world)
74                         continue;
75
76                 if(cp.isshielded)
77                         continue;
78
79                 if(self.team == COLOR_TEAM1)
80                 {
81                         if( (cp.isgenneighbor_blue || cp.iscpneighbor_blue) && !(cp.isgenneighbor_red || cp.iscpneighbor_red) )
82                                 continue;
83                 }
84                 else if(self.team == COLOR_TEAM2)
85                 {
86                         if( (cp.isgenneighbor_red || cp.iscpneighbor_red) && !(cp.isgenneighbor_blue || cp.iscpneighbor_blue) )
87                                 continue;
88                 }
89
90                 if(cp.goalentity)
91                 {
92                         // Should be attacked
93                         // Rate waypoints near it
94                         found = FALSE;
95                         bestwp = world;
96                         bestcounter = 99999999999;
97                         for(radius=0; radius<1000 && !found; radius+=500)
98                         {
99                                 for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
100                                 {
101                                         if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
102                                         if(wp.classname=="waypoint")
103                                         if(checkpvs(wp.origin,cp))
104                                         {
105                                                 found = TRUE;
106                                                 if(wp.cnt<bestcounter)
107                                                 {
108                                                         bestwp = wp;
109                                                         bestcounter = wp.cnt;
110                                                 }
111                                         }
112                                 }
113                         }
114
115                         if(bestwp)
116                         {
117                                 navigation_routerating(bestwp, ratingscale, 10000);
118                                 bestwp.cnt += 1;
119
120                                 if(checkpvs(self.view_ofs,cp))
121                                 if(checkpvs(self.view_ofs,bestwp))
122                                         self.havocbot_attack_time = time + 2;
123                         }
124                         else
125                         {
126                                 navigation_routerating(cp, ratingscale, 10000);
127                         }
128                         dprint(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n");
129                 }
130                 else
131                 {
132                         dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
133                         // Should be touched
134                         if not(bot_waypoints_for_items)
135                         {
136                                 navigation_routerating(cp, ratingscale, 10000);
137                                 return TRUE;
138                         }
139
140                         for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
141                         {
142                                 if(wp.classname=="waypoint")
143                                 {
144                                         navigation_routerating(wp, ratingscale, 10000);
145                                         return TRUE;
146                                 }
147                         }
148                         navigation_routerating(cp, ratingscale, 10000);
149                 }
150         }
151         return FALSE;
152 };
153
154 float havocbot_goalrating_ons_generator_attack(float ratingscale)
155 {
156         local entity g, wp, bestwp;
157         local float found, best;
158
159         for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
160         {
161                 if(g.team == self.team || g.isshielded)
162                         continue;
163
164                 // Should be attacked
165                 // Rate waypoints near it
166                 found = FALSE;
167                 bestwp = world;
168                 best = 99999999999;
169
170                 for(wp=findradius(g.origin,350); wp; wp=wp.chain)
171                 {
172                         if(wp.classname=="waypoint")
173                         if(checkpvs(wp.origin,g))
174                         {
175                                 found = TRUE;
176                                 if(wp.cnt<best)
177                                 {
178                                         bestwp = wp;
179                                         best = wp.cnt;
180                                 }
181                         }
182                 }
183
184                 if(bestwp)
185                 {
186                         dprint("waypoints found around generator\n");
187                         navigation_routerating(bestwp, ratingscale, 10000);
188                         bestwp.cnt += 1;
189
190                         if(checkpvs(self.view_ofs,g))
191                         if(checkpvs(self.view_ofs,bestwp))
192                                 self.havocbot_attack_time = time + 5;
193
194                         return TRUE;
195                 }
196                 else
197                 {
198                         dprint("generator found without waypoints around\n");
199                         // if there aren't waypoints near the generator go straight to it
200                         navigation_routerating(g, ratingscale, 10000);
201                         self.havocbot_attack_time = 0;
202                         return TRUE;
203                 }
204         }
205         return FALSE;
206 };
207
208 void havocbot_role_ons_offense()
209 {
210         if(self.deadflag != DEAD_NO)
211         {
212                 self.havocbot_attack_time = 0;
213                 havocbot_ons_reset_role(self);
214                 return;
215         }
216
217         // Set the role timeout if necessary
218         if (!self.havocbot_role_timeout)
219                 self.havocbot_role_timeout = time + 120;
220
221         if (time > self.havocbot_role_timeout)
222         {
223                 havocbot_ons_reset_role(self);
224                 return;
225         }
226
227         if(self.havocbot_attack_time>time)
228                 return;
229
230         if (self.bot_strategytime < time)
231         {
232                 navigation_goalrating_start();
233                 havocbot_goalrating_enemyplayers(20000, self.origin, 650);
234
235                 if(havocbot_goalrating_ons_generator_attack(20000))
236                         havocbot_goalrating_items(10000, self.origin, 300);
237                 else
238                 {
239                         havocbot_goalrating_ons_controlpoints_attack(20000);
240                         havocbot_goalrating_items(10000, self.origin, 500);
241                 }
242                 havocbot_goalrating_items(500, self.origin, 10000);
243                 navigation_goalrating_end();
244
245                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
246         }
247 };
248
249 void havocbot_role_ons_assistant()
250 {
251         havocbot_ons_reset_role(self);
252 };
253
254 void havocbot_role_ons_defense()
255 {
256         havocbot_ons_reset_role(self);
257 };
258
259 void havocbot_ons_reset_role(entity bot)
260 {
261         local entity head;
262         local float c;
263
264         if(self.deadflag != DEAD_NO)
265                 return;
266
267         // TODO: Defend control points or generator if necessary
268
269         // if there is only me on the team switch to offense
270         c = 0;
271         FOR_EACH_PLAYER(head)
272         if(head.team==self.team)
273                 ++c;
274
275         if(c==1)
276         {
277                 havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
278                 return;
279         }
280
281         havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
282 };
283
284 void havocbot_chooserole_ons()
285 {
286         havocbot_ons_reset_role(self);
287 };