trace_dphitq3surfaceflags = endq3surfaceflags;
}
-float fireBallisticBullet_trace_callback_eff;
-void fireBallisticBullet_trace_callback(vector start, vector hit, vector end)
+float fireBullet_trace_callback_eff;
+entity fireBullet_last_hit;
+void fireBullet_trace_callback(vector start, vector hit, vector end)
{
if(vlen(hit - start) > 16)
- trailparticles(world, fireBallisticBullet_trace_callback_eff, start, hit);
+ trailparticles(world, fireBullet_trace_callback_eff, start, hit);
WarpZone_trace_forent = world;
+ fireBullet_last_hit = world;
}
void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects)
end = start + dir * MAX_SHOT_DISTANCE;
entity pl;
- entity last_hit = world;
+ fireBullet_last_hit = world;
float solid_penetration_left = 1;
float total_damage = 0;
if(tracereffects & EF_RED)
- fireBallisticBullet_trace_callback_eff = particleeffectnum("tr_rifle");
+ fireBullet_trace_callback_eff = particleeffectnum("tr_rifle");
else if(tracereffects & EF_BLUE)
- fireBallisticBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak");
+ fireBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak");
else
- fireBallisticBullet_trace_callback_eff = particleeffectnum("tr_bullet");
+ fireBullet_trace_callback_eff = particleeffectnum("tr_bullet");
float lag = ANTILAG_LATENCY(self);
if(lag < 0.001)
if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag)
lag = 0; // only do hitscan, but no antilag
if(lag)
+ {
FOR_EACH_PLAYER(pl)
if(pl != self)
antilag_takeback(pl, time - lag);
+ FOR_EACH_MONSTER(pl)
+ antilag_takeback(pl, time - lag);
+ }
+
+ WarpZone_trace_forent = self;
for (;;)
{
// TODO also show effect while tracing
- WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, self, world, fireBallisticBullet_trace_callback);
+ WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, WarpZone_trace_forent, world, fireBullet_trace_callback);
dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir);
end = WarpZone_TransformOrigin(WarpZone_trace_transform, end);
start = trace_endpos;
if (!(trace_dphitcontents & DPCONTENTS_OPAQUE))
is_weapclip = 1;
- // Avoid self-damage // FIXME can this happen?
- if (hit != self)
- {
- if(hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
- Damage_DamageInfo(self.origin, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self);
+ if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
+ Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self);
- if(hit && hit != last_hit)
+ if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit) // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug).
+ {
+ fireBullet_last_hit = hit;
+ yoda = 0;
+ float g = accuracy_isgooddamage(self, hit);
+ Damage(hit, self, self, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left);
+ // calculate hits for ballistic weapons
+ if(g)
{
- yoda = 0;
- float g = accuracy_isgooddamage(self, hit);
- // FIXME preserve trace stuff
- Damage(hit, self, self, damage * solid_penetration_left, dtype, self.origin, force * dir * solid_penetration_left);
- // calculate hits for ballistic weapons
- if(g)
- {
- // do not exceed 100%
- float added_damage = min(damage - total_damage, damage * solid_penetration_left);
- total_damage += damage * solid_penetration_left;
- accuracy_add(self, self.weapon, 0, added_damage);
- }
+ // do not exceed 100%
+ float added_damage = min(damage - total_damage, damage * solid_penetration_left);
+ total_damage += damage * solid_penetration_left;
+ accuracy_add(self, self.weapon, 0, added_damage);
}
-
- last_hit = hit; // don't hit the same player twice with the same bullet
}
if (is_weapclip)
// go through solid!
// outside the world? forget it
- if(end_x > world.maxs_x || end_y > world.maxs_y || end_z > world.maxs_z || end_x < world.mins_x || end_y < world.mins_y || end_z < world.mins_z)
+ if(start_x > world.maxs_x || start_y > world.maxs_y || start_z > world.maxs_z || start_x < world.mins_x || start_y < world.mins_y || start_z < world.mins_z)
break;
float maxdist;
break;
// move the entity along its velocity until it's out of solid, then let it resume
- traceline_inverted (start, self.origin + dir * maxdist, MOVE_NORMAL, self, TRUE);
+ // The previously hit entity is ignored here!
+ traceline_inverted (start, start + dir * maxdist, MOVE_NORMAL, WarpZone_trace_forent, TRUE, hit);
if(trace_fraction == 1) // 1: we never got out of solid
break;
// Only show effect when going through a player (invisible otherwise)
if (hit && (hit.solid != SOLID_BSP))
if(vlen(trace_endpos - start) > 4)
- trailparticles(self, fireBallisticBullet_trace_callback_eff, start, trace_endpos);
+ trailparticles(self, fireBullet_trace_callback_eff, start, trace_endpos);
start = trace_endpos;
}
if(lag)
+ {
FOR_EACH_PLAYER(pl)
if(pl != self)
antilag_restore(pl);
-}
-
-// DEPRECATED kill this adaptor once we can
-void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float force, float dtype, float tracereffects, float bulletconstant)
-{
- fireBullet(start, dir, spread, (0.5 * pSpeed * pSpeed * bulletconstant) / autocvar_g_ballistics_materialconstant, damage, force, dtype, tracereffects);
-}
-void endFireBallisticBullet()
-{
+ FOR_EACH_MONSTER(pl)
+ antilag_restore(pl);
+ }
}
float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)