centerprints now are managed independently per line
[divverent/nexuiz.git] / data / qcsrc / server / havocbot.qc
1
2 .void() havocbot_role;
3 void() havocbot_chooserole;
4
5 vector() havocbot_dodge =
6 {
7         local entity head;
8         local vector dodge, v, n;
9         local float danger, bestdanger, vl, d;
10         dodge = '0 0 0';
11         bestdanger = -20;
12         // check for dangerous objects near bot or approaching bot
13         head = findchainfloat(bot_dodge, TRUE);
14         while(head)
15         {
16                 if (head.owner != self)
17                 {
18                         vl = vlen(head.velocity);
19                         if (vl > sv_maxspeed * 0.3)
20                         {
21                                 n = normalize(head.velocity);
22                                 v = self.origin - head.origin;
23                                 d = v * n;
24                                 if (d > (0 - head.bot_dodgerating))
25                                 if (d < (vl * 0.2 + head.bot_dodgerating))
26                                 {
27                                         // calculate direction and distance from the flight path, by removing the forward axis
28                                         v = v - (n * (v * n));
29                                         danger = head.bot_dodgerating - vlen(v);
30                                         if (bestdanger < danger)
31                                         {
32                                                 bestdanger = danger;
33                                                 // dodge to the side of the object
34                                                 dodge = normalize(v);
35                                         }
36                                 }
37                         }
38                         else
39                         {
40                                 danger = head.bot_dodgerating - vlen(head.origin - self.origin);
41                                 if (bestdanger < danger)
42                                 {
43                                         bestdanger = danger;
44                                         dodge = normalize(self.origin - head.origin);
45                                 }
46                         }
47                 }
48                 head = head.chain;
49         }
50         return dodge;
51 };
52
53 //.float havocbotignoretime;
54 void() havocbot_movetogoal =
55 {
56         local vector destorg;
57         local vector diff;
58         local vector dir;
59         local vector flatdir;
60         local vector m1;
61         local vector m2;
62         local vector evadeobstacle;
63         local vector evadelava;
64         local float s;
65         //local float dist;
66         local vector dodge;
67         //if (self.goalentity)
68         //      te_lightning2(self, self.origin, (self.goalentity.absmin + self.goalentity.absmax) * 0.5);
69         self.movement = '0 0 0';
70         if (self.goalcurrent == world)
71                 return;
72         navigation_poptouchedgoals();
73         if (self.goalcurrent == world)
74         {
75                 // ran out of goals, rethink strategy as soon as possible
76                 self.bot_strategytime = 0;
77                 return;
78         }
79         evadeobstacle = '0 0 0';
80         evadelava = '0 0 0';
81         m1 = self.goalcurrent.origin + self.goalcurrent.mins;
82         m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
83         destorg = self.origin;
84         destorg_x = bound(m1_x, destorg_x, m2_x);
85         destorg_y = bound(m1_y, destorg_y, m2_y);
86         destorg_z = bound(m1_z, destorg_z, m2_z);
87         diff = destorg - self.origin;
88         //dist = vlen(diff);
89         dir = normalize(diff);
90         flatdir = diff;flatdir_z = 0;
91         flatdir = normalize(flatdir);
92         if (!self.waterlevel)
93         {
94                 if (!(self.flags & FL_ONGROUND))
95                 {
96                         // prevent goal checks when we can't walk
97                         if (self.bot_strategytime < time + 0.1)
98                                 self.bot_strategytime = time + 0.1;
99                         return;
100                 }
101
102                 // jump if going toward an obstacle that doesn't look like stairs we
103                 // can walk up directly
104                 tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.2, FALSE, self);
105                 if (trace_fraction < 1)
106                 if (trace_plane_normal_z < 0.7)
107                 {
108                         s = trace_fraction;
109                         tracebox(self.origin + '0 0 16', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 16', FALSE, self);
110                         if (trace_fraction < s + 0.01)
111                         if (trace_plane_normal_z < 0.7)
112                         {
113                                 s = trace_fraction;
114                                 tracebox(self.origin + '0 0 48', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 48', FALSE, self);
115                                 if (trace_fraction > s)
116                                         self.button2 = 1;
117                         }
118                 }
119
120                 traceline(self.origin + self.velocity * 0.3, self.origin + self.velocity * 0.3 + '0 0 -1000', TRUE, world);
121                 s = pointcontents(trace_endpos + '0 0 1');
122                 if (s == CONTENT_LAVA || s == CONTENT_SLIME)
123                         evadelava = normalize(self.velocity) * -1;
124
125                 dir = flatdir;
126         }
127         dodge = havocbot_dodge();
128         dir = normalize(dir + dodge + evadeobstacle + evadelava) * 400;
129         makevectors(self.v_angle);
130         self.movement_x = dir * v_forward;
131         self.movement_y = dir * v_right;
132         self.movement_z = dir * v_up;
133 };
134
135 .float havocbot_chooseenemy_finished;
136 void() havocbot_chooseenemy =
137 {
138         local entity head, best;
139         local float rating, bestrating;
140         local vector eye, v;
141         if (cvar("bot_nofire"))
142         {
143                 self.enemy = world;
144                 return;
145         }
146         if (time < self.havocbot_chooseenemy_finished)
147                 return;
148         self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval");
149         eye = (self.origin + self.view_ofs);
150         best = world;
151         bestrating = 100000000;
152         head = findchainfloat(bot_attack, TRUE);
153         while (head)
154         {
155                 v = (head.absmin + head.absmax) * 0.5;
156                 rating = vlen(v - eye);
157                 if (bestrating > rating)
158                 if (bot_shouldattack(head))
159                 {
160                         traceline(eye, v, TRUE, self);
161                         if (trace_ent == head || trace_fraction >= 1)
162                         {
163                                 best = head;
164                                 bestrating = rating;
165                         }
166                 }
167                 head = head.chain;
168         }
169         self.enemy = best;
170 };
171
172 float(entity e) w_getbestweapon;
173 void() havocbot_chooseweapon =
174 {
175         self.switchweapon = w_getbestweapon(self);
176 };
177
178 .float nextaim;
179 void() havocbot_aim =
180 {
181         local vector selfvel, enemyvel;
182         if (time < self.nextaim)
183                 return;
184         self.nextaim = time + 0.1;
185         selfvel = self.velocity;
186         if (!self.waterlevel)
187                 selfvel_z = 0;
188         if (self.enemy)
189         {
190                 enemyvel = self.enemy.velocity;
191                 if (!self.enemy.waterlevel)
192                         enemyvel_z = 0;
193                 lag_additem(time + self.ping, 0, 0, self.enemy, self.origin, selfvel, self.enemy.origin, enemyvel);
194         }
195         else
196                 lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, self.goalcurrent.origin, '0 0 0');
197 };
198
199 void() havocbot_ai =
200 {
201         if (bot_strategytoken == self)
202                 self.havocbot_role();
203         havocbot_chooseenemy();
204         havocbot_chooseweapon();
205         havocbot_aim();
206         lag_update();
207         if (self.bot_aimtarg)
208                 weapon_action(self.weapon, WR_AIM);
209         else if (self.goalcurrent)
210         {
211                 local vector v;
212                 v = self.goalcurrent.origin - self.origin;
213                 //v = self.velocity;
214                 if (self.waterlevel < 2)
215                         v_z = 0;
216                 //dprint("walk at:", vtos(v), "\n");
217                 //te_lightning2(world, self.origin, self.goalcurrent.origin);
218                 bot_aimdir(v, -1);
219         }
220         havocbot_movetogoal();
221 };
222
223 void() havocbot_setupbot =
224 {
225         self.bot_ai = havocbot_ai;
226         // will be updated by think code
227         havocbot_chooserole();
228 }