X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_common.qc;h=3816594a97fda0a1ab824941f9947ecc3e6ee72a;hb=43528747368b3c2395edc28dc9298059a5542e40;hp=320ffb7507e6173714af897ba43ab4ed917316bb;hpb=49413c98cec6a272d0c103a85c1f71aad51ee77c;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index 320ffb750..3816594a9 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -23,11 +23,14 @@ void W_GiveWeapon (entity e, float wep, string name) } .float railgundistance; +.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; + float totaldmg; + entity o; float length; vector beampos; @@ -35,8 +38,6 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f entity pseudoprojectile; float f, ffs; - float hit; - railgun_start = start; railgun_end = end; @@ -47,15 +48,23 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f // go a little bit into the wall because we need to hit this wall later end = end + dir; + totaldmg = 0; + // 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) @@ -66,6 +75,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f trace_ent.railgunhitloc = end; trace_ent.railgunhitsolidbackup = trace_ent.solid; trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start); + trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force); // stop if this is a wall if (trace_ent.solid == SOLID_BSP) @@ -121,21 +131,15 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f // get the details we need to call the damage function hitloc = ent.railgunhitloc; - //for stats so that team hit will count as a miss - if(ent.flags & FL_CLIENT) - if(ent.deadflag == DEAD_NO) - hit = 1; - - if(teams_matter) - if(ent.team == self.team) - hit = 0; - f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); + if(accuracy_isgooddamage(self.realowner, ent)) + totaldmg += bdamage * f; + // apply the damage if (ent.takedamage) - Damage (ent, self, self, bdamage * f, deathtype, hitloc, force * ffs); + Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs); // create a small explosion to throw gibs around (if applicable) //setorigin (explosion, hitloc); @@ -151,16 +155,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f } // calculate hits and fired shots for hitscan - if not(inWarmupStage) - { - self.stats_fired[self.weapon - 1] += 1; - self.stat_fired = self.weapon + 64 * floor(self.stats_fired[self.weapon - 1]); - - if(hit) { - self.stats_hit[self.weapon - 1] += 1; - self.stat_hit = self.weapon + 64 * floor(self.stats_hit[self.weapon - 1]); - } - } + accuracy_add(self, self.weapon, 0, min(bdamage, totaldmg)); trace_endpos = endpoint; trace_ent = endent; @@ -170,11 +165,13 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f .float dmg_edge; .float dmg_force; .float dmg_radius; +.float dmg_total; void W_BallisticBullet_Hit (void) { - float f; + float f, q, g; 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); @@ -185,29 +182,30 @@ void W_BallisticBullet_Hit (void) headshot = 0; yoda = 0; - damage_headshotbonus = self.dmg_edge; + damage_headshotbonus = self.dmg_edge * f; railgun_start = self.origin - 2 * frametime * self.velocity; railgun_end = self.origin + 2 * frametime * self.velocity; - - 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(self.dmg_edge != 0) + if(headshot) + f *= q; + 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 - if (other.flags & FL_CLIENT) // is the player a client - if (other.deadflag == DEAD_NO) // is the victim a corpse - if ((!(teamplay)) | (other.team != self.owner.team)) // not teamplay (ctf, kh, tdm etc) or the victim is in the same team - if not(inWarmupStage) // not in warm up stage + if(g) { - self.owner.stats_hit[self.owner.weapon - 1] += 1; - self.owner.stat_hit = self.owner.weapon + 64 * floor(self.owner.stats_hit[self.owner.weapon - 1]); + // 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.realowner, self.realowner.weapon, 0, q); } } @@ -260,7 +258,7 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) // maxdist = 0.5 * v0 * v0 / constant // dprint("max dist = ", ftos(maxdist), "\n"); - if(maxdist <= cvar("g_ballistics_mindistance")) + if(maxdist <= autocvar_g_ballistics_mindistance) return 0; traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self); @@ -270,7 +268,7 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) self.W_BallisticBullet_LeaveSolid_origin = trace_endpos; - dst = max(cvar("g_ballistics_mindistance"), vlen(trace_endpos - self.origin)); + dst = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - self.origin)); // E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass Es_m = E0_m - constant * dst; if(Es_m <= 0) @@ -363,12 +361,12 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f entity pl, oldself; float antilagging; - antilagging = (cvar("g_antilag_bullets") && (pSpeed >= cvar("g_antilag_bullets"))); + antilagging = (autocvar_g_antilag_bullets && (pSpeed >= autocvar_g_antilag_bullets)); entity proj; proj = spawn(); proj.classname = "bullet"; - proj.owner = self; + proj.owner = proj.realowner = self; PROJECTILE_MAKETRIGGER(proj); if(gravityfactor > 0) { @@ -381,7 +379,7 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed); W_SetupProjectileVelocityEx(proj, dir, v_up, pSpeed, 0, 0, spread, antilagging); proj.angles = vectoangles(proj.velocity); - proj.dmg_radius = cvar("g_ballistics_materialconstant") / bulletconstant; + proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant; // so: bulletconstant = bullet mass / area of bullet circle setorigin(proj, start); proj.flags = FL_PROJECTILE; @@ -402,6 +400,8 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if(tracereffects & EF_RED) eff = particleeffectnum("tr_rifle"); + else if(tracereffects & EF_BLUE) + eff = particleeffectnum("tr_rifle_weak"); else eff = particleeffectnum("tr_bullet"); @@ -411,7 +411,7 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f lag = 0; if(clienttype(self) != CLIENTTYPE_REAL) lag = 0; - if(cvar("g_antilag") == 0 || self.cvar_cl_noantilag) + if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag) lag = 0; // only do hitscan, but no antilag if(lag) @@ -424,13 +424,6 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f savetime = frametime; frametime = 0.05; - // update the accuracy stats - increase shots fired by 1 - if not(inWarmupStage) - { - oldself.stats_fired[oldself.weapon - 1] += 1; - oldself.stat_fired = oldself.weapon + 64 * floor(oldself.stats_fired[oldself.weapon - 1]); - } - for(;;) { // DP tracetoss is stupid and always traces in 0.05s @@ -445,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; @@ -469,6 +471,23 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f W_BallisticBullet_Hit(); } + // if we hit "weapclip", bail out + // + // rationale of this check: + // + // any shader that is solid, nodraw AND trans is meant to clip weapon + // shots and players, but has no other effect! + // + // if it is not trans, it is caulk and should not have this side effect + // + // matching shaders: + // common/weapclip (intended) + // common/noimpact (is supposed to eat projectiles, but is erased farther above) + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW) + if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID) + if not(trace_dphitcontents & DPCONTENTS_OPAQUE) + break; + density = other.ballistics_density; if(density == 0) density = 1; @@ -491,13 +510,6 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f return; } - // update the accuracy stats - if not(inWarmupStage) - { - self.stats_fired[self.weapon - 1] += 1; - self.stat_fired = self.weapon + 64 * floor(self.stats_fired[self.weapon - 1]); - } - if(tracereffects & EF_RED) CSQCProjectile(proj, TRUE, PROJECTILE_BULLET_GLOWING_TRACER, TRUE); else if(tracereffects & EF_BLUE) @@ -521,11 +533,10 @@ 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; }