]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_violence.qc
Merge branch 'master' into mirceakitsune/damage_effects
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_violence.qc
index a1cd8932687018a0def403a0b19254880e6063bf..1c3c8d04ec3edbc1465a9517c57682e587117f5a 100644 (file)
@@ -3,6 +3,7 @@ float Violence_GibSplash_SendEntity(entity to, float sf)
        WriteByte(MSG_ENTITY, ENT_CLIENT_GIBSPLASH);
        WriteByte(MSG_ENTITY, self.state); // actually type
        WriteByte(MSG_ENTITY, bound(1, self.cnt * 16, 255)); // gibbage amount multiplier
+       WriteByte(MSG_ENTITY, self.team); // player num
        WriteShort(MSG_ENTITY, floor(self.origin_x / 4)); // not using a coord here, as gibs don't need this accuracy
        WriteShort(MSG_ENTITY, floor(self.origin_y / 4)); // not using a coord here, as gibs don't need this accuracy
        WriteShort(MSG_ENTITY, floor(self.origin_z / 4)); // not using a coord here, as gibs don't need this accuracy
@@ -25,6 +26,13 @@ void Violence_GibSplash_At(vector org, vector dir, float type, float amount, ent
        if(!sound_allowed(MSG_BROADCAST, gibowner) || !sound_allowed(MSG_BROADCAST, attacker))
                e.state |= 0x40; // "silence" bit
        e.state |= 8 * self.species; // gib type, ranges from 0 to 15
+
+       // if this is a copied dead body, send the num of its player instead
+       if(self.classname == "body")
+               e.team = num_for_edict(self.owner);
+       else
+               e.team = num_for_edict(self);
+
        setorigin(e, org);
        e.velocity = dir;
 
@@ -38,12 +46,25 @@ void Violence_GibSplash(entity source, float type, float amount, entity attacker
        Violence_GibSplash_At(source.origin + source.view_ofs, source.velocity, type, amount, source, attacker);
 }
 
+// damage effect
+
+.float damageeffect_lifetime;
+.entity damageeffect_repeater;
+
 float Violence_DamageEffect_SendEntity(entity to, float sf)
 {
+       // if the client doesn't have the effect enabled, don't send to him and waste bandwidth
+       if not(to.cvar_cl_damageeffect)
+               return FALSE;
+       // if the client cannot see the damaged player, avoid sending and further save bandwidth
+       if not(checkpvs(to.origin + to.view_ofs, self))
+               return FALSE;
+
        WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEEFFECT);
-       WriteByte(MSG_ENTITY, self.cnt); // the damage weapon
-       WriteByte(MSG_ENTITY, self.state); // species
+       WriteByte(MSG_ENTITY, self.cnt); // damage weapon
+       WriteByte(MSG_ENTITY, self.state); // player species
        WriteByte(MSG_ENTITY, self.team); // player entnum
+       WriteByte(MSG_ENTITY, self.deadflag); // is dead body / gibbed
        WriteCoord(MSG_ENTITY, floor(self.origin_x));
        WriteCoord(MSG_ENTITY, floor(self.origin_y));
        WriteCoord(MSG_ENTITY, floor(self.origin_z));
@@ -55,25 +76,37 @@ void Violence_DamageEffect(entity pl, float type)
        entity e;
 
        e = spawn();
-       e.classname = "weapondamage";
+       e.classname = "damageeffect";
        e.cnt = type;
        e.state |= 8 * pl.species; // gib type, ranges from 0 to 15
-       e.team = num_for_edict(pl);
-       setorigin(e, pl.origin);
+
+       // if this is a copied dead body, send the num of its player instead
+       if(pl.classname == "body")
+               e.team = num_for_edict(pl.owner);
+       else
+               e.team = num_for_edict(pl);
+
+       // is this a whole dead body, or a gibbed body / player?
+       if(!pl.modelindex) // gibbed
+               e.deadflag = 2;
+       else if(pl.classname == "body")
+               e.deadflag = 1;
+
+       // if the player is dead, show the effect lower, else it appears floating above the body
+       if(pl.health <= 0)
+               setorigin(e, pl.origin - '0 0 25');
+       else
+               setorigin(e, pl.origin);
 
        Net_LinkEntity(e, FALSE, 0.2, Violence_DamageEffect_SendEntity);
 }
 
-.entity damageeffect_repeater;
-.float lifetime;
-
+void Violence_DamageEffect_Remove(entity pl);
 void Violence_DamageEffect_DoRepeat()
 {
-       if(time > self.lifetime)
+       if(time > self.damageeffect_lifetime || (self.owner.classname != "player" && self.owner.classname != "body"))
        {
-               self.nextthink = 0;
-               remove(self.owner.damageeffect_repeater);
-               self.owner.damageeffect_repeater = world;
+               Violence_DamageEffect_Remove(self.owner);
                return;
        }
 
@@ -96,15 +129,34 @@ void Violence_DamageEffect_SetRepeat(entity pl, float damage, float type)
                pl.damageeffect_repeater.owner = pl;
                pl.damageeffect_repeater.think = Violence_DamageEffect_DoRepeat;
 
-               pl.damageeffect_repeater.lifetime = time + (autocvar_sv_damageeffect_lifetime * damage);
+               pl.damageeffect_repeater.damageeffect_lifetime = time + (autocvar_sv_damageeffect_lifetime * damage);
        }
        else
        {
                // if the repeater is being updated, increase its lifetime instead of re-setting it entirely
                // this fixes the shotgun among other things, where only the damage of one bullet would be taken into account
-               pl.damageeffect_repeater.lifetime += (autocvar_sv_damageeffect_lifetime * damage);
+               pl.damageeffect_repeater.damageeffect_lifetime += (autocvar_sv_damageeffect_lifetime * damage);
        }
 
+       if(autocvar_sv_damageeffect_lifetime_max)
+               pl.damageeffect_repeater.damageeffect_lifetime = bound(0, pl.damageeffect_repeater.damageeffect_lifetime, time + autocvar_sv_damageeffect_lifetime_max);
+
        pl.damageeffect_repeater.cnt = type;
        pl.damageeffect_repeater.nextthink = time;
 }
+
+void Violence_DamageEffect_Remove(entity pl)
+{
+       pl.damageeffect_repeater.nextthink = 0;
+       remove(pl.damageeffect_repeater);
+       pl.damageeffect_repeater = world;
+}
+
+void Violence_DamageEffect_Copy(entity old_pl, entity pl)
+{
+       if(pl.damageeffect_repeater != world)
+               Violence_DamageEffect_Remove(pl);
+
+       Violence_DamageEffect_SetRepeat(pl, 0, old_pl.damageeffect_repeater.cnt); // spawn a new repeater
+       pl.damageeffect_repeater.damageeffect_lifetime = old_pl.damageeffect_repeater.damageeffect_lifetime; // copy the lifetime
+}