]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/urrebot_ai_main.c
fix for previous printstats patch (strings were messed up by long playernames)
[divverent/nexuiz.git] / data / qcsrc / server / gamec / urrebot_ai_main.c
1 /* --- UrreBotInfront ---\r
2 I could've used id's infront, but as it wasn't in LordHavoc's multiplayer\r
3 only mod, I had to add a new one, named something else to not mess with people's\r
4 possible/eventual plugin-attempts*/\r
5 \r
6 float(entity targ) UrreBotInfront =\r
7 {\r
8         local float dot;\r
9         local vector vec;\r
10 \r
11         makevectors (self.angles);\r
12         vec = normalize (targ.origin - self.origin);\r
13         dot = vec * v_forward;\r
14 \r
15         if (dot > 0.3)\r
16                 return TRUE;\r
17         return FALSE;\r
18 };\r
19 \r
20 /* --- UrreBotEvalTargets ---\r
21 Enemies are found and lost using this function\r
22 If the bot can't see his enemy for 3 seconds, it is dropped*/\r
23 \r
24 void() UrreBotEvalTargets =\r
25 {\r
26         local float old, new;\r
27         local vector v1, v2;\r
28         local entity e;\r
29 \r
30         v1 = self.origin + self.view_ofs;\r
31 \r
32         /*\r
33         if (self.enemy)\r
34         {\r
35                 if (self.enemy.health >= 1 && !self.enemy.deadflag)\r
36                 {\r
37                         if (self.evaltime <= time)\r
38                         {\r
39                                 self.evaltime = time + 3;\r
40                                 v2 = (self.enemy.absmin + self.enemy.absmax) * 0.5;\r
41                                 traceline(v1, v2, TRUE, self);\r
42                                 if (trace_fraction < 1)\r
43                                         self.enemy = world;\r
44                         }\r
45                 }\r
46                 else\r
47                         self.enemy = world;\r
48         }\r
49         */\r
50         e = findradius(v1, 1500);\r
51         while (e)\r
52         {\r
53                 if (!(e.flags & FL_NOTARGET))\r
54                 if (!(cvar("teamplay") && self.team == e.team))      // don't target teammates\r
55                 if (e.flags & FL_CLIENT)\r
56                 if (e != self)\r
57                 if (!e.deadflag)\r
58                 if (UrreBotInfront(e))\r
59                 if (e.health >= 1)\r
60                 {\r
61                         v2 = (e.absmin + e.absmax) * 0.5;\r
62                         traceline(v1, v2, TRUE, self);\r
63                         if (trace_fraction == 1 || trace_ent == e)\r
64                         {\r
65                                 if (self.enemy)\r
66                                 {\r
67                                         old = vlen(self.origin - (self.enemy.absmin + self.enemy.absmax)*0.5);\r
68                                         new = vlen(self.origin - v2);\r
69                                         if (new < old)\r
70                                         {\r
71                                                 self.enemy = e;\r
72                                                 self.enemytimeout = time + 3;\r
73                                         }\r
74                                 }\r
75                                 else\r
76                                 {\r
77                                         self.enemy = e;\r
78                                         self.enemytimeout = time + 3;\r
79                                 }\r
80                         }\r
81                 }\r
82                 e = e.chain;\r
83         }\r
84 \r
85         e = world;\r
86         if (self.goalcurrent.sflags & S_DOOR)\r
87                 e = self.goalcurrent.goalentity;\r
88         else if (self.link0.sflags & S_DOOR)\r
89                 e = self.link0.goalentity;\r
90         if (e.health >= 1)\r
91         {\r
92                 self.enemy = e;\r
93                 self.enemytimeout = time + 3;\r
94         }\r
95 };\r
96 \r
97 /* --- UrreBotAim ---\r
98 Very crude and simple aiming, with some leading capability*/\r
99 \r
100 void() UrreBotAim =\r
101 {\r
102         //local float dist;\r
103         local float f;\r
104         local float skeel;\r
105         local vector v, desiredang, testang, diffang, aimpoint;\r
106 \r
107         if (self.deadflag)\r
108                 return;\r
109         skeel = bound(1, skill, 10);\r
110 \r
111         v = (self.enemy.absmin + self.enemy.absmax) * 0.5;\r
112 \r
113         if (self.enemy)\r
114         {\r
115                 if (time > self.enemytimeout || self.enemy.takedamage == DAMAGE_NO || self.enemy.deadflag)\r
116                         self.enemy = world;\r
117                 else if (self.aimtime <= time)\r
118                 {\r
119                         self.aimtime = time + 0.1; // LordHavoc: changed from time + 0.3 to time + 0.1\r
120                         self.aimfire = FALSE;\r
121                         if (self.enemy)\r
122                         {\r
123                                 traceline(self.origin + self.view_ofs, v, TRUE, self);\r
124                                 if (trace_fraction == 1)\r
125                                 {\r
126                                         self.enemytimeout = time + 3;\r
127                                         self.aimfire = TRUE;\r
128                                 }\r
129                         }\r
130                 }\r
131         }\r
132 \r
133         // get the desired angles to aim at\r
134         desiredang = self.v_angle_y * '0 1 0';\r
135         aimpoint = v;\r
136         if (self.enemy)\r
137         {\r
138                 //dprint("urrebotaim (skeel == ", ftos(skeel), ") : old aimpoint ", vtos(self.aimpoint));\r
139                 aimpoint = v + self.enemy.velocity*vlen(self.origin - v)*self.lead;\r
140                 //dprint(", v = ", vtos(v));\r
141                 //dprint(", self.enemy.velocity = ", vtos(self.enemy.velocity));\r
142                 //dprint(", vlen(self.origin - v) = ", ftos(vlen(self.origin - v)));\r
143                 //dprint(", self.lead = ", ftos(self.lead));\r
144                 aimpoint = aimpoint + randomvec()*max(0, 120 - skeel*12);\r
145                 //dprint(", final aimpoint = ", vtos(self.aimpoint), "\n");\r
146                 //eprint(self);\r
147                 //eprint(self.enemy);\r
148                 desiredang = vectoangles(aimpoint - (self.origin + self.view_ofs));\r
149         }\r
150         else if (vlen(self.velocity) >= 50)\r
151                 desiredang = vectoyaw(self.velocity) * '0 1 0';\r
152         desiredang_x = 0-desiredang_x;\r
153 \r
154         // calculate turn angles\r
155         testang = desiredang - self.v_angle;\r
156         testang_z = 0;\r
157 \r
158         while (testang_y < -180)\r
159                 testang_y = testang_y + 360;\r
160         while (testang_y >= 180)\r
161                 testang_y = testang_y - 360;\r
162         while (testang_x < -180)\r
163                 testang_x = testang_x + 360;\r
164         while (testang_x >= 180)\r
165                 testang_x = testang_x - 360;\r
166 \r
167         // turn\r
168         // LordHavoc: simplified to one line\r
169         diffang = testang * min(1, ((skeel * 2) * frametime));\r
170 \r
171         self.v_angle = self.v_angle + diffang;\r
172         self.angles_y = self.v_angle_y;\r
173 \r
174         if (self.aimfire)\r
175         if (self.enemy)\r
176         {\r
177                 makevectors (self.v_angle);\r
178                 //v = self.origin + '0 0 16';\r
179                 v = self.origin + self.view_ofs; // neuiz trueaim\r
180                 f = vlen(v - aimpoint);\r
181                 traceline (v, v + v_forward*f, FALSE, self);\r
182                 if (vlen(trace_endpos - aimpoint) < (200 - skeel * 15))\r
183                 {\r
184                         f = 0.1 + skeel*0.1;\r
185                         if (f >= 1)\r
186                                 self.button0 = 1;\r
187                         else if (random() < f)\r
188                                 self.button0 = 1;\r
189                 }\r
190         }\r
191 };\r
192 \r
193 /* --- UrreBotMove ---\r
194 Moves towards the closest point on the next goal in the bots list,\r
195 which can be a navnode, item or domination point*/\r
196 \r
197 void() UrreBotMove =\r
198 {\r
199         local float f, bad;\r
200         local vector dir, tvec;\r
201         local entity plane, optpoint;\r
202 \r
203         if (self.link0)\r
204         {\r
205                 if (boxesoverlap(self.origin + self.mins, self.origin + self.maxs, self.link0.origin + self.link0.mins, self.link0.origin + self.link0.maxs))\r
206                 {\r
207                         optpoint = world;\r
208                         plane = self.link0.plane_chain;\r
209                         while (plane)\r
210                         {\r
211                                 tvec = self.maxs;\r
212                                 if (plane.mangle_x < 0)\r
213                                         tvec_x = self.mins_x;\r
214                                 if (plane.mangle_y < 0)\r
215                                         tvec_y = self.mins_y;\r
216                                 if (plane.mangle_z < 0)\r
217                                         tvec_z = self.mins_z;\r
218                                 tvec += self.origin;\r
219                                 f = tvec*plane.mangle - self.link0.origin*plane.mangle-plane.delay;\r
220                                 if (f > 0)\r
221                                         bad = TRUE;\r
222                                 plane = plane.list;\r
223                         }\r
224                         if (!bad)\r
225                         {\r
226                                 PopRoute();\r
227                                 if (self.goalcurrent.sflags & S_TELEPORT)\r
228                                         self.movepoint = self.goalcurrent.origin;\r
229                                 else\r
230                                 {\r
231                                         if (urrebots_navopt)\r
232                                                 optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.link0);\r
233                                         if (optpoint)\r
234                                                 self.movepoint = optpoint.origin;\r
235                                         else\r
236                                                 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.link0);\r
237                                 }\r
238                         }\r
239                 }\r
240                 else if (((self.goalcurrent.sflags & S_TOUCH) && boxesoverlap(self.origin + self.mins, self.origin + self.maxs, self.goalcurrent.origin + self.goalcurrent.mins, self.goalcurrent.origin + self.goalcurrent.maxs)) || boxenclosed(self.origin + self.mins, self.origin + self.maxs, self.goalcurrent.origin + self.goalcurrent.mins, self.goalcurrent.origin + self.goalcurrent.maxs))\r
241                 {\r
242                         optpoint = world;\r
243                         plane = self.goalcurrent.plane_chain;\r
244                         while (plane)\r
245                         {\r
246                                 tvec = self.maxs;\r
247                                 if (plane.mangle_x < 0)\r
248                                         tvec_x = self.mins_x;\r
249                                 if (plane.mangle_y < 0)\r
250                                         tvec_y = self.mins_y;\r
251                                 if (plane.mangle_z < 0)\r
252                                         tvec_z = self.mins_z;\r
253                                 tvec += self.origin;\r
254                                 f = tvec*plane.mangle - self.goalcurrent.origin*plane.mangle-plane.delay;\r
255                                 if (f > 0)\r
256                                         bad = TRUE;\r
257                                 plane = plane.list;\r
258                         }\r
259                         if (!bad)\r
260                         {\r
261                                 PopRoute();\r
262                                 if (self.goalcurrent.sflags & S_TELEPORT)\r
263                                         self.movepoint = self.goalcurrent.origin;\r
264                                 else\r
265                                 {\r
266                                         if (urrebots_navopt)\r
267                                                 optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.goalcurrent);\r
268                                         if (optpoint)\r
269                                                 self.movepoint = optpoint.origin;\r
270                                         else\r
271                                                 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);\r
272                                 }\r
273                                 if (self.movepoint == '0 0 0')\r
274                                 {\r
275                                         self.strat_me = TRUE;\r
276                                         UrreBotPath(minisearch_distance);\r
277                                 }\r
278                         }\r
279                 }\r
280         }\r
281         else\r
282         {\r
283                 optpoint = world;\r
284                 if (!self.goalcurrent || ((self.goalcurrent.flags & FL_ITEM) && !self.goalcurrent.solid) || (self.goalcurrent.classname == "dom_controlpoint" && self.goalcurrent.enemy.team == self.team))\r
285                 {\r
286                         self.strat_me = TRUE;\r
287                         UrreBotPath(minisearch_distance);\r
288                 }\r
289                 if (urrebots_navopt)\r
290                         optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.goalcurrent);\r
291                 if (optpoint)\r
292                         self.movepoint = optpoint.origin;\r
293                 else\r
294                         self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);\r
295         }\r
296 //      dir = normalize(ToPointInSpace(self.goalcurrent, self.movepoint));\r
297         dir = ToPointInSpace(self.goalcurrent, self.movepoint);\r
298         dir = dir * sv_maxspeed;\r
299         makevectors(self.v_angle);\r
300         self.movement_x = dir * v_forward;\r
301         self.movement_y = dir * v_right;\r
302         self.movement_z = dir * v_up;\r
303 };\r
304 \r
305 /* --- UrreBotImpulses ---\r
306 Returns the impulse for the best weapon in the given situation*/\r
307 \r
308 float() UrreBotImpulses =\r
309 {\r
310         local float dist, l, w;\r
311         local float cells, rockets, nails, shells;\r
312         local vector v;\r
313 \r
314         if (random() < 0.5)\r
315                 return 0;\r
316 \r
317         dist = 400; // we like nex and mortar\r
318         if (self.enemy)\r
319         {\r
320                 v = (self.enemy.absmin + self.enemy.absmax) * 0.5;\r
321                 dist = vlen(v - self.origin);\r
322         }\r
323 \r
324         cells = self.ammo_cells;\r
325         rockets = self.ammo_rockets;\r
326         nails = self.ammo_nails;\r
327         shells = self.ammo_shells;\r
328 \r
329         l = 0;\r
330         w = 0;\r
331 \r
332         if (!w)\r
333         if (self.items & IT_NEX)\r
334         if (dist > 300)\r
335         if (cells >= cvar("g_balance_nex_ammo"))\r
336         {\r
337                 l = 1000000;\r
338                 w = WEP_NEX;\r
339         }\r
340         if (!w)\r
341         if (self.items & IT_GRENADE_LAUNCHER)\r
342         if (dist >= 200)\r
343         if (dist < 2000)\r
344         if (rockets >= cvar("g_balance_grenadelauncher_primary_ammo"))\r
345         {\r
346                 l = cvar("g_balance_grenadelauncher_primary_speed");\r
347                 w = WEP_GRENADE_LAUNCHER;\r
348         }\r
349         if (!w)\r
350         if (self.items & IT_HAGAR)\r
351         if (dist >= 100)\r
352         if (dist < 2000)\r
353         if (rockets >= cvar("g_balance_hagar_primary_ammo"))\r
354         {\r
355                 l = cvar("g_balance_hagar_primary_speed");\r
356                 w = WEP_HAGAR;\r
357         }\r
358         if (!w)\r
359         if (self.items & IT_ROCKET_LAUNCHER)\r
360         if (dist >= 200)\r
361         if (dist < 800)\r
362         if (rockets >= cvar("g_balance_rocketlauncher_ammo"))\r
363         {\r
364                 l = cvar("g_balance_rocketlauncher_speed");\r
365                 w = WEP_ROCKET_LAUNCHER;\r
366         }\r
367         if (!w)\r
368         if (self.items & IT_ELECTRO)\r
369         if (dist >= 100)\r
370         if (dist < 2000)\r
371         if (cells >= cvar("g_balance_electro_primary_ammo"))\r
372         {\r
373                 l = cvar("g_balance_electro_primary_speed");\r
374                 w = WEP_ELECTRO;\r
375         }\r
376         if (!w)\r
377         if (self.items & IT_CRYLINK)\r
378         if (dist < 800)\r
379         if (cells >= cvar("g_balance_crylink_primary_ammo"))\r
380         {\r
381                 l = cvar("g_balance_crylink_primary_speed");\r
382                 w = WEP_CRYLINK;\r
383         }\r
384         if (!w)\r
385         if (self.items & IT_UZI)\r
386         if (dist < 1000)\r
387         if (nails >= cvar("g_balance_uzi_first_ammo"))\r
388         {\r
389                 l = 1000000;\r
390                 w = WEP_UZI;\r
391         }\r
392         if (!w)\r
393         if (self.items & IT_SHOTGUN)\r
394         if (dist < 1000)\r
395         if (nails >= cvar("g_balance_shotgun_primary_ammo"))\r
396         {\r
397                 l = 1000000;\r
398                 w = WEP_SHOTGUN;\r
399         }\r
400         if (!w)\r
401         {\r
402                 l = cvar("g_balance_laser_speed");\r
403                 w = WEP_LASER;\r
404         }\r
405         if (l < 1)\r
406                 error("UrreBotImpulses: missing cvar for weapon\n");\r
407         self.lead = 1 / l;\r
408         return w;\r
409 };\r
410 \r
411 /* --- BeamBox ---\r
412 Used for some debugging, occasionally*/\r
413 \r
414 float BT_LIGHTNING = 0;\r
415 float BT_BEAM = 1;\r
416 void(float beamtype, vector bmins, vector bmaxs) BeamBox =\r
417 {\r
418         local vector v1, v2;\r
419 \r
420         v1 = bmaxs;\r
421         v2 = bmaxs;\r
422         v2_x = bmins_x;\r
423         if (beamtype == BT_LIGHTNING)\r
424                 te_lightning1(world, v1, v2);\r
425         else\r
426                 te_beam(world, v1, v2);\r
427         v1 = bmaxs;\r
428         v2 = bmaxs;\r
429         v2_y = bmins_y;\r
430         if (beamtype == BT_LIGHTNING)\r
431                 te_lightning1(world, v1, v2);\r
432         else\r
433                 te_beam(world, v1, v2);\r
434         v1 = bmaxs;\r
435         v2 = bmaxs;\r
436         v2_z = bmins_z;\r
437         if (beamtype == BT_LIGHTNING)\r
438                 te_lightning1(world, v1, v2);\r
439         else\r
440                 te_beam(world, v1, v2);\r
441         v1 = bmins;\r
442         v2 = bmins;\r
443         v2_x = bmaxs_x;\r
444         if (beamtype == BT_LIGHTNING)\r
445                 te_lightning1(world, v1, v2);\r
446         else\r
447                 te_beam(world, v1, v2);\r
448         v1 = bmins;\r
449         v2 = bmins;\r
450         v2_y = bmaxs_y;\r
451         if (beamtype == BT_LIGHTNING)\r
452                 te_lightning1(world, v1, v2);\r
453         else\r
454                 te_beam(world, v1, v2);\r
455         v1 = bmins;\r
456         v2 = bmins;\r
457         v2_z = bmaxs_z;\r
458         if (beamtype == BT_LIGHTNING)\r
459                 te_lightning1(world, v1, v2);\r
460         else\r
461                 te_beam(world, v1, v2);\r
462         v1 = bmins;\r
463         v1_z = bmaxs_z;\r
464         v2 = bmins;\r
465         v2_x = bmaxs_x;\r
466         v2_z = bmaxs_z;\r
467         if (beamtype == BT_LIGHTNING)\r
468                 te_lightning1(world, v1, v2);\r
469         else\r
470                 te_beam(world, v1, v2);\r
471         v1 = bmins;\r
472         v1_z = bmaxs_z;\r
473         v2 = bmins;\r
474         v2_y = bmaxs_y;\r
475         v2_z = bmaxs_z;\r
476         if (beamtype == BT_LIGHTNING)\r
477                 te_lightning1(world, v1, v2);\r
478         else\r
479                 te_beam(world, v1, v2);\r
480         v1 = bmaxs;\r
481         v1_z = bmins_z;\r
482         v2 = bmaxs;\r
483         v2_x = bmins_x;\r
484         v2_z = bmins_z;\r
485         if (beamtype == BT_LIGHTNING)\r
486                 te_lightning1(world, v1, v2);\r
487         else\r
488                 te_beam(world, v1, v2);\r
489         v1 = bmaxs;\r
490         v1_z = bmins_z;\r
491         v2 = bmaxs;\r
492         v2_y = bmins_y;\r
493         v2_z = bmins_z;\r
494         if (beamtype == BT_LIGHTNING)\r
495                 te_lightning1(world, v1, v2);\r
496         else\r
497                 te_beam(world, v1, v2);\r
498         v1 = bmins;\r
499         v1_x = bmaxs_x;\r
500         v2 = bmaxs;\r
501         v2_y = bmins_y;\r
502         if (beamtype == BT_LIGHTNING)\r
503                 te_lightning1(world, v1, v2);\r
504         else\r
505                 te_beam(world, v1, v2);\r
506         v1 = bmins;\r
507         v1_y = bmaxs_y;\r
508         v2 = bmaxs;\r
509         v2_x = bmins_x;\r
510         if (beamtype == BT_LIGHTNING)\r
511                 te_lightning1(world, v1, v2);\r
512         else\r
513                 te_beam(world, v1, v2);\r
514 };\r
515 \r
516 /* --- UrreBotPath ---\r
517 Marks route and determines which goal is the most useful to head for*/\r
518 \r
519 void(float sdist) UrreBotPath =\r
520 {\r
521         local float f, f2, f3;\r
522         local entity e, best;\r
523 \r
524         ClearRoute();\r
525         MarkRoute(sdist);\r
526         DistEvalItems();\r
527         f2 = 10000000;\r
528         e = findchainflags(flags, FL_ITEM);\r
529         while (e)\r
530         {\r
531                 f = 0;\r
532                 if (e.evalfunc)\r
533                         f = e.evalfunc(e);\r
534                 if (f > 0)\r
535                 if (e.goallist)\r
536                 {\r
537                         f = f + e.costl;\r
538                         if (f < f2)\r
539                         if (e.solid)\r
540                         {\r
541                                 best = e;\r
542                                 f2 = e.costl;\r
543                         }\r
544                 }\r
545                 e = e.chain;\r
546         }\r
547         if (best)\r
548         {\r
549                 while (best)\r
550                 {\r
551                         PushRoute(best);\r
552                         best = best.goallist;\r
553                 }\r
554         }\r
555         else\r
556         {\r
557                 f3 = 0;\r
558                 while (f3 < 3)\r
559                 {\r
560                         f = 0;\r
561                         f2 = 0;\r
562                         f = ceil(random() * navnodes);\r
563                         e = navnode_chain;\r
564                         while (e)\r
565                         {\r
566                                 if (f == f2)\r
567                                 if (e.goallist)\r
568                                 {\r
569                                         best = e;\r
570                                         f3 = 3;\r
571                                 }\r
572                                 f2 = f2 + 1;\r
573                                 e = e.list;\r
574                         }\r
575                         f3 = f3 + 1;\r
576                 }\r
577                 while (best)\r
578                 {\r
579                         PushRoute(best);\r
580                         best = best.goallist;\r
581                 }\r
582         }\r
583 };\r
584 \r
585 /* --- UrreBotThink ---\r
586 In this version, UrreBot does a path search based on timer and turn\r
587 Then it aims, moves, checks if it's stuck, finds/loses stuff to shoot at,\r
588 picks best weapon, shoots, and optionally displays debug stuff, in that\r
589 order\r
590 Aiming must happen before movement, because movement depends on angles\r
591 He does not yet have any combat movement*/\r
592 \r
593 void() UrreBotThink =\r
594 {\r
595         self.movement = '0 0 0';\r
596         self.button0 = 0;\r
597         self.button2 = 0;\r
598         self.impulse = 0;\r
599 \r
600         if (cvar("teamplay") && self.team == self.enemy.team) // don't return fire if hit by a teammate\r
601                 self.enemy = world;\r
602 \r
603         if (self.deadflag)\r
604         {\r
605                 ClearRoute();\r
606                 if (random() < 0.2)\r
607                         self.button0 = 1;\r
608                 return;\r
609         }\r
610 \r
611         if (strategytime <= time)\r
612         if (strategytoken == self)\r
613         {\r
614                 strategytime = time + urrebots_strategytime;\r
615                 strategytoken = self.list;\r
616                 if (!strategytoken)\r
617                         strategytoken = urrebot_chain;\r
618                 if (self.strat_me)\r
619                 {\r
620                         self.strat_me = FALSE;\r
621                         UrreBotPath(stratsearch_distance);\r
622                 }\r
623         }\r
624 \r
625         UrreBotAim();\r
626         UrreBotMove();\r
627 \r
628         if (self.camptime <= time)\r
629         {\r
630                 if (vlen(self.origin - self.campcheck) < 200) // stuckage avoidage\r
631                 {\r
632                         self.camptime = time + urrebots;\r
633                         self.strat_me = TRUE;\r
634                         UrreBotPath(minisearch_distance);\r
635                 }\r
636                 else\r
637                 {\r
638                         self.campcheck = self.origin;\r
639                         self.camptime = time + 2;\r
640                 }\r
641         }\r
642 \r
643         if (self.combattime <= time)\r
644         {\r
645                 self.combattime = time + urrebots_combattime;\r
646                 UrreBotEvalTargets();\r
647                 self.impulse = UrreBotImpulses();\r
648         }\r
649 \r
650         if (cvar("urrebots_debug"))\r
651         {\r
652                 te_lightning1(self, self.origin, self.movepoint);\r
653                 if (!self.goalcurrent)\r
654                 {\r
655                         bprint(self.netname);\r
656                         bprint(" has no goalcurrent\n");\r
657                 }\r
658         }\r
659 };\r