#include "../antilag.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/util.qh>
-#include <common/weapons/all.qh>
+#include <common/weapons/_all.qh>
#include <common/state.qh>
#include <lib/warpzone/common.qh>
// make sure you call makevectors first (FIXME?)
void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vector s_forward, vector mi, vector ma, float antilag, float recoil, Sound snd, float chan, float maxdamage, float range)
{
- TC(Sound, snd);
+ TC(Sound, snd);
float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
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;
// 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)
// 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)
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();
{
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);
}
));
}
// 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;
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;
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
{
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);
// 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!
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)
if (hit && (hit.solid != SOLID_BSP))