Explode bouncing projectiles if hit damageable geometry

This commit is contained in:
ZZYZX 2018-11-05 17:56:49 +02:00 committed by Christoph Oelckers
parent d85e5afdfb
commit ed3355acc6
4 changed files with 76 additions and 19 deletions

View file

@ -569,24 +569,27 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
}
// check 3d floors
for (auto f : othersector->e->XFloor.ffloors)
if (othersector)
{
if (!(f->flags & FF_EXISTS)) continue;
if (!(f->flags & FF_SOLID)) continue;
for (auto f : othersector->e->XFloor.ffloors)
{
if (!(f->flags & FF_EXISTS)) continue;
if (!(f->flags & FF_SOLID)) continue;
if (!f->model || !f->model->health3d) continue;
if (!f->model || !f->model->health3d) continue;
// 3d floors over real ceiling, or under real floor, are ignored
double z_ff_top = clamp(f->top.plane->ZatPoint(to2d), z_bottom2, z_top2);
double z_ff_bottom = clamp(f->bottom.plane->ZatPoint(to2d), z_bottom2, z_top2);
if (z_ff_top < z_ff_bottom)
continue; // also ignore eldritch geometry
// 3d floors over real ceiling, or under real floor, are ignored
double z_ff_top = clamp(f->top.plane->ZatPoint(to2d), z_bottom2, z_top2);
double z_ff_bottom = clamp(f->bottom.plane->ZatPoint(to2d), z_bottom2, z_top2);
if (z_ff_top < z_ff_bottom)
continue; // also ignore eldritch geometry
DVector3 to3d_ffloor(to2d.X, to2d.Y, clamp(bombspot->Z(), z_ff_bottom, z_ff_top));
int grp = f->model->health3dgroup;
if (grp <= 0)
grp = 0x20000000 | (f->model->sectornum & 0x0FFFFFFF);
PGRA_InsertIfCloser(damageGroupPos, grp, to3d_ffloor, bombspot->Pos(), srcsector, f->model, nullptr, SECPART_3D);
DVector3 to3d_ffloor(to2d.X, to2d.Y, clamp(bombspot->Z(), z_ff_bottom, z_ff_top));
int grp = f->model->health3dgroup;
if (grp <= 0)
grp = 0x20000000 | (f->model->sectornum & 0x0FFFFFFF);
PGRA_InsertIfCloser(damageGroupPos, grp, to3d_ffloor, bombspot->Pos(), srcsector, f->model, nullptr, SECPART_3D);
}
}
}
@ -646,13 +649,17 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
// Called if P_ExplodeMissile was called against a wall.
//==========================================================================
void P_ProjectileHitLinedef(AActor* mo, line_t* line)
bool P_ProjectileHitLinedef(AActor* mo, line_t* line)
{
bool washit = false;
// detect 3d floor hit
if (mo->Blocking3DFloor)
{
if (mo->Blocking3DFloor->health3d > 0)
{
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos());
washit = true;
}
}
int wside = P_PointOnLineSide(mo->Pos(), line);
@ -676,33 +683,59 @@ void P_ProjectileHitLinedef(AActor* mo, line_t* line)
if (zbottom < (otherfloorz + EQUAL_EPSILON) && othersector->healthfloor > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Floor))
{
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos());
washit = true;
}
if (ztop > (otherceilingz - EQUAL_EPSILON) && othersector->healthceiling > 0 && P_CheckLinedefVulnerable(line, wside, SECPART_Ceiling))
{
P_DamageSector(othersector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos());
washit = true;
}
}
if (line->health > 0 && P_CheckLinedefVulnerable(line, wside))
{
P_DamageLinedef(line, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, wside, mo->Pos());
washit = true;
}
return washit;
}
void P_ProjectileHitPlane(AActor* mo, int part)
// part = -1 means "detect from blocking"
bool P_ProjectileHitPlane(AActor* mo, int part)
{
if (part < 0)
{
if (mo->BlockingCeiling)
part = SECPART_Ceiling;
else if (mo->BlockingFloor)
part = SECPART_Floor;
}
// detect 3d floor hit
if (mo->Blocking3DFloor)
{
if (mo->Blocking3DFloor->health3d > 0)
{
P_DamageSector(mo->Blocking3DFloor, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_3D, mo->Pos());
return;
return true;
}
return false;
}
if (part == SECPART_Floor && mo->Sector->healthfloor > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Floor))
{
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Floor, mo->Pos());
return true;
}
else if (part == SECPART_Ceiling && mo->Sector->healthceiling > 0 && P_CheckSectorVulnerable(mo->Sector, SECPART_Ceiling))
{
P_DamageSector(mo->Sector, mo, mo->GetMissileDamage((mo->flags4 & MF4_STRIFEDAMAGE) ? 3 : 7, 1), mo->DamageType, SECPART_Ceiling, mo->Pos());
return true;
}
return false;
}
//==========================================================================

View file

@ -33,8 +33,8 @@ void P_DamageLinedef(line_t* line, AActor* source, int damage, FName damagetype,
void P_GeometryLineAttack(FTraceResults& trace, AActor* thing, int damage, FName damageType);
void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance);
void P_ProjectileHitLinedef(AActor* projectile, line_t* line);
void P_ProjectileHitPlane(AActor* projectile, int part);
bool P_ProjectileHitLinedef(AActor* projectile, line_t* line);
bool P_ProjectileHitPlane(AActor* projectile, int part);
bool P_CheckLinedefVulnerable(line_t* line, int side, int part = -1);
bool P_CheckSectorVulnerable(sector_t* sector, int part);

View file

@ -3552,6 +3552,18 @@ bool FSlide::BounceWall(AActor *mo)
return true;
}
// [ZZ] if bouncing missile hits a damageable linedef, it dies
if (P_ProjectileHitLinedef(mo, line) && mo->bouncecount > 0)
{
mo->Vel.Zero();
mo->Speed = 0;
mo->bouncecount = 0;
if (mo->flags & MF_MISSILE)
P_ExplodeMissile(mo, line, nullptr);
else mo->CallDie(nullptr, nullptr);
return true;
}
// The amount of bounces is limited
if (mo->bouncecount>0 && --mo->bouncecount == 0)
{

View file

@ -2127,6 +2127,18 @@ void AActor::PlayBounceSound(bool onfloor)
bool AActor::FloorBounceMissile (secplane_t &plane)
{
// [ZZ] if bouncing missile hits a damageable sector(plane), it dies
if (P_ProjectileHitPlane(this, -1) && bouncecount > 0)
{
Vel.Zero();
Speed = 0;
bouncecount = 0;
if (flags & MF_MISSILE)
P_ExplodeMissile(this, nullptr, nullptr);
else CallDie(nullptr, nullptr);
return true;
}
if (Z() <= floorz && P_HitFloor (this))
{
// Landed in some sort of liquid