diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp index d45a9f2a8..c019fcbf6 100644 --- a/src/g_shared/a_fastprojectile.cpp +++ b/src/g_shared/a_fastprojectile.cpp @@ -28,6 +28,7 @@ void AFastProjectile::Tick () PrevX = x; PrevY = y; PrevZ = z; + fixed_t oldz = z; PrevAngle = angle; if (!(flags5 & MF5_NOTIMEFREEZE)) @@ -99,6 +100,8 @@ void AFastProjectile::Tick () } } z += zfrac; + UpdateWaterLevel (oldz); + oldz = z; if (z <= floorz) { // Hit the floor diff --git a/src/p_map.cpp b/src/p_map.cpp index 9e927698b..b9e6dc125 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -64,7 +64,7 @@ CVAR (Int, sv_smartaim, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) static void CheckForPushSpecial (line_t *line, int side, AActor *mobj); static void SpawnShootDecal (AActor *t1, const FTraceResults &trace); static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff, - fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz); + fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor = false); static FRandom pr_tracebleed ("TraceBleed"); static FRandom pr_checkthing ("CheckThing"); @@ -3555,7 +3555,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, *victim = trace.Actor; } } - if (trace.CrossedWater) + if (trace.Crossed3DWater || trace.CrossedWater) { if (puff == NULL) @@ -3563,7 +3563,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, puff = P_SpawnPuff (t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING|PF_TEMPORARY); killPuff = true; } - SpawnDeepSplash (t1, trace, puff, vx, vy, vz, shootz); + SpawnDeepSplash (t1, trace, puff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); } } if (killPuff && puff != NULL) @@ -3925,11 +3925,11 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color P_HitWater (thepuff, trace.Sector); } } - if (trace.CrossedWater) + if (trace.Crossed3DWater || trace.CrossedWater) { if (thepuff != NULL) { - SpawnDeepSplash (source, trace, thepuff, vx, vy, vz, shootz); + SpawnDeepSplash (source, trace, thepuff, vx, vy, vz, shootz, trace.Crossed3DWater != NULL); } } thepuff->Destroy (); @@ -5469,13 +5469,16 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace) //========================================================================== static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff, - fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz) + fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz, bool ffloor) { - if (!trace.CrossedWater->heightsec) return; - - fixed_t num, den, hitdist; - const secplane_t *plane = &trace.CrossedWater->heightsec->floorplane; + const secplane_t *plane; + if (ffloor && trace.Crossed3DWater) + plane = trace.Crossed3DWater->top.plane; + else if (trace.CrossedWater && trace.CrossedWater->heightsec) + plane = &trace.CrossedWater->heightsec->floorplane; + else return; + fixed_t num, den, hitdist; den = TMulScale16 (plane->a, vx, plane->b, vy, plane->c, vz); if (den != 0) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 73a4cd49b..7eb2d39b9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4737,7 +4737,16 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z if (y == FIXED_MIN) y = thing->y; if (z == FIXED_MIN) z = thing->z; // don't splash above the object - if (checkabove && z > thing->z + (thing->height >> 1)) return false; + if (checkabove) + { + fixed_t compare_z = thing->z + (thing->height >> 1); + // Missiles are typically small and fast, so they might + // end up submerged by the move that calls P_HitWater. + if (thing->flags & MF_MISSILE) + compare_z -= thing->velz; + if (z > compare_z) + return false; + } #if 0 // needs some rethinking before activation diff --git a/src/p_trace.cpp b/src/p_trace.cpp index bd00da36f..59dbe08f9 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -59,7 +59,9 @@ struct FTraceInfo int sectorsel; bool TraceTraverse (int ptflags); + bool CheckPlane(const secplane_t &plane); bool CheckSectorPlane (const sector_t *sector, bool checkFloor); + bool Check3DFloorPlane(const F3DFloor *ffloor, bool checkBottom); }; static bool EditTraceResult (DWORD flags, FTraceResults &res); @@ -90,17 +92,18 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, inf.EnterDist = 0; inf.TraceCallback = callback; inf.TraceFlags = flags; - res.CrossedWater = NULL; inf.Results = &res; inf.inshootthrough = true; - - res.HitType = TRACE_HitNone; - - // Do a 3D floor check in the starting sector - memset(&res, 0, sizeof(res)); inf.sectorsel=0; + memset(&res, 0, sizeof(res)); + /* // Redundant with the memset + res.HitType = TRACE_HitNone; + res.CrossedWater = NULL; + res.Crossed3DWater = NULL; + */ #ifdef _3DFLOORS + // Do a 3D floor check in the starting sector TDeletingArray &ff = sector->e->XFloor.ffloors; if (ff.Size()) @@ -114,8 +117,16 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, for(unsigned int i=0;iflags&FF_EXISTS)) + continue; - if (!(rover->flags&FF_SHOOTTHROUGH) && rover->flags&FF_EXISTS) + if (rover->flags&FF_SWIMMABLE && res.Crossed3DWater == NULL) + { + if (inf.Check3DFloorPlane(rover, false)) + res.Crossed3DWater = rover; + } + + if (!(rover->flags&FF_SHOOTTHROUGH)) { fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y); fixed_t ff_top=rover->top.plane->ZatPoint(x, y); @@ -243,6 +254,26 @@ bool FTraceInfo::TraceTraverse (int ptflags) fixed_t hitx, hity, hitz; fixed_t dist; + // Deal with splashes in 3D floors +#ifdef _3DFLOORS + if (CurSector->e->XFloor.ffloors.Size()) + { + for(unsigned int i=0;ie->XFloor.ffloors.Size();i++) + { + F3DFloor * rover=CurSector->e->XFloor.ffloors[i]; + if (!(rover->flags&FF_EXISTS)) + continue; + + // Deal with splashy stuff + if (rover->flags&FF_SWIMMABLE && Results->Crossed3DWater == NULL) + { + if (Check3DFloorPlane(rover, false)) + Results->Crossed3DWater = rover; + } + } + } +#endif + if (in->isaline) { int lineside; @@ -287,7 +318,7 @@ bool FTraceInfo::TraceTraverse (int ptflags) entersector = (lineside == 0) ? in->d.line->backsector : in->d.line->frontsector; // For backwards compatibility: Ignore lines with the same sector on both sides. - // This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15 need it. + // This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15) need it. if (i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector) { // We must check special activation here because the code below is never reached. @@ -587,19 +618,8 @@ cont1: return true; } -bool FTraceInfo::CheckSectorPlane (const sector_t *sector, bool checkFloor) +bool FTraceInfo::CheckPlane (const secplane_t &plane) { - secplane_t plane; - - if (checkFloor) - { - plane = sector->floorplane; - } - else - { - plane = sector->ceilingplane; - } - fixed_t den = TMulScale16 (plane.a, Vx, plane.b, Vy, plane.c, Vz); if (den != 0) @@ -623,6 +643,38 @@ bool FTraceInfo::CheckSectorPlane (const sector_t *sector, bool checkFloor) return false; } +bool FTraceInfo::CheckSectorPlane (const sector_t *sector, bool checkFloor) +{ + secplane_t plane; + + if (checkFloor) + { + plane = sector->floorplane; + } + else + { + plane = sector->ceilingplane; + } + + return CheckPlane(plane); +} + +bool FTraceInfo::Check3DFloorPlane (const F3DFloor *ffloor, bool checkBottom) +{ + secplane_t plane; + + if (checkBottom) + { + plane = *(ffloor->bottom.plane); + } + else + { + plane = *(ffloor->top.plane); + } + + return CheckPlane(plane); +} + static bool EditTraceResult (DWORD flags, FTraceResults &res) { if (flags & TRACE_NoSky) diff --git a/src/p_trace.h b/src/p_trace.h index e13a7f905..8ce905da3 100644 --- a/src/p_trace.h +++ b/src/p_trace.h @@ -73,8 +73,9 @@ struct FTraceResults BYTE Side; BYTE Tier; ETraceResult HitType; - sector_t *CrossedWater; - F3DFloor * ffloor; + sector_t *CrossedWater; // For Boom-style, Transfer_Heights-based deep water + F3DFloor *Crossed3DWater; // For 3D floor-based deep water + F3DFloor *ffloor; }; enum