]> 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 cee0c28a68bf07aa97c9fc3db73b9c584fd77ed3..1c3c8d04ec3edbc1465a9517c57682e587117f5a 100644 (file)
@@ -26,7 +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
-       e.team = num_for_edict(self);
+
+       // 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;
 
@@ -42,32 +48,23 @@ void Violence_GibSplash(entity source, float type, float amount, entity attacker
 
 // damage effect
 
-.float lifetime;
+.float damageeffect_lifetime;
 .entity damageeffect_repeater;
 
-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);
-
-       pl.damageeffect_repeater = spawn();
-       copyentity(old_pl.damageeffect_repeater, pl.damageeffect_repeater);
-       pl.damageeffect_repeater.owner = pl;
-}
-
 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));
@@ -79,18 +76,35 @@ 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);
 }
 
+void Violence_DamageEffect_Remove(entity pl);
 void Violence_DamageEffect_DoRepeat()
 {
-       if(time > self.lifetime || (self.owner.classname != "player" && self.owner.classname != "body"))
+       if(time > self.damageeffect_lifetime || (self.owner.classname != "player" && self.owner.classname != "body"))
        {
                Violence_DamageEffect_Remove(self.owner);
                return;
@@ -115,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
+}