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