]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/vehicles/vehicle/spiderbot.qc
Fix indentation
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / vehicles / vehicle / spiderbot.qc
1 #ifndef VEHICLE_SPIDERBOT
2 #define VEHICLE_SPIDERBOT
3
4 #include "spiderbot_weapons.qc"
5
6 CLASS(Spiderbot, Vehicle)
7 /* spawnflags */ ATTRIB(Spiderbot, spawnflags, int, VHF_DMGSHAKE);
8 /* mins       */ ATTRIB(Spiderbot, mins, vector, '-75 -75 10');
9 /* maxs       */ ATTRIB(Spiderbot, maxs, vector, '75 75 125');
10 /* view offset*/ ATTRIB(Spiderbot, view_ofs, vector, '0 0 70');
11 /* view dist  */ ATTRIB(Spiderbot, height, float, 170);
12 /* model          */ ATTRIB(Spiderbot, mdl, string, "models/vehicles/spiderbot.dpm");
13 /* model          */ ATTRIB(Spiderbot, model, string, "models/vehicles/spiderbot.dpm");
14 /* head_model */ ATTRIB(Spiderbot, head_model, string, "models/vehicles/spiderbot_top.dpm");
15 /* hud_model  */ ATTRIB(Spiderbot, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
16 /* tags       */ ATTRIB(Spiderbot, tag_head, string, "tag_head");
17 /* tags       */ ATTRIB(Spiderbot, tag_hud, string, "tag_hud");
18 /* tags       */ ATTRIB(Spiderbot, tag_view, string, "");
19 /* netname    */ ATTRIB(Spiderbot, netname, string, "spiderbot");
20 /* fullname   */ ATTRIB(Spiderbot, vehicle_name, string, _("Spiderbot"));
21 /* icon       */ ATTRIB(Spiderbot, m_icon, string, "vehicle_spider");
22 ENDCLASS(Spiderbot)
23
24 REGISTER_VEHICLE(SPIDERBOT, NEW(Spiderbot));
25
26 #endif
27
28 #ifdef IMPLEMENTATION
29
30 const int SBRM_FIRST = 1;
31 const int SBRM_VOLLY = 1;
32 const int SBRM_GUIDE = 2;
33 const int SBRM_ARTILLERY = 3;
34 const int SBRM_LAST = 3;
35
36 #include "spiderbot_weapons.qc"
37
38 #ifdef SVQC
39 bool autocvar_g_vehicle_spiderbot;
40
41 float autocvar_g_vehicle_spiderbot_respawntime;
42
43 float autocvar_g_vehicle_spiderbot_speed_stop;
44 float autocvar_g_vehicle_spiderbot_speed_strafe;
45 float autocvar_g_vehicle_spiderbot_speed_walk;
46 float autocvar_g_vehicle_spiderbot_speed_run = 700;
47 float autocvar_g_vehicle_spiderbot_turnspeed;
48 float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
49 float autocvar_g_vehicle_spiderbot_movement_inertia;
50
51 float autocvar_g_vehicle_spiderbot_springlength;
52 float autocvar_g_vehicle_spiderbot_springup;
53 float autocvar_g_vehicle_spiderbot_springblend;
54 float autocvar_g_vehicle_spiderbot_tiltlimit;
55
56 float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
57 float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
58 float autocvar_g_vehicle_spiderbot_head_turnlimit;
59 float autocvar_g_vehicle_spiderbot_head_turnspeed;
60
61 int autocvar_g_vehicle_spiderbot_health;
62 float autocvar_g_vehicle_spiderbot_health_regen;
63 float autocvar_g_vehicle_spiderbot_health_regen_pause;
64
65 int autocvar_g_vehicle_spiderbot_shield;
66 float autocvar_g_vehicle_spiderbot_shield_regen;
67 float autocvar_g_vehicle_spiderbot_shield_regen_pause;
68
69 vector autocvar_g_vehicle_spiderbot_bouncepain;
70
71 .float jump_delay;
72 float spiderbot_frame()
73 {SELFPARAM();
74         vector ad, vf;
75         entity player, spider;
76         float ftmp;
77
78         if(intermission_running)
79         {
80                 self.vehicle.velocity = '0 0 0';
81                 self.vehicle.avelocity = '0 0 0';
82                 return 1;
83         }
84
85         player = self;
86         spider = self.vehicle;
87
88         vehicles_frame(spider, player);
89
90         setself(spider);
91
92         PHYS_INPUT_BUTTON_ZOOM(player) = false;
93         PHYS_INPUT_BUTTON_CROUCH(player) = false;
94         PS(player).m_switchweapon = WEP_Null;
95         player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
96
97
98 #if 1 // 0 to enable per-gun impact aux crosshairs
99         // Avarage gun impact point's -> aux cross
100         ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
101         vf = v_forward;
102         ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
103         vf += v_forward;
104         ad = ad * 0.5;
105         v_forward = vf * 0.5;
106         traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
107         UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
108 #else
109         ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
110         traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
111         UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
112         vf = ad;
113         ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
114         traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
115         UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
116         ad = 0.5 * (ad + vf);
117 #endif
118
119         crosshair_trace(player);
120         ad = vectoangles(normalize(trace_endpos - ad));
121         ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
122         ad = AnglesTransform_Normalize(ad, true);
123         //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
124
125         // Rotate head
126         ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
127         ad_y = bound(-ftmp, ad_y, ftmp);
128         spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
129
130         // Pitch head
131         ad_x = bound(ftmp * -1, ad_x, ftmp);
132         spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
133
134
135         //fixedmakevectors(spider.angles);
136         makevectors(spider.angles + '-2 0 0' * spider.angles_x);
137
138         movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
139
140         if(IS_ONGROUND(spider))
141                 spider.jump_delay = time; // reset now so movement can begin
142
143         //if(IS_ONGROUND(spider))
144         {
145                 if(IS_ONGROUND(spider))
146                 if(spider.frame == 4 && self.tur_head.wait != 0)
147                 {
148                         sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_LAND, VOL_VEHICLEENGINE, ATTEN_NORM);
149                         spider.frame = 5;
150                 }
151
152                 if (!PHYS_INPUT_BUTTON_JUMP(player))
153                         PHYS_INPUT_BUTTON_JUMP(spider) = false;
154
155                 if((IS_ONGROUND(spider)) && PHYS_INPUT_BUTTON_JUMP(player) && !PHYS_INPUT_BUTTON_JUMP(spider) && self.tur_head.wait < time)
156                 {
157                         sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_JUMP, VOL_VEHICLEENGINE, ATTEN_NORM);
158                         //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
159                         self.delay = 0;
160
161                         self.tur_head.wait = time + 2;
162                         spider.jump_delay = time + 2;
163                         PHYS_INPUT_BUTTON_JUMP(spider) = true; // set spider's jump
164                         //PHYS_INPUT_BUTTON_JUMP(player) = false;
165
166                         vector movefix = '0 0 0';
167                         if(player.movement_x > 0) movefix_x = 1;
168                         if(player.movement_x < 0) movefix_x = -1;
169                         if(player.movement_y > 0) movefix_y = 1;
170                         if(player.movement_y < 0) movefix_y = -1;
171
172                         vector rt = movefix_y * v_right;
173                         vector sd = movefix_x * v_forward;
174                         if(movefix_y == 0 && movefix_x == 0)
175                                 sd = v_forward; // always do forward
176
177                         UNSET_ONGROUND(spider);
178
179                         spider.velocity = sd * 700 + rt * 600 + v_up * 600;
180                         spider.frame = 4;
181                 }
182                 else if(time >= spider.jump_delay)
183                 {
184                         if(!player.movement)
185                         {
186                                 if(IS_ONGROUND(spider))
187                                 {
188                                         if(self.sound_nexttime < time || self.delay != 3)
189                                         {
190                                                 self.delay = 3;
191                                                 self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
192                                                 //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
193                                                 sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
194                                         }
195                                         movelib_brake_simple(self, autocvar_g_vehicle_spiderbot_speed_stop);
196                                         spider.frame = 5;
197                                 }
198                         }
199                         else
200                         {
201                                 // Turn Body
202                                 if(player.movement_x == 0 && player.movement_y != 0)
203                                         ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
204                                 else
205                                         ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
206
207                                 ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
208                                 spider.angles_y = anglemods(spider.angles_y + ftmp);
209                                 spider.tur_head.angles_y -= ftmp;
210
211                                 if(player.movement_x != 0)
212                                 {
213                                         if(player.movement_x > 0)
214                                         {
215                                                 player.movement_x = 1;
216                                                 if(IS_ONGROUND(spider))
217                                                         spider.frame = 0;
218                                         }
219                                         else if(player.movement_x < 0)
220                                         {
221                                                 player.movement_x = -1;
222                                                 if(IS_ONGROUND(spider))
223                                                         spider.frame = 1;
224                                         }
225                                         player.movement_y = 0;
226                                         float oldvelz = spider.velocity_z;
227                                         movelib_move_simple(self, normalize(v_forward * player.movement_x),((PHYS_INPUT_BUTTON_JUMP(player)) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
228                                         spider.velocity_z = oldvelz;
229                                         float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
230                                         if(spider.velocity_z <= 20) // not while jumping
231                                                 spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
232                                         if(IS_ONGROUND(spider))
233                                         if(self.sound_nexttime < time || self.delay != 1)
234                                         {
235                                                 self.delay = 1;
236                                                 self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
237                                                 sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_WALK, VOL_VEHICLEENGINE, ATTEN_NORM);
238                                                 //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
239                                         }
240                                 }
241                                 else if(player.movement_y != 0)
242                                 {
243                                         if(player.movement_y < 0)
244                                         {
245                                                 player.movement_y = -1;
246                                                 if(IS_ONGROUND(spider))
247                                                         spider.frame = 2;
248                                         }
249                                         else if(player.movement_y > 0)
250                                         {
251                                                 player.movement_y = 1;
252                                                 if(IS_ONGROUND(spider))
253                                                         spider.frame = 3;
254                                         }
255
256                                         float oldvelz = spider.velocity_z;
257                                         movelib_move_simple(self, normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
258                                         spider.velocity_z = oldvelz;
259                                         float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
260                                         if(spider.velocity_z <= 20) // not while jumping
261                                                 spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
262                                         if(IS_ONGROUND(spider))
263                                         if(self.sound_nexttime < time || self.delay != 2)
264                                         {
265                                                 self.delay = 2;
266                                                 self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
267                                                 sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_STRAFE, VOL_VEHICLEENGINE, ATTEN_NORM);
268                                                 //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
269                                         }
270                                 }
271                         }
272                 }
273         }
274
275         self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
276         self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
277
278         if(!forbidWeaponUse(player))
279         if(PHYS_INPUT_BUTTON_ATCK(player))
280         {
281                 spider.cnt = time;
282                 if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single[0] <= time)
283                 {
284                         entity gun;
285                         vector v;
286                         spider.misc_bulletcounter += 1;
287
288                         setself(player);
289
290                         gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
291
292                         v = gettaginfo(gun, gettagindex(gun, "barrels"));
293                         v_forward = normalize(v_forward);
294                         v += v_forward * 50;
295
296                         fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
297                                 autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN.m_id, 0);
298
299                         sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
300                         //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
301                         pointparticles(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH, v, v_forward * 2500, 1);
302
303                         setself(spider);
304
305                         spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
306                         spider.tur_head.attack_finished_single[0] = time + autocvar_g_vehicle_spiderbot_minigun_refire;
307                         player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
308                         spider.gun1.angles_z += 45;
309                         spider.gun2.angles_z -= 45;
310                         if(spider.gun1.angles_z >= 360)
311                         {
312                                 spider.gun1.angles_z = 0;
313                                 spider.gun2.angles_z = 0;
314                         }
315                 }
316         }
317         else
318                 vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
319                                                                                    autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
320                                                                                    autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false);
321
322
323         spiderbot_rocket_do();
324
325         if(self.vehicle_flags  & VHF_SHIELDREGEN)
326                 vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
327
328         if(self.vehicle_flags  & VHF_HEALTHREGEN)
329                 vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
330
331         PHYS_INPUT_BUTTON_ATCK(player) = PHYS_INPUT_BUTTON_ATCK2(player) = false;
332         //player.vehicle_ammo2 = spider.tur_head.frame;
333         player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
334
335         if(spider.gun2.cnt <= time)
336                 player.vehicle_reload2 = 100;
337         else
338                 player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single[0]) * 100;
339
340         setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
341         player.velocity = spider.velocity;
342
343         VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
344
345         if(self.vehicle_flags & VHF_HASSHIELD)
346                 VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
347
348         setself(player);
349         return 1;
350 }
351
352 void spiderbot_exit(float eject)
353 {SELFPARAM();
354         entity e;
355         vector spot;
356
357         e = findchain(classname,"spiderbot_rocket");
358         while(e)
359         {
360                 if(e.owner == self.owner)
361                 {
362                         e.realowner = self.owner;
363                         e.owner = world;
364                 }
365                 e = e.chain;
366         }
367
368         self.think = vehicles_think;
369         self.nextthink = time;
370         self.frame = 5;
371         self.movetype = MOVETYPE_WALK;
372
373         if(!self.owner)
374                 return;
375
376         makevectors(self.angles);
377         if(eject)
378         {
379                 spot = self.origin + v_forward * 100 + '0 0 64';
380                 spot = vehicles_findgoodexit(spot);
381                 setorigin(self.owner , spot);
382                 self.owner.velocity = (v_up + v_forward * 0.25) * 750;
383                 self.owner.oldvelocity = self.owner.velocity;
384         }
385         else
386         {
387                 if(vdist(self.velocity, >, autocvar_g_vehicle_spiderbot_speed_strafe))
388                 {
389                         self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
390                         self.owner.velocity_z += 200;
391                         spot = self.origin + v_forward * 128 + '0 0 64';
392                         spot = vehicles_findgoodexit(spot);
393                 }
394                 else
395                 {
396                         self.owner.velocity = self.velocity * 0.5;
397                         self.owner.velocity_z += 10;
398                         spot = self.origin + v_forward * 256 + '0 0 64';
399                         spot = vehicles_findgoodexit(spot);
400                 }
401                 self.owner.oldvelocity = self.owner.velocity;
402                 setorigin(self.owner , spot);
403         }
404
405         antilag_clear(self.owner);
406         self.owner = world;
407 }
408
409 void spiderbot_headfade()
410 {SELFPARAM();
411         self.think = spiderbot_headfade;
412         self.nextthink = self.fade_time;
413         self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
414
415         if(self.cnt < time || self.alpha < 0.1)
416         {
417                 if(self.alpha > 0.1)
418                 {
419                         sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
420                         Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
421                 }
422                 remove(self);
423         }
424 }
425
426 void spiderbot_blowup()
427 {SELFPARAM();
428         if(self.cnt > time)
429         {
430                 if(random() < 0.1)
431                 {
432                         sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
433                         Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
434                 }
435                 self.nextthink = time + 0.1;
436                 return;
437         }
438
439         entity h, g1, g2, b;
440         b = spawn();
441         h = spawn();
442         g1 = spawn();
443         g2 = spawn();
444
445         setmodel(b, MDL_VEH_SPIDERBOT_BODY);
446         setmodel(h, MDL_VEH_SPIDERBOT_TOP);
447         setmodel(g1, MDL_VEH_SPIDERBOT_GUN);
448         setmodel(g2, MDL_VEH_SPIDERBOT_GUN);
449
450         setorigin(b, self.origin);
451         b.frame = 11;
452         b.angles = self.angles;
453         setsize(b, self.mins, self.maxs);
454
455         vector org = gettaginfo(self, gettagindex(self, "tag_head"));
456         setorigin(h, org);
457         h.movetype = MOVETYPE_BOUNCE;
458         h.solid = SOLID_BBOX;
459         h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
460         h.modelflags = MF_ROCKET;
461         h.effects = EF_FLAME | EF_LOWPRECISION;
462         h.avelocity = randomvec() * 360;
463
464         h.alpha = 1;
465         h.cnt = time + (3.5 * random());
466         h.fade_rate = 1 / min(self.respawntime, 10);
467         h.fade_time = time;
468         h.think = spiderbot_headfade;
469         h.nextthink = time;
470
471         org = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01"));
472         setorigin(g1, org);
473         g1.movetype = MOVETYPE_TOSS;
474         g1.solid = SOLID_CORPSE;
475         g1.velocity = v_forward * 700 + (randomvec() * 32);
476         g1.avelocity = randomvec() * 180;
477
478         org = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02"));
479         setorigin(g2, org);
480         g2.movetype = MOVETYPE_TOSS;
481         g2.solid = SOLID_CORPSE;
482         g2.velocity = v_forward * 700 + (randomvec() * 32);
483         g2.avelocity = randomvec() * 180;
484
485         h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
486
487         SUB_SetFade(b,  time + 5, min(self.respawntime, 1));
488         //SUB_SetFade(h,  time, min(self.respawntime, 10));
489         SUB_SetFade(g1, time, min(self.respawntime, 10));
490         SUB_SetFade(g2, time, min(self.respawntime, 10));
491
492         RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH.m_id, world);
493
494         self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
495         self.movetype = MOVETYPE_NONE;
496         self.deadflag = DEAD_DEAD;
497         self.solid = SOLID_NOT;
498         self.tur_head.effects &= ~EF_FLAME;
499         self.vehicle_hudmodel.viewmodelforclient = self;
500 }
501
502 bool spiderbot_impulse(int _imp)
503 {SELFPARAM();
504         switch(_imp)
505         {
506                 case IMP_weapon_group_1.impulse:
507                         self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
508                         CSQCVehicleSetup(self, 0);
509                         return true;
510                 case IMP_weapon_group_2.impulse:
511                         self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
512                         CSQCVehicleSetup(self, 0);
513                         return true;
514                 case IMP_weapon_group_3.impulse:
515                         self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
516                         CSQCVehicleSetup(self, 0);
517                         return true;
518
519                 case IMP_weapon_next_byid.impulse:
520                 case IMP_weapon_next_bypriority.impulse:
521                 case IMP_weapon_next_bygroup.impulse:
522                         self.vehicle.vehicle_weapon2mode += 1;
523                         if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
524                                 self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
525
526                         //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
527                         CSQCVehicleSetup(self, 0);
528                         return true;
529                 case IMP_weapon_last.impulse:
530                 case IMP_weapon_prev_byid.impulse:
531                 case IMP_weapon_prev_bypriority.impulse:
532                 case IMP_weapon_prev_bygroup.impulse:
533                         self.vehicle.vehicle_weapon2mode -= 1;
534                         if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
535                                 self.vehicle.vehicle_weapon2mode = SBRM_LAST;
536
537                         //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
538                         CSQCVehicleSetup(self, 0);
539                         return true;
540
541                 /*
542                 case IMP_weapon_drop.impulse: // toss gun, could be used to exit?
543                         break;
544                 case IMP_weapon_reload.impulse: // Manual minigun reload?
545                         break;
546                 */
547         }
548         return false;
549 }
550
551 spawnfunc(vehicle_spiderbot)
552 {
553         if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
554         if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
555 }
556
557 METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh, entity instance))
558 {
559     if(autocvar_g_vehicle_spiderbot_bouncepain)
560         vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
561 }
562 METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh, entity instance))
563 {
564     self.vehicle_weapon2mode = SBRM_GUIDE;
565     self.movetype = MOVETYPE_WALK;
566     CSQCVehicleSetup(self.owner, 0);
567     self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
568     self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
569
570     if(self.owner.flagcarried)
571     {
572         setattachment(self.owner.flagcarried, self.tur_head, "");
573         setorigin(self.owner.flagcarried, '-20 0 120');
574     }
575 }
576 METHOD(Spiderbot, vr_think, void(Spiderbot thisveh, entity instance))
577 {
578     if(IS_ONGROUND(self))
579         movelib_brake_simple(self, autocvar_g_vehicle_spiderbot_speed_stop);
580 }
581 METHOD(Spiderbot, vr_death, void(Spiderbot thisveh, entity instance))
582 {
583     instance.health                             = 0;
584     instance.event_damage               = func_null;
585     instance.takedamage                 = DAMAGE_NO;
586     instance.touch                              = func_null;
587     instance.cnt                                = 3.4 + time + random() * 2;
588     instance.think                              = spiderbot_blowup;
589     instance.nextthink                  = time;
590     instance.deadflag                   = DEAD_DYING;
591     instance.frame                              = 5;
592     instance.tur_head.effects  |= EF_FLAME;
593     instance.colormod                   = instance.tur_head.colormod = '-1 -1 -1';
594     instance.frame                              = 10;
595     instance.movetype                   = MOVETYPE_TOSS;
596
597     CSQCModel_UnlinkEntity(instance); // networking the death scene would be a nightmare
598 }
599 METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh, entity instance))
600 {
601     if(!self.gun1)
602     {
603         self.vehicles_impulse = spiderbot_impulse;
604         self.gun1 = spawn();
605         self.gun2 = spawn();
606         setmodel(self.gun1, MDL_VEH_SPIDERBOT_GUN);
607         setmodel(self.gun2, MDL_VEH_SPIDERBOT_GUN);
608         setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
609         setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
610         self.gravity = 2;
611         self.mass = 5000;
612     }
613
614     self.frame = 5;
615     self.tur_head.frame = 1;
616     self.movetype = MOVETYPE_WALK;
617     self.solid = SOLID_SLIDEBOX;
618     self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
619     self.tur_head.angles = '0 0 0';
620     self.vehicle_exit = spiderbot_exit;
621
622     setorigin(self, self.pos1 + '0 0 128');
623     self.angles = self.pos2;
624     self.damageforcescale = 0.03;
625     self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
626     self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
627
628     self.PlayerPhysplug = spiderbot_frame;
629 }
630 METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh, entity instance))
631 {
632     if(autocvar_g_vehicle_spiderbot_shield)
633         self.vehicle_flags |= VHF_HASSHIELD;
634
635     if(autocvar_g_vehicle_spiderbot_shield_regen)
636         self.vehicle_flags |= VHF_SHIELDREGEN;
637
638     if(autocvar_g_vehicle_spiderbot_health_regen)
639         self.vehicle_flags |= VHF_HEALTHREGEN;
640
641     self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
642     self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
643     self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
644     self.max_health = self.vehicle_health;
645     self.pushable = true; // spiderbot can use jumppads
646 }
647
648 #endif // SVQC
649 #ifdef CSQC
650 float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
651 float autocvar_cl_vehicle_spiderbot_cross_size = 1;
652
653 METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh))
654 {
655     Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
656                      "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
657                      "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color);
658 }
659 METHOD(Spiderbot, vr_crosshair, void(Spiderbot thisveh))
660 {
661     string crosshair;
662
663     switch(weapon2mode)
664     {
665         case SBRM_VOLLY:     crosshair = vCROSS_BURST; break;
666         case SBRM_GUIDE:     crosshair = vCROSS_GUIDE; break;
667         case SBRM_ARTILLERY: crosshair = vCROSS_RAIN;  break;
668         default:             crosshair = vCROSS_BURST;
669     }
670
671     Vehicles_drawCrosshair(crosshair);
672 }
673 METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh, entity instance))
674 {
675     AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
676     AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
677 }
678
679 #endif
680 #endif