]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/bot/havocbot/role_assault.qc
Many minor improvements
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / havocbot / role_assault.qc
1 #define HAVOCBOT_AST_ROLE_NONE          0
2 #define HAVOCBOT_AST_ROLE_DEFENSE       2
3 #define HAVOCBOT_AST_ROLE_OFFENSE       4
4
5 .float havocbot_role_flags;
6 .float havocbot_attack_time;
7
8 .void() havocbot_role;
9 .void() havocbot_previous_role;
10
11 void() havocbot_role_ast_defense;
12 void() havocbot_role_ast_offense;
13 .entity havocbot_ast_target;
14
15 entity havocbot_ast_core;
16 float havocbot_ast_core_unreachable;
17
18 void(entity bot) havocbot_ast_reset_role;
19
20 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
21 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
22
23 void havocbot_ast_find_core()
24 {
25         entity are, to1, to2, to3;
26
27         if(havocbot_ast_core_unreachable)
28                 return;
29
30         are = findchain(classname, "target_assault_roundend");
31
32         for (; are; are = are.chain)
33         {
34                 for(to1 = world; (to1 = find(to1, target, are.targetname)); )
35                 {
36                         if(to1.classname == "func_assault_destructible")
37                         {
38                                 havocbot_ast_core = to1;
39                                 return;
40                         }
41
42                         for(to2 = world; (to2 = find(to2, target, to1.targetname)); )
43                         {
44                                 if(to2.classname == "func_assault_destructible")
45                                 {
46                                         havocbot_ast_core = to2;
47                                         return;
48                                 }
49
50                                 for(to3 = world; (to3 = find(to3, target, to2.targetname)); )
51                                 {
52                                         if(to3.classname == "func_assault_destructible")
53                                         {
54                                                 havocbot_ast_core = to3;
55                                                 return;
56                                         }
57                                 }
58                         }
59                 }
60         }
61
62         dprint("ERROR: Power core unreachable\n");
63         havocbot_ast_core_unreachable = TRUE;
64 }
65
66 void havocbot_goalrating_ast_core(float ratingscale)
67 {
68         entity best, wp;
69         float radius, found, bestvalue, c;
70         vector p;
71
72         havocbot_ast_find_core();
73
74         if not(havocbot_ast_core)
75                 return;
76
77         if not(havocbot_ast_core.takedamage)
78                 havocbot_ast_core.takedamage = TRUE;
79
80         p = 0.5 * (havocbot_ast_core.absmin + havocbot_ast_core.absmax);
81 //      dprint(vtos(ad.origin), " ", vtos(ad.absmin), " ", vtos(ad.absmax),"\n");
82         te_knightspike(p);
83         te_lightning2(world, '0 0 0', p);
84
85         // Find and rate waypoints around it
86         found = FALSE;
87         best = world;
88         bestvalue = 99999999999;
89         for(radius=0; radius<1000 && !found; radius+=500)
90         {
91                 for(wp=findradius(p, radius); wp; wp=wp.chain)
92                 {
93                         if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
94                         if(wp.classname=="waypoint")
95                         if(checkpvs(wp.origin, havocbot_ast_core))
96                         {
97                                 found = TRUE;
98                                 if(wp.cnt<bestvalue)
99                                 {
100                                         best = wp;
101                                         bestvalue = wp.cnt;
102                                 }
103                         }
104                 }
105         }
106
107         if(best)
108         {
109                 dprint("waypoints around target were found\n");
110         //      te_lightning2(world, '0 0 0', best.origin);
111         //      te_knightspike(best.origin);
112
113                 navigation_routerating(best, ratingscale, 10000);
114                 best.cnt += 1;
115
116                 self.havocbot_attack_time = 0;
117
118                 if(checkpvs(self.view_ofs, havocbot_ast_core))
119                 if(checkpvs(self.view_ofs, best))
120                 {
121                 //      dprint("increasing attack time for this target\n");
122                         self.havocbot_attack_time = time + 2;
123                 }
124         }
125 }
126
127 void havocbot_goalrating_ast_targets(float ratingscale)
128 {
129         entity ad, best, pl, wp, tod;
130         float radius, found, bestvalue, c;
131         vector p;
132
133         ad = findchain(classname, "func_assault_destructible");
134
135         for (; ad; ad = ad.chain)
136         {
137                 if (ad.target == "")
138                         continue;
139
140                 if not(ad.bot_attack)
141                         continue;
142
143                 found = FALSE;
144                 for(tod = world; (tod = find(tod, targetname, ad.target)); )
145                 {
146                         if(tod.classname == "target_objective_decrease")
147                         {
148                                 if(tod.enemy.health > 0 && tod.enemy.health < ASSAULT_VALUE_INACTIVE)
149                                 {
150                                 //      dprint(etos(ad),"\n");
151                                         found = TRUE;
152                                         break;
153                                 }
154                         }
155                 }
156
157                 if(!found)
158                 {
159                         dprint("target not found\n");
160                         continue;
161                 }
162                 dprint("target #", etos(ad), " found\n");
163
164
165                 p = 0.5 * (ad.absmin + ad.absmax);
166         //      dprint(vtos(ad.origin), " ", vtos(ad.absmin), " ", vtos(ad.absmax),"\n");
167         //      te_knightspike(p);
168         //      te_lightning2(world, '0 0 0', p);
169
170                 // Find and rate waypoints around it
171                 found = FALSE;
172                 best = world;
173                 bestvalue = 99999999999;
174                 for(radius=0; radius<1500 && !found; radius+=500)
175                 {
176                         for(wp=findradius(p, radius); wp; wp=wp.chain)
177                         {
178                                 if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
179                                 if(wp.classname=="waypoint")
180                                 if(checkpvs(wp.origin, ad))
181                                 {
182                                         found = TRUE;
183                                         if(wp.cnt<bestvalue)
184                                         {
185                                                 best = wp;
186                                                 bestvalue = wp.cnt;
187                                         }
188                                 }
189                         }
190                 }
191
192                 if(best)
193                 {
194                         dprint("waypoints around target were found\n");
195                 //      te_lightning2(world, '0 0 0', best.origin);
196                 //      te_knightspike(best.origin);
197
198                         navigation_routerating(best, ratingscale, 10000);
199                         best.cnt += 1;
200
201                         self.havocbot_attack_time = 0;
202
203                         if(checkpvs(self.view_ofs,ad))
204                         if(checkpvs(self.view_ofs,best))
205                         {
206                         //      dprint("increasing attack time for this target\n");
207                                 self.havocbot_attack_time = time + 2;
208                         }
209                 }
210         }
211 }
212
213 void havocbot_role_ast_offense()
214 {
215         if(self.deadflag != DEAD_NO)
216         {
217                 self.havocbot_attack_time = 0;
218                 havocbot_ast_reset_role(self);
219                 return;
220         }
221
222         // Set the role timeout if necessary
223         if (!self.havocbot_role_timeout)
224                 self.havocbot_role_timeout = time + 120;
225
226         if (time > self.havocbot_role_timeout)
227         {
228                 havocbot_ast_reset_role(self);
229                 return;
230         }
231
232         if(self.havocbot_attack_time>time)
233                 return;
234
235         if (self.bot_strategytime < time)
236         {
237                 navigation_goalrating_start();
238         ///     havocbot_goalrating_enemyplayers(20000, self.origin, 650);
239
240         //      if(!havocbot_goalrating_ast_generator_attack(20000))
241         //              havocbot_goalrating_ast_controlpoints_attack(20000);
242         //      havocbot_goalrating_ast_offenseitems(10000, self.origin, 10000);
243
244                 havocbot_goalrating_ast_targets(20000);
245         ///     havocbot_goalrating_items(10000, self.origin, 10000);
246                 navigation_goalrating_end();
247
248                 self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
249         }
250 };
251
252 void havocbot_role_ast_defense()
253 {
254         if(self.deadflag != DEAD_NO)
255         {
256                 self.havocbot_attack_time = 0;
257                 havocbot_ast_reset_role(self);
258                 return;
259         }
260
261         // Set the role timeout if necessary
262         if (!self.havocbot_role_timeout)
263                 self.havocbot_role_timeout = time + 120;
264
265         if (time > self.havocbot_role_timeout)
266         {
267                 havocbot_ast_reset_role(self);
268                 return;
269         }
270
271         if(self.havocbot_attack_time>time)
272                 return;
273
274         if (self.bot_strategytime < time)
275         {
276                 navigation_goalrating_start();
277                 havocbot_goalrating_enemyplayers(20000, self.origin, 650);
278         //      if(!havocbot_goalrating_ast_generator_attack(20000))
279         //              havocbot_goalrating_ast_controlpoints_attack(20000);
280         //      havocbot_goalrating_ast_offenseitems(10000, self.origin, 10000);
281                 havocbot_goalrating_items(10000, self.origin, 10000);
282                 navigation_goalrating_end();
283
284                 self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
285         }
286 };
287
288 void havocbot_role_ast_setrole(entity bot, float role)
289 {
290         switch(role)
291         {
292                 case HAVOCBOT_AST_ROLE_DEFENSE:
293                         bot.havocbot_role = havocbot_role_ast_defense;
294                         bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_DEFENSE;
295                         bot.havocbot_role_timeout = 0;
296                         break;
297                 case HAVOCBOT_AST_ROLE_OFFENSE:
298                         bot.havocbot_role = havocbot_role_ast_offense;
299                         bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_OFFENSE;
300                         bot.havocbot_role_timeout = 0;
301                         break;
302         }
303 };
304
305 void havocbot_ast_reset_role(entity bot)
306 {
307         local entity head;
308         local float c;
309
310         if(self.deadflag != DEAD_NO)
311                 return;
312
313         bot.havocbot_ast_target = world;
314
315         if(bot.team==assault_attacker_team)
316                 havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_OFFENSE);
317         else
318                 havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_DEFENSE);
319 };
320
321 void havocbot_chooserole_ast()
322 {
323         havocbot_ast_reset_role(self);
324 };