From: Mircea Kitsune Date: Mon, 9 Jan 2012 19:07:53 +0000 (+0200) Subject: Attempt to make damage effects use skeletal attachments for all rigged objects, not... X-Git-Tag: xonotic-v0.6.0~110^2^2~37 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2a93c96f938d9ac285ec2ca27bbb9c581f405ecc;p=xonotic%2Fxonotic-data.pk3dir.git Attempt to make damage effects use skeletal attachments for all rigged objects, not only players. Useful if eg: Vehicles will also be made client-side, or someone uses misc_clientmodel. Does not work exactly as it should yet --- diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 868e41f21..69dbea106 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -321,7 +321,7 @@ 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 cl_damageeffect 1 "enable weapon damage effects. 1 enables the effect on players, 2 on players and objects" +set cl_damageeffect 1 "enable weapon damage effects. 1 enables the effect on skeletal models, 2 on all objects" set cl_damageeffect_ticrate 0.1 "particles spawn rate" set cl_damageeffect_limit 5 "how many damages to allow on a player at once (objects are limited to one)" set cl_damageeffect_distribute 1 "divide particle intensity if multiple damages are present on a player" diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 423c3cf6c..4e42794b1 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -276,7 +276,7 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum) { // particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets) - float life; + float life, skeletal; string specstr, effectnum; entity e; @@ -284,16 +284,39 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum) return; if(!self || !self.modelindex || !self.drawmask) return; + + // if this is a rigged mesh, the effect will show on the bone where damage was dealt + // we do this by choosing the skeletal bone closest to the impact, and attaching our entity to it + // if there's no skeleton, object origin will automatically be selected + float closest; + FOR_EACH_TAG(self) + { + // blacklist bones positioned outside the mesh, or the effect will be floating + // TODO: Do we have to do it this way? Why do these bones exist at all? + if(gettaginfo_name == "master" || gettaginfo_name == "knee_L" || gettaginfo_name == "knee_R" || gettaginfo_name == "leg_L" || gettaginfo_name == "leg_R") + continue; // player model bone blacklist + if(gettaginfo_name == "") + continue; // skip empty bones + + // now choose the bone closest to impact origin + if(!closest || vlen(hitorg - gettaginfo(self, tagnum)) <= vlen(hitorg - gettaginfo(self, closest))) + { + closest = tagnum; + skeletal = TRUE; + } + } + gettaginfo(self, closest); // set gettaginfo_name + // return if we reached our damage effect limit or damages are disabled - if(self.isplayermodel) + if(skeletal) { if(autocvar_cl_damageeffect < 1 || self.total_damages >= autocvar_cl_damageeffect_limit) - return; // allow multiple damages on players + return; // allow multiple damages on skeletal models } else { if(autocvar_cl_damageeffect < 2 || self.total_damages) - return; // allow a single damage on objects + return; // allow a single damage on non-skeletal models } life = bound(autocvar_cl_damageeffect_lifetime_min, dmg * autocvar_cl_damageeffect_lifetime, autocvar_cl_damageeffect_lifetime_max); @@ -315,27 +338,6 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum) return; // objects don't bleed } - // if this is a player, the effect will show on the limb where damage was dealt - // we do this by choosing the skeletal bone closest to the impact, and attaching our entity to it - if(self.isplayermodel) - { - float closest; - FOR_EACH_TAG(self) - { - // blacklist bones positioned outside the mesh, or the effect will be floating - // TODO: Do we have to do it this way? Why do these bones exist at all? - if(gettaginfo_name == "master" || gettaginfo_name == "knee_L" || gettaginfo_name == "knee_R" || gettaginfo_name == "leg_L" || gettaginfo_name == "leg_R") - continue; - - // now choose the bone closest to impact origin - if(!closest || vlen(hitorg - gettaginfo(self, tagnum)) <= vlen(hitorg - gettaginfo(self, closest))) - closest = tagnum; - } - gettaginfo(self, closest); // set gettaginfo_name to our bone - } - else - gettaginfo(self, 0); // set gettaginfo_name to entity origin - e = spawn(); setmodel(e, "models/null.md3"); // necessary to attach and read origin setattachment(e, self, gettaginfo_name); // attach to the given bone