From ed3355acc641f35e99884e3250a758c32951cea2 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Mon, 5 Nov 2018 17:56:49 +0200 Subject: [PATCH] Explode bouncing projectiles if hit damageable geometry --- src/p_destructible.cpp | 67 +++++++++++++++++++++++++++++++----------- src/p_destructible.h | 4 +-- src/p_map.cpp | 12 ++++++++ src/p_mobj.cpp | 12 ++++++++ 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/p_destructible.cpp b/src/p_destructible.cpp index 3d213b689..d881f6728 100755 --- a/src/p_destructible.cpp +++ b/src/p_destructible.cpp @@ -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; } //========================================================================== diff --git a/src/p_destructible.h b/src/p_destructible.h index f1ac1a0de..1af088679 100755 --- a/src/p_destructible.h +++ b/src/p_destructible.h @@ -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); diff --git a/src/p_map.cpp b/src/p_map.cpp index 838612a37..e092ef80f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1788161ba..8f2cf64ff 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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