Merge branch 'master' into mirceakitsune/hud_postprocessing
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / projectile.qc
index 1cbab30..cede03c 100644 (file)
@@ -22,6 +22,11 @@ void SUB_Stop()
 .float silent;
 .float traileffect;
 
+void Projectile_ResetTrail(vector to)
+{
+       self.trail_oldorigin = to;
+       self.trail_oldtime = time;
+}
 void Projectile_DrawTrail(vector to)
 {
        vector from;
@@ -31,8 +36,16 @@ void Projectile_DrawTrail(vector to)
        self.trail_oldorigin = to;
        self.trail_oldtime = time;
 
+       // force the effect even for stationary firemine
+       if(self.cnt == PROJECTILE_FIREMINE)
+               if(from == to)
+                       from_z += 1;
+
        if (self.traileffect)
-               trailparticles(self, self.traileffect, from, to);
+       {
+               particles_alphamin = particles_alphamax = sqrt(self.alpha);
+               boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, sqrt(self.alpha), PARTICLES_USEALPHA);
+       }
 }
 
 void Projectile_Draw()
@@ -49,9 +62,18 @@ void Projectile_Draw()
        if(self.count & 0x80)
        {
                //self.move_flags &~= FL_ONGROUND;
-               Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+               if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
+                       Movetype_Physics_NoMatchServer();
+                       // the trivial movetypes do not have to match the
+                       // server's ticrate as they are ticrate independent
+                       // NOTE: this assumption is only true if MOVETYPE_FLY
+                       // projectiles detonate on impact. If they continue
+                       // moving, we might still be ticrate dependent.
+               else
+                       Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
                if(!(self.move_flags & FL_ONGROUND))
-                       self.angles = vectoangles(self.velocity);
+                       if(self.velocity != '0 0 0')
+                               self.angles = vectoangles(self.velocity);
        }
        else
        {
@@ -97,8 +119,10 @@ void Projectile_Draw()
        makevectors(ang);
 
        a = 1 - (time - self.fade_time) * self.fade_rate;
-       if(a <= 0)
+       self.alpha = bound(0, self.alphamod * a, 1);
+       if(self.alpha <= 0)
                drawn = 0;
+       self.renderflags = 0;
 
        trailorigin = self.origin;
        switch(self.cnt)
@@ -113,10 +137,9 @@ void Projectile_Draw()
        if(drawn)
                Projectile_DrawTrail(trailorigin);
        else
-       {
-               self.trail_oldorigin = trailorigin;
-               self.trail_oldtime = time;
-       }
+               Projectile_ResetTrail(trailorigin);
+
+       self.drawmask = 0;
 
        if(!drawn)
                return;
@@ -131,10 +154,7 @@ void Projectile_Draw()
                        break;
        }
 
-       self.alpha = self.alphamod * a;
-       self.renderflags = 0;
-
-       R_AddEntity(self);
+       self.drawmask = MASK_NORMAL;
 }
 
 void loopsound(entity e, float ch, string samp, float vol, float attn)
@@ -213,12 +233,15 @@ void Ent_Projectile()
                        self.velocity_x = ReadCoord();
                        self.velocity_y = ReadCoord();
                        self.velocity_z = ReadCoord();
-                       self.gravity = ReadCoord();
+                       if(f & 0x10)
+                               self.gravity = ReadCoord();
+                       else
+                               self.gravity = 0; // none
                        self.move_origin = self.origin;
                        self.move_velocity = self.velocity;
                }
 
-               if(time == self.spawntime || (self.count & 0x80) || (f & 0x10))
+               if(time == self.spawntime || (self.count & 0x80) || (f & 0x08))
                {
                        self.trail_oldorigin = self.origin;
                        if(!(self.count & 0x80))
@@ -251,13 +274,14 @@ void Ent_Projectile()
                        case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
                        case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
                        case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
-                       case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
+                       case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle_weak"); break;
                        case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break;
                        case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
                        case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
                        case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
                        case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
                        case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
+                       case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
                        case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
@@ -267,6 +291,9 @@ void Ent_Projectile()
                        case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break;
                        case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
                        case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
+                       case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
+                       case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_ROCKET"); break;
+                       case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.scale = 2; self.traileffect = particleeffectnum("TR_ROCKET"); break;
                        default:
                                error("Received invalid CSQC projectile, can't work with this!");
                                break;
@@ -284,10 +311,12 @@ void Ent_Projectile()
                        case PROJECTILE_ELECTRO:
                                // only new engines support sound moving with object
                                loopsound(self, CHAN_PROJECTILE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
-                               self.mins = '0 0 -3';
-                               self.maxs = '0 0 -3';
+                               self.mins = '0 0 -4';
+                               self.maxs = '0 0 -4';
                                self.move_movetype = MOVETYPE_BOUNCE;
                                self.move_touch = SUB_Null;
+                               self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
+                               self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
                                break;
                        case PROJECTILE_ROCKET:
                                loopsound(self, CHAN_PROJECTILE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM);
@@ -295,16 +324,20 @@ void Ent_Projectile()
                                self.maxs = '3 3 3';
                                break;
                        case PROJECTILE_GRENADE:
-                               self.mins = '0 0 -3';
-                               self.maxs = '0 0 -3';
+                               self.mins = '-3 -3 -3';
+                               self.maxs = '3 3 3';
                                break;
                        case PROJECTILE_GRENADE_BOUNCING:
-                               self.mins = '0 0 -3';
-                               self.maxs = '0 0 -3';
+                               self.mins = '-3 -3 -3';
+                               self.maxs = '3 3 3';
                                self.move_movetype = MOVETYPE_BOUNCE;
                                self.move_touch = SUB_Null;
-                               self.move_bounce_factor = g_balance_grenadelauncher_secondary_bouncefactor;
-                               self.move_bounce_stopspeed = g_balance_grenadelauncher_secondary_bouncestop;
+                               self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
+                               self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
+                               break;
+                       case PROJECTILE_MINE:
+                               self.mins = '-4 -4 -4';
+                               self.maxs = '4 4 4';
                                break;
                        case PROJECTILE_PORTO_RED:
                                self.colormod = '2 1 1';
@@ -338,6 +371,19 @@ void Ent_Projectile()
                                self.mins = '-4 -4 -4';
                                self.maxs = '4 4 4';
                                break;
+                       case PROJECTILE_TAG:
+                               loopsound(self, CHAN_PROJECTILE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
+                               self.mins = '-2 -2 -2';
+                               self.maxs = '2 2 2';
+                               break;
+                       case PROJECTILE_FLAC:
+                               self.mins = '-2 -2 -2';
+                               self.maxs = '2 2 2';
+                               break;
+                       case PROJECTILE_SEEKER:
+                               self.mins = '-4 -4 -4';
+                               self.maxs = '4 4 4';
+                               break;
                        default:
                                break;
                }
@@ -370,14 +416,17 @@ void Projectile_Precache()
        precache_model("models/ebomb.mdl");
        precache_model("models/elaser.mdl");
        precache_model("models/grenademodel.md3");
+       precache_model("models/mine.md3");
        precache_model("models/hagarmissile.mdl");
        precache_model("models/hlac_bullet.md3");
        precache_model("models/laser.mdl");
        precache_model("models/plasmatrail.mdl");
        precache_model("models/rocket.md3");
+       precache_model("models/tagrocket.md3");
        precache_model("models/tracer.mdl");
        precache_sound("weapons/electro_fly.wav");
        precache_sound("weapons/rocket_fly.wav");
        precache_sound("weapons/fireball_fly.wav");
        precache_sound("weapons/fireball_fly2.wav");
+       precache_sound("weapons/tag_rocket_fly.wav");
 }