]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/vehicles/unit/bumblebee.qc
Remove vehicleid globals
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / vehicles / unit / bumblebee.qc
1 #ifndef VEHICLE_BUMBLEBEE
2 #define VEHICLE_BUMBLEBEE
3 #include "bumblebee.qh"
4 int v_bumblebee(int);
5 REGISTER_VEHICLE_SIMPLE(
6 /* VEH_##id   */ BUMBLEBEE,
7 /* function   */ v_bumblebee,
8 /* spawnflags */ VHF_DMGSHAKE,
9 /* mins,maxs  */ '-245 -130 -130', '230 130 130',
10 /* model          */ "models/vehicles/bumblebee_body.dpm",
11 /* head_model */ "",
12 /* hud_model  */ "models/vehicles/spiderbot_cockpit.dpm",
13 /* tags           */ "", "", "tag_viewport",
14 /* netname        */ "bumblebee",
15 /* fullname   */ _("Bumblebee")
16 );
17 #endif
18
19 #ifdef IMPLEMENTATION
20
21 const float BRG_SETUP = 2;
22 const float BRG_START = 4;
23 const float BRG_END = 8;
24
25 #ifdef SVQC
26 float autocvar_g_vehicle_bumblebee_speed_forward;
27 float autocvar_g_vehicle_bumblebee_speed_strafe;
28 float autocvar_g_vehicle_bumblebee_speed_up;
29 float autocvar_g_vehicle_bumblebee_speed_down;
30 float autocvar_g_vehicle_bumblebee_turnspeed;
31 float autocvar_g_vehicle_bumblebee_pitchspeed;
32 float autocvar_g_vehicle_bumblebee_pitchlimit;
33 float autocvar_g_vehicle_bumblebee_friction;
34
35 float autocvar_g_vehicle_bumblebee_energy;
36 float autocvar_g_vehicle_bumblebee_energy_regen;
37 float autocvar_g_vehicle_bumblebee_energy_regen_pause;
38
39 float autocvar_g_vehicle_bumblebee_health;
40 float autocvar_g_vehicle_bumblebee_health_regen;
41 float autocvar_g_vehicle_bumblebee_health_regen_pause;
42
43 float autocvar_g_vehicle_bumblebee_shield;
44 float autocvar_g_vehicle_bumblebee_shield_regen;
45 float autocvar_g_vehicle_bumblebee_shield_regen_pause;
46
47 float autocvar_g_vehicle_bumblebee_cannon_cost;
48 float autocvar_g_vehicle_bumblebee_cannon_damage;
49 float autocvar_g_vehicle_bumblebee_cannon_radius;
50 float autocvar_g_vehicle_bumblebee_cannon_refire;
51 float autocvar_g_vehicle_bumblebee_cannon_speed;
52 float autocvar_g_vehicle_bumblebee_cannon_spread;
53 float autocvar_g_vehicle_bumblebee_cannon_force;
54
55 float autocvar_g_vehicle_bumblebee_cannon_ammo;
56 float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
57 float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
58
59 float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
60
61 float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
62 float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
63 float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
64 float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
65 float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
66
67
68 float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
69 float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
70 float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
71 float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
72
73 float autocvar_g_vehicle_bumblebee_raygun_range;
74 float autocvar_g_vehicle_bumblebee_raygun_dps;
75 float autocvar_g_vehicle_bumblebee_raygun_aps;
76 float autocvar_g_vehicle_bumblebee_raygun_fps;
77
78 float autocvar_g_vehicle_bumblebee_raygun;
79 float autocvar_g_vehicle_bumblebee_healgun_hps;
80 float autocvar_g_vehicle_bumblebee_healgun_hmax;
81 float autocvar_g_vehicle_bumblebee_healgun_aps;
82 float autocvar_g_vehicle_bumblebee_healgun_amax;
83 float autocvar_g_vehicle_bumblebee_healgun_sps;
84 float autocvar_g_vehicle_bumblebee_healgun_locktime;
85
86 float autocvar_g_vehicle_bumblebee_respawntime;
87
88 float autocvar_g_vehicle_bumblebee_blowup_radius;
89 float autocvar_g_vehicle_bumblebee_blowup_coredamage;
90 float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
91 float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
92 vector autocvar_g_vehicle_bumblebee_bouncepain;
93
94 bool autocvar_g_vehicle_bumblebee = 0;
95
96 float bumble_raygun_send(entity to, int sf);
97
98 void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner)
99 {
100         vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
101         vehicles_projectile("bigplasma_muzzleflash", "weapons/flacexp3.wav",
102                                                 v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
103                                                 autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force,  0,
104                                                 DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
105 }
106
107 float bumblebee_gunner_frame()
108 {
109         entity vehic    = self.vehicle.owner;
110         entity gun      = self.vehicle;
111         entity gunner   = self;
112         self = vehic;
113
114         vehic.solid = SOLID_NOT;
115         //setorigin(gunner, vehic.origin);
116         gunner.velocity = vehic.velocity;
117
118         float _in, _out;
119         vehic.angles_x *= -1;
120         makevectors(vehic.angles);
121         vehic.angles_x *= -1;
122         if(gun == vehic.gun1)
123         {
124                 _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
125                 _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
126                 setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
127         }
128         else
129         {
130                 _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
131                 _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
132                 setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
133         }
134
135         crosshair_trace(gunner);
136         vector _ct = trace_endpos;
137         vector ad;
138
139         if(autocvar_g_vehicle_bumblebee_cannon_lock)
140         {
141                 if(gun.lock_time < time)
142                         gun.enemy = world;
143
144                 if(trace_ent)
145                         if(trace_ent.movetype)
146                                 if(trace_ent.takedamage)
147                                         if(!trace_ent.deadflag)
148                                         {
149                                                 if(DIFF_TEAM(trace_ent, gunner))
150                                                 {
151                                                         gun.enemy = trace_ent;
152                                                         gun.lock_time = time + 5;
153                                                 }
154                                         }
155         }
156
157         if(gun.enemy)
158         {
159                 float distance, impact_time;
160
161                 vector vf = real_origin(gun.enemy);
162                 vector _vel = gun.enemy.velocity;
163                 if(gun.enemy.movetype == MOVETYPE_WALK)
164                         _vel.z *= 0.1;
165
166
167                 ad = vf;
168                 distance = vlen(ad - gunner.origin);
169                 impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
170                 ad = vf + _vel * impact_time;
171                 trace_endpos = ad;
172
173
174                 UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
175                 vehicle_aimturret(vehic, trace_endpos, gun, "fire",
176                                                   autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
177                                                   _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
178
179         }
180         else
181                 vehicle_aimturret(vehic, _ct, gun, "fire",
182                                                   autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
183                                                   _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
184
185         if(!forbidWeaponUse(gunner))
186         if(gunner.BUTTON_ATCK)
187                 if(time > gun.attack_finished_single)
188                         if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
189                         {
190                                 gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
191                                 bumblebee_fire_cannon(gun, "fire", gunner);
192                                 gun.delay = time;
193                                 gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
194                         }
195
196         VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
197
198         if(vehic.vehicle_flags & VHF_HASSHIELD)
199                 VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
200
201         ad = gettaginfo(gun, gettagindex(gun, "fire"));
202         traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
203
204         UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
205
206         if(vehic.owner)
207                 UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
208
209         vehic.solid = SOLID_BBOX;
210         gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
211         gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
212
213         self = gunner;
214         return 1;
215 }
216
217 vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
218 {
219         //vector exitspot;
220         float mysize;
221
222         tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
223         if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
224                 return prefer_spot;
225
226         mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
227         float i;
228         vector v, v2;
229         v2 = 0.5 * (gunner.absmin + gunner.absmax);
230         for(i = 0; i < 100; ++i)
231         {
232                 v = randomvec();
233                 v_z = 0;
234                 v = v2 + normalize(v) * mysize;
235                 tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
236                 if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
237                         return v;
238         }
239
240         return prefer_spot; // this should be considered a fallback?!
241 }
242
243 void bumblebee_gunner_exit(int _exitflag)
244 {
245         entity player = self;
246         entity gunner = player.vehicle;
247         entity vehic = gunner.owner;
248
249         if(IS_REAL_CLIENT(player))
250         {
251                 msg_entity = player;
252                 WriteByte(MSG_ONE, SVC_SETVIEWPORT);
253                 WriteEntity(MSG_ONE, player);
254
255                 WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
256                 WriteAngle(MSG_ONE, 0);
257                 WriteAngle(MSG_ONE, vehic.angles.y);
258                 WriteAngle(MSG_ONE, 0);
259         }
260
261         CSQCVehicleSetup(player, HUD_NORMAL);
262         setsize(player, PL_MIN, PL_MAX);
263
264         player.takedamage     = DAMAGE_AIM;
265         player.solid          = SOLID_SLIDEBOX;
266         player.movetype       = MOVETYPE_WALK;
267         player.effects       &= ~EF_NODRAW;
268         player.alpha          = 1;
269         player.PlayerPhysplug = func_null;
270         player.view_ofs       = PL_VIEW_OFS;
271         player.event_damage   = PlayerDamage;
272         player.hud            = HUD_NORMAL;
273         player.teleportable       = TELEPORT_NORMAL;
274         player.switchweapon   = gunner.switchweapon;
275         player.vehicle_enter_delay = time + 2;
276
277         fixedmakevectors(vehic.angles);
278
279         if(player == vehic.gunner1) { vehic.gunner1 = world; }
280         if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
281
282         vector spot = real_origin(gunner);
283         spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
284         spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
285
286         // TODO: figure a way to move player out of the gunner
287
288         player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
289         player.velocity_z += 10;
290
291         gunner.phase = time + 5;
292         gunner.vehicle_hudmodel.viewmodelforclient = gunner;
293
294         MUTATOR_CALLHOOK(VehicleExit, player, gunner);
295
296         player.vehicle = world;
297 }
298
299 bool bumblebee_gunner_enter()
300 {
301         entity vehic = self;
302         entity player = other;
303         entity gunner = world;
304
305         if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
306         {
307                 // we can have some fun
308                 if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
309                 {
310                         gunner = vehic.gun2;
311                         vehic.gunner2 = player;
312                 }
313                 else
314                 {
315                         gunner = vehic.gun1;
316                         vehic.gunner1 = player;
317                 }
318         }
319         else if(!vehic.gunner1 && time >= vehic.gun1.phase)     { gunner = vehic.gun1; vehic.gunner1 = player; }
320         else if(!vehic.gunner2 && time >= vehic.gun2.phase)             { gunner = vehic.gun2; vehic.gunner2 = player; }
321         else { dprint("Vehicle is full, fail\n"); return false; }
322
323         player.vehicle                  = gunner;
324         player.angles                   = vehic.angles;
325         player.takedamage               = DAMAGE_NO;
326         player.solid                    = SOLID_NOT;
327         player.alpha                    = -1;
328         player.movetype                 = MOVETYPE_NOCLIP;
329         player.event_damage     = func_null;
330         player.view_ofs                 = '0 0 0';
331         player.hud                              = gunner.hud;
332         player.teleportable     = false;
333         player.PlayerPhysplug   = gunner.PlayerPhysplug;
334         player.vehicle_ammo1    = vehic.vehicle_ammo1;
335         player.vehicle_ammo2    = vehic.vehicle_ammo2;
336         player.vehicle_reload1  = vehic.vehicle_reload1;
337         player.vehicle_reload2  = vehic.vehicle_reload2;
338         player.vehicle_energy   = vehic.vehicle_energy;
339         player.flags               &= ~FL_ONGROUND;
340
341         RemoveGrapplingHook(player);
342
343         gunner.switchweapon = player.switchweapon;
344         gunner.vehicle_exit = bumblebee_gunner_exit;
345         gunner.vehicle_hudmodel.viewmodelforclient = player;
346
347         if(IS_REAL_CLIENT(player))
348         {
349                 msg_entity = player;
350                 WriteByte(MSG_ONE,              SVC_SETVIEWPORT);
351                 WriteEntity(MSG_ONE,    gunner.vehicle_viewport);
352
353                 WriteByte(MSG_ONE,              SVC_SETVIEWANGLES);
354                 WriteAngle(MSG_ONE,     gunner.angles_x + vehic.angles_x); // tilt
355                 WriteAngle(MSG_ONE,     gunner.angles_y + vehic.angles_y); // yaw
356                 WriteAngle(MSG_ONE,     0); // roll
357         }
358
359         CSQCVehicleSetup(player, player.hud);
360
361         MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
362
363         return true;
364 }
365
366 bool vehicles_valid_pilot()
367 {
368         if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
369                 return false;
370
371         if((!IS_PLAYER(other))
372         || (other.deadflag != DEAD_NO)
373         || (other.vehicle)
374         || (DIFF_TEAM(other, self))
375         ) { return false; }
376
377         return true;
378 }
379
380 void bumblebee_touch()
381 {
382         if(autocvar_g_vehicles_enter) { return; }
383
384         if(self.gunner1 != world && self.gunner2 != world)
385         {
386                 vehicles_touch();
387                 return;
388         }
389
390         if(vehicles_valid_pilot())
391         {
392                 float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
393
394                 if(time >= other.vehicle_enter_delay && phase_time)
395                 if(bumblebee_gunner_enter())
396                         return;
397         }
398
399         vehicles_touch();
400 }
401
402 void bumblebee_regen()
403 {
404         if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
405                 self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
406                                                                            self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
407
408         if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
409                 self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
410                                                                            self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
411
412         if(self.vehicle_flags  & VHF_SHIELDREGEN)
413                 vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
414
415         if(self.vehicle_flags  & VHF_HEALTHREGEN)
416                 vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
417
418         if(self.vehicle_flags  & VHF_ENERGYREGEN)
419                 vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
420
421 }
422
423 float bumblebee_pilot_frame()
424 {
425         entity pilot, vehic;
426         vector newvel;
427         
428         if(intermission_running)
429         {
430                 self.vehicle.velocity = '0 0 0';
431                 self.vehicle.avelocity = '0 0 0';
432                 return 1;
433         }
434
435         pilot = self;
436         vehic = self.vehicle;
437         self   = vehic;
438
439         if(vehic.deadflag != DEAD_NO)
440         {
441                 self = pilot;
442                 pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
443                 return 1;
444         }
445
446         bumblebee_regen();
447
448         crosshair_trace(pilot);
449
450         vector vang;
451         float ftmp;
452
453         vang = vehic.angles;
454         newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
455         vang.x *= -1;
456         newvel.x *= -1;
457         if(newvel.x > 180)  newvel.x -= 360;
458         if(newvel.x < -180) newvel.x += 360;
459         if(newvel.y > 180)  newvel.y -= 360;
460         if(newvel.y < -180) newvel.y += 360;
461
462         ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
463         if(ftmp > 180)  ftmp -= 360;
464         if(ftmp < -180) ftmp += 360;
465         vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
466
467         // Pitch
468         ftmp = 0;
469         if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
470                 ftmp = 4;
471         else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
472                 ftmp = -8;
473
474         newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
475         ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
476         vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
477
478         vehic.angles_x = anglemods(vehic.angles.x);
479         vehic.angles_y = anglemods(vehic.angles.y);
480         vehic.angles_z = anglemods(vehic.angles.z);
481
482         makevectors('0 1 0' * vehic.angles.y);
483         newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
484
485         if(pilot.movement.x != 0)
486         {
487                 if(pilot.movement.x > 0)
488                         newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
489                 else if(pilot.movement.x < 0)
490                         newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
491         }
492
493         if(pilot.movement.y != 0)
494         {
495                 if(pilot.movement.y < 0)
496                         newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
497                 else if(pilot.movement.y > 0)
498                         newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
499                 ftmp = newvel * v_right;
500                 ftmp *= frametime * 0.1;
501                 vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
502         }
503         else
504         {
505                 vehic.angles_z *= 0.95;
506                 if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
507                         vehic.angles_z = 0;
508         }
509
510         if(pilot.BUTTON_CROUCH)
511                 newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
512         else if(pilot.BUTTON_JUMP)
513                 newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
514
515         vehic.velocity  += newvel * frametime;
516         pilot.velocity = pilot.movement  = vehic.velocity;
517
518
519         if(autocvar_g_vehicle_bumblebee_healgun_locktime)
520         {
521                 if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
522                         vehic.tur_head.enemy = world;
523
524                 if(trace_ent)
525                 if(trace_ent.movetype)
526                 if(trace_ent.takedamage)
527                 if(!trace_ent.deadflag)
528                 {
529                         if(teamplay)
530                         {
531                                 if(trace_ent.team == pilot.team)
532                                 {
533                                         vehic.tur_head.enemy = trace_ent;
534                                         vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
535                                 }
536                         }
537                         else
538                         {
539                                 vehic.tur_head.enemy = trace_ent;
540                                 vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
541                         }
542                 }
543
544                 if(vehic.tur_head.enemy)
545                 {
546                         trace_endpos = real_origin(vehic.tur_head.enemy);
547                         UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
548                 }
549         }
550
551         vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
552                                           autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
553                                           autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
554
555         if(!forbidWeaponUse(pilot))
556         if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
557         {
558                 vehic.gun3.enemy.realowner = pilot;
559                 vehic.gun3.enemy.effects &= ~EF_NODRAW;
560
561                 vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
562                 vehic.gun3.enemy.SendFlags |= BRG_START;
563
564                 traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
565
566                 if(trace_ent)
567                 {
568                         if(autocvar_g_vehicle_bumblebee_raygun)
569                         {
570                                 Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
571                                 vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
572                         }
573                         else
574                         {
575                                 if(trace_ent.deadflag == DEAD_NO)
576                                         if((teamplay && trace_ent.team == pilot.team) || !teamplay)
577                                         {
578
579                                                 if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
580                                                 {
581                                                         if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
582                                                                 trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health);
583
584                                                         if(autocvar_g_vehicle_bumblebee_healgun_hps)
585                                                                 trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
586                                                 }
587                                                 else if(IS_CLIENT(trace_ent))
588                                                 {
589                                                         if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
590                                                                 trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
591
592                                                         if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
593                                                                 trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
594
595                                                         trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
596                                                 }
597                                                 else if(IS_TURRET(trace_ent))
598                                                 {
599                                                         if(trace_ent.health  <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps)
600                                                                 trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
601                                                         //else ..hmmm what? ammo?
602
603                                                         trace_ent.SendFlags |= TNSF_STATUS;
604                                                 }
605                                         }
606                         }
607                 }
608
609                 vehic.gun3.enemy.hook_end = trace_endpos;
610                 setorigin(vehic.gun3.enemy, trace_endpos);
611                 vehic.gun3.enemy.SendFlags |= BRG_END;
612
613                 vehic.wait = time + 1;
614         }
615         else
616                 vehic.gun3.enemy.effects |= EF_NODRAW;
617         /*{
618                 if(vehic.gun3.enemy)
619                         remove(vehic.gun3.enemy);
620
621                 vehic.gun3.enemy = world;
622         }
623         */
624
625         VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
626         VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
627
628         pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
629         pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
630
631         if(vehic.vehicle_flags & VHF_HASSHIELD)
632                 VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
633
634         vehic.angles_x *= -1;
635         makevectors(vehic.angles);
636         vehic.angles_x *= -1;
637         setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
638
639         pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
640         self = pilot;
641
642         return 1;
643 }
644
645 void bumblebee_land()
646 {
647         float hgt;
648
649         hgt = raptor_altitude(512);
650         self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
651         self.angles_x *= 0.95;
652         self.angles_z *= 0.95;
653
654         if(hgt < 16)
655                 self.think      = vehicles_think;
656
657         self.nextthink = time;
658         
659         CSQCMODEL_AUTOUPDATE();
660 }
661
662 void bumblebee_exit(float eject)
663 {
664         if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
665         {
666                 bumblebee_gunner_exit(eject);
667                 return;
668         }
669
670         self.touch = vehicles_touch;
671
672         if(self.deadflag == DEAD_NO)
673         {
674                 self.think = bumblebee_land;
675                 self.nextthink  = time;
676         }
677         
678         self.movetype = MOVETYPE_TOSS;
679
680         if(!self.owner)
681                 return;
682
683         fixedmakevectors(self.angles);
684         vector spot;
685         if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
686                 spot = self.origin + v_up * 128 + v_forward * 300;
687         else
688                 spot = self.origin + v_up * 128 - v_forward * 300;
689
690         spot = vehicles_findgoodexit(spot);
691
692         // Hide beam
693         if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
694                 self.gun3.enemy.effects |= EF_NODRAW;
695         }
696
697         self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
698         self.owner.velocity_z += 10;
699         setorigin(self.owner, spot);
700
701         antilag_clear(self.owner);
702         self.owner = world;
703 }
704
705 void bumblebee_blowup()
706 {
707         RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
708                                  autocvar_g_vehicle_bumblebee_blowup_edgedamage,
709                                  autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
710                                  autocvar_g_vehicle_bumblebee_blowup_forceintensity,
711                                  DEATH_VH_BUMB_DEATH, world);
712
713         sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
714         Send_Effect("explosion_big", (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
715
716         if(self.owner.deadflag == DEAD_DYING)
717                 self.owner.deadflag = DEAD_DEAD;
718
719         remove(self);
720 }
721
722 void bumblebee_diethink()
723 {
724         if(time >= self.wait)
725                 self.think = bumblebee_blowup;
726
727         if(random() < 0.1)
728         {
729                 sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
730                 Send_Effect("explosion_small", randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
731         }
732
733         self.nextthink = time + 0.1;
734 }
735
736 float bumble_raygun_send(entity to, float sf)
737 {
738         WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
739
740         WriteByte(MSG_ENTITY, sf);
741         if(sf & BRG_SETUP)
742         {
743                 WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
744                 WriteByte(MSG_ENTITY, self.realowner.team);
745                 WriteByte(MSG_ENTITY, self.cnt);
746         }
747
748         if(sf & BRG_START)
749         {
750                 WriteCoord(MSG_ENTITY, self.hook_start_x);
751                 WriteCoord(MSG_ENTITY, self.hook_start_y);
752                 WriteCoord(MSG_ENTITY, self.hook_start_z);
753         }
754
755         if(sf & BRG_END)
756         {
757                 WriteCoord(MSG_ENTITY, self.hook_end_x);
758                 WriteCoord(MSG_ENTITY, self.hook_end_y);
759                 WriteCoord(MSG_ENTITY, self.hook_end_z);
760         }
761
762         return true;
763 }
764
765 void spawnfunc_vehicle_bumblebee()
766 {
767         if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
768         if(!vehicle_initialize(VEH_BUMBLEBEE.vehicleid, false)) { remove(self); return; }
769 }
770
771 float v_bumblebee(float req)
772 {
773         switch(req)
774         {
775                 case VR_IMPACT:
776                 {
777                         if(autocvar_g_vehicle_bumblebee_bouncepain)
778                                 vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
779                                 
780                         return true;
781                 }
782                 case VR_ENTER:
783                 {
784                         self.touch = bumblebee_touch;
785                         self.nextthink = 0;
786                         self.movetype = MOVETYPE_BOUNCEMISSILE;
787                         return true;
788                 }
789                 case VR_THINK:
790                 {
791                         self.angles_z *= 0.8;
792                         self.angles_x *= 0.8;
793                         
794                         self.nextthink = time;
795                         
796                         if(!self.owner)
797                         {
798                                 entity oldself = self;          
799                                 if(self.gunner1)
800                                 {
801                                         self = self.gunner1;
802                                         oldself.gun1.vehicle_exit(VHEF_EJECT);
803                                         entity oldother = other;
804                                         other = self;
805                                         self = oldself;
806                                         self.phase = 0;
807                                         self.touch();
808                                         other = oldother;
809                                         return true;
810                                 }
811                                 
812                                 if(self.gunner2)
813                                 {
814                                         self = self.gunner2;
815                                         oldself.gun2.vehicle_exit(VHEF_EJECT);
816                                         entity oldother = other;
817                                         other = self;
818                                         self = oldself;
819                                         self.phase = 0;
820                                         self.touch();
821                                         other = oldother;
822                                         return true;
823                                 }               
824                         }
825                         
826                         return true;
827                 }
828                 case VR_DEATH:
829                 {
830                         entity oldself = self;
831
832                         CSQCModel_UnlinkEntity();
833
834                         // Hide beam
835                         if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
836                                 self.gun3.enemy.effects |= EF_NODRAW;
837                         
838                         if(self.gunner1)
839                         {
840                                 self = self.gunner1;
841                                 oldself.gun1.vehicle_exit(VHEF_EJECT);
842                                 self = oldself;
843                         }
844
845                         if(self.gunner2)
846                         {
847                                 self = self.gunner2;
848                                 oldself.gun2.vehicle_exit(VHEF_EJECT);
849                                 self = oldself;
850                         }
851
852                         self.vehicle_exit(VHEF_EJECT);
853
854                         fixedmakevectors(self.angles);
855                         vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
856                         vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
857                         vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
858
859                         entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
860
861                         if(random() > 0.5)
862                                 _body.touch = bumblebee_blowup;
863                         else
864                                 _body.touch = func_null;
865                                 
866                         _body.think = bumblebee_diethink;
867                         _body.nextthink = time;
868                         _body.wait = time + 2 + (random() * 8);
869                         _body.owner = self;
870                         _body.enemy = self.enemy;
871                         _body.scale = 1.5;
872                         _body.angles = self.angles;
873
874                         Send_Effect("explosion_medium", findbetterlocation(self.origin, 16), '0 0 0', 1);
875                         
876                         self.health                     = 0;
877                         self.event_damage       = func_null;
878                         self.solid                      = SOLID_NOT;
879                         self.takedamage         = DAMAGE_NO;
880                         self.deadflag           = DEAD_DYING;
881                         self.movetype           = MOVETYPE_NONE;
882                         self.effects            = EF_NODRAW;
883                         self.colormod           = '0 0 0';
884                         self.avelocity          = '0 0 0';
885                         self.velocity           = '0 0 0';
886                         self.touch                      = func_null;
887                         self.nextthink          = 0;
888
889                         setorigin(self, self.pos1);
890                         return true;
891                 }
892                 case VR_SPAWN:
893                 {
894                         if(!self.gun1)
895                         {
896                                 // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
897                                 self.vehicle_shieldent = spawn();
898                                 self.vehicle_shieldent.effects = EF_LOWPRECISION;
899                                 setmodel(self.vehicle_shieldent, "models/vhshield.md3");
900                                 setattachment(self.vehicle_shieldent, self, "");
901                                 setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
902                                 self.vehicle_shieldent.scale       = 512 / vlen(self.maxs - self.mins);
903                                 self.vehicle_shieldent.think       = shieldhit_think;
904                                 self.vehicle_shieldent.alpha = -1;
905                                 self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
906
907                                 self.gun1 = spawn();
908                                 self.gun2 = spawn();
909                                 self.gun3 = spawn();
910
911                                 self.vehicle_flags |= VHF_MULTISLOT;
912
913                                 self.gun1.owner = self;
914                                 self.gun2.owner = self;
915                                 self.gun3.owner = self;
916
917                                 self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
918
919                                 setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
920                                 setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
921                                 setmodel(self.gun3, "models/vehicles/bumblebee_ray.dpm");
922
923                                 setattachment(self.gun1, self, "cannon_right");
924                                 setattachment(self.gun2, self, "cannon_left");
925
926                                 // Angled bones are no fun, messes up gun-aim; so work arround it.
927                                 self.gun3.pos1 = self.angles;
928                                 self.angles = '0 0 0';
929                                 vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
930                                 ofs -= self.origin;
931                                 setattachment(self.gun3, self, "");
932                                 setorigin(self.gun3, ofs);
933                                 self.angles = self.gun3.pos1;
934
935                                 vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
936                                 vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
937
938                                 setorigin(self.vehicle_hudmodel, '50 0 -5');    // Move cockpit forward - down.
939                                 setorigin(self.vehicle_viewport, '5 0 2');    // Move camera forward up
940
941                                 //fixme-model-bones
942                                 setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
943                                 setorigin(self.gun1.vehicle_viewport, '-85 0 50');
944                                 //fixme-model-bones
945                                 setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
946                                 setorigin(self.gun2.vehicle_viewport, '-85 0 50');
947
948                                 self.scale = 1.5;
949                                 
950                                 // Raygun beam
951                                 if(self.gun3.enemy == world)
952                                 {                       
953                                         self.gun3.enemy = spawn();
954                                         Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
955                                         self.gun3.enemy.SendFlags = BRG_SETUP;                  
956                                         self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;                      
957                                         self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
958                                 }
959                         }
960
961                         self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
962                         self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
963                         self.solid = SOLID_BBOX;
964                         self.movetype = MOVETYPE_TOSS;
965                         self.damageforcescale = 0.025;
966                         
967                         self.PlayerPhysplug = bumblebee_pilot_frame;
968                         
969                         setorigin(self, self.origin + '0 0 25');
970                         return true;
971                 }
972                 case VR_SETUP:
973                 {
974                         if(autocvar_g_vehicle_bumblebee_energy)
975                         if(autocvar_g_vehicle_bumblebee_energy_regen)
976                                 self.vehicle_flags |= VHF_ENERGYREGEN;
977
978                         if(autocvar_g_vehicle_bumblebee_shield)
979                                 self.vehicle_flags |= VHF_HASSHIELD;
980
981                         if(autocvar_g_vehicle_bumblebee_shield_regen)
982                                 self.vehicle_flags |= VHF_SHIELDREGEN;
983
984                         if(autocvar_g_vehicle_bumblebee_health_regen)
985                                 self.vehicle_flags |= VHF_HEALTHREGEN;
986                                 
987                         self.vehicle_exit = bumblebee_exit;
988                         self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
989                         self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
990                         self.max_health = self.vehicle_health;
991                         self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
992                                 
993                         return true;
994                 }
995                 case VR_PRECACHE:
996                 {
997                         precache_model("models/vehicles/bumblebee_body.dpm");
998                         precache_model("models/vehicles/bumblebee_plasma_left.dpm");
999                         precache_model("models/vehicles/bumblebee_plasma_right.dpm");
1000                         precache_model("models/vehicles/bumblebee_ray.dpm");
1001                         precache_model("models/vehicles/wakizashi_cockpit.dpm");
1002                         precache_model("models/vehicles/spiderbot_cockpit.dpm");
1003                         precache_model("models/vehicles/raptor_cockpit.dpm");
1004                         return true;
1005                 }
1006         }
1007
1008         return true;
1009 }
1010
1011 #endif // SVQC
1012 #ifdef CSQC
1013
1014 void CSQC_BUMBLE_GUN_HUD()
1015 {
1016         Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
1017                                          "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
1018                                          string_null, '0 0 0',
1019                                          string_null);
1020 }
1021
1022 void bumble_raygun_draw()
1023 {
1024         float _len;
1025         vector _dir;
1026         vector _vtmp1, _vtmp2;
1027
1028         _len = vlen(self.origin - self.move_origin);
1029         _dir = normalize(self.move_origin - self.origin);
1030
1031         if(self.total_damages < time)
1032         {
1033                 boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
1034                 boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
1035                 self.total_damages = time + 0.1;
1036         }
1037
1038         float i, df, sz, al;
1039         for(i = -0.1; i < 0.2; i += 0.1)
1040         {
1041                 df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
1042                 sz = 5 + random() * 5;
1043                 al = 0.25 + random() * 0.5;
1044                 _vtmp1 = self.origin + _dir * _len * (0.25 + i);
1045                 _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2));       //self.raygun_l1;
1046                 Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
1047
1048                 _vtmp2 = self.origin + _dir * _len * (0.5 + i);
1049                 _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5));       //self.raygun_l2;
1050                 Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
1051
1052                 _vtmp1 = self.origin + _dir * _len * (0.75 + i);
1053                 _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10);     //self.raygun_l3;
1054                 Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
1055
1056                 Draw_CylindricLine(_vtmp1, self.move_origin +  randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
1057         }
1058 }
1059
1060 void bumble_raygun_read(bool bIsNew)
1061 {
1062         int sf = ReadByte();
1063
1064         if(sf & BRG_SETUP)
1065         {
1066                 self.cnt  = ReadByte();
1067                 self.team = ReadByte();
1068                 self.cnt  = ReadByte();
1069
1070                 if(self.cnt)
1071                         self.colormod = '1 0 0';
1072                 else
1073                         self.colormod = '0 1 0';
1074
1075                 self.traileffect = particleeffectnum("healray_muzzleflash");
1076                 self.lip = particleeffectnum("healray_impact");
1077
1078                 self.draw = bumble_raygun_draw;
1079         }
1080
1081
1082         if(sf & BRG_START)
1083         {
1084                 self.origin_x = ReadCoord();
1085                 self.origin_y = ReadCoord();
1086                 self.origin_z = ReadCoord();
1087                 setorigin(self, self.origin);
1088         }
1089
1090         if(sf & BRG_END)
1091         {
1092                 self.move_origin_x = ReadCoord();
1093                 self.move_origin_y = ReadCoord();
1094                 self.move_origin_z = ReadCoord();
1095         }
1096 }
1097
1098 float v_bumblebee(float req)
1099 {
1100         switch(req)
1101         {
1102                 case VR_HUD:
1103                 {
1104                         Vehicles_drawHUD("vehicle_bumble", "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
1105                                                          "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
1106                                                          "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
1107                                                          vCROSS_HEAL);
1108                         return true;
1109                 }
1110                 case VR_SETUP:
1111                 {
1112                         AuxiliaryXhair[0].axh_image = vCROSS_LOCK;  // Raygun-locked
1113                         AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
1114                         AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
1115                         return true;
1116                 }
1117                 case VR_PRECACHE:
1118                 {
1119                         return true;
1120                 }
1121         }
1122
1123         return true;
1124 }
1125
1126 #endif // CSQC
1127 #endif // REGISTER_VEHICLE