]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Vehicles: factor out attacks
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 30 Sep 2015 23:27:55 +0000 (09:27 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 30 Sep 2015 23:27:55 +0000 (09:27 +1000)
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/raptor_weapons.qc [new file with mode: 0644]

index dad0fd12eebf362f764295f1c6d50e801255edb9..da10b87d005d4b14bdfb24a8af62b86d59e247dc 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef VEHICLE_RACER
 #define VEHICLE_RACER
 
+#include "racer_weapon.qc"
+
 CLASS(Racer, Vehicle)
 /* spawnflags */ ATTRIB(Racer, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
 /* mins       */ ATTRIB(Racer, mins, vector, '-120 -120 -40' * 0.5);
@@ -16,74 +18,18 @@ CLASS(Racer, Vehicle)
 /* fullname   */ ATTRIB(Racer, vehicle_name, string, _("Racer"));
 /* icon       */ ATTRIB(Racer, m_icon, string, "vehicle_racer");
 ENDCLASS(Racer)
-
 REGISTER_VEHICLE(RACER, NEW(Racer));
 
-#include "../../weapons/all.qh"
-
-CLASS(RacerAttack, PortoLaunch)
-/* flags     */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER);
-/* impulse   */ ATTRIB(RacerAttack, impulse, int, 3);
-/* refname   */ ATTRIB(RacerAttack, netname, string, "racercannon");
-/* wepname   */ ATTRIB(RacerAttack, message, string, _("Racer cannon"));
-ENDCLASS(RacerAttack)
-REGISTER_WEAPON(RACER, NEW(RacerAttack));
-
 #endif
 
 #ifdef IMPLEMENTATION
+
+#include "racer_weapon.qc"
+
 #ifdef SVQC
 #include "../../effects/effects.qh"
 #include "../../triggers/trigger/impulse.qh"
 
-float autocvar_g_vehicle_racer_cannon_cost;
-float autocvar_g_vehicle_racer_cannon_damage;
-float autocvar_g_vehicle_racer_cannon_radius;
-float autocvar_g_vehicle_racer_cannon_refire;
-float autocvar_g_vehicle_racer_cannon_speed;
-float autocvar_g_vehicle_racer_cannon_spread;
-float autocvar_g_vehicle_racer_cannon_force;
-
-void racer_fire_rocket(vector org, vector dir, entity trg);
-METHOD(RacerAttack, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       entity veh = player.vehicle;
-       setself(player);
-       if (fire1)
-       if (weapon_prepareattack(false, autocvar_g_vehicle_racer_cannon_refire)) {
-               if (veh) {
-                       veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
-                       veh.wait = time;
-               }
-               if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
-               vector org = w_shotorg;
-               vector dir = w_shotdir;
-               entity bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
-                                                          org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
-                                                          autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
-                                                          DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, player);
-               bolt.velocity = normalize(dir) * autocvar_g_vehicle_racer_cannon_speed;
-               weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
-       }
-       if (fire2)
-       if (!isPlayer || weapon_prepareattack(false, 0.2)) {
-               if (isPlayer) W_SetupShot_Dir(self, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
-               racer_fire_rocket(w_shotorg, w_shotdir, NULL);
-               weapon_thinkf(WFRAME_FIRE2, 0, w_ready);
-       }
-       setself(this);
-       return true;
-}
-METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       entity veh = player.vehicle;
-       return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost;
-}
-
 bool autocvar_g_vehicle_racer;
 
 float autocvar_g_vehicle_racer_speed_afterburn;
@@ -130,20 +76,10 @@ float autocvar_g_vehicle_racer_shield;
 float autocvar_g_vehicle_racer_shield_regen;
 float autocvar_g_vehicle_racer_shield_regen_pause;
 
-float autocvar_g_vehicle_racer_rocket_accel;
-float autocvar_g_vehicle_racer_rocket_damage;
-float autocvar_g_vehicle_racer_rocket_radius;
-float autocvar_g_vehicle_racer_rocket_force;
-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_rocket_climbspeed;
 
 float autocvar_g_vehicle_racer_respawntime;
 
@@ -218,129 +154,6 @@ void racer_align4point(float _delta)
        self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
 }
 
-void racer_rocket_groundhugger()
-{SELFPARAM();
-       vector olddir, newdir;
-       float oldvel, newvel;
-
-       self.nextthink  = time;
-
-       if(self.owner.deadflag != DEAD_NO || self.cnt < time)
-       {
-               self.use();
-               return;
-       }
-
-       if(!self.realowner.vehicle)
-       {
-               UpdateCSQCProjectile(self);
-               return;
-       }
-
-       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)
-       {
-               // 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
-       }
-
-       int cont = pointcontents(self.origin - '0 0 32');
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-               self.velocity_z += 200;
-
-       UpdateCSQCProjectile(self);
-       return;
-}
-
-void racer_rocket_tracker()
-{SELFPARAM();
-       vector olddir, newdir;
-       float oldvel, newvel;
-
-       self.nextthink  = time;
-
-       if (self.owner.deadflag != DEAD_NO || self.cnt < time)
-       {
-               self.use();
-               return;
-       }
-
-       if(!self.realowner.vehicle)
-       {
-               UpdateCSQCProjectile(self);
-               return;
-       }
-
-       olddir = normalize(self.velocity);
-       oldvel = vlen(self.velocity);
-       newvel = oldvel + self.lip;
-       makevectors(vectoangles(olddir));
-
-       float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
-       vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
-
-       traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
-       newdir = normalize(predicted_origin - self.origin);
-
-       //vector
-       float height_diff = predicted_origin_z - self.origin_z;
-
-       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;
-       }
-
-       if(trace_fraction != 1.0 && trace_ent != self.enemy)
-               newdir_z += 16 * sys_frametime;
-
-       self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
-       self.velocity_z -= 800 * sys_frametime;
-       self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
-
-       UpdateCSQCProjectile(self);
-       return;
-}
-
-void racer_fire_rocket(vector org, vector dir, entity trg)
-{SELFPARAM();
-       entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
-                                                  org, dir * autocvar_g_vehicle_racer_rocket_speed,
-                                                  autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
-                                                  DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
-
-       rocket.lip                        = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
-       rocket.wait                      = autocvar_g_vehicle_racer_rocket_turnrate;
-       rocket.nextthink                = time;
-       rocket.enemy                    = trg;
-       rocket.cnt                        = time + 15;
-
-       if(trg)
-               rocket.think                    = racer_rocket_tracker;
-       else
-               rocket.think                    = racer_rocket_groundhugger;
-}
-
 void racer_fire_rocket_aim(string tagname, entity trg)
 {
        SELFPARAM();
diff --git a/qcsrc/common/vehicles/vehicle/racer_weapon.qc b/qcsrc/common/vehicles/vehicle/racer_weapon.qc
new file mode 100644 (file)
index 0000000..79bb2d6
--- /dev/null
@@ -0,0 +1,215 @@
+#ifndef VEHICLE_RACER_WEAPON_H
+#define VEHICLE_RACER_WEAPON_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RacerAttack, PortoLaunch)
+/* flags     */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER);
+/* impulse   */ ATTRIB(RacerAttack, impulse, int, 3);
+/* refname   */ ATTRIB(RacerAttack, netname, string, "racercannon");
+/* wepname   */ ATTRIB(RacerAttack, message, string, _("Racer cannon"));
+ENDCLASS(RacerAttack)
+REGISTER_WEAPON(RACER, NEW(RacerAttack));
+
+// TODO: move into implementation
+#ifdef SVQC
+float autocvar_g_vehicle_racer_rocket_refire;
+void racer_fire_rocket(vector org, vector dir, entity trg);
+#endif
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_racer_cannon_cost;
+float autocvar_g_vehicle_racer_cannon_damage;
+float autocvar_g_vehicle_racer_cannon_radius;
+float autocvar_g_vehicle_racer_cannon_refire;
+float autocvar_g_vehicle_racer_cannon_speed;
+float autocvar_g_vehicle_racer_cannon_spread;
+float autocvar_g_vehicle_racer_cannon_force;
+
+float autocvar_g_vehicle_racer_rocket_accel;
+float autocvar_g_vehicle_racer_rocket_damage;
+float autocvar_g_vehicle_racer_rocket_radius;
+float autocvar_g_vehicle_racer_rocket_force;
+float autocvar_g_vehicle_racer_rocket_speed;
+float autocvar_g_vehicle_racer_rocket_turnrate;
+
+float autocvar_g_vehicle_racer_rocket_climbspeed;
+float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+
+void racer_fire_rocket(vector org, vector dir, entity trg);
+METHOD(RacerAttack, wr_think, bool(entity thiswep, bool fire1, bool fire2))
+{
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    setself(player);
+    if (fire1)
+    if (weapon_prepareattack(false, autocvar_g_vehicle_racer_cannon_refire)) {
+        if (veh) {
+            veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
+            veh.wait = time;
+        }
+        if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+        vector org = w_shotorg;
+        vector dir = w_shotdir;
+        entity bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+                               org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
+                               autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
+                               DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, player);
+        bolt.velocity = normalize(dir) * autocvar_g_vehicle_racer_cannon_speed;
+        weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
+    }
+    if (fire2)
+    if (!isPlayer || weapon_prepareattack(false, 0.2)) {
+        if (isPlayer) W_SetupShot_Dir(self, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+        racer_fire_rocket(w_shotorg, w_shotdir, NULL);
+        weapon_thinkf(WFRAME_FIRE2, 0, w_ready);
+    }
+    setself(this);
+    return true;
+}
+
+METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep))
+{
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost;
+}
+
+void racer_rocket_tracker();
+void racer_rocket_groundhugger();
+
+void racer_fire_rocket(vector org, vector dir, entity trg)
+{SELFPARAM();
+    entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+                           org, dir * autocvar_g_vehicle_racer_rocket_speed,
+                           autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
+                           DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
+
+    rocket.lip                   = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
+    rocket.wait                         = autocvar_g_vehicle_racer_rocket_turnrate;
+    rocket.nextthink           = time;
+    rocket.enemy                       = trg;
+    rocket.cnt                   = time + 15;
+
+    if(trg)
+        rocket.think                   = racer_rocket_tracker;
+    else
+        rocket.think                   = racer_rocket_groundhugger;
+}
+
+void racer_rocket_tracker()
+{SELFPARAM();
+    vector olddir, newdir;
+    float oldvel, newvel;
+
+    self.nextthink  = time;
+
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+    {
+        self.use();
+        return;
+    }
+
+    if(!self.realowner.vehicle)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    olddir = normalize(self.velocity);
+    oldvel = vlen(self.velocity);
+    newvel = oldvel + self.lip;
+    makevectors(vectoangles(olddir));
+
+    float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
+    vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
+
+    traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
+    newdir = normalize(predicted_origin - self.origin);
+
+    //vector
+    float height_diff = predicted_origin_z - self.origin_z;
+
+    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;
+    }
+
+    if(trace_fraction != 1.0 && trace_ent != self.enemy)
+        newdir_z += 16 * sys_frametime;
+
+    self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
+    self.velocity_z -= 800 * sys_frametime;
+    self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
+
+    UpdateCSQCProjectile(self);
+    return;
+}
+
+void racer_rocket_groundhugger()
+{SELFPARAM();
+    vector olddir, newdir;
+    float oldvel, newvel;
+
+    self.nextthink  = time;
+
+    if(self.owner.deadflag != DEAD_NO || self.cnt < time)
+    {
+        self.use();
+        return;
+    }
+
+    if(!self.realowner.vehicle)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    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)
+    {
+        // 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
+    }
+
+    int cont = pointcontents(self.origin - '0 0 32');
+    if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+        self.velocity_z += 200;
+
+    UpdateCSQCProjectile(self);
+    return;
+}
+
+#endif
+
+#endif
index aa6f3096ee212f753462d7b7d3cc836b77c8b10e..6d06cbc382c2ff62698a0fe31f541587bb70912c 100644 (file)
@@ -2,6 +2,8 @@
 #define VEHICLE_RAPTOR
 #include "raptor.qh"
 
+#include "raptor_weapons.qc"
+
 CLASS(Raptor, Vehicle)
 /* spawnflags */ ATTRIB(Raptor, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
 /* mins       */ ATTRIB(Raptor, mins, vector, '-80 -80 0');
@@ -17,143 +19,15 @@ CLASS(Raptor, Vehicle)
 /* fullname   */ ATTRIB(Raptor, vehicle_name, string, _("Raptor"));
 /* icon       */ ATTRIB(Raptor, m_icon, string, "vehicle_raptor");
 ENDCLASS(Raptor)
-
 REGISTER_VEHICLE(RAPTOR, NEW(Raptor));
 
-#include "../../weapons/all.qh"
-
-CLASS(RaptorCannon, PortoLaunch)
-/* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_TYPE_OTHER);
-/* impulse   */ ATTRIB(RaptorCannon, impulse, int, 3);
-/* refname   */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
-/* wepname   */ ATTRIB(RaptorCannon, message, string, _("Raptor cannon"));
-ENDCLASS(RaptorCannon)
-REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
-
-CLASS(RaptorBomb, PortoLaunch)
-/* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_TYPE_OTHER);
-/* impulse   */ ATTRIB(RaptorBomb, impulse, int, 3);
-/* refname   */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
-/* wepname   */ ATTRIB(RaptorBomb, message, string, _("Raptor bomb"));
-ENDCLASS(RaptorBomb)
-REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
-
-CLASS(RaptorFlare, PortoLaunch)
-/* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER);
-/* impulse   */ ATTRIB(RaptorFlare, impulse, int, 3);
-/* refname   */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
-/* wepname   */ ATTRIB(RaptorFlare, message, string, _("Raptor flare"));
-ENDCLASS(RaptorFlare)
-REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
-
 #endif
 
 #ifdef IMPLEMENTATION
 
-#ifdef SVQC
-float autocvar_g_vehicle_raptor_cannon_cost;
-float autocvar_g_vehicle_raptor_cannon_damage;
-float autocvar_g_vehicle_raptor_cannon_radius;
-float autocvar_g_vehicle_raptor_cannon_refire;
-float autocvar_g_vehicle_raptor_cannon_speed;
-float autocvar_g_vehicle_raptor_cannon_spread;
-float autocvar_g_vehicle_raptor_cannon_force;
-
-METHOD(RaptorCannon, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       entity veh = player.vehicle;
-       setself(player);
-       // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
-       float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
-       if (fire1)
-       if (weapon_prepareattack(false, t)) {
-               if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
-               vector org = w_shotorg;
-               vector dir = w_shotdir;
-               if (veh) {
-                       veh.misc_bulletcounter += 1;
-                       org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
-                         : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
-                       dir = v_forward;
-                       veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
-                       self.cnt = time;
-               }
-               vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
-                                                          org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
-                                                          autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
-                                                          DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, player);
-               weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
-       }
-       setself(this);
-       return true;
-}
-METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       entity veh = player.vehicle;
-       return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_raptor_cannon_cost;
-}
+#include "raptor_weapons.qc"
 
-float autocvar_g_vehicle_raptor_bombs_refire;
-
-void raptor_bombdrop();
-METHOD(RaptorBomb, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       setself(player);
-       if (fire2)
-       if (weapon_prepareattack(false, autocvar_g_vehicle_raptor_bombs_refire)) {
-               raptor_bombdrop();
-               weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
-       }
-       setself(this);
-       return true;
-}
-
-float autocvar_g_vehicle_raptor_flare_refire;
-float autocvar_g_vehicle_raptor_flare_lifetime;
-float autocvar_g_vehicle_raptor_flare_chase;
-float autocvar_g_vehicle_raptor_flare_range;
-
-void raptor_flare_think();
-void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
-void raptor_flare_touch();
-
-METHOD(RaptorFlare, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
-       SELFPARAM();
-       bool isPlayer = IS_PLAYER(self);
-       entity player = isPlayer ? self : self.owner;
-       setself(player);
-       if (fire2)
-       if (weapon_prepareattack(true, autocvar_g_vehicle_raptor_flare_refire)) {
-               for(int i = 0; i < 3; ++i) {
-                       entity _flare = spawn();
-                       setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
-                       _flare.effects = EF_LOWPRECISION | EF_FLAME;
-                       _flare.scale = 0.5;
-                       setorigin(_flare, self.origin - '0 0 16');
-                       _flare.movetype = MOVETYPE_TOSS;
-                       _flare.gravity = 0.15;
-                       _flare.velocity = 0.25 * self.velocity + (v_forward + randomvec() * 0.25)* -500;
-                       _flare.think = raptor_flare_think;
-                       _flare.nextthink = time;
-                       _flare.owner = self;
-                       _flare.solid = SOLID_CORPSE;
-                       _flare.takedamage = DAMAGE_YES;
-                       _flare.event_damage = raptor_flare_damage;
-                       _flare.health = 20;
-                       _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
-                       _flare.touch = raptor_flare_touch;
-               }
-               weapon_thinkf(WFRAME_FIRE2, 0, w_ready);
-       }
-       setself(this);
-       return true;
-}
+#ifdef SVQC
 
 bool autocvar_g_vehicle_raptor;
 
@@ -171,16 +45,6 @@ float autocvar_g_vehicle_raptor_speed_up;
 float autocvar_g_vehicle_raptor_speed_down;
 float autocvar_g_vehicle_raptor_friction;
 
-float autocvar_g_vehicle_raptor_bomblets;
-float autocvar_g_vehicle_raptor_bomblet_alt;
-float autocvar_g_vehicle_raptor_bomblet_time;
-float autocvar_g_vehicle_raptor_bomblet_damage;
-float autocvar_g_vehicle_raptor_bomblet_spread;
-float autocvar_g_vehicle_raptor_bomblet_edgedamage;
-float autocvar_g_vehicle_raptor_bomblet_radius;
-float autocvar_g_vehicle_raptor_bomblet_force;
-float autocvar_g_vehicle_raptor_bomblet_explode_delay;
-
 float autocvar_g_vehicle_raptor_cannon_turnspeed;
 float autocvar_g_vehicle_raptor_cannon_turnlimit;
 float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
@@ -217,98 +81,6 @@ float raptor_altitude(float amax)
        return vlen(self.origin - trace_endpos);
 }
 
-void raptor_bomblet_boom()
-{SELFPARAM();
-       RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
-                                                                       autocvar_g_vehicle_raptor_bomblet_edgedamage,
-                                                                       autocvar_g_vehicle_raptor_bomblet_radius, world, world,
-                                                                       autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
-       remove(self);
-}
-
-void raptor_bomblet_touch()
-{SELFPARAM();
-       if(other == self.owner)
-               return;
-
-       PROJECTILE_TOUCH;
-       self.think = raptor_bomblet_boom;
-       self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
-}
-
-void raptor_bomb_burst()
-{SELFPARAM();
-       if(self.cnt > time)
-       if(autocvar_g_vehicle_raptor_bomblet_alt)
-       {
-               self.nextthink = time;
-               traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
-               if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
-               {
-                       UpdateCSQCProjectile(self);
-                       return;
-               }
-       }
-
-       entity bomblet;
-       float i;
-
-       Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
-
-       for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
-       {
-               bomblet = spawn();
-               setorigin(bomblet, self.origin);
-
-               bomblet.movetype        = MOVETYPE_TOSS;
-               bomblet.touch      = raptor_bomblet_touch;
-               bomblet.think      = raptor_bomblet_boom;
-               bomblet.nextthink   = time + 5;
-               bomblet.owner      = self.owner;
-               bomblet.realowner   = self.realowner;
-               bomblet.velocity        = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
-
-               PROJECTILE_MAKETRIGGER(bomblet);
-               CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
-       }
-
-       remove(self);
-}
-
-void raptor_bombdrop()
-{SELFPARAM();
-       entity bomb_1, bomb_2;
-
-       bomb_1 = spawn();
-       bomb_2 = spawn();
-
-       setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
-       setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
-
-       bomb_1.movetype  = bomb_2.movetype   = MOVETYPE_BOUNCE;
-       bomb_1.velocity  = bomb_2.velocity   = self.velocity;
-       bomb_1.touch            = bomb_2.touch    = raptor_bomb_burst;
-       bomb_1.think            = bomb_2.think    = raptor_bomb_burst;
-       bomb_1.cnt                = bomb_2.cnt          = time + 10;
-
-       if(autocvar_g_vehicle_raptor_bomblet_alt)
-               bomb_1.nextthink = bomb_2.nextthink  = time;
-       else
-               bomb_1.nextthink = bomb_2.nextthink  = time + autocvar_g_vehicle_raptor_bomblet_time;
-
-       bomb_1.owner     = bomb_2.owner   = self;
-       bomb_1.realowner = bomb_2.realowner  = self.owner;
-       bomb_1.solid     = bomb_2.solid   = SOLID_BBOX;
-       bomb_1.gravity   = bomb_2.gravity       = 1;
-
-       PROJECTILE_MAKETRIGGER(bomb_1);
-       PROJECTILE_MAKETRIGGER(bomb_2);
-
-       CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
-       CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
-}
-
-
 void raptor_land()
 {SELFPARAM();
        float hgt;
@@ -384,35 +156,6 @@ void raptor_exit(float eject)
        self.owner = world;
 }
 
-void raptor_flare_touch()
-{SELFPARAM();
-       remove(self);
-}
-
-void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{SELFPARAM();
-       self.health -= damage;
-       if(self.health <= 0)
-               remove(self);
-}
-
-void raptor_flare_think()
-{SELFPARAM();
-       self.nextthink = time + 0.1;
-       entity _missile = findchainentity(enemy, self.owner);
-       while(_missile)
-       {
-               if(_missile.flags & FL_PROJECTILE)
-               if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
-               if(random() > autocvar_g_vehicle_raptor_flare_chase)
-                       _missile.enemy = self;
-               _missile = _missile.chain;
-       }
-
-       if(self.tur_impacttime < time)
-               remove(self);
-}
-
 float raptor_frame()
 {SELFPARAM();
        entity player, raptor;
@@ -1046,50 +789,6 @@ void spawnfunc_vehicle_raptor()
 #endif // SVQC
 #ifdef CSQC
 
-void RaptorCBShellfragDraw()
-{SELFPARAM();
-       if(wasfreed(self))
-               return;
-
-       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
-       self.move_avelocity += randomvec() * 15;
-       self.renderflags = 0;
-
-       if(self.cnt < time)
-               self.alpha = bound(0, self.nextthink - time, 1);
-
-       if(self.alpha < ALPHA_MIN_VISIBLE)
-               remove(self);
-}
-
-void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
-{SELFPARAM();
-       entity sfrag;
-
-       sfrag = spawn();
-       setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT);
-       setorigin(sfrag, _org);
-
-       sfrag.move_movetype = MOVETYPE_BOUNCE;
-       sfrag.gravity = 0.15;
-       sfrag.solid = SOLID_CORPSE;
-
-       sfrag.draw = RaptorCBShellfragDraw;
-
-       sfrag.move_origin = sfrag.origin = _org;
-       sfrag.move_velocity = _vel;
-       sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
-       sfrag.angles = self.move_angles = _ang;
-
-       sfrag.move_time = time;
-       sfrag.damageforcescale = 4;
-
-       sfrag.nextthink = time + 3;
-       sfrag.cnt = time + 2;
-       sfrag.alpha = 1;
-       sfrag.drawmask = MASK_NORMAL;
-}
-
                METHOD(Raptor, vr_hud, bool(Raptor thisveh))
                {
                        string crosshair;
diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc
new file mode 100644 (file)
index 0000000..24b885e
--- /dev/null
@@ -0,0 +1,321 @@
+#ifndef VEHICLE_RAPTOR_WEAPONS_H
+#define VEHICLE_RAPTOR_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RaptorCannon, PortoLaunch)
+/* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_TYPE_OTHER);
+/* impulse   */ ATTRIB(RaptorCannon, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
+/* wepname   */ ATTRIB(RaptorCannon, message, string, _("Raptor cannon"));
+ENDCLASS(RaptorCannon)
+REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
+
+CLASS(RaptorBomb, PortoLaunch)
+/* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_TYPE_OTHER);
+/* impulse   */ ATTRIB(RaptorBomb, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
+/* wepname   */ ATTRIB(RaptorBomb, message, string, _("Raptor bomb"));
+ENDCLASS(RaptorBomb)
+REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
+
+CLASS(RaptorFlare, PortoLaunch)
+/* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER);
+/* impulse   */ ATTRIB(RaptorFlare, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
+/* wepname   */ ATTRIB(RaptorFlare, message, string, _("Raptor flare"));
+ENDCLASS(RaptorFlare)
+REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_raptor_cannon_cost;
+float autocvar_g_vehicle_raptor_cannon_damage;
+float autocvar_g_vehicle_raptor_cannon_radius;
+float autocvar_g_vehicle_raptor_cannon_refire;
+float autocvar_g_vehicle_raptor_cannon_speed;
+float autocvar_g_vehicle_raptor_cannon_spread;
+float autocvar_g_vehicle_raptor_cannon_force;
+
+float autocvar_g_vehicle_raptor_bomblets;
+float autocvar_g_vehicle_raptor_bomblet_alt;
+float autocvar_g_vehicle_raptor_bomblet_time;
+float autocvar_g_vehicle_raptor_bomblet_damage;
+float autocvar_g_vehicle_raptor_bomblet_spread;
+float autocvar_g_vehicle_raptor_bomblet_edgedamage;
+float autocvar_g_vehicle_raptor_bomblet_radius;
+float autocvar_g_vehicle_raptor_bomblet_force;
+float autocvar_g_vehicle_raptor_bomblet_explode_delay;
+
+METHOD(RaptorCannon, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    setself(player);
+    // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
+    float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
+    if (fire1)
+    if (weapon_prepareattack(false, t)) {
+        if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+        vector org = w_shotorg;
+        vector dir = w_shotdir;
+        if (veh) {
+            veh.misc_bulletcounter += 1;
+            org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
+              : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
+            dir = v_forward;
+            veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
+            self.cnt = time;
+        }
+        vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+                               org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
+                               autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
+                               DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, player);
+        weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
+    }
+    setself(this);
+    return true;
+}
+METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep)) {
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_raptor_cannon_cost;
+}
+
+float autocvar_g_vehicle_raptor_bombs_refire;
+
+void raptor_bombdrop();
+METHOD(RaptorBomb, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    setself(player);
+    if (fire2)
+    if (weapon_prepareattack(false, autocvar_g_vehicle_raptor_bombs_refire)) {
+        raptor_bombdrop();
+        weapon_thinkf(WFRAME_FIRE1, 0, w_ready);
+    }
+    setself(this);
+    return true;
+}
+
+float autocvar_g_vehicle_raptor_flare_refire;
+float autocvar_g_vehicle_raptor_flare_lifetime;
+float autocvar_g_vehicle_raptor_flare_chase;
+float autocvar_g_vehicle_raptor_flare_range;
+
+void raptor_flare_think();
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void raptor_flare_touch();
+
+METHOD(RaptorFlare, wr_think, bool(entity thiswep, bool fire1, bool fire2)) {
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    setself(player);
+    if (fire2)
+    if (weapon_prepareattack(true, autocvar_g_vehicle_raptor_flare_refire)) {
+        for(int i = 0; i < 3; ++i) {
+            entity _flare = spawn();
+            setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
+            _flare.effects = EF_LOWPRECISION | EF_FLAME;
+            _flare.scale = 0.5;
+            setorigin(_flare, self.origin - '0 0 16');
+            _flare.movetype = MOVETYPE_TOSS;
+            _flare.gravity = 0.15;
+            _flare.velocity = 0.25 * self.velocity + (v_forward + randomvec() * 0.25)* -500;
+            _flare.think = raptor_flare_think;
+            _flare.nextthink = time;
+            _flare.owner = self;
+            _flare.solid = SOLID_CORPSE;
+            _flare.takedamage = DAMAGE_YES;
+            _flare.event_damage = raptor_flare_damage;
+            _flare.health = 20;
+            _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
+            _flare.touch = raptor_flare_touch;
+        }
+        weapon_thinkf(WFRAME_FIRE2, 0, w_ready);
+    }
+    setself(this);
+    return true;
+}
+
+
+void raptor_bomblet_boom()
+{SELFPARAM();
+    RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
+                                    autocvar_g_vehicle_raptor_bomblet_edgedamage,
+                                    autocvar_g_vehicle_raptor_bomblet_radius, world, world,
+                                    autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
+    remove(self);
+}
+
+void raptor_bomblet_touch()
+{SELFPARAM();
+    if(other == self.owner)
+        return;
+
+    PROJECTILE_TOUCH;
+    self.think = raptor_bomblet_boom;
+    self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
+}
+
+void raptor_bomb_burst()
+{SELFPARAM();
+    if(self.cnt > time)
+    if(autocvar_g_vehicle_raptor_bomblet_alt)
+    {
+        self.nextthink = time;
+        traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
+        if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
+        {
+            UpdateCSQCProjectile(self);
+            return;
+        }
+    }
+
+    entity bomblet;
+    float i;
+
+    Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
+
+    for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
+    {
+        bomblet = spawn();
+        setorigin(bomblet, self.origin);
+
+        bomblet.movetype       = MOVETYPE_TOSS;
+        bomblet.touch     = raptor_bomblet_touch;
+        bomblet.think     = raptor_bomblet_boom;
+        bomblet.nextthink   = time + 5;
+        bomblet.owner     = self.owner;
+        bomblet.realowner   = self.realowner;
+        bomblet.velocity       = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
+
+        PROJECTILE_MAKETRIGGER(bomblet);
+        CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
+    }
+
+    remove(self);
+}
+
+void raptor_bombdrop()
+{SELFPARAM();
+    entity bomb_1, bomb_2;
+
+    bomb_1 = spawn();
+    bomb_2 = spawn();
+
+    setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
+    setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
+
+    bomb_1.movetype     = bomb_2.movetype   = MOVETYPE_BOUNCE;
+    bomb_1.velocity     = bomb_2.velocity   = self.velocity;
+    bomb_1.touch               = bomb_2.touch    = raptor_bomb_burst;
+    bomb_1.think               = bomb_2.think    = raptor_bomb_burst;
+    bomb_1.cnt           = bomb_2.cnt          = time + 10;
+
+    if(autocvar_g_vehicle_raptor_bomblet_alt)
+        bomb_1.nextthink = bomb_2.nextthink  = time;
+    else
+        bomb_1.nextthink = bomb_2.nextthink  = time + autocvar_g_vehicle_raptor_bomblet_time;
+
+    bomb_1.owner        = bomb_2.owner   = self;
+    bomb_1.realowner = bomb_2.realowner  = self.owner;
+    bomb_1.solid        = bomb_2.solid   = SOLID_BBOX;
+    bomb_1.gravity   = bomb_2.gravity  = 1;
+
+    PROJECTILE_MAKETRIGGER(bomb_1);
+    PROJECTILE_MAKETRIGGER(bomb_2);
+
+    CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
+    CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
+}
+
+void raptor_flare_touch()
+{SELFPARAM();
+    remove(self);
+}
+
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{SELFPARAM();
+    self.health -= damage;
+    if(self.health <= 0)
+        remove(self);
+}
+
+void raptor_flare_think()
+{SELFPARAM();
+    self.nextthink = time + 0.1;
+    entity _missile = findchainentity(enemy, self.owner);
+    while(_missile)
+    {
+        if(_missile.flags & FL_PROJECTILE)
+        if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
+        if(random() > autocvar_g_vehicle_raptor_flare_chase)
+            _missile.enemy = self;
+        _missile = _missile.chain;
+    }
+
+    if(self.tur_impacttime < time)
+        remove(self);
+}
+
+#endif
+
+#ifdef CSQC
+
+void RaptorCBShellfragDraw()
+{SELFPARAM();
+    if(wasfreed(self))
+        return;
+
+    Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+    self.move_avelocity += randomvec() * 15;
+    self.renderflags = 0;
+
+    if(self.cnt < time)
+        self.alpha = bound(0, self.nextthink - time, 1);
+
+    if(self.alpha < ALPHA_MIN_VISIBLE)
+        remove(self);
+}
+
+void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
+{SELFPARAM();
+    entity sfrag;
+
+    sfrag = spawn();
+    setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT);
+    setorigin(sfrag, _org);
+
+    sfrag.move_movetype = MOVETYPE_BOUNCE;
+    sfrag.gravity = 0.15;
+    sfrag.solid = SOLID_CORPSE;
+
+    sfrag.draw = RaptorCBShellfragDraw;
+
+    sfrag.move_origin = sfrag.origin = _org;
+    sfrag.move_velocity = _vel;
+    sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
+    sfrag.angles = self.move_angles = _ang;
+
+    sfrag.move_time = time;
+    sfrag.damageforcescale = 4;
+
+    sfrag.nextthink = time + 3;
+    sfrag.cnt = time + 2;
+    sfrag.alpha = 1;
+    sfrag.drawmask = MASK_NORMAL;
+}
+
+#endif
+
+#endif