X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fclient%2Fdamage.qc;h=fe2e8b67b0488a28d7f759bad87c435715ff7216;hb=fe8fa62ddd3321825b7628645e3d4b809f07929d;hp=783f66759b50b3881d533b083e732db2866d7d55;hpb=624acc7330757b4a993e263763eced27f475c4f7;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 783f66759..fe2e8b67b 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -69,9 +69,147 @@ void Ent_DamageInfo(float isNew) } self = oldself; + + if(DEATH_ISVEHICLE(w_deathtype)) + { + traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world); + if(trace_plane_normal != '0 0 0') + w_backoff = trace_plane_normal; + else + w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16)); + + setorigin(self, w_org + w_backoff * 2); // for sound() calls + + switch(w_deathtype) + { + case DEATH_VHCRUSH: + break; + + case DEATH_SBMINIGUN: + string _snd; + _snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw"); + sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("spiderbot_minigun_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_SBROCKET: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("spiderbot_rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_SBBLOWUP: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_WAKIGUN: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("wakizashi_gun_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_WAKIROCKET: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("wakizashi_rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_WAKIBLOWUP: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_RAPTOR_CANNON: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_cannon_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_BOMB_SPLIT: + float i; + vector ang, vel; + for(i = 1; i < 4; ++i) + { + vel = normalize(w_org - (w_org + normalize(force) * 16)) + randomvec() * 128; + ang = vectoangles(vel); + RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i)); + } + + + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_bomb_spread"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_BOMB: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("raptor_bomb_impact"), self.origin, w_backoff * 1000, 1); + break; + case DEATH_RAPTOR_DEATH: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1); + break; + } + } + + + if(DEATH_ISTURRET(w_deathtype)) + { + traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world); + if(trace_plane_normal != '0 0 0') + w_backoff = trace_plane_normal; + else + w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16)); + + setorigin(self, w_org + w_backoff * 2); // for sound() calls + + switch(w_deathtype) + { + case DEATH_TURRET_EWHEEL: + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_FLAC: + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); + if (w_random<0.15) + sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM); + else if (w_random<0.7) + sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM); + else + sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM); + + break; + + case DEATH_TURRET_MLRS: + case DEATH_TURRET_HK: + case DEATH_TURRET_WALKER_ROCKET: + case DEATH_TURRET_HELLION: + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("rocket_explode"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_MACHINEGUN: + case DEATH_TURRET_WALKER_GUN: + string _snd; + _snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw"); + sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("machinegun_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_PLASMA: + sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1); + break; + + case DEATH_TURRET_WALKER_MEELE: + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_MIN); + pointparticles(particleeffectnum("TE_SPARK"), self.origin, w_backoff * 1000, 1); + break; - // TODO spawn particle effects and sounds based on w_deathtype + case DEATH_TURRET_PHASER: + break; + + case DEATH_TURRET_TESLA: + te_smallflash(self.origin); + break; + + } + } + // TODO spawn particle effects and sounds based on w_deathtype if(!DEATH_ISSPECIAL(w_deathtype)) { float hitwep; @@ -96,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; +}