return true;
}
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
+void Damage_DamageInfo(vector org, bool is_solid_hit, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
{
// TODO maybe call this from non-edgedamage too?
// TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info?
e.dmg_force = vlen(force);
e.velocity = force;
e.species = bloodtype;
+ if(is_solid_hit)
+ e.species |= 0x80;
Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity);
}
edge = ReadByte();
force = ReadVector();
species = ReadByte();
+ bool is_solid_hit = (species & 0x80);
+ species = (species & 0x7F);
return = true;
w_random = prandom();
vector force_dir = normalize(force);
- traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
- if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN))
- w_backoff = trace_plane_normal;
- else
+ if (is_solid_hit) // traceline not needed
w_backoff = -force_dir;
+ else
+ {
+ traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
+ if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN))
+ w_backoff = trace_plane_normal;
+ else
+ w_backoff = -force_dir;
+ }
setorigin(this, w_org + w_backoff * 2); // for sound() calls
if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
- Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
+ Damage_DamageInfo(this.origin, false, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
}
delete(this);
{
RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
- Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
+ Damage_DamageInfo(this.origin, false, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
}
if(this.takedamage)
entity bomblet;
float i;
- Damage_DamageInfo(this.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT.m_id, 0, this);
+ Damage_DamageInfo(this.origin, false, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT.m_id, 0, this);
for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
{
{
//if(other==this.realowner)
// return;
- Damage_DamageInfo(this.origin, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, 0, this);
+ Damage_DamageInfo(this.origin, false, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, 0, this);
delete(this);
}
te_knightspike(org2);
this.event_damage = func_null;
- Damage_DamageInfo(this.origin, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY, toucher.species, this);
+ Damage_DamageInfo(this.origin, false, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY, toucher.species, this);
if(toucher.takedamage == DAMAGE_AIM && !IS_DEAD(toucher))
{
W_Shockwave_Send(actor);
Damage_DamageInfo(
attack_hitpos,
+ trace_ent && trace_ent.solid == SOLID_BSP,
WEP_CVAR(shockwave, blast_splash_damage),
WEP_CVAR(shockwave, blast_splash_edgedamage),
WEP_CVAR(shockwave, blast_splash_radius),
else
force = normalize(force);
if(forceintensity >= 0)
- Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, false, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
else
- Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, false, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
}
stat_damagedone = 0;
bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
+void Damage_DamageInfo(vector org, bool is_solid_hit, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
float checkrules_firstblood;
}
if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX)
- Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, this);
+ Damage_DamageInfo(trace_endpos, (trace_ent.solid == SOLID_BSP), bdamage, 0, 0, force, deathtype, trace_ent.species, this);
// if it is NULL we can't hurt it so stop now
if (trace_ent == NULL || trace_fraction == 1)
is_weapclip = true;
if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
- Damage_DamageInfo(start, damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this);
+ Damage_DamageInfo(start, (hit && hit.solid == SOLID_BSP), damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this);
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).
{
start = trace_endpos;
if(hit.solid == SOLID_BSP)
- Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this);
+ Damage_DamageInfo(start, true, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this);
}
if(headshot)