]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/vehicles/racer.qc
Switching branch
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / vehicles / racer.qc
index 2e6f97cf08e221ebb61945a3d09d0eaa8c5ec9c4..81fbea5f46e055db80e27f038d716b51064289db 100644 (file)
@@ -49,9 +49,20 @@ float autocvar_g_vehicle_racer_rocket_refire;
 float autocvar_g_vehicle_racer_rocket_speed;
 float autocvar_g_vehicle_racer_rocket_turnrate;
 
+float autocvar_g_vehicle_racer_rocket_locktarget;
+float autocvar_g_vehicle_racer_rocket_locking_time;
+float autocvar_g_vehicle_racer_rocket_locking_releasetime;
+float autocvar_g_vehicle_racer_rocket_locked_time;
+float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+
 float autocvar_g_vehicle_racer_respawntime;
 float autocvar_g_vehicle_racer_collision_multiplier;
 
+float autocvar_g_vehicle_racer_blowup_radius;
+float autocvar_g_vehicle_racer_blowup_coredamage;
+float autocvar_g_vehicle_racer_blowup_edgedamage;
+float autocvar_g_vehicle_racer_blowup_forceintensity;
+
 var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
 
 void racer_align4point()
@@ -84,8 +95,6 @@ void racer_align4point()
     self.velocity += v_add;
     self.velocity_z -= autocvar_sv_gravity * frametime;
 
-
-
     push_vector_x =  (fl_push - bl_push);
     push_vector_x += (fr_push - br_push);
     push_vector_x *= 360;
@@ -94,21 +103,12 @@ void racer_align4point()
     push_vector_z += (br_push - bl_push);
     push_vector_z *= 360;
 
-    //if (push_vector_z != 0)
-        if(self.angles_z > 0)
-            self.angles_z = max(0, self.angles_z - (autocvar_g_vehicle_racer_anglestabilizer * frametime));
-        else
-            self.angles_z = min(0, self.angles_z + (autocvar_g_vehicle_racer_anglestabilizer * frametime));
-    //else
-        self.angles_z += push_vector_z * frametime;
-
-    //if (push_vector_x != 0)
-        if(self.angles_x > 0)
-            self.angles_x = max(0, self.angles_x - (autocvar_g_vehicle_racer_anglestabilizer * frametime));
-        else
-            self.angles_x = min(0, self.angles_x + (autocvar_g_vehicle_racer_anglestabilizer * frametime));
-    //else
-        self.angles_x += push_vector_x * frametime;
+    // Apply angle diffrance
+    self.angles_z += push_vector_z * frametime;
+    self.angles_x += push_vector_x * frametime;
+    // Apply stabilizer
+    self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
+    self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * frametime);
 }
 
 void racer_rocket_explode()
@@ -158,7 +158,6 @@ void racer_fire_cannon(string tagname)
     bolt.bot_dodgerating = autocvar_g_vehicle_racer_laser_damage;
 
        // Fix z-aim (for chase mode)
-       crosshair_trace(self.owner);
     v = normalize(trace_endpos - bolt.origin);
     v_forward_z = v_z * 0.5;
 
@@ -171,7 +170,8 @@ void racer_fire_cannon(string tagname)
 
 void racer_rocket_groundhugger()
 {
-    vector olddir;
+    vector olddir, newdir;
+    float oldvel, newvel;
 
     self.nextthink  = time;
 
@@ -188,33 +188,80 @@ void racer_rocket_groundhugger()
     }
 
     olddir = normalize(self.velocity);
+    oldvel = vlen(self.velocity);
+    newvel = oldvel + self.lip;
+
     tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
-    if(trace_fraction >= 0.5)
+    if(trace_fraction <= 0.5)
     {
-        traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
-        if(trace_fraction != 1.0)
-        {
-            // Follow ground
-            self.velocity = normalize(olddir + normalize((trace_endpos + '0 0 32') - self.origin) * self.wait) * (vlen(self.velocity) + self.lip);
-            UpdateCSQCProjectile(self);
-            return;
-        }
-        else
-        {
-            // "In air", add gravity.
-            self.velocity = olddir * (vlen(self.velocity) + self.lip);
-            self.velocity_z -= sys_frametime * 1250;
-            UpdateCSQCProjectile(self);
-            return;
-        }
+        // Hitting somethign soon, just speed ahead
+        self.velocity = olddir * newvel;
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
+    if(trace_fraction != 1.0)
+    {
+        newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
+        self.velocity = normalize(olddir + newdir) * newvel;
+    }
+    else
+    {
+        self.velocity = olddir * newvel;
+        self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
+    }
+
+    UpdateCSQCProjectile(self);
+    return;
+}
+
+void racer_rocket_tracker()
+{
+    vector olddir, newdir;
+    float oldvel, newvel;
+
+    self.nextthink  = time;
+
+    if ((self.owner.deadflag != DEAD_NO) || (self.cnt < time))
+    {
+        racer_rocket_explode();
+        return;
+    }
+
+    if not (self.realowner.vehicle)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    olddir = normalize(self.velocity);
+    oldvel = vlen(self.velocity);
+    newvel = oldvel + self.lip;
+    makevectors(vectoangles(olddir));
+
+    traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
+    newdir = normalize(self.enemy.origin - self.origin);
+
+    if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
+    {
+        //bprint("Target lost!\n");
+        //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
+        self.think = racer_rocket_groundhugger;
+        return;
     }
 
-    // Hitting somethign soon.
-    self.velocity = olddir * (vlen(self.velocity) + self.lip);
+    if(trace_fraction != 1.0)
+        newdir_z += 16 * sys_frametime;
+
+    self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
+    self.velocity_z -= 800 * sys_frametime;
+
     UpdateCSQCProjectile(self);
+    return;
 }
 
-void racer_fire_rocket(string tagname)
+void racer_fire_rocket(string tagname, entity trg)
 {
     entity rocket;
 
@@ -236,17 +283,25 @@ void racer_fire_rocket(string tagname)
     rocket.bot_dodgerating  = autocvar_g_vehicle_racer_rocket_damage;
     rocket.cnt              = time + 9;
     rocket.velocity         = v_forward * autocvar_g_vehicle_racer_rocket_speed;
-    rocket.think            = racer_rocket_groundhugger;
+
+    if(trg)
+        rocket.think            = racer_rocket_tracker;
+    else
+        rocket.think            = racer_rocket_groundhugger;
+
     rocket.nextthink        = time;
+    rocket.enemy            = trg;
 
     CSQCProjectile(rocket, TRUE, PROJECTILE_ROCKET, TRUE);
 }
 
+.float fire1_waspressed;
+.float fire2_waspressed;
 float racer_frame()
 {
     entity player, racer;
-    float ftmp, ftmp2;
     vector df;
+    float ftmp, ftmp2;
 
     player          = self;
     racer           = self.vehicle;
@@ -270,32 +325,59 @@ float racer_frame()
     }
 
     racer_align4point();
-
+    // Move abt crosshir insted of v_angle. this allows custom chase camera.
+    crosshair_trace(player);
+#if VEHICLES_VIEWROTATE_CROSSHAIR
     racer.angles_x *= -1;
-    makevectors(racer.angles);
+    df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+    if(df_x > 180)  df_x -= 360;
+    if(df_x < -180) df_x += 360;
+    if(df_y > 180)  df_y -= 360;
+    if(df_y < -180) df_y += 360;
 
     // Yaw
     ftmp = autocvar_g_vehicle_racer_turnspeed * sys_frametime;
     ftmp2 = ftmp * -1;
 
-    ftmp = bound(ftmp2, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
+    ftmp = bound(ftmp2, shortangle_f(df_y - racer.angles_y, racer.angles_y), ftmp);
     ftmp2 = anglemods(racer.angles_y + ftmp);
 
     // Roll
-    ftmp = bound(-45, shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * autocvar_g_vehicle_racer_turnroll), racer.angles_z), 45);
+    ftmp = bound(-45, shortangle_f(df_z + ((racer.angles_y - ftmp2) * autocvar_g_vehicle_racer_turnroll), racer.angles_z), 45);
     ftmp = anglemods(racer.angles_z + ftmp) * frametime;
     racer.angles_z = bound(-65, racer.angles_z + ftmp, 65);
 
     // Turn
     racer.angles_y = ftmp2;
 
-    // Pitch Body
+    // Pitch
     ftmp = autocvar_g_vehicle_racer_pitchspeed * sys_frametime;
     ftmp2 = ftmp * -1;
 
     ftmp = bound(ftmp2, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
     racer.angles_x = anglemods(racer.angles_x + ftmp);
+
+    makevectors(racer.angles);
+    racer.angles_x *= -1;
+#else
+    racer.angles_x *= -1;
+
+    // Yaw
+    ftmp = autocvar_g_vehicle_racer_turnspeed * sys_frametime;
+    ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
+    racer.angles_y = anglemods(racer.angles_y + ftmp);
+
+    // Roll
+    racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * sys_frametime;
+
+    // Pitch
+    ftmp = autocvar_g_vehicle_racer_pitchspeed  * sys_frametime;
+    ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
+    racer.angles_x = bound(-30, anglemods(racer.angles_x + ftmp), 30);
+
+    makevectors(racer.angles);
     racer.angles_x *= -1;
+#endif
 
     df = racer.velocity * -0.5;
 
@@ -319,7 +401,6 @@ float racer_frame()
     if(df_z > 0)
         df_z = min(df_z, 700);
 
-
     // Afterburn
     if (player.BUTTON_JUMP)
     if(racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * frametime))
@@ -343,6 +424,7 @@ float racer_frame()
         racer.vehicle_energy -= autocvar_g_vehicle_racer_laser_cost;
         racer.wait = time;
 
+        crosshair_trace(player);
         if(racer.cnt)
         {
             racer_fire_cannon("tag_fire1");
@@ -357,15 +439,46 @@ float racer_frame()
         self.owner.vehicle_energy = racer.vehicle_energy / autocvar_g_vehicle_racer_energy;
     }
 
-    if(player.BUTTON_ATCK2)
+    if(autocvar_g_vehicle_racer_rocket_locktarget)
+    {
+        vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
+                         (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
+                         autocvar_g_vehicle_racer_rocket_locked_time);
+
+        if(self.lock_target)
+        {
+            if(racer.lock_strength == 1)
+                UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
+            else if(self.lock_strength > 0.5)
+                UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
+            else if(self.lock_strength < 0.5)
+                UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
+        }
+    }
+
     if(time > racer.delay)
+    if(player.BUTTON_ATCK2)
     {
-        racer_fire_rocket("tag_rocket_r");
-        racer_fire_rocket("tag_rocket_l");
-        racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
-        racer.lip = time;
+        self.misc_bulletcounter += 1;
+        racer.delay = time + 0.2;
+        if(self.misc_bulletcounter == 1)
+            racer_fire_rocket("tag_rocket_r", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
+        else if(self.misc_bulletcounter == 2)
+            racer_fire_rocket("tag_rocket_l", (self.lock_strength == 1 && self.lock_target) ? self.lock_target : world);
+        else
+        {
+            self.lock_strength  = 0;
+            self.lock_target    = world;
+            self.misc_bulletcounter = 0;
+
+            racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
+            racer.lip = time;
+
+        }
     }
 
+    player.fire2_waspressed = player.BUTTON_ATCK2;
+
     player.vehicle_reload1 = (time - racer.lip) / (racer.delay - racer.lip);
 
     if(self.vehicle_flags  & VHF_SHIELDREGEN)
@@ -421,102 +534,48 @@ void racer_think()
 
 void racer_enter()
 {
+    self.movetype = MOVETYPE_BOUNCEMISSILE;
     self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health);
     self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield);
 }
 
-void racer_spawn();
-
 void racer_exit(float eject)
 {
-    vehicles_setreturn(autocvar_g_vehicle_racer_respawntime, racer_spawn);
-
     self.think      = racer_think;
     self.nextthink  = time;
+    self.movetype   = MOVETYPE_BOUNCEMISSILE;
 
     if not (self.owner)
         return;
 
+       makevectors(self.angles);
        if(eject)
        {
-           makevectors(self.angles);
-           setorigin(self.owner,self.origin + v_forward * 100);
+           setorigin(self.owner, self.origin + v_forward * 100 + v_up * 32);
            self.owner.velocity = (v_up + v_forward * 0.25) * 750;
        }
        else
        {
+           setorigin(self.owner, self.origin - v_forward * 100 + v_up * 32);
            self.owner.velocity = v_forward * -150;
-        setorigin(self.owner, self.origin - v_forward * 128);
        }
-
     self.owner = world;
 }
 
-void racer_touch()
-{
-    if(self.owner)
-    {
-        if(vlen(self.velocity) == 0)
-            return;
-
-        if(other.classname != "player")
-            return;
-
-        vector a;
-        a = normalize(other.origin - self.origin);
-        a = a - normalize(self.velocity);
-
-        return;
-    }
-
-    if(other.classname != "player")
-        return;
-
-    if(other.deadflag != DEAD_NO)
-        return;
-
-    if(other.vehicle != world)
-        return;
-
-    vehicles_enter();
-}
-
 void racer_spawn()
 {
-    self.think = racer_think;
-    self.nextthink = time;
-
-    self.flags      = FL_NOTARGET;
-    self.effects   = 0;
-
+    self.think          = racer_think;
+    self.nextthink      = time;
     self.vehicle_health = autocvar_g_vehicle_racer_health;
     self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-
-    self.event_damage = vehicles_damage;
-    self.touch      = racer_touch;
-
-    self.iscreature = TRUE;
-    self.scale      = 0.5;
-    self.movetype   = MOVETYPE_BOUNCEMISSILE;
-    self.solid      = SOLID_SLIDEBOX;
-    self.takedamage = DAMAGE_AIM;
-
-    self.alpha      = 1;
-       self.colormap   = 1024;
-       self.deadflag   = DEAD_NO;
-    self.bot_attack = TRUE;
-
-    self.vehicle_energy = 1;
-    self.vehicle_hudmodel.viewmodelforclient = self;
-
-    setorigin(self, self.pos1);
-    self.angles = self.pos2;
-
+    self.movetype       = MOVETYPE_TOSS;
+    self.solid          = SOLID_SLIDEBOX;
+    self.delay          = time;
+    self.scale          = 0.5;
     setsize(self, RACER_MIN * 0.5, RACER_MAX * 0.5);
-    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
-    self.delay = time;
 }
 
+
 void racer_blowup()
 {
 
@@ -525,7 +584,12 @@ void racer_blowup()
 
     self.deadflag    = DEAD_DEAD;
     self.vehicle_exit(VHEF_NORMAL);
-    RadiusDamage (self, self, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world);
+
+    RadiusDamage (self, self, autocvar_g_vehicle_racer_blowup_coredamage,
+                                       autocvar_g_vehicle_racer_blowup_edgedamage,
+                                       autocvar_g_vehicle_racer_blowup_radius, world,
+                                       autocvar_g_vehicle_racer_blowup_forceintensity,
+                                       DEATH_WAKIBLOWUP, world);
 
     self.alpha = -1;
     self.nextthink  = time + autocvar_g_vehicle_racer_respawntime;
@@ -533,12 +597,13 @@ void racer_blowup()
     self.movetype   = MOVETYPE_NONE;
     self.effects    = EF_NODRAW;
 
-    self.avelocity_z  = 0;
-    self.colormod = '0 0 0';
-
-    setorigin(self,self.pos1);
+    self.colormod  = '0 0 0';
     self.avelocity = '0 0 0';
-    self.velocity = '0 0 0';
+    self.velocity  = '0 0 0';
+
+    setorigin(self, self.pos1);
+       self.think     = racer_spawn;
+       self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
 }
 
 void racer_deadtouch()
@@ -564,15 +629,13 @@ void racer_die()
 
     pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
 
-    self.velocity     += '0 0 700';
-
     if(random() < 0.5)
         self.avelocity_z  = 16;
     else
         self.avelocity_z  = -16;
 
     self.avelocity_x = -vlen(self.velocity) * 0.2;
-
+    self.velocity     += '0 0 700';
     self.colormod = '-0.5 -0.5 -0.5';
 
        self.think     = racer_blowup;
@@ -590,7 +653,8 @@ void racer_dinit()
              HUD_WAKIZASHI,
              0.5 * RACER_MIN, 0.5 * RACER_MAX,
              FALSE,
-             racer_spawn, racer_frame,
+             racer_spawn, autocvar_g_vehicle_racer_respawntime,
+             racer_frame,
              racer_enter, racer_exit,
              racer_die,   racer_think))
     {
@@ -607,6 +671,8 @@ void racer_dinit()
     self.scale = 0.5;
     setattachment(self.vehicle_hudmodel, self, "");
     setattachment(self.vehicle_viewport, self, "tag_viewport");
+
+    self.mass               = 900;
 }
 
 void spawnfunc_vehicle_racer()