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 dt, dst, velfactor, v0, vs;
float maxdist;
float E0_m, Es_m;
+ float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1);
// outside the world? forget it
if(self.origin_x > world.maxs_x || self.origin_y > world.maxs_y || self.origin_z > world.maxs_z || self.origin_x < world.mins_x || self.origin_y < world.mins_y || self.origin_z < world.mins_z)
return 0;
+ // special case for zero density and zero bullet constant:
+
+ if(self.dmg_radius == 0)
+ {
+ if(other.ballistics_density < 0)
+ constant = 0; // infinite travel distance
+ else
+ return 0; // no penetration
+ }
+ else
+ {
+ if(other.ballistics_density < 0)
+ constant = 0; // infinite travel distance
+ else if(other.ballistics_density == 0)
+ constant = self.dmg_radius;
+ else
+ constant = self.dmg_radius * other.ballistics_density;
+ }
+
// E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
v0 = vlen(vel);
E0_m = 0.5 * v0 * v0;
- maxdist = E0_m / constant;
- // maxdist = 0.5 * v0 * v0 / constant
- // dprint("max dist = ", ftos(maxdist), "\n");
- if(maxdist <= autocvar_g_ballistics_mindistance)
- return 0;
+ if(constant)
+ {
+ maxdist = E0_m / constant;
+ // maxdist = 0.5 * v0 * v0 / constant
+ // dprint("max dist = ", ftos(maxdist), "\n");
- traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self);
+ if(maxdist <= autocvar_g_ballistics_mindistance)
+ return 0;
+ }
+ else
+ {
+ maxdist = vlen(other.maxs - other.mins) + 1; // any distance, as long as we leave the entity
+ }
+ 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;
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;
}
void W_BallisticBullet_Touch (void)
{
- float density;
+ //float density;
if(self.think == W_BallisticBullet_LeaveSolid_think) // skip this!
return;
PROJECTILE_TOUCH;
W_BallisticBullet_Hit ();
+ if(self.dmg_radius < 0) // these NEVER penetrate solid
+ {
+ remove(self);
+ return;
+ }
+
// if we hit "weapclip", bail out
//
// rationale of this check:
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;
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)
{
- float lag, dt, savetime, density;
+ float lag, dt, savetime; //, density;
entity pl, oldself;
float antilagging;
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 = autocvar_g_ballistics_materialconstant / bulletconstant;
+ if(bulletconstant > 0)
+ proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+ else if(bulletconstant == 0)
+ proj.dmg_radius = 0;
+ else
+ proj.dmg_radius = -1;
// so: bulletconstant = bullet mass / area of bullet circle
setorigin(proj, start);
proj.flags = FL_PROJECTILE;
W_BallisticBullet_Hit();
}
+ if(proj.dmg_radius < 0) // these NEVER penetrate solid
+ break;
+
// if we hit "weapclip", bail out
//
// rationale of this check:
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;
self.takedamage = DAMAGE_NO;
self.event_damage = SUB_Null;
- if not(g_ca)
+ if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner)
{
self.owner = attacker;
self.realowner = attacker;