Merge branch 'master' into mirceakitsune/damage_effects
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / gibs.qc
index 409f8094264abd9c943250431f109ad246a857d5..78aee37752dc2b7fc8efbe9f6e4dcb4018abcf88 100644 (file)
@@ -103,17 +103,19 @@ void Gib_Draw()
        }
 }
 
-void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, float specnum, float destroyontouch, float issilent)
+void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, float specnum, float destroyontouch, float issilent, float gibownernum)
 {
        entity gib;
 
        // TODO remove some gibs according to cl_nogibs
        gib = RubbleNew("gib");
+       gib.classname = "gib";
        gib.move_movetype = MOVETYPE_BOUNCE;
        gib.gravity = 1;
        gib.solid = SOLID_CORPSE;
        gib.cnt = specnum;
        gib.silent = issilent;
+       gib.team = gibownernum;
        Gib_setmodel(gib, mdlname, specnum);
 
        setsize (gib, '-8 -8 -8', '8 8 8');
@@ -145,7 +147,7 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector
 
 void Ent_GibSplash(float isNew)
 {
-       float amount, type, specnum;
+       float amount, type, specnum, entnumber;
        vector org, vel;
        string specstr;
        float issilent;
@@ -155,6 +157,7 @@ void Ent_GibSplash(float isNew)
 
        type = ReadByte(); // gibbage type
        amount = ReadByte() / 16.0; // gibbage amount
+       entnumber = ReadByte(); // player num
        org_x = ReadShort() * 4 + 2;
        org_y = ReadShort() * 4 + 2;
        org_z = ReadShort() * 4 + 2;
@@ -202,37 +205,37 @@ void Ent_GibSplash(float isNew)
                                sound (self, CH_PAIN, "misc/gib.wav", VOL_BASE, ATTN_NORM);
 
                        if(prandom() < amount)
-                               TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
+                               TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent, entnumber);
                        new_te_bloodshower(particleeffectnum(strcat(specstr, "bloodshower")), org, 1200, amount);
                        if(prandom() < amount)
-                               TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent);
+                               TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent, entnumber);
 
                        for(c = 0; c < amount; ++c)
                        {
                                randomvalue = amount - c;
 
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
+                                       TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
+                                       TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/chest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
+                                       TossGib ("models/gibs/chest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/smallchest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent);
+                                       TossGib ("models/gibs/smallchest.md3", org, org + 16 * prandomvec(), vel, prandomvec() * (prandom() * 120 + 80), specnum,0, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/leg1.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
+                                       TossGib ("models/gibs/leg1.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/leg2.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent);
+                                       TossGib ("models/gibs/leg2.md3", org, org + 16 * prandomvec() + '0 0 -5', vel, prandomvec() * (prandom() * 120 + 85), specnum,0, issilent, entnumber);
 
                                // these splat on impact
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
+                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
+                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
+                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent, entnumber);
                                if(prandom() < randomvalue)
-                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent);
+                                       TossGib ("models/gibs/chunk.mdl", org, org + 16 * prandomvec(), vel, prandomvec() * 450, specnum,1, issilent, entnumber);
                        }
                        break;
                case 0x02:
@@ -240,7 +243,7 @@ void Ent_GibSplash(float isNew)
                        break;
                case 0x03:
                        if(prandom() < amount)
-                               TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization?
+                               TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent, entnumber); // TODO maybe adjust to more randomization?
                        break;
                case 0x81:
                        pointparticles(particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);
@@ -281,3 +284,63 @@ void GibSplash_Precache()
     precache_sound ("misc/gib_splat03.wav");
     precache_sound ("misc/gib_splat04.wav");
 }
+
+void Ent_DamageEffect()
+{
+       float type, specnum1, specnum2, entnumber, body;
+       vector org;
+       string specstr, effectnum;
+       entity e;
+
+       type = ReadByte(); // damage weapon
+       specnum1 = ReadByte(); // player species
+       entnumber = ReadByte(); // player entnum
+       body = ReadByte(); // is dead body / gibbed
+       org_x = ReadCoord();
+       org_y = ReadCoord();
+       org_z = ReadCoord();
+
+       if not(autocvar_cl_damageeffect)
+               return;
+       if(autocvar_cl_gentle || autocvar_cl_gentle_damage)
+               return;
+
+       e = get_weaponinfo(type);
+
+       specnum2 = (specnum1 & 0x78) / 8; // blood type: using four bits (0..7, bit indexes 3,4,5)
+       specstr = species_prefix(specnum2);
+
+       effectnum = strcat("weapondamage_", e.netname);
+       // If the weapon is a bullet weapon, its damage effect is blood.
+       // Since blood is species dependent, we make this effect per-species.
+       if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
+       if(specstr != "")
+       {
+               effectnum = strcat(effectnum, "_", specstr);
+               effectnum = substring(effectnum, 0, strlen(effectnum) - 1); // remove the _ symbol at the end of the species name
+       }
+
+       entity head;
+
+       // Scan the owner of all gibs in the world. If a gib owner is the same as the player we're applying the
+       // effect to, it means our player is gibbed. Therefore, apply the particles to the gibs as well.
+       if(autocvar_cl_damageeffect_gibs && body > 1)
+       for(head = world; (head = find(head, classname, "gib")); )
+       {
+               if(head.team == entnumber)
+               if(random() < autocvar_cl_damageeffect_gibs)
+                       pointparticles(particleeffectnum(effectnum), head.origin, '0 0 0', 1);
+       }
+
+       // if we aren't in third person mode, hide our own damage effect
+       if(entnumber == player_localentnum && !body)
+       if(!autocvar_chase_active)
+               return;
+       // if this is a gibbed dead body, don't apply the effects to it, only the gibs as done above
+       if(body > 1)
+               return;
+
+       // Now apply the effect to the actual player.
+       if(random() < autocvar_cl_damageeffect)
+               pointparticles(particleeffectnum(effectnum), org, '0 0 0', 1);
+}