4 REGISTER_VEHICLE_SIMPLE(
6 /* function */ v_racer,
7 /* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
8 /* mins,maxs */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5,
9 /* model */ "models/vehicles/wakizashi.dpm",
10 /* head_model */ "null",
11 /* hud_model */ "models/vehicles/wakizashi_cockpit.dpm",
12 /* tags */ "", "", "tag_viewport",
13 /* netname */ "racer",
14 /* fullname */ _("Racer")
16 this.m_icon = "vehicle_racer";
22 #include "../../effects.qh"
23 #include "../../triggers/trigger/impulse.qh"
25 bool autocvar_g_vehicle_racer;
27 float autocvar_g_vehicle_racer_speed_afterburn;
28 float autocvar_g_vehicle_racer_afterburn_cost;
30 float autocvar_g_vehicle_racer_waterburn_cost;
31 float autocvar_g_vehicle_racer_waterburn_speed;
33 float autocvar_g_vehicle_racer_water_speed_forward;
34 float autocvar_g_vehicle_racer_water_speed_strafe;
36 float autocvar_g_vehicle_racer_pitchlimit = 30;
38 float autocvar_g_vehicle_racer_water_downforce = 0.03;
39 float autocvar_g_vehicle_racer_water_upforcedamper = 15;
41 float autocvar_g_vehicle_racer_anglestabilizer;
42 float autocvar_g_vehicle_racer_downforce;
44 float autocvar_g_vehicle_racer_speed_forward;
45 float autocvar_g_vehicle_racer_speed_strafe;
46 float autocvar_g_vehicle_racer_springlength;
47 float autocvar_g_vehicle_racer_upforcedamper;
48 float autocvar_g_vehicle_racer_friction;
50 float autocvar_g_vehicle_racer_water_time = 5;
52 float autocvar_g_vehicle_racer_hovertype;
53 float autocvar_g_vehicle_racer_hoverpower;
55 float autocvar_g_vehicle_racer_turnroll;
56 float autocvar_g_vehicle_racer_turnspeed;
57 float autocvar_g_vehicle_racer_pitchspeed;
59 float autocvar_g_vehicle_racer_energy;
60 float autocvar_g_vehicle_racer_energy_regen;
61 float autocvar_g_vehicle_racer_energy_regen_pause;
63 float autocvar_g_vehicle_racer_health;
64 float autocvar_g_vehicle_racer_health_regen;
65 float autocvar_g_vehicle_racer_health_regen_pause;
67 float autocvar_g_vehicle_racer_shield;
68 float autocvar_g_vehicle_racer_shield_regen;
69 float autocvar_g_vehicle_racer_shield_regen_pause;
71 float autocvar_g_vehicle_racer_cannon_cost;
72 float autocvar_g_vehicle_racer_cannon_damage;
73 float autocvar_g_vehicle_racer_cannon_radius;
74 float autocvar_g_vehicle_racer_cannon_refire;
75 float autocvar_g_vehicle_racer_cannon_speed;
76 float autocvar_g_vehicle_racer_cannon_spread;
77 float autocvar_g_vehicle_racer_cannon_force;
79 float autocvar_g_vehicle_racer_rocket_accel;
80 float autocvar_g_vehicle_racer_rocket_damage;
81 float autocvar_g_vehicle_racer_rocket_radius;
82 float autocvar_g_vehicle_racer_rocket_force;
83 float autocvar_g_vehicle_racer_rocket_refire;
84 float autocvar_g_vehicle_racer_rocket_speed;
85 float autocvar_g_vehicle_racer_rocket_turnrate;
87 float autocvar_g_vehicle_racer_rocket_locktarget;
88 float autocvar_g_vehicle_racer_rocket_locking_time;
89 float autocvar_g_vehicle_racer_rocket_locking_releasetime;
90 float autocvar_g_vehicle_racer_rocket_locked_time;
91 float autocvar_g_vehicle_racer_rocket_locked_maxangle;
92 float autocvar_g_vehicle_racer_rocket_climbspeed;
94 float autocvar_g_vehicle_racer_respawntime;
96 float autocvar_g_vehicle_racer_blowup_radius;
97 float autocvar_g_vehicle_racer_blowup_coredamage;
98 float autocvar_g_vehicle_racer_blowup_edgedamage;
99 float autocvar_g_vehicle_racer_blowup_forceintensity;
101 float autocvar_g_vehicle_racer_bouncefactor;
102 float autocvar_g_vehicle_racer_bouncestop;
103 vector autocvar_g_vehicle_racer_bouncepain;
105 .float racer_watertime;
107 var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
109 void racer_align4point(float _delta)
112 float fl_push, fr_push, bl_push, br_push;
114 push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
115 fr_push = force_fromtag_normpower;
116 //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
118 push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
119 fl_push = force_fromtag_normpower;
120 //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
122 push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
123 br_push = force_fromtag_normpower;
124 //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
126 push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
127 bl_push = force_fromtag_normpower;
128 //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
130 self.velocity += push_vector * _delta;
132 float uforce = autocvar_g_vehicle_racer_upforcedamper;
134 int cont = pointcontents(self.origin - '0 0 64');
135 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
137 uforce = autocvar_g_vehicle_racer_water_upforcedamper;
139 if(self.owner.BUTTON_CROUCH && time < self.air_finished)
140 self.velocity_z += 30;
142 self.velocity_z += 200;
147 if(self.velocity_z > 0)
148 self.velocity_z *= 1 - uforce * _delta;
150 push_vector_x = (fl_push - bl_push);
151 push_vector_x += (fr_push - br_push);
152 push_vector_x *= 360;
154 push_vector_z = (fr_push - fl_push);
155 push_vector_z += (br_push - bl_push);
156 push_vector_z *= 360;
158 // Apply angle diffrance
159 self.angles_z += push_vector_z * _delta;
160 self.angles_x += push_vector_x * _delta;
163 self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
164 self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
167 void racer_fire_cannon(string tagname)
172 v = gettaginfo(self, gettagindex(self, tagname));
173 bolt = vehicles_projectile("wakizashi_gun_muzzleflash", "weapons/lasergun_fire.wav",
174 v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
175 autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0,
176 DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, self.owner);
178 // Fix z-aim (for chase mode)
179 v = normalize(trace_endpos - bolt.origin);
180 v_forward_z = v_z * 0.5;
181 bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed;
184 void racer_rocket_groundhugger()
186 vector olddir, newdir;
187 float oldvel, newvel;
189 self.nextthink = time;
191 if(self.owner.deadflag != DEAD_NO || self.cnt < time)
197 if(!self.realowner.vehicle)
199 UpdateCSQCProjectile(self);
203 olddir = normalize(self.velocity);
204 oldvel = vlen(self.velocity);
205 newvel = oldvel + self.lip;
207 tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
208 if(trace_fraction <= 0.5)
210 // Hitting somethign soon, just speed ahead
211 self.velocity = olddir * newvel;
212 UpdateCSQCProjectile(self);
216 traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
217 if(trace_fraction != 1.0)
219 newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
220 self.velocity = normalize(olddir + newdir) * newvel;
224 self.velocity = olddir * newvel;
225 self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
228 int cont = pointcontents(self.origin - '0 0 32');
229 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
230 self.velocity_z += 200;
232 UpdateCSQCProjectile(self);
236 void racer_rocket_tracker()
238 vector olddir, newdir;
239 float oldvel, newvel;
241 self.nextthink = time;
243 if (self.owner.deadflag != DEAD_NO || self.cnt < time)
249 if(!self.realowner.vehicle)
251 UpdateCSQCProjectile(self);
255 olddir = normalize(self.velocity);
256 oldvel = vlen(self.velocity);
257 newvel = oldvel + self.lip;
258 makevectors(vectoangles(olddir));
260 float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
261 vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
263 traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
264 newdir = normalize(predicted_origin - self.origin);
267 float height_diff = predicted_origin_z - self.origin_z;
269 if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
271 //bprint("Target lost!\n");
272 //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
273 self.think = racer_rocket_groundhugger;
277 if(trace_fraction != 1.0 && trace_ent != self.enemy)
278 newdir_z += 16 * sys_frametime;
280 self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
281 self.velocity_z -= 800 * sys_frametime;
282 self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
284 UpdateCSQCProjectile(self);
288 void racer_fire_rocket(string tagname, entity trg)
290 vector v = gettaginfo(self, gettagindex(self, tagname));
291 entity rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
292 v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
293 autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
294 DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
296 rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
297 rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate;
298 rocket.nextthink = time;
300 rocket.cnt = time + 15;
303 rocket.think = racer_rocket_tracker;
305 rocket.think = racer_rocket_groundhugger;
310 entity player, racer;
314 if(intermission_running)
316 self.vehicle.velocity = '0 0 0';
317 self.vehicle.avelocity = '0 0 0';
322 racer = self.vehicle;
325 vehicles_painframe();
327 if(pointcontents(racer.origin) != CONTENT_WATER)
328 racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
330 if(racer.deadflag != DEAD_NO)
333 player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
337 racer_align4point(PHYS_INPUT_TIMELENGTH);
339 player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
341 crosshair_trace(player);
343 racer.angles_x *= -1;
346 ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
347 ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
348 racer.angles_y = anglemods(racer.angles_y + ftmp);
351 racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
354 ftmp = autocvar_g_vehicle_racer_pitchspeed * PHYS_INPUT_TIMELENGTH;
355 ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
356 racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
358 makevectors(racer.angles);
359 racer.angles_x *= -1;
361 //ftmp = racer.velocity_z;
362 df = racer.velocity * -autocvar_g_vehicle_racer_friction;
363 //racer.velocity_z = ftmp;
365 int cont = pointcontents(racer.origin);
366 if(vlen(player.movement) != 0)
368 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
370 if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
371 if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
375 if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
376 if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
380 if(self.sound_nexttime < time || self.sounds != 1)
383 self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
384 sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
391 if(self.sound_nexttime < time || self.sounds != 0)
394 self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
395 sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
401 if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
404 if(time - racer.wait > 0.2)
405 pointparticles(particleeffectnum("wakizashi_booster_smoke"), self.origin - v_forward * 32, v_forward * vlen(self.velocity), 1);
410 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
412 racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
413 df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
417 racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
418 df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
422 if(racer.invincible_finished < time)
424 traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
425 if(trace_fraction != 1.0)
426 pointparticles(particleeffectnum("smoke_small"), trace_endpos, '0 0 0', 1);
428 racer.invincible_finished = time + 0.1 + (random() * 0.1);
431 if(racer.strength_finished < time)
433 racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
434 sound (racer.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
440 racer.strength_finished = 0;
441 sound (racer.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
444 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
445 racer.racer_watertime = time;
447 float dforce = autocvar_g_vehicle_racer_downforce;
448 if(time - racer.racer_watertime <= 3)
449 dforce = autocvar_g_vehicle_racer_water_downforce;
451 df -= v_up * (vlen(racer.velocity) * dforce);
452 player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
455 if(!forbidWeaponUse(player))
456 if(player.BUTTON_ATCK)
457 if(time > racer.attack_finished_single)
458 if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost)
460 racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
463 crosshair_trace(player);
466 racer_fire_cannon("tag_fire1");
471 racer_fire_cannon("tag_fire2");
474 racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire;
477 if(autocvar_g_vehicle_racer_rocket_locktarget)
479 vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
480 (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
481 autocvar_g_vehicle_racer_rocket_locked_time);
485 if(racer.lock_strength == 1)
486 UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
487 else if(self.lock_strength > 0.5)
488 UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
489 else if(self.lock_strength < 0.5)
490 UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
494 if(!forbidWeaponUse(player))
495 if(time > racer.delay)
496 if(player.BUTTON_ATCK2)
498 racer.misc_bulletcounter += 1;
499 racer.delay = time + 0.3;
501 if(racer.misc_bulletcounter == 1)
503 racer_fire_rocket("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
504 player.vehicle_ammo2 = 50;
506 else if(racer.misc_bulletcounter == 2)
508 racer_fire_rocket("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
509 racer.lock_strength = 0;
510 racer.lock_target = world;
511 racer.misc_bulletcounter = 0;
512 racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
514 player.vehicle_ammo2 = 0;
517 else if(racer.misc_bulletcounter == 0)
518 player.vehicle_ammo2 = 100;
520 player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
522 if(racer.vehicle_flags & VHF_SHIELDREGEN)
523 vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
525 if(racer.vehicle_flags & VHF_HEALTHREGEN)
526 vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
528 if(racer.vehicle_flags & VHF_ENERGYREGEN)
529 vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
532 VEHICLE_UPDATE_PLAYER(player, health, racer);
533 VEHICLE_UPDATE_PLAYER(player, energy, racer);
535 if(racer.vehicle_flags & VHF_HASSHIELD)
536 VEHICLE_UPDATE_PLAYER(player, shield, racer);
538 player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
541 setorigin(player,racer.origin + '0 0 32');
542 player.velocity = racer.velocity;
550 self.nextthink = time;
552 float pushdeltatime = time - self.lastpushtime;
553 if (pushdeltatime > 0.15) pushdeltatime = 0;
554 self.lastpushtime = time;
555 if(!pushdeltatime) return;
557 tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
559 vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
560 df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
562 float forced = autocvar_g_vehicle_racer_upforcedamper;
564 int cont = pointcontents(self.origin - '0 0 64');
565 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
567 forced = autocvar_g_vehicle_racer_water_upforcedamper;
568 self.velocity_z += 200;
571 self.velocity += df * pushdeltatime;
572 if(self.velocity_z > 0)
573 self.velocity_z *= 1 - forced * pushdeltatime;
575 self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
576 self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
578 CSQCMODEL_AUTOUPDATE();
581 void racer_exit(float eject)
585 self.think = racer_think;
586 self.nextthink = time;
587 self.movetype = MOVETYPE_BOUNCE;
588 sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
593 makevectors(self.angles);
596 spot = self.origin + v_forward * 100 + '0 0 64';
597 spot = vehicles_findgoodexit(spot);
598 setorigin(self.owner , spot);
599 self.owner.velocity = (v_up + v_forward * 0.25) * 750;
600 self.owner.oldvelocity = self.owner.velocity;
604 if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
606 self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
607 self.owner.velocity_z += 200;
608 spot = self.origin + v_forward * 32 + '0 0 32';
609 spot = vehicles_findgoodexit(spot);
613 self.owner.velocity = self.velocity * 0.5;
614 self.owner.velocity_z += 10;
615 spot = self.origin - v_forward * 200 + '0 0 32';
616 spot = vehicles_findgoodexit(spot);
618 self.owner.oldvelocity = self.owner.velocity;
619 setorigin(self.owner , spot);
621 antilag_clear(self.owner);
627 self.deadflag = DEAD_DEAD;
628 self.vehicle_exit(VHEF_NORMAL);
630 RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
631 autocvar_g_vehicle_racer_blowup_edgedamage,
632 autocvar_g_vehicle_racer_blowup_radius, world, world,
633 autocvar_g_vehicle_racer_blowup_forceintensity,
634 DEATH_VH_WAKI_DEATH, world);
636 self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
637 self.think = vehicles_spawn;
638 self.movetype = MOVETYPE_NONE;
639 self.effects = EF_NODRAW;
641 self.colormod = '0 0 0';
642 self.avelocity = '0 0 0';
643 self.velocity = '0 0 0';
645 setorigin(self, self.pos1);
648 void racer_blowup_think()
650 self.nextthink = time;
652 if(time >= self.delay)
655 CSQCMODEL_AUTOUPDATE();
658 void racer_deadtouch()
660 self.avelocity_x *= 0.7;
666 void spawnfunc_vehicle_racer()
668 if(!autocvar_g_vehicle_racer) { remove(self); return; }
669 if(!vehicle_initialize(VEH_RACER.vehicleid, false)) { remove(self); return; }
678 float pushdeltatime = time - self.lastpushtime;
679 if (pushdeltatime > 0.15) pushdeltatime = 0;
680 self.lastpushtime = time;
681 if(!pushdeltatime) return;
683 tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
685 vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
686 df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
688 float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
690 int cont = pointcontents(self.move_origin - '0 0 64');
691 if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
693 forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
694 self.move_velocity_z += 200;
697 self.move_velocity += df * pushdeltatime;
698 if(self.move_velocity_z > 0)
699 self.move_velocity_z *= 1 - forced * pushdeltatime;
701 self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
702 self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
704 Movetype_Physics_MatchServer(false);
709 bool v_racer(int req)
716 if(autocvar_g_vehicle_racer_bouncepain)
717 vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
725 self.movetype = MOVETYPE_BOUNCE;
726 self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100;
727 self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100;
729 if(self.owner.flagcarried)
730 setorigin(self.owner.flagcarried, '-190 0 96');
733 self.move_movetype = MOVETYPE_BOUNCE;
742 if(self.scale != 0.5)
744 if(autocvar_g_vehicle_racer_hovertype != 0)
745 racer_force_from_tag = vehicles_force_fromtag_maglev;
747 racer_force_from_tag = vehicles_force_fromtag_hover;
749 // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
751 setattachment(self.vehicle_hudmodel, self, "");
752 setattachment(self.vehicle_viewport, self, "tag_viewport");
757 self.think = racer_think;
758 self.nextthink = time;
759 self.vehicle_health = autocvar_g_vehicle_racer_health;
760 self.vehicle_shield = autocvar_g_vehicle_racer_shield;
762 self.movetype = MOVETYPE_TOSS;
763 self.solid = SOLID_SLIDEBOX;
767 self.PlayerPhysplug = racer_frame;
769 self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
770 self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
771 self.damageforcescale = 0.5;
772 self.vehicle_health = autocvar_g_vehicle_racer_health;
773 self.vehicle_shield = autocvar_g_vehicle_racer_shield;
781 self.SendEntity = func_null; // stop networking this racer (for now)
783 self.event_damage = func_null;
784 self.solid = SOLID_CORPSE;
785 self.takedamage = DAMAGE_NO;
786 self.deadflag = DEAD_DYING;
787 self.movetype = MOVETYPE_BOUNCE;
789 self.delay = 2 + time + random() * 3;
790 self.cnt = 1 + random() * 2;
791 self.touch = racer_deadtouch;
793 Send_Effect("explosion_medium", self.origin, '0 0 0', 1);
796 self.avelocity_z = 32;
798 self.avelocity_z = -32;
800 self.avelocity_x = -vlen(self.velocity) * 0.2;
801 self.velocity += '0 0 700';
802 self.colormod = '-0.5 -0.5 -0.5';
804 self.think = racer_blowup_think;
805 self.nextthink = time;
813 Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
814 "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
815 "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
823 self.vehicle_exit = racer_exit;
827 // we have no need to network energy
828 if(autocvar_g_vehicle_racer_energy)
829 if(autocvar_g_vehicle_racer_energy_regen)
830 self.vehicle_flags |= VHF_ENERGYREGEN;
832 if(autocvar_g_vehicle_racer_shield)
833 self.vehicle_flags |= VHF_HASSHIELD;
835 if(autocvar_g_vehicle_racer_shield_regen)
836 self.vehicle_flags |= VHF_SHIELDREGEN;
838 if(autocvar_g_vehicle_racer_health_regen)
839 self.vehicle_flags |= VHF_HEALTHREGEN;
841 self.respawntime = autocvar_g_vehicle_racer_respawntime;
842 self.vehicle_health = autocvar_g_vehicle_racer_health;
843 self.vehicle_shield = autocvar_g_vehicle_racer_shield;
844 self.max_health = self.vehicle_health;
848 AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
856 precache_sound ("weapons/lasergun_fire.wav");
857 precache_sound ("weapons/rocket_fire.wav");
859 precache_sound ("vehicles/racer_idle.wav");
860 precache_sound ("vehicles/racer_move.wav");
861 precache_sound ("vehicles/racer_boost.wav");
863 precache_model ("models/vhshield.md3");
866 precache_model ("models/vehicles/wakizashi.dpm");
867 precache_model ("models/vehicles/wakizashi_cockpit.dpm");
876 #endif // REGISTER_VEHICLE