X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_common.qc;h=08c56121b5c6a110661fe6c6977bc90edee2d992;hb=fb61c977ddeed686ef587fd54e40f55a4bdc2322;hp=1efd6132d084e217b586015bf4910fb61446ebcc;hpb=324d1afe64b738ee2e6960f6da5174ce11d87753;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index 1efd6132d..08c56121b 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -26,10 +26,11 @@ void W_GiveWeapon (entity e, float wep, string name) .vector railgunforce; void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype) { - local vector hitloc, force, endpoint, dir; - local entity ent, endent; - local float endq3surfaceflags; + vector hitloc, force, endpoint, dir; + entity ent, endent; + float endq3surfaceflags; float totaldmg; + entity o; float length; vector beampos; @@ -52,12 +53,18 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f // trace multiple times until we hit a wall, each obstacle will be made // non-solid so we can hit the next, while doing this we spawn effects and // note down which entities were hit so we can damage them later + o = self; while (1) { if(self.antilag_debug) - WarpZone_traceline_antilag (self, start, end, FALSE, self, self.antilag_debug); + WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug); else - WarpZone_traceline_antilag (self, start, end, FALSE, self, ANTILAG_LATENCY(self)); + WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self)); + if(o && WarpZone_trace_firstzone) + { + o = world; + continue; + } // if it is world we can't hurt it so stop now if (trace_ent == world || trace_fraction == 1) @@ -110,7 +117,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f if(!pseudoprojectile) pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume - soundtoat(MSG_ONE, pseudoprojectile, beampos, CHAN_PROJECTILE, snd, VOL_BASE * f, ATTN_NONE); + soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTN_NONE); } if(pseudoprojectile) @@ -127,7 +134,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); - if(accuracy_isgooddamage(self.owner, ent)) + if(accuracy_isgooddamage(self.realowner, ent)) totaldmg += bdamage * f; // apply the damage @@ -178,8 +185,8 @@ void W_BallisticBullet_Hit (void) damage_headshotbonus = self.dmg_edge * f; railgun_start = self.origin - 2 * frametime * self.velocity; railgun_end = self.origin + 2 * frametime * self.velocity; - g = accuracy_isgooddamage(self.owner, other); - Damage(other, self, self.owner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f); + g = accuracy_isgooddamage(self.realowner, other); + Damage(other, self, self.realowner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f); damage_headshotbonus = 0; if(headshot) @@ -187,9 +194,9 @@ void W_BallisticBullet_Hit (void) if(self.dmg_edge > 0) { if(headshot) - AnnounceTo(self.owner, "headshot"); + AnnounceTo(self.realowner, "headshot"); if(yoda) - AnnounceTo(self.owner, "awesome"); + AnnounceTo(self.realowner, "awesome"); } // calculate hits for ballistic weapons @@ -198,7 +205,7 @@ void W_BallisticBullet_Hit (void) // do not exceed 100% q = min(self.dmg * q, self.dmg_total + f * self.dmg) - self.dmg_total; self.dmg_total += f * self.dmg; - accuracy_add(self.owner, self.owner.weapon, 0, q); + accuracy_add(self.realowner, self.realowner.weapon, 0, q); } } @@ -359,7 +366,7 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f entity proj; proj = spawn(); proj.classname = "bullet"; - proj.owner = self; + proj.owner = proj.realowner = self; PROJECTILE_MAKETRIGGER(proj); if(gravityfactor > 0) { @@ -431,7 +438,16 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f trace_fraction = 0; fireBallisticBullet_trace_callback_ent = self; fireBallisticBullet_trace_callback_eff = eff; - WarpZone_TraceToss_ThroughZone(self, oldself, world, fireBallisticBullet_trace_callback); + // FIXME can we somehow do this with just ONE trace? + WarpZone_TraceToss(self, self.owner); + if(self.owner && WarpZone_trace_firstzone) + { + self.owner = world; + self.velocity = v0; + self.gravity = g0; + continue; + } + WarpZone_TraceToss_ThroughZone(self, self.owner, world, fireBallisticBullet_trace_callback); self.velocity = v0; self.gravity = g0; @@ -517,15 +533,56 @@ void fireBullet (vector start, vector dir, float spread, float damage, float for if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY)) { - pointparticles(particleeffectnum("TE_KNIGHTSPIKE"),end,trace_plane_normal * 2500,1); - if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) - Damage_DamageInfo(trace_endpos, damage, 0, 0, dir * max(1, force), dtype, self); + if not (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + Damage_DamageInfo(trace_endpos, damage, 0, 0, dir * max(1, force), dtype, self); + Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force); - //void(float effectnum, vector org, vector vel, float howmany) pointparticles = #337; // same as in CSQC } trace_endpos = end; } +float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception) +{ + float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA); + float is_from_owner = (inflictor == projowner); + float is_from_exception = (exception != -1); + + //print(strcat("from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n"))); + + if(autocvar_g_projectiles_damage <= -2) + { + return FALSE; // no damage to projectiles at all, not even with the exceptions + } + else if(autocvar_g_projectiles_damage == -1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else + return FALSE; // otherwise, no other damage is allowed + } + else if(autocvar_g_projectiles_damage == 0) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if not(is_from_contents) + return FALSE; // otherwise, only allow damage from contents + } + else if(autocvar_g_projectiles_damage == 1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if not(is_from_contents || is_from_owner) + return FALSE; // otherwise, only allow self damage and damage from contents + } + else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + } + + return TRUE; // if none of these return, then allow damage anyway. +} + void W_PrepareExplosionByDamage(entity attacker, void() explode) { self.takedamage = DAMAGE_NO;