X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fweapons%2Ftracing.qc;h=b37e1578e2878ed0011c4fe22d59cf42eee168ad;hp=eace8ce0c79b086d8107488b274890e198bd3960;hb=edf6dc79ea73da8ee78f426ba13675ef482d17f1;hpb=40c59ad07fa52fe99ede5da067b69ff0dd532934 diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index eace8ce0c..b37e1578e 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -10,9 +10,10 @@ #include "../antilag.qh" #include +#include #include -#include +#include #include #include @@ -27,7 +28,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect float oldsolid; vector vecs, dv; oldsolid = ent.dphitcontentsmask; - if (IS_PLAYER(ent) && PS(ent).m_weapon == WEP_RIFLE) + if (IS_PLAYER(ent) && ent.(weaponentity).m_weapon == WEP_RIFLE) ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE; else ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; @@ -53,10 +54,10 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect // track max damage if (IS_PLAYER(ent) && accuracy_canbegooddamage(ent)) - accuracy_add(ent, PS(ent).m_weapon.m_id, maxdamage, 0); + accuracy_add(ent, ent.(weaponentity).m_weapon.m_id, maxdamage, 0); if(IS_PLAYER(ent)) - W_HitPlotAnalysis(ent, v_forward, v_right, v_up); + W_HitPlotAnalysis(ent, weaponentity, v_forward, v_right, v_up); vector md = ent.(weaponentity).movedir; if(md.x > 0) @@ -196,35 +197,23 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p // Ballistics Tracing // ==================== -void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype) +void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype) { - vector hitloc, force, endpoint, dir; - entity ent, endent; - float endq3surfaceflags; - float totaldmg; - entity o; + entity pseudoprojectile = NULL; - float length; - vector beampos; - string snd; - entity pseudoprojectile; - float f, ffs; - - pseudoprojectile = NULL; - - dir = normalize(end - start); - length = vlen(end - start); - force = dir * bforce; + vector dir = normalize(end - start); + float length = vlen(end - start); + vector force = dir * bforce; // go a little bit into the wall because we need to hit this wall later end = end + dir; - totaldmg = 0; + float 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 = this; + entity o = this; while (1) { if(CS(this).antilag_debug) @@ -259,18 +248,15 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl trace_ent.solid = SOLID_NOT; } - endpoint = trace_endpos; - endent = trace_ent; - endq3surfaceflags = trace_dphitq3surfaceflags; + vector endpoint = trace_endpos; + entity endent = trace_ent; + float endq3surfaceflags = trace_dphitq3surfaceflags; // find all the entities the railgun hit and restore their solid state - ent = findfloat(NULL, railgunhit, true); - while (ent) + FOREACH_ENTITY_FLOAT(railgunhit, true, { - // restore their solid type - ent.solid = ent.railgunhitsolidbackup; - ent = findfloat(ent, railgunhit, true); - } + it.solid = it.railgunhitsolidbackup; + }); // spawn a temporary explosion entity for RadiusDamage calls //explosion = spawn(); @@ -284,17 +270,15 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl { msg_entity = it; // nearest point on the beam - beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length); + vector beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length); - f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1); + float f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1); if(f <= 0) continue; - snd = SND(NEXWHOOSH_RANDOM()); - if(!pseudoprojectile) pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume - soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTEN_NONE); + soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASE * f, ATTEN_NONE); } )); @@ -303,37 +287,33 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl } // find all the entities the railgun hit and hurt them - ent = findfloat(NULL, railgunhit, true); - while (ent) + FOREACH_ENTITY_FLOAT(railgunhit, true, { // get the details we need to call the damage function - hitloc = ent.railgunhitloc; + vector hitloc = it.railgunhitloc; - f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); - ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); + float foff = ExponentialFalloff(mindist, maxdist, halflifedist, it.railgundistance); + float ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, it.railgundistance); - if(accuracy_isgooddamage(this, ent)) - totaldmg += bdamage * f; + if(accuracy_isgooddamage(this, it)) + totaldmg += bdamage * foff; // apply the damage - if (ent.takedamage) - Damage (ent, this, this, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs); + if (it.takedamage) + Damage (it, this, this, bdamage * foff, deathtype, hitloc, it.railgunforce * ffs); // create a small explosion to throw gibs around (if applicable) //setorigin(explosion, hitloc); //RadiusDamage (explosion, this, 10, 0, 50, NULL, NULL, 300, deathtype); - ent.railgunhitloc = '0 0 0'; - ent.railgunhitsolidbackup = SOLID_NOT; - ent.railgunhit = false; - ent.railgundistance = 0; - - // advance to the next entity - ent = findfloat(ent, railgunhit, true); - } + it.railgunhitloc = '0 0 0'; + it.railgunhitsolidbackup = SOLID_NOT; + it.railgunhit = false; + it.railgundistance = 0; + }); // calculate hits and fired shots for hitscan - accuracy_add(this, PS(this).m_weapon.m_id, 0, min(bdamage, totaldmg)); + accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, min(bdamage, totaldmg)); trace_endpos = endpoint; trace_ent = endent; @@ -348,12 +328,12 @@ void fireBullet_trace_callback(vector start, vector hit, vector end) fireBullet_last_hit = NULL; } -void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects) +void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects) { vector end; dir = normalize(dir + randomvec() * spread); - end = start + dir * MAX_SHOT_DISTANCE; + end = start + dir * max_shot_distance; fireBullet_last_hit = NULL; float solid_penetration_left = 1; @@ -398,8 +378,12 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s start = trace_endpos; entity hit = trace_ent; + // traced up to max_shot_distance and didn't hit anything at all + if (trace_fraction == 1.0) + break; + // When hitting sky, stop. - if (pointcontents(start) == CONTENT_SKY) + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) break; // can't use noimpact, as we need to pass through walls @@ -431,7 +415,7 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s { fireBullet_last_hit = hit; yoda = 0; - MUTATOR_CALLHOOK(FireBullet_Hit, this, hit, start, end, damage); + MUTATOR_CALLHOOK(FireBullet_Hit, this, hit, start, end, damage, this.(weaponentity)); damage = M_ARGV(4, float); float g = accuracy_isgooddamage(this, hit); Damage(hit, this, this, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left); @@ -441,11 +425,11 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s // do not exceed 100% float added_damage = min(damage - total_damage, damage * solid_penetration_left); total_damage += damage * solid_penetration_left; - accuracy_add(this, PS(this).m_weapon.m_id, 0, added_damage); + accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, added_damage); } } - if (is_weapclip) + if (is_weapclip && !autocvar_g_ballistics_penetrate_clips) break; // go through solid! @@ -475,7 +459,9 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s break; float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start)); - solid_penetration_left -= (dist_taken / maxdist); + // fraction_used_of_what_is_left = dist_taken / maxdist + // solid_penetration_left = solid_penetration_left - solid_penetration_left * fraction_used_of_what_is_left + solid_penetration_left *= 1 - dist_taken / maxdist; solid_penetration_left = max(solid_penetration_left, 0); // Only show effect when going through a player (invisible otherwise)