From: Mircea Kitsune Date: Thu, 25 Aug 2011 14:04:50 +0000 (+0300) Subject: Attempt to move the repeater of the damage effect client side, using entcs to get... X-Git-Tag: xonotic-v0.6.0~110^2^2~100 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=fe8fa62ddd3321825b7628645e3d4b809f07929d;p=xonotic%2Fxonotic-data.pk3dir.git Attempt to move the repeater of the damage effect client side, using entcs to get the player's origin. Previously, the server would send the effect to all clients every 0.1 seconds (lots of bandwidth). With this change, it will only send it once per damage event, and the client will find the origin and repeat it. Not guaranteed to work yet, and this commit might break it! --- diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index b896923f7..4bd3849e5 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -358,11 +358,11 @@ set g_telefrags_teamplay 1 "never telefrag team mates" set g_telefrags_avoid 1 "when teleporters have a random destination, avoid teleporting to locations where a telefrag would happen" set g_teleport_maxspeed 0 "maximum speed that a player can keep when going through a teleporter (if a misc_teleporter_dest also has a cap the smallest one of these will be used), 0 = don't limit, -1 = keep no speed" -set sv_damageeffect_tick 0.05 "how often the damage effect is updated (particles per second), low values might cause lag" -set sv_damageeffect_lifetime 0.04 "how much a damage effect lasts, multiplied by damage amount" -set sv_damageeffect_lifetime_max 5 "maximum amount of lifetime a damage effect may have at a time" set cl_damageeffect 1 "enable weapon damage effects on players, values between 0 and 1 specify probability of the effect showing on players each tick (used to reduce the effect)" set cl_damageeffect_gibs 0.15 "probability of the effect showing on gibs each tick (used to reduce the effect)" +set cl_damageeffect_tick 0.05 "how often the damage effect is updated (particles per second), low values might cause lag" +set cl_damageeffect_lifetime 0.04 "how much a damage effect lasts, multiplied by damage amount" +set cl_damageeffect_lifetime_max 5 "maximum amount of lifetime a damage effect may have at a time" set g_respawn_ghosts 1 "if 1 dead bodies become ghosts and float away when the player respawns" set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate" diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 1617e4923..fe2e8b67b 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -234,3 +234,89 @@ void DamageInfo_Precache() for(i = WEP_FIRST; i <= WEP_LAST; ++i) (get_weaponinfo(i)).weapon_func(WR_PRECACHE); } + +.entity dmgeffect; +.string dmgparticles; + +void Ent_DamageEffect_Think() +{ + self.nextthink = time; + + entity entcs; + entcs = entcs_receiver[self.team]; + if(!entcs) + return; + + // 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) + { + entity head; + for(head = world; (head = find(head, classname, "gib")); ) + { + if(head.team == self.team) + if(random() < autocvar_cl_damageeffect_gibs) + pointparticles(particleeffectnum(self.dmgparticles), head.origin, '0 0 0', 1); + } + } + + // if we aren't in third person mode, hide our own damage effect + if(self.team == player_localentnum) + if(!autocvar_chase_active) + return; + + // Now apply the effect to the actual player. + if(random() < autocvar_cl_damageeffect) + pointparticles(particleeffectnum(self.dmgparticles), entcs.origin, '0 0 0', 1); +} + +void Ent_DamageEffect() +{ + float dmg, type, specnum1, specnum2, entnumber; + vector org; + string specstr, effectnum; + entity e; + + dmg = ReadByte(); // damage amount + type = ReadByte(); // damage weapon + specnum1 = ReadByte(); // player species + entnumber = ReadByte(); // player entnum + + if not(autocvar_cl_damageeffect) + return; + if(autocvar_cl_gentle || autocvar_cl_gentle_damage) + return; + + specnum2 = (specnum1 & 0x78) / 8; // blood type: using four bits (0..7, bit indexes 3,4,5) + specstr = species_prefix(specnum2); + + e = get_weaponinfo(type); + 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 + } + + // if the player already has a damage effect, replace it with the new one + entity head; + for(head = world; (head = find(head, classname, "dmgeffect")); ) + { + if(head.team == entnumber) + { + remove(head); + head = world; + } + } + + entity e; + e = spawn(); + e.classname = "dmgeffect"; + e.team = entnumber; + e.dmgparticles = effectnum; + e.think = Ent_DamageEffect_Think; + e.nextthink = time; +} diff --git a/qcsrc/client/gibs.qc b/qcsrc/client/gibs.qc index 78aee3775..eebad4c73 100644 --- a/qcsrc/client/gibs.qc +++ b/qcsrc/client/gibs.qc @@ -284,63 +284,3 @@ 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); -} diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 401dd0797..ff9982333 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -1170,9 +1170,6 @@ float autocvar_sv_warsowbunny_topspeed; float autocvar_sv_warsowbunny_turnaccel; string autocvar_sv_weaponstats_file; float autocvar_sv_gibhealth; -float autocvar_sv_damageeffect_tick; -float autocvar_sv_damageeffect_lifetime; -float autocvar_sv_damageeffect_lifetime_max; float autocvar_sys_ticrate; float autocvar_teamplay_lockonrestart; float autocvar_teamplay_mode; diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 61884b878..f3d34bb47 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -887,8 +887,6 @@ void PutClientInServer (void) RemoveGrapplingHook(self); // Wazat's Grappling Hook - Violence_DamageEffect_Remove(self); - self.classname = "player"; self.wasplayer = TRUE; self.iscreature = TRUE; @@ -1953,7 +1951,6 @@ void respawn(void) pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1); if(autocvar_g_respawn_ghosts_maxtime) SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5); - Violence_DamageEffect_Remove(self); } CopyBody(1); diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 4b8dc143f..9182452e9 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -180,8 +180,6 @@ void CopyBody(float keepvelocity) Drag_MoveDrag(oldself, self); - Violence_DamageEffect_Copy(oldself, self); - self.owner = oldself; self = oldself; } diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index efdd9ed1c..8985765cf 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -495,7 +495,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float { // if the target is a player or dead body, activate damage effects if(targ.classname == "player" || targ.classname == "body") - Violence_DamageEffect_SetRepeat(targ, damage, DEATH_WEAPONOF(deathtype)); + Violence_DamageEffect(targ, damage, DEATH_WEAPONOF(deathtype)); float mirrordamage; float mirrorforce; diff --git a/qcsrc/server/g_violence.qc b/qcsrc/server/g_violence.qc index 1c3c8d04e..8f5f55f2f 100644 --- a/qcsrc/server/g_violence.qc +++ b/qcsrc/server/g_violence.qc @@ -48,36 +48,28 @@ void Violence_GibSplash(entity source, float type, float amount, entity 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; + return FALSE; // if the client doesn't have the effect enabled, don't send to him and waste bandwidth WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEEFFECT); - WriteByte(MSG_ENTITY, self.cnt); // damage weapon + WriteByte(MSG_ENTITY, self.cnt); // damage amount + WriteByte(MSG_ENTITY, self.weapon); // 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)); return TRUE; } -void Violence_DamageEffect(entity pl, float type) +void Violence_DamageEffect(entity pl, float damage, float type) { - entity e; + if(sv_gentle || !type) + return; // return if gentle mode is enabled or the damage was not caused by a weapon + entity e; e = spawn(); - e.classname = "damageeffect"; - e.cnt = type; + e.cnt = damage; + e.weapon = type; e.state |= 8 * pl.species; // gib type, ranges from 0 to 15 // if this is a copied dead body, send the num of its player instead @@ -86,77 +78,5 @@ void Violence_DamageEffect(entity pl, float type) 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.damageeffect_lifetime || (self.owner.classname != "player" && self.owner.classname != "body")) - { - Violence_DamageEffect_Remove(self.owner); - return; - } - - Violence_DamageEffect(self.owner, self.cnt); - self.nextthink = time + autocvar_sv_damageeffect_tick; -} - -void Violence_DamageEffect_SetRepeat(entity pl, float damage, float type) -{ - if not(autocvar_sv_damageeffect_tick && autocvar_sv_damageeffect_lifetime) - return; - if(sv_gentle || !type) - return; // return if gentle mode is enabled or the damage was not caused by a weapon - - // if a repeater doesn't exist, spawn one, else update the existing one - if(pl.damageeffect_repeater == world) - { - pl.damageeffect_repeater = spawn(); - pl.damageeffect_repeater.classname = "damageeffect_repeater"; - pl.damageeffect_repeater.owner = pl; - pl.damageeffect_repeater.think = Violence_DamageEffect_DoRepeat; - - 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.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 -}