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
6 float(entity targ) UrreBotInfront =
\r
11 makevectors (self.angles);
\r
12 vec = normalize (targ.origin - self.origin);
\r
13 dot = vec * v_forward;
\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
24 void() UrreBotEvalTargets =
\r
26 local float old, new;
\r
27 local vector v1, v2;
\r
30 v1 = self.origin + self.view_ofs;
\r
34 if (self.enemy.health >= 1 && !self.enemy.deadflag)
\r
36 if (self.evaltime <= time)
\r
38 self.evaltime = time + 3;
\r
39 v2 = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
40 traceline(v1, v2, TRUE, self);
\r
41 if (trace_fraction < 1)
\r
48 e = findradius(v1, 1500);
\r
51 if (!(e.flags & FL_NOTARGET))
\r
52 if (!(cvar("teamplay") && self.team == e.team)) // don't target teammates
\r
53 if (e.flags & FL_CLIENT)
\r
56 if (UrreBotInfront(e))
\r
59 v2 = (e.absmin + e.absmax) * 0.5;
\r
60 traceline(v1, v2, TRUE, self);
\r
61 if (trace_fraction == 1 || trace_ent == e)
\r
65 old = vlen(self.origin - (self.enemy.absmin + self.enemy.absmax)*0.5);
\r
66 new = vlen(self.origin - v2);
\r
78 if (self.goalcurrent.sflags & S_DOOR)
\r
79 e = self.goalcurrent.goalentity;
\r
80 else if (self.link0.sflags & S_DOOR)
\r
81 e = self.link0.goalentity;
\r
86 /* --- UrreBotAim ---
\r
87 Very crude and simple aiming, with some leading capability*/
\r
91 local float dist, skeel;
\r
92 local vector v, desiredang, testang, diffang;
\r
94 skeel = bound(1, skill, 10);
\r
96 // get the desired angles to aim at
\r
99 v = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
100 if (self.enemy.classname == "door")
\r
102 else if (self.aimtime <= time)
\r
104 self.aimtime = time + 0.3;
\r
105 traceline(self.origin + self.view_ofs, (self.enemy.absmin + self.enemy.absmax) * 0.5, TRUE, self);
\r
106 if (trace_fraction == 1)
\r
108 self.aimpoint = v + self.enemy.velocity*vlen(self.origin - v)*self.lead;
\r
109 self.aimpoint = self.aimpoint + randomvec()*max(0, 120 - skeel*12);
\r
112 desiredang = vectoangles(self.aimpoint - (self.origin + self.view_ofs));
\r
115 desiredang = vectoangles(self.velocity);
\r
116 desiredang_x = 0-desiredang_x;
\r
118 if (desiredang_y <= -180)
\r
119 desiredang_y = desiredang_y + 360;
\r
120 else if (desiredang_y >= 180)
\r
121 desiredang_y = desiredang_y - 360;
\r
122 if (desiredang_x <= -180)
\r
123 desiredang_x = desiredang_x + 360;
\r
124 else if (desiredang_x >= 180)
\r
125 desiredang_x = desiredang_x - 360;
\r
127 // calculate turn angles
\r
128 testang = desiredang - self.v_angle;
\r
132 dist = vlen(testang * ((skeel + 1) * frametime));
\r
133 if (vlen(normalize(testang) * skeel) > dist)
\r
135 diffang = normalize(testang) * skeel;
\r
136 dist = vlen(normalize(testang) * skeel);
\r
139 diffang = testang * ((skeel + 1) * frametime);
\r
140 if (dist > vlen(testang))
\r
143 self.v_angle = self.v_angle + diffang;
\r
144 self.angles_y = self.v_angle_y;
\r
147 /* --- UrreBotMove ---
\r
148 Moves towards the closest point on the next goal in the bots list,
\r
149 which can be a navnode, item or domination point*/
\r
151 void() UrreBotMove =
\r
153 local float f, bad;
\r
154 local vector dir, tvec;
\r
155 local entity plane, optpoint;
\r
159 if (boxesoverlap(self.origin + self.mins, self.origin + self.maxs, self.link0.origin + self.link0.mins, self.link0.origin + self.link0.maxs))
\r
162 plane = self.link0.plane_chain;
\r
166 if (plane.mangle_x < 0)
\r
167 tvec_x = self.mins_x;
\r
168 if (plane.mangle_y < 0)
\r
169 tvec_y = self.mins_y;
\r
170 if (plane.mangle_z < 0)
\r
171 tvec_z = self.mins_z;
\r
172 tvec += self.origin;
\r
173 f = tvec*plane.mangle - self.link0.origin*plane.mangle-plane.delay;
\r
176 plane = plane.list;
\r
181 if (self.goalcurrent.sflags & S_TELEPORT)
\r
182 self.movepoint = self.goalcurrent.origin;
\r
185 if (urrebots_navopt)
\r
186 optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.link0);
\r
188 self.movepoint = optpoint.origin;
\r
190 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.link0);
\r
194 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
197 plane = self.goalcurrent.plane_chain;
\r
201 if (plane.mangle_x < 0)
\r
202 tvec_x = self.mins_x;
\r
203 if (plane.mangle_y < 0)
\r
204 tvec_y = self.mins_y;
\r
205 if (plane.mangle_z < 0)
\r
206 tvec_z = self.mins_z;
\r
207 tvec += self.origin;
\r
208 f = tvec*plane.mangle - self.goalcurrent.origin*plane.mangle-plane.delay;
\r
211 plane = plane.list;
\r
216 if (self.goalcurrent.sflags & S_TELEPORT)
\r
217 self.movepoint = self.goalcurrent.origin;
\r
220 if (urrebots_navopt)
\r
221 optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.goalcurrent);
\r
223 self.movepoint = optpoint.origin;
\r
225 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);
\r
227 if (self.movepoint == '0 0 0')
\r
229 self.strat_me = TRUE;
\r
230 UrreBotPath(minisearch_distance);
\r
238 if (!self.goalcurrent || ((self.goalcurrent.flags & FL_ITEM) && !self.goalcurrent.solid) || (self.goalcurrent.classname == "dom_controlpoint" && self.goalcurrent.enemy.team == self.team))
\r
240 self.strat_me = TRUE;
\r
241 UrreBotPath(minisearch_distance);
\r
243 if (urrebots_navopt)
\r
244 optpoint = MatchOptPoint(self.goalcurrent, self.goallist, self.goalcurrent);
\r
246 self.movepoint = optpoint.origin;
\r
248 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);
\r
250 dir = normalize(ToPointInSpace(self.goalcurrent, self.movepoint));
\r
251 dir = dir * sv_maxspeed;
\r
252 makevectors(self.v_angle);
\r
253 self.movement_x = dir * v_forward;
\r
254 self.movement_y = dir * v_right;
\r
255 self.movement_z = dir * v_up;
\r
258 /* --- UrreBotImpulses ---
\r
259 Returns the impulse for the best weapon in the given situation*/
\r
261 float() UrreBotImpulses =
\r
264 local float cells, rockets, nails, shells;
\r
267 if (random() < 0.5)
\r
270 dist = 400; // we like nex and mortar
\r
273 v = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
274 dist = vlen(v - self.origin);
\r
277 cells = self.ammo_cells;
\r
278 rockets = self.ammo_rockets;
\r
279 nails = self.ammo_nails;
\r
280 shells = self.ammo_shells;
\r
282 if (dist > 300 && cells && (self.items & IT_NEX))
\r
290 if (self.items & IT_GRENADE_LAUNCHER)
\r
292 self.lead = 1 / cvar("g_balance_grenadelauncher_speed");
\r
293 return WEP_GRENADE_LAUNCHER;
\r
295 if (self.items & IT_HAGAR)
\r
297 self.lead = 1 / cvar("g_balance_hagar_speed");
\r
300 else if (self.items & IT_ROCKET_LAUNCHER)
\r
302 self.lead = 1 / cvar("g_balance_rocketlauncher_speed");
\r
303 return WEP_ROCKET_LAUNCHER;
\r
308 if (self.items & IT_ELECTRO)
\r
310 self.lead = 1 / cvar("g_balance_electro_speed");
\r
311 return WEP_ELECTRO;
\r
313 else if (self.items & IT_CRYLINK)
\r
315 self.lead = 1 / cvar("g_balance_crylink_speed");
\r
316 return WEP_CRYLINK;
\r
321 if (self.items & IT_UZI)
\r
329 if (self.items & IT_SHOTGUN)
\r
332 return WEP_SHOTGUN;
\r
335 self.lead = 1 / cvar("g_balance_laser_speed");
\r
340 Used for some debugging, occasionally*/
\r
342 float BT_LIGHTNING = 0;
\r
344 void(float beamtype, vector bmins, vector bmaxs) BeamBox =
\r
346 local vector v1, v2;
\r
351 if (beamtype == BT_LIGHTNING)
\r
352 te_lightning1(world, v1, v2);
\r
354 te_beam(world, v1, v2);
\r
358 if (beamtype == BT_LIGHTNING)
\r
359 te_lightning1(world, v1, v2);
\r
361 te_beam(world, v1, v2);
\r
365 if (beamtype == BT_LIGHTNING)
\r
366 te_lightning1(world, v1, v2);
\r
368 te_beam(world, v1, v2);
\r
372 if (beamtype == BT_LIGHTNING)
\r
373 te_lightning1(world, v1, v2);
\r
375 te_beam(world, v1, v2);
\r
379 if (beamtype == BT_LIGHTNING)
\r
380 te_lightning1(world, v1, v2);
\r
382 te_beam(world, v1, v2);
\r
386 if (beamtype == BT_LIGHTNING)
\r
387 te_lightning1(world, v1, v2);
\r
389 te_beam(world, v1, v2);
\r
395 if (beamtype == BT_LIGHTNING)
\r
396 te_lightning1(world, v1, v2);
\r
398 te_beam(world, v1, v2);
\r
404 if (beamtype == BT_LIGHTNING)
\r
405 te_lightning1(world, v1, v2);
\r
407 te_beam(world, v1, v2);
\r
413 if (beamtype == BT_LIGHTNING)
\r
414 te_lightning1(world, v1, v2);
\r
416 te_beam(world, v1, v2);
\r
422 if (beamtype == BT_LIGHTNING)
\r
423 te_lightning1(world, v1, v2);
\r
425 te_beam(world, v1, v2);
\r
430 if (beamtype == BT_LIGHTNING)
\r
431 te_lightning1(world, v1, v2);
\r
433 te_beam(world, v1, v2);
\r
438 if (beamtype == BT_LIGHTNING)
\r
439 te_lightning1(world, v1, v2);
\r
441 te_beam(world, v1, v2);
\r
444 /* --- UrreBotPath ---
\r
445 Marks route and determines which goal is the most useful to head for*/
\r
447 void(float sdist) UrreBotPath =
\r
449 local float f, f2, f3;
\r
450 local entity e, best;
\r
456 e = findchainflags(flags, FL_ITEM);
\r
480 best = best.goallist;
\r
490 f = ceil(random() * navnodes);
\r
508 best = best.goallist;
\r
513 /* --- UrreBotThink ---
\r
514 In this version, UrreBot does a path search based on timer and turn
\r
515 Then it aims, moves, checks if it's stuck, finds/loses stuff to shoot at,
\r
516 picks best weapon, shoots, and optionally displays debug stuff, in that
\r
518 Aiming must happen before movement, because movement depends on angles
\r
519 He does not yet have any combat movement*/
\r
521 void() UrreBotThink =
\r
526 self.movement = '0 0 0';
\r
531 if (cvar("teamplay") && self.team == self.enemy.team) // don't return fire if hit by a teammate
\r
532 self.enemy = world;
\r
537 if (random() < 0.2)
\r
542 if (strategytime <= time)
\r
543 if (strategytoken == self)
\r
545 strategytime = time + urrebots_strategytime;
\r
546 strategytoken = self.list;
\r
547 if (!strategytoken)
\r
548 strategytoken = urrebot_chain;
\r
551 self.strat_me = FALSE;
\r
552 UrreBotPath(stratsearch_distance);
\r
559 if (self.camptime <= time)
\r
561 if (vlen(self.origin - self.campcheck) < 200) // stuckage avoidage
\r
563 self.camptime = time + urrebots;
\r
564 self.strat_me = TRUE;
\r
565 UrreBotPath(minisearch_distance);
\r
569 self.campcheck = self.origin;
\r
570 self.camptime = time + 2;
\r
574 if (self.combattime <= time)
\r
576 self.combattime = time + urrebots_combattime;
\r
577 UrreBotEvalTargets();
\r
578 self.impulse = UrreBotImpulses();
\r
583 makevectors (self.v_angle);
\r
584 v = self.origin + '0 0 16';
\r
585 f = vlen(v - self.aimpoint);
\r
586 traceline (v, v + v_forward*f, FALSE, self);
\r
587 if (vlen(trace_endpos - self.aimpoint) < 150)
\r
599 if (cvar("urrebots_debug"))
\r
601 te_lightning1(self, self.origin, self.movepoint);
\r
602 if (!self.goalcurrent)
\r
604 bprint(self.netname);
\r
605 bprint(" has no goalcurrent\n");
\r