]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/w_seeker.qc
fix the death messages of seeker
[divverent/nexuiz.git] / data / qcsrc / server / w_seeker.qc
1 //.float speed; = switchweapon\r
2 //.float proxytime; = autoswitch\r
3 //.float tl; = wait\r
4 \r
5 void Seeker_Missile_Explode ()\r
6 {\r
7     vector      org2;\r
8     float b;\r
9     org2 = findbetterlocation (self.origin, 12);\r
10     te_explosion (org2);\r
11 \r
12     b = crandom();\r
13     if (b<-0.7)\r
14         sound (self, CHAN_PROJECTILE, "weapons/hagexp1.ogg", 1, ATTN_NORM);\r
15     else if (b<0.4)\r
16         sound (self, CHAN_PROJECTILE, "weapons/hagexp2.ogg", 1, ATTN_NORM);\r
17     else if (b<1)\r
18         sound (self, CHAN_PROJECTILE, "weapons/hagexp3.ogg", 1, ATTN_NORM);\r
19 \r
20     self.event_damage = SUB_Null;\r
21     RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);\r
22 \r
23     remove (self);\r
24 }\r
25 \r
26 void Seeker_Missile_Touch()\r
27 {\r
28     if (other == self.owner)\r
29         return;\r
30 \r
31     Seeker_Missile_Explode();\r
32 }\r
33 \r
34 void Seeker_Missile_Think()\r
35 {\r
36     entity e;\r
37     vector desireddir, olddir, newdir;\r
38     float turnrate;\r
39     float dist;\r
40 \r
41     if (time > self.cnt)\r
42         Seeker_Missile_Explode();\r
43 \r
44     if (!self.switchweapon)\r
45         self.switchweapon = cvar("g_balance_seeker_missile_speed");\r
46 \r
47     if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))\r
48         self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");\r
49 \r
50     if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))\r
51         self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");\r
52 \r
53     if (self.enemy != world)\r
54     {\r
55         e               = self.enemy;\r
56         turnrate        = cvar("g_balance_seeker_missile_turnrate");                // how fast to turn\r
57         desireddir      = normalize(e.origin - self.origin);\r
58         olddir          = normalize(self.velocity);                                         // get my current direction\r
59         dist            = vlen(e.origin - self.origin);\r
60 \r
61         // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )\r
62         if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))\r
63         {\r
64             // Is it a better idea (shorter distance) to trace to the target itself?\r
65             if ( vlen(self.origin + olddir * self.wait) < dist)\r
66                 traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);\r
67             else\r
68                 traceline(self.origin, self.enemy.origin, FALSE, self);\r
69 \r
70             // Setup adaptive tracelength\r
71             self.wait = vlen(self.origin - trace_endpos);\r
72             if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");\r
73             if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");\r
74 \r
75             // Calc how important it is that we turn and add this to the desierd (enemy) dir.\r
76             desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);\r
77         }\r
78 \r
79         //newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy\r
80         newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy\r
81 \r
82         self.velocity = newdir * self.switchweapon;                                         // make me fly in the new direction at my flight speed\r
83     }\r
84 \r
85     // Proxy\r
86     if (cvar("g_balance_seeker_missile_proxy"))\r
87     {\r
88         if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))\r
89         {\r
90             if (self.autoswitch == 0)\r
91             {\r
92                 self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");\r
93             }\r
94             else\r
95             {\r
96                 if (self.autoswitch <= time)\r
97                 {\r
98                     Seeker_Missile_Explode();\r
99                     self.autoswitch = 0;\r
100                 }\r
101             }\r
102         }\r
103         else\r
104         {\r
105             if (self.autoswitch != 0)\r
106                 self.autoswitch = 0;\r
107         }\r
108     }\r
109     ///////////////\r
110 \r
111     if (self.enemy.deadflag != DEAD_NO)\r
112     {\r
113         self.enemy = world;\r
114         self.cnt = time + 1 + (random() * 4);\r
115         self.nextthink = self.cnt;\r
116         return;\r
117     }\r
118 \r
119     self.angles = vectoangles(self.velocity);                   // turn model in the new flight direction\r
120     self.nextthink = time + 0.05;\r
121 \r
122 }\r
123 \r
124 \r
125 \r
126 void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
127 {\r
128 \r
129     float d;\r
130     d = damage;\r
131 \r
132     if (self.owner == attacker)\r
133         d = d * 0.25;\r
134 \r
135     self.health = self.health - d;\r
136 \r
137     if (self.health <= 0)\r
138         Seeker_Missile_Explode();\r
139 }\r
140 \r
141 #define EF_ROCKET                               16777216\r
142 void Seeker_Missile_Animate()\r
143 {\r
144     self.frame = self.frame +1;\r
145     self.nextthink = time + 0.05;\r
146 \r
147     if(self.frame == 5)\r
148     {   self.think           = Seeker_Missile_Think;\r
149         self.nextthink       = time + cvar("g_balance_seeker_missile_activate_delay");\r
150         self.effects         = EF_LOWPRECISION | EF_NOSHADOW | EF_ROCKET;\r
151 \r
152         if (cvar("g_balance_seeker_guided_proxy"))\r
153             self.movetype    = MOVETYPE_BOUNCEMISSILE;\r
154         else\r
155             self.movetype    = MOVETYPE_FLYMISSILE;\r
156 \r
157     }\r
158 }\r
159 \r
160 void Seeker_Fire_Missile(vector f_org)\r
161 {\r
162     local entity missile;\r
163 \r
164     if not(self.items & IT_UNLIMITED_AMMO)\r
165         self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");\r
166 \r
167     makevectors(self.v_angle);\r
168     W_SetupShot (self, f_org, FALSE, 2, "weapons/hagar_fire.ogg");\r
169     pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);\r
170 \r
171     //self.detornator         = FALSE;\r
172 \r
173     missile                 = spawn();\r
174     missile.owner           = self;\r
175     missile.classname       = "seeker_missile";\r
176     missile.bot_dodge       = TRUE;\r
177     missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");\r
178 \r
179     missile.think           = Seeker_Missile_Animate;\r
180 \r
181     //if (!cvar("g_balance_seeker_missile_proxy"))\r
182     missile.touch           = Seeker_Missile_Touch;\r
183 \r
184     missile.event_damage    = Seeker_Missile_Damage;\r
185     missile.nextthink       = time + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");\r
186     missile.cnt             = time + cvar("g_balance_seeker_missile_lifetime");\r
187     missile.enemy           = self.enemy;\r
188     missile.switchweapon           = cvar("g_balance_seeker_missile_speed");\r
189     missile.effects         = EF_LOWPRECISION | EF_NOSHADOW;// | EF_ROCKET;\r
190     missile.solid           = SOLID_BBOX;\r
191     missile.scale           = 2;\r
192     missile.takedamage          = DAMAGE_YES;\r
193     missile.damageforcescale    = 4;\r
194     missile.health              = 5;\r
195         missile.projectiledeathtype = WEP_SEEKER;\r
196 \r
197     setorigin (missile, w_shotorg);\r
198     setmodel  (missile, "models/tagrocket.md3");\r
199     setsize (missile, '0 0 0', '0 0 0');\r
200 \r
201 \r
202     missile.movetype    = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;\r
203 \r
204     missile.flags       = FL_PROJECTILE;\r
205 \r
206     missile.velocity    = (w_shotdir + '0 0 0.45') * missile.switchweapon;\r
207     W_SetupProjectileVelocity(missile);\r
208 \r
209     missile.switchweapon = vlen(missile.velocity);\r
210     missile.angles = vectoangles (missile.velocity);\r
211 \r
212 }\r
213 \r
214 void Seeker_Vollycontroler_Think()\r
215 {\r
216     entity oldself,oldenemy;\r
217     self.cnt = self.cnt - 1;\r
218     if ((self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1))\r
219     {\r
220         remove(self);\r
221         return;\r
222 \r
223     }\r
224 \r
225     self.nextthink = time + cvar("g_balance_seeker_missile_delay");\r
226 \r
227     oldself = self;\r
228     self = self.owner;\r
229 \r
230     oldenemy = self.enemy;\r
231     self.enemy = oldself.enemy;\r
232 \r
233     switch(oldself.cnt)\r
234     {\r
235         case 0:\r
236             Seeker_Fire_Missile('37.5 17 -22');\r
237             break;\r
238         case 1:\r
239             Seeker_Fire_Missile('37.5 9.5 -22');\r
240             break;\r
241         case 2:\r
242             Seeker_Fire_Missile('40 17 -29');\r
243             break;\r
244         case 3:\r
245             Seeker_Fire_Missile('40 09.5 -29');\r
246             break;\r
247     }\r
248 \r
249 \r
250 \r
251     self.enemy = oldenemy;\r
252     self = oldself;\r
253 }\r
254 \r
255 void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
256 {\r
257     self.health = self.health - damage;\r
258     if (self.health <= 0)\r
259         self.think ();\r
260 }\r
261 \r
262 void Seeker_Tag_Explode ()\r
263 {\r
264     vector      org2;\r
265     float b;\r
266 \r
267     //if(other==self.owner)\r
268     //    return;\r
269 \r
270     org2 = findbetterlocation (self.origin, 12);\r
271     te_explosion (org2);\r
272 \r
273     b = crandom();\r
274     if (b<-0.7)\r
275         sound (self, CHAN_PROJECTILE, "weapons/hagexp1.ogg", 1, ATTN_NORM);\r
276     else if (b<0.4)\r
277         sound (self, CHAN_PROJECTILE, "weapons/hagexp2.ogg", 1, ATTN_NORM);\r
278     else if (b<1)\r
279         sound (self, CHAN_PROJECTILE, "weapons/hagexp3.ogg", 1, ATTN_NORM);\r
280 \r
281     remove (self);\r
282 }\r
283 \r
284 void Seeker_Tag_Think()\r
285 {\r
286     remove(self);\r
287     return;\r
288 }\r
289 \r
290 void Seeker_Tag_Touch()\r
291 {\r
292     vector dir;\r
293     vector org2;\r
294 \r
295         if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)\r
296         {\r
297                 remove(self);\r
298                 return;\r
299         }\r
300 \r
301     if (other == self.owner)\r
302         return;\r
303 \r
304     dir     = normalize (self.owner.origin - self.origin);\r
305     org2    = findbetterlocation (self.origin, 8);\r
306 \r
307     te_knightspike(org2);\r
308 \r
309     self.event_damage = SUB_Null;\r
310     sound (self, CHAN_PROJECTILE, "weapons/laserimpact.ogg", 1, ATTN_NORM);\r
311 \r
312     if (other.classname == "player")\r
313     {\r
314 \r
315         entity e;\r
316         e           = spawn();\r
317         e.cnt       = cvar("g_balance_seeker_missile_count");\r
318         e.owner     = self.owner;\r
319         e.enemy     = other;\r
320         e.think     = Seeker_Vollycontroler_Think;\r
321         e.nextthink = time;\r
322 \r
323         //sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");\r
324         //sprint(other,"^1You are targeted!\n");\r
325 \r
326         // stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");\r
327         // stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");\r
328     }\r
329 \r
330     remove(self);\r
331     return;\r
332 }\r
333 \r
334 \r
335 \r
336 void Seeker_Fire_Tag()\r
337 {\r
338     local entity missile;\r
339     if not(self.items & IT_UNLIMITED_AMMO)\r
340         self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");\r
341 \r
342     W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/hagar_fire.ogg");\r
343 \r
344     missile                 = spawn();\r
345     missile.owner           = self;\r
346     missile.classname       = "seeker_tag";\r
347     missile.bot_dodge       = TRUE;\r
348     missile.bot_dodgerating = 50;\r
349     missile.touch           = Seeker_Tag_Touch;\r
350     missile.think           = Seeker_Tag_Think;\r
351     missile.nextthink       = time + 15;\r
352     missile.movetype        = MOVETYPE_FLY;\r
353     missile.solid           = SOLID_BBOX;\r
354     missile.owner           = self;\r
355 \r
356     missile.takedamage       = DAMAGE_YES;\r
357     missile.event_damage    = Seeker_Tag_Explode;\r
358     missile.health          = 5;\r
359 \r
360     setmodel (missile, "models/laser.mdl");\r
361     setorigin (missile, w_shotorg);\r
362 \r
363     missile.effects     = EF_BRIGHTFIELD | EF_FULLBRIGHT | EF_NOSHADOW | EF_LOWPRECISION;\r
364     missile.flags       = FL_PROJECTILE;\r
365 \r
366     missile.velocity    = w_shotdir  * cvar("g_balance_seeker_tag_speed");\r
367     missile.movetype    = MOVETYPE_BOUNCEMISSILE;\r
368     W_SetupProjectileVelocity(missile);\r
369     missile.angles = vectoangles (missile.velocity);\r
370 }\r
371 \r
372 \r
373 void Seeker_Flac_Explode ()\r
374 {\r
375     vector      org2;\r
376     float b;\r
377     org2 = findbetterlocation (self.origin, 12);\r
378     te_explosion (org2);\r
379 \r
380     b = crandom();\r
381     if (b<-0.7)\r
382         sound (self, CHAN_PROJECTILE, "weapons/hagexp1.ogg", 1, ATTN_NORM);\r
383     else if (b<0.4)\r
384         sound (self, CHAN_PROJECTILE, "weapons/hagexp2.ogg", 1, ATTN_NORM);\r
385     else if (b<1)\r
386         sound (self, CHAN_PROJECTILE, "weapons/hagexp3.ogg", 1, ATTN_NORM);\r
387 \r
388     self.event_damage = SUB_Null;\r
389 \r
390     RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);\r
391 \r
392     remove (self);\r
393 }\r
394 \r
395 void Seeker_Flac_Touch()\r
396 {\r
397     if (other == self.owner)\r
398         return;\r
399 \r
400     Seeker_Flac_Explode();\r
401 }\r
402 \r
403 void Seeker_Fire_Flac()\r
404 {\r
405         local entity missile;\r
406     vector f_org;\r
407 \r
408         if not(self.items & IT_UNLIMITED_AMMO)\r
409                 self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_flac_ammo");\r
410 \r
411     switch(floor(random() * 3))\r
412     {\r
413         case 0:\r
414             f_org = '37.5 17 -22';\r
415             break;\r
416         case 1:\r
417             f_org = '37.5 9.5 -22';\r
418             break;\r
419         case 2:\r
420             f_org = '40 17 -29';\r
421             break;\r
422         case 3:\r
423             f_org = '40 09.5 -29';\r
424             break;\r
425     }\r
426     W_SetupShot (self, f_org, FALSE, 2, "weapons/hagar_fire.wav");\r
427 \r
428         pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);\r
429 \r
430         missile = spawn ();\r
431         missile.owner = missile.realowner = self;\r
432         missile.classname = "missile";\r
433         missile.bot_dodge = TRUE;\r
434         missile.bot_dodgerating = cvar("g_balance_seeker_flac_damage");\r
435         missile.touch = Seeker_Flac_Explode;\r
436         missile.use = Seeker_Flac_Explode;\r
437         missile.think = Seeker_Flac_Explode;\r
438         missile.nextthink = time + cvar("g_balance_seeker_flac_lifetime") + cvar("g_balance_seeker_flac_lifetime_rand");\r
439         missile.solid = SOLID_BBOX;\r
440         missile.scale = 0.4; // BUG: the model is too big\r
441         missile.projectiledeathtype = WEP_SEEKER;\r
442         setorigin (missile, w_shotorg);\r
443         setmodel (missile, "models/hagarmissile.mdl"); // precision set below\r
444         setsize (missile, '0 0 0', '0 0 0');\r
445         missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;\r
446 \r
447         missile.effects = EF_LOWPRECISION;\r
448         missile.modelflags = MF_GRENADE;\r
449 \r
450         missile.movetype = MOVETYPE_FLY;\r
451         w_shotdir = w_shotdir + '0 0 0.3';\r
452         missile.velocity    = (w_shotdir  + randomvec() * cvar("g_balance_seeker_flac_spread")) * cvar("g_balance_seeker_flac_speed");\r
453 \r
454         W_SetupProjectileVelocity(missile);\r
455 \r
456         missile.angles = vectoangles (missile.velocity);\r
457         missile.flags = FL_PROJECTILE;\r
458 }\r
459 \r
460 float w_seeker(float req)\r
461 {\r
462     if (req == WR_AIM)\r
463         self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);\r
464 \r
465     else if (req == WR_THINK)\r
466     {\r
467         if (self.BUTTON_ATCK)\r
468             if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))\r
469             {\r
470                 Seeker_Fire_Tag();\r
471                 weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);\r
472             }\r
473 \r
474         if (self.BUTTON_ATCK2)\r
475             if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))\r
476             {\r
477                 Seeker_Fire_Flac();\r
478                 weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_flac_animtime"), w_ready);\r
479             }\r
480 \r
481     }\r
482     else if (req == WR_PRECACHE)\r
483     {\r
484         precache_model ("models/tagrocket.md3");\r
485         precache_model ("models/weapons/g_seeker.md3");\r
486         precache_model ("models/weapons/v_seeker.md3");\r
487         precache_model ("models/weapons/w_seeker.zym");\r
488         precache_sound ("weapons/hagar_fire.wav");\r
489         precache_sound ("weapons/hagexp1.wav");\r
490         precache_sound ("weapons/hagexp2.wav");\r
491         precache_sound ("weapons/hagexp3.wav");\r
492     }\r
493     else if (req == WR_SETUP)\r
494         weapon_setup(WEP_SEEKER);\r
495     else if (req == WR_CHECKAMMO1)\r
496         return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo");\r
497     else if (req == WR_CHECKAMMO2)\r
498         return self.ammo_rockets >= cvar("g_balance_seeker_secondary_ammo");\r
499     else if (req == WR_SUICIDEMESSAGE)\r
500         w_deathtypestring = "played with tiny rockets";\r
501     else if (req == WR_KILLMESSAGE)\r
502         {\r
503                 if(w_deathtype & HITTYPE_SECONDARY)\r
504                         w_deathtypestring = "ran into #'s flac";\r
505                 else\r
506                         w_deathtypestring = "was tagged by";\r
507         }\r
508     return TRUE;\r
509 };\r
510 \r