Explode bouncing projectiles if hit damageable geometry

This commit is contained in:
ZZYZX 2018-11-05 17:56:49 +02:00 committed by drfrag666
parent b581648d6f
commit 89bdd1adf0
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 // check 3d floors
for (auto f : othersector->e->XFloor.ffloors) if (othersector)
{ {
if (!(f->flags & FF_EXISTS)) continue; for (auto f : othersector->e->XFloor.ffloors)
if (!(f->flags & FF_SOLID)) continue; {
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 // 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_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); double z_ff_bottom = clamp(f->bottom.plane->ZatPoint(to2d), z_bottom2, z_top2);
if (z_ff_top < z_ff_bottom) if (z_ff_top < z_ff_bottom)
continue; // also ignore eldritch geometry continue; // also ignore eldritch geometry
DVector3 to3d_ffloor(to2d.X, to2d.Y, clamp(bombspot->Z(), z_ff_bottom, z_ff_top)); DVector3 to3d_ffloor(to2d.X, to2d.Y, clamp(bombspot->Z(), z_ff_bottom, z_ff_top));
int grp = f->model->health3dgroup; int grp = f->model->health3dgroup;
if (grp <= 0) if (grp <= 0)
grp = 0x20000000 | (f->model->sectornum & 0x0FFFFFFF); grp = 0x20000000 | (f->model->sectornum & 0x0FFFFFFF);
PGRA_InsertIfCloser(damageGroupPos, grp, to3d_ffloor, bombspot->Pos(), srcsector, f->model, nullptr, SECPART_3D); 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. // 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 // detect 3d floor hit
if (mo->Blocking3DFloor) if (mo->Blocking3DFloor)
{ {
if (mo->Blocking3DFloor->health3d > 0) 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()); 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); 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)) 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()); 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)) 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()); 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)) 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()); 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 // detect 3d floor hit
if (mo->Blocking3DFloor) if (mo->Blocking3DFloor)
{ {
if (mo->Blocking3DFloor->health3d > 0) 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()); 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)) 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()); 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)) 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()); 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_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_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage, int bombdistance, FName damagetype, int fulldamagedistance);
void P_ProjectileHitLinedef(AActor* projectile, line_t* line); bool P_ProjectileHitLinedef(AActor* projectile, line_t* line);
void P_ProjectileHitPlane(AActor* projectile, int part); bool P_ProjectileHitPlane(AActor* projectile, int part);
bool P_CheckLinedefVulnerable(line_t* line, int side, int part = -1); bool P_CheckLinedefVulnerable(line_t* line, int side, int part = -1);
bool P_CheckSectorVulnerable(sector_t* sector, int part); bool P_CheckSectorVulnerable(sector_t* sector, int part);

View file

@ -3561,6 +3561,18 @@ bool FSlide::BounceWall(AActor *mo)
return true; 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 // The amount of bounces is limited
if (mo->bouncecount>0 && --mo->bouncecount == 0) if (mo->bouncecount>0 && --mo->bouncecount == 0)
{ {

View file

@ -2141,6 +2141,18 @@ void AActor::PlayBounceSound(bool onfloor)
bool AActor::FloorBounceMissile (secplane_t &plane) 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)) if (Z() <= floorz && P_HitFloor (this))
{ {
// Landed in some sort of liquid // Landed in some sort of liquid