]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/mauvebot.c
- removed rocket launcher from nexdm15 (wasn't there in 1.2.1)
[divverent/nexuiz.git] / data / qcsrc / server / gamec / mauvebot.c
1 /*
2 MauveBot v1.0 for Nexuiz
3 */
4
5 string(float r) BotName =
6 {
7         if (r == 1)
8         {
9                 self.playermodel = "models/player/visitant.zym";
10                 self.playerskin = "1";
11                 return "Fricka";
12         }
13         else if (r == 2)
14         {
15                 self.playermodel = "models/player/marine.zym";
16                 self.playerskin = "0";
17                 return "Marine";
18         }
19         else if (r == 3)
20         {
21                 self.playermodel = "models/player/specop.zym";
22                 self.playerskin = "0";
23                 return "Specop";
24         }
25         else if (r == 4)
26         {
27                 self.playermodel = "models/player/nexus.zym";
28                 self.playerskin = "0";
29                 return "Nexus";
30         }
31         else if (r == 5)
32         {
33                 self.playermodel = "models/player/skadi.zym";
34                 self.playerskin = "0";
35                 return "Skadi";
36         }
37         else if (r == 6)
38         {
39                 self.playermodel = "models/player/lurk.zym";
40                 self.playerskin = "0";
41                 return "Lurk";
42         }
43         else if (r == 7)
44         {
45                 self.playermodel = "models/player/headhunter.zym";
46                 self.playerskin = "0";
47                 return "HeadHunter";
48         }
49         else if (r == 8)
50         {
51                 self.playermodel = "models/player/carni.zym";
52                 self.playerskin = "0";
53                 return "Carni";
54         }
55         else if (r == 9)
56         {
57                 self.playermodel = "models/player/grunt.zym";
58                 self.playerskin = "0";
59                 return "Grunt";
60         }
61         else if (r == 10)
62         {
63                 self.playermodel = "models/player/insurrectionist.zym";
64                 self.playerskin = "0";
65                 return "Insurrectionist";
66         }
67         else if (r == 11)
68         {
69                 self.playermodel = "models/player/lycanthrope.zym";
70                 self.playerskin = "0";
71                 return "Lycanthrope";
72         }
73         else if (r == 12)
74         {
75                 self.playermodel = "models/player/pyria.zym";
76                 self.playerskin = "0";
77                 return "Pyria";
78         }
79         else if (r == 13)
80         {
81                 self.playermodel = "models/player/shock.zym";
82                 self.playerskin = "0";
83                 return "Shock";
84         }
85         else if (r == 14)
86         {
87                 self.playermodel = "models/player/lurk.zym";
88                 self.playerskin = "1";
89                 return "Reptile";
90         }
91         else if (r == 15)
92         {
93                 self.playermodel = "models/player/crash.zym";
94                 self.playerskin = "0";
95                 return "Quark";
96         }
97         else if (r == 16)
98         {
99                 self.playermodel = "models/player/insurrectionist.zym";
100                 self.playerskin = "1";
101                 return "Anarchist";
102         }
103         else if (r == 17)
104         {
105                 self.playermodel = "models/player/carni.zym";
106                 self.playerskin = "1";
107                 return "Armored Carni";
108         }
109         else if (r == 18)
110         {
111                 self.playermodel = "models/player/nexus.zym";
112                 self.playerskin = "1";
113                 return "Mulder";
114         }
115         else
116         {
117                 self.playermodel = "models/player/carni.zym";
118                 self.playerskin = "0";
119                 return "Carni";
120         }
121 };
122
123 string () PickARandomName =
124 {
125         local float y, test;
126         local string h;
127         local entity t;
128
129         t = findflags(world, flags, FL_CLIENT);
130         while(t)
131         {
132                 if (clienttype(self) == CLIENTTYPE_BOT)
133                         y = y + 1;
134                 t = findflags(t, flags, FL_CLIENT);
135         }
136
137         if (y > 18)
138         {
139                 self.playermodel = "models/player/marine.zym";
140                 self.playerskin = "0";
141                 return "EJP_Tank";
142         }
143
144         y = TRUE;
145         while(y)
146         {
147                 test = ceil(random() * 18);
148                 h = BotName(test);
149                 t = find(world, netname, h);
150                 if (t == world)
151                         y = FALSE;
152         }
153         return h;
154 };
155
156 // Adds a bot to the server
157 entity(float bottype) add_MauveBot =
158 {
159         local entity oldself, ret;
160         local float shirt, pants;
161
162         oldself = self;
163         self = spawnclient();
164         if (!self)
165         {
166                 bprint("Can not add bot, server full.\n");
167                 if (bottype == BOT_TYPE_MAUVEBOT)
168                         cvar_set("mauvebots", ftos(mauvebots));
169                 else
170                         cvar_set("bot_number", ftos(bot_number));
171                 self = oldself;
172                 return world;
173         }
174
175         if(teamplay)
176         {
177                 // keep teams balanced
178                 JoinBestTeam(self, 0);
179         }
180         else
181         {
182                 shirt = floor(random()*15);
183                 pants = floor(random()*15);
184                 self.clientcolors = pants + shirt * 16;
185         }
186
187         self.netname = PickARandomName();
188  
189         ClientConnect();
190         PutClientInServer();
191         self.autoswitch = 1; // bots currently need autoswitching
192         self.skill_level = cvar("skill");
193         if (self.skill_level > 10)
194                 self.skill_level = 10;
195         if (self.skill_level < 1)
196                 self.skill_level = 1;
197         ret = self;
198         self = oldself;
199
200         return ret;
201 };
202
203 void() remove_MauveBot = 
204 {
205         local float flo, i;
206         local entity ent;
207
208         flo = floor(random() * mauvebots);
209         
210         ent = findflags(world, flags, FL_CLIENT);
211         
212         while(ent)
213         {
214                 if (clienttype(ent) == CLIENTTYPE_BOT)
215                 {
216                         if (ent.bot_type == BOT_TYPE_MAUVEBOT)
217                         {
218                                 if (flo == i)
219                                 {
220                                         self = ent;
221                                         ClientDisconnect();
222                                         dropclient(ent);
223                                         if (mauvebots > 0)
224                                                 mauvebots = mauvebots - 1;
225                                         return;
226                                 }
227                                 i = i + 1;
228                         }
229                 }
230                 ent = findflags(ent, flags, FL_CLIENT);
231         }
232 };
233
234 float (entity targ) visible =
235 {
236         local vector start, end, org;
237
238 //      if (self.skill_level < 3)
239 //              if (random() > self.skill_level / 10)
240 //                      return FALSE;
241
242         org = targ.origin;
243         if (org == '0 0 0')
244                 org = (targ.absmin + targ.absmax) * 0.5;
245
246         start = self.origin + self.view_ofs;
247         end = org;
248         traceline (start, end, TRUE, self);     
249         if (!(trace_inopen && trace_inwater))   
250                 if (trace_fraction == 1)
251                         return TRUE;
252         return FALSE;
253 };
254
255 void(entity ent) bot_set_angle =
256 {
257         local vector view;
258         local float flo;
259         if (ent != world)
260         {
261                 view = ent.origin;
262                 if (view == '0 0 0')
263                         view = (ent.absmin + ent.absmax) * 0.5;
264                 
265                 if (self.skill_level < 6)
266                         view = view - ent.velocity * (0.5 / self.skill_level);
267
268                 flo = vlen(ent.origin - self.origin) / (self.skill_level * 4);
269
270                 view_x = view_x + (random() * flo * 2) - flo;
271                 view_y = view_y + (random() * flo * 2) - flo;
272                 view_z = view_z + (random() * flo * 2) - flo;
273
274                 view = view - (self.origin + self.view_ofs);
275                 self.v_angle = vectoangles(view);
276                 self.v_angle_x = self.v_angle_x * -1;
277                 self.angles = self.v_angle;
278                 self.angles_x = self.angles_x * -1;
279                 if (self.angles_x > 180)
280                         self.angles_x = self.angles_x - 360;
281                 if (self.angles_x != 0)
282                         self.angles_x = self.angles_x / 6;
283         }
284         else
285                 self.angles_x = 0;// hack!
286 };
287
288 void() MauveToGoal =
289 {
290         local vector vec, en, diff, dir;
291
292         vec = self.origin;
293         movetogoal(20);
294         en = self.origin;
295         self.origin = vec;
296
297         diff = en - self.origin;
298         if (diff == '0 0 0')
299                 diff = self.goalentity.origin - self.origin;
300
301         if (self.search_time < time)
302         {
303                 self.goalentity.search_time = time + 20;
304                 self.goalentity = world;
305                 return;
306         }       
307
308         dir = normalize(diff);
309         dir = dir * cvar("sv_maxspeed");// - (self.velocity - dir * (self.velocity * dir));
310
311         makevectors(self.v_angle);
312         self.movement_x = dir * v_forward;
313         self.movement_y = dir * v_right;
314         self.movement_z = dir * v_up;
315 };
316
317 void() look_for_stuff =
318 {
319         local entity item, best, best2, best3;
320         local float dist, tdist, dist2, topthreat;
321         
322         item = findradius(self.origin, 1000);
323         
324         if (self.search_time < time)
325                 self.enemy = world;
326
327         if (self.enemy.health < 0)
328                 self.enemy = world;
329
330         if (self.enemy.deadflag)
331                 self.enemy = world;
332         
333         dist = dist2 = SEARCH_DIST;
334         topthreat = 0;
335
336         while(item)
337         {
338                 if (item.flags & FL_CLIENT)
339                 {
340                         if (!(item.flags & FL_NOTARGET))
341                         if (item != self && !(cvar("teamplay") && (item.clientcolors == self.clientcolors)))
342                         if ((item.health > 0) && (!item.deadflag))
343                         if (visible(item))
344                         {
345                                 tdist = vlen(item.origin - self.origin);
346                                 if (tdist < dist)
347                                 {
348                                         best = item;
349                                         dist = tdist;
350                                 }
351                         }
352                 }
353                 else if (( (item.flags & FL_ITEM) && item.model != string_null) && (item.search_time < time))
354                 {
355                         if (visible(item))
356                         {
357                                 tdist = vlen(item.origin - self.origin);
358                                 if (tdist < dist2)
359                                 {
360                                         best2 = item;
361                                         dist2 = tdist;
362                                 }
363                         }
364                 }
365                 if (item.threat == THREAT_UNFLAGGED)
366                 {
367                         if (item.classname == "missile")
368                                 item.threat = 100;
369                         else if (item.classname == "laserbolt") 
370                                 item.threat = 10;
371                         else if (item.classname == "grenade") 
372                                 item.threat = 50;
373                         else if (item.classname == "plasma") 
374                                 item.threat = 60;
375                         else if (item.classname == "spike")
376                                 item.threat = 30;
377                         else
378                                 item.threat = THREAT_IGNORE;
379                 }
380                 if (item.threat > 0)
381                 {
382                         if ((item.owner != self) || (item.velocity == '0 0 0'))
383                         {
384                                 tdist = vlen(item.origin - self.origin);
385                                 if (tdist < DODGE_DIST)
386                                 {
387                                         if (item.threat / tdist > topthreat)
388                                         {
389                                                 topthreat = item.threat / tdist;
390                                                 best3 = item;
391                                         }
392                                 }
393                         }
394                 }
395                 item = item.chain;
396         }
397         if ((best != self.enemy) && (best != world))
398                 self.enemy = best;
399         if ((best2 != self.goalentity) && (best2 != world))
400         {
401                 self.goalentity = best2;
402                 self.search_time = time + 5;
403         }
404         self.dodgeent = best3;
405 };
406
407 void() DodgeProjectile =
408 {
409         local vector vec;
410
411         vec = vectoangles(self.dodgeent.origin - self.origin);
412         makevectors(vec);
413         
414         self.goalentity = spawn();
415
416         if (self.dodgeent.velocity != '0 0 0')
417                 setorigin(self.goalentity, self.origin + v_right * 50);
418         else
419                 setorigin(self.goalentity, self.origin - v_forward * 50);
420         
421         MauveToGoal();
422
423         remove(self.goalentity);
424         self.goalentity = world;
425 };
426
427 void() MauveBot_AI =
428 {
429         self.button0 = 0;
430         self.button2 = 0;
431         self.button3 = 0;
432
433         self.movement = '0 0 0';
434
435         if (self.deadflag == DEAD_RESPAWNABLE)
436         {
437                 self.button0 = 1;
438                 return;
439         }
440         else if (self.deadflag)
441                 return;
442
443         if (self.goalentity.model == string_null)
444                 self.goalentity = world;
445
446         if (time > self.ai_time)
447         {
448                 self.ai_time = time + (0.5 / self.skill_level) + (random() * (1 / self.skill_level));
449
450                 look_for_stuff();
451         
452                 if (self.enemy)
453                 {
454                         bot_set_angle(self.enemy);
455                         if (visible(self.enemy))
456                         {
457                                 self.button0 = 1;
458                                 self.search_time = 100000;
459                         }
460                         else    if (self.search_time == 100000)
461                                 self.search_time = time + 5;
462                         if (self.goalentity == world)
463                         {
464                                 if (self.enemy)
465                                 {
466                                         self.goalentity = self.enemy;
467                                         if (vlen(self.enemy.origin - self.origin) < 300)
468                                                 self.dodgeent = self.enemy;
469                                 }
470                         }
471                 }
472                 else if (self.goalentity)
473                         bot_set_angle(self.goalentity);
474
475                 if (random() < 0.03)
476                         self.button2 = 1;
477         }
478         else
479         {
480                 if (self.skill_level > 3)
481                 {
482                         if (visible(self.enemy))
483                         {
484                                 self.button0 = 1;
485                                 self.search_time = 100000;
486                         }
487                 }
488         }
489
490         if (self.dodgeent != world)
491                 DodgeProjectile();
492         else if (self.goalentity != world)
493                 MauveToGoal();
494 };