X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_common.qc;h=f1e33ec968aec26b989f22dd29c7c98786ac0242;hb=c7412d57c97da7e1d8a4e12c08271dbdb492ea94;hp=1efd6132d084e217b586015bf4910fb61446ebcc;hpb=efcb7951f02072e2abf9c02677ba01099966e271;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index 1efd6132d..d2f172b4d 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -6,7 +6,7 @@ void W_GiveWeapon (entity e, float wep, string name) if (!wep) return; - e.weapons = e.weapons | W_WeaponBit(wep); + WEPSET_OR_EW(e, wep); oldself = self; self = e; @@ -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; @@ -37,6 +38,8 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f entity pseudoprojectile; float f, ffs; + pseudoprojectile = world; + railgun_start = start; railgun_end = end; @@ -52,12 +55,21 @@ 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(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX) + Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, self); // if it is world we can't hurt it so stop now if (trace_ent == world || trace_fraction == 1) @@ -110,7 +122,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 +139,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 @@ -166,8 +178,8 @@ void W_BallisticBullet_Hit (void) f = pow(bound(0, vlen(self.velocity) / vlen(self.oldvelocity), 1), 2); // energy multiplier q = 1 + self.dmg_edge / self.dmg; - if(other.solid == SOLID_BSP) - Damage_DamageInfo(self.origin, self.dmg * f, 0, 0, max(1, self.dmg_force) * normalize(self.velocity) * f, self.projectiledeathtype, self); + if(other.solid == SOLID_BSP || other.solid == SOLID_SLIDEBOX) + Damage_DamageInfo(self.origin, self.dmg * f, 0, 0, max(1, self.dmg_force) * normalize(self.velocity) * f, self.projectiledeathtype, other.species, self); if(other && other != self.enemy) { @@ -178,8 +190,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 +199,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 +210,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); } } @@ -225,16 +237,17 @@ void W_BallisticBullet_LeaveSolid_think() { float f; f = pow(bound(0, vlen(self.velocity) / vlen(self.oldvelocity), 1), 2); // energy multiplier - Damage_DamageInfo(self.origin, 0, 0, 0, max(1, self.dmg_force) * normalize(self.velocity) * -f, self.projectiledeathtype, self); + Damage_DamageInfo(self.origin, 0, 0, 0, max(1, self.dmg_force) * normalize(self.velocity) * -f, self.projectiledeathtype, 0, self); } UpdateCSQCProjectile(self); } -float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) +float W_BallisticBullet_LeaveSolid(float eff) { // move the entity along its velocity until it's out of solid, then let it resume - + vector vel = self.velocity; + float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1); float dt, dst, velfactor, v0, vs; float maxdist; float E0_m, Es_m; @@ -254,8 +267,7 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) if(maxdist <= autocvar_g_ballistics_mindistance) return 0; - traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self); - + traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self, TRUE); if(trace_fraction == 1) // 1: we never got out of solid return 0; @@ -288,6 +300,13 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) self.flags |= FL_ONGROUND; // prevent moving self.W_BallisticBullet_LeaveSolid_velocity = vel; + if(eff >= 0) + if(vlen(trace_endpos - self.origin) > 4) + { + endzcurveparticles(); + trailparticles(self, eff, self.origin, trace_endpos); + } + return 1; } @@ -321,12 +340,8 @@ void W_BallisticBullet_Touch (void) return; } - density = other.ballistics_density; - if(density == 0) - density = 1; - // go through solid! - if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density)) + if(!W_BallisticBullet_LeaveSolid(-1)) { remove(self); return; @@ -346,6 +361,8 @@ void fireBallisticBullet_trace_callback(vector start, vector hit, vector end) { if(vlen(trace_endpos - fireBallisticBullet_trace_callback_ent.origin) > 16) zcurveparticles_from_tracetoss(fireBallisticBullet_trace_callback_eff, fireBallisticBullet_trace_callback_ent.origin, trace_endpos, fireBallisticBullet_trace_callback_ent.velocity); + WarpZone_trace_forent = world; + self.owner = world; } void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant) @@ -359,7 +376,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) { @@ -409,7 +426,8 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if(lag) FOR_EACH_PLAYER(pl) - antilag_takeback(pl, time - lag); + if(pl != self) + antilag_takeback(pl, time - lag); oldself = self; self = proj; @@ -431,7 +449,7 @@ 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); + WarpZone_TraceToss_ThroughZone(self, self.owner, world, fireBallisticBullet_trace_callback); self.velocity = v0; self.gravity = g0; @@ -472,22 +490,21 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if not(trace_dphitcontents & DPCONTENTS_OPAQUE) break; - density = other.ballistics_density; - if(density == 0) - density = 1; - // go through solid! - if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density)) + if(!W_BallisticBullet_LeaveSolid((other && (other.solid != SOLID_BSP)) ? eff : -1)) break; W_BallisticBullet_LeaveSolid_think(); + + self.projectiledeathtype |= HITTYPE_BOUNCE; } frametime = savetime; self = oldself; if(lag) FOR_EACH_PLAYER(pl) - antilag_restore(pl); + if(pl != self) + antilag_restore(pl); remove(proj); @@ -515,24 +532,69 @@ void fireBullet (vector start, vector dir, float spread, float damage, float for end = trace_endpos; - if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY)) + if (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, trace_ent.species, 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); + + //dprint(strcat("W_CheckProjectileDamage: 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; self.event_damage = SUB_Null; - self.owner = attacker; - self.realowner = attacker; - + + if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner) + { + self.owner = attacker; + self.realowner = attacker; + } + // do not explode NOW but in the NEXT FRAME! // because recursive calls to RadiusDamage are not allowed self.nextthink = time;