diff --git a/polymer/eduke32/source/actors.c b/polymer/eduke32/source/actors.c index e805a69c3..e1ac6ec2b 100644 --- a/polymer/eduke32/source/actors.c +++ b/polymer/eduke32/source/actors.c @@ -143,15 +143,19 @@ void A_RadiusDamage(int32_t i, int32_t r, int32_t hp1, int32_t hp2, int32_t hp3, const int32_t dasect = sectorlist[sectcnt++]; const int32_t startwall = sector[dasect].wallptr; const int32_t endwall = startwall+sector[dasect].wallnum; + int32_t w; + const int32_t w2 = wall[startwall].point2; - if (((sector[dasect].ceilingz-s->z)>>8) < r) + // Check if "hit" 1st or 3rd wall-point. This mainly makes sense + // for rectangular "ceiling light"-style sectors. + if (G_WallSpriteDist(&wall[startwall], s) < r || + G_WallSpriteDist(&wall[wall[w2].point2], s) < r) { - const int32_t w2 = wall[startwall].point2; - - if (G_WallSpriteDist(&wall[startwall], s) < r || - G_WallSpriteDist(&wall[wall[w2].point2], s) < r) - Sect_DamageCeiling(dasect); + if (((sector[dasect].ceilingz-s->z)>>8) < r) + Sect_DamageCeilingOrFloor(0, dasect); + if (((s->z-sector[dasect].floorz)>>8) < r) + Sect_DamageCeilingOrFloor(1, dasect); } for (w=startwall,wal=&wall[startwall]; wsectnum].ceilingstat&1) && sector[s->sectnum].ceilingpal == 0) return 1; - Sect_DamageCeiling(s->sectnum); + Sect_DamageCeilingOrFloor(0, s->sectnum); + } + else if (s->zvel > 0) + { + if ((sector[s->sectnum].floorstat&1) && sector[s->sectnum].floorpal == 0) + { + // Keep original Duke3D behavior: pass projectiles through + // parallaxed ceilings, but NOT through such floors. + return 0; + } + + Sect_DamageCeilingOrFloor(1, s->sectnum); } return 0; diff --git a/polymer/eduke32/source/player.c b/polymer/eduke32/source/player.c index e1bbc2b44..f859f51a5 100644 --- a/polymer/eduke32/source/player.c +++ b/polymer/eduke32/source/player.c @@ -611,7 +611,20 @@ static int32_t Proj_MaybeDamageCF2(int32_t zvel, int32_t hitsect) if (sector[hitsect].ceilingstat&1) return 1; - Sect_DamageCeiling(hitsect); + Sect_DamageCeilingOrFloor(0, hitsect); + } + else if (zvel > 0) + { + Bassert(hitsect >= 0); + + if (sector[hitsect].floorstat&1) + { + // Keep original Duke3D behavior: pass projectiles through + // parallaxed ceilings, but NOT through such floors. + return 0; + } + + Sect_DamageCeilingOrFloor(1, hitsect); } return 0; diff --git a/polymer/eduke32/source/sector.c b/polymer/eduke32/source/sector.c index ae35c4956..68d67a424 100644 --- a/polymer/eduke32/source/sector.c +++ b/polymer/eduke32/source/sector.c @@ -1874,10 +1874,13 @@ void A_DamageWall(int32_t spr,int32_t dawallnum,const vec3_t *pos,int32_t atwith } } -int32_t Sect_DamageCeiling(int32_t sn) +int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn) { int32_t i, j; + if (floorp) + return 0; + switch (DYNAMICTILEMAP(sector[sn].ceilingpicnum)) { case WALLLIGHT1__STATIC: diff --git a/polymer/eduke32/source/sector.h b/polymer/eduke32/source/sector.h index 3683afa64..07b63d2ed 100644 --- a/polymer/eduke32/source/sector.h +++ b/polymer/eduke32/source/sector.h @@ -128,7 +128,7 @@ int32_t ldist(const spritetype *s1, const spritetype *s2); int32_t dist(const spritetype *s1, const spritetype *s2); int32_t P_ActivateSwitch(int32_t snum,int32_t w,int32_t switchissprite); void P_CheckSectors(int32_t snum); -int32_t Sect_DamageCeiling(int32_t sn); +int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn); int32_t SetAnimation(int32_t animsect,int32_t *animptr,int32_t thegoal,int32_t thevel); #include "sector_inline.h"