diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index 58d67ce44..aee50d228 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -248,17 +248,12 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, TSectIterator it(dasect); while (auto actor = it.Next()) { - const int32_t cstat = actor->spr.cstat; + int cstat = actor->spr.cstat; if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) continue; - if ((cstat&dasprclipmask) == 0) + if ((cstat & dasprclipmask) == 0) continue; - auto p1 = actor->int_pos().vec2; - - CollisionBase obj; - obj.setSprite(actor); - switch (cstat & (CSTAT_SPRITE_ALIGNMENT_MASK)) { case CSTAT_SPRITE_ALIGNMENT_FACING: @@ -274,63 +269,7 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, break; case CSTAT_SPRITE_ALIGNMENT_SLOPE: - { - - if (!processClipFloorSprite(clip, actor)) continue; - int heinum = spriteGetSlope(actor); - - if (heinum == 0) continue; - - // the rest is for slope sprites only. - auto tex = TexMan.GetGameTexture(actor->spr.spritetexture()); - const int32_t cosang = bcos(actor->int_ang()); - const int32_t sinang = bsin(actor->int_ang()); - vec2_t const span = { (int)tex->GetDisplayWidth(), (int)tex->GetDisplayHeight() }; - vec2_t const repeat = { int(actor->spr.scale.X * scaletoint), int(actor->spr.scale.Y * scaletoint) }; - vec2_t adjofs = { (int)tex->GetDisplayLeftOffset(), (int)tex->GetDisplayTopOffset() }; - - if (actor->spr.cstat & CSTAT_SPRITE_XFLIP) - adjofs.X = -adjofs.X; - - if (actor->spr.cstat & CSTAT_SPRITE_YFLIP) - adjofs.Y = -adjofs.Y; - - int32_t const centerx = ((span.X >> 1) + adjofs.X) * repeat.X; - int32_t const centery = ((span.Y >> 1) + adjofs.Y) * repeat.Y; - int32_t const rspanx = span.X * repeat.X; - int32_t const rspany = span.Y * repeat.Y; - int32_t const ratio = ksqrt(heinum * heinum + SLOPEVAL_FACTOR * SLOPEVAL_FACTOR); - int32_t zz[3] = { pos->Z, pos->Z + flordist, pos->Z - ceildist }; - for (int k = 0; k < 3; k++) - { - int32_t jj = DivScale(actor->int_pos().Z - zz[k], heinum, 18); - int32_t jj2 = MulScale(jj, ratio, 12); - if (jj2 > (centery << 8) || jj2 < ((centery - rspany) << 8)) - continue; - int32_t x1 = actor->int_pos().X + MulScale(sinang, centerx, 16) + MulScale(jj, cosang, 24); - int32_t y1 = actor->int_pos().Y - MulScale(cosang, centerx, 16) + MulScale(jj, sinang, 24); - int32_t x2 = x1 - MulScale(sinang, rspanx, 16); - int32_t y2 = y1 + MulScale(cosang, rspanx, 16); - - vec2_t const v = { MulScale(bcos(actor->int_ang() - 256), walldist, 14), - MulScale(bsin(actor->int_ang() - 256), walldist, 14) }; - - if (clipinsideboxline(cent.X, cent.Y, x1, y1, x2, y2, rad) != 0) - { - if ((x1 - pos->X) * (y2 - pos->Y) >= (x2 - pos->X) * (y1 - pos->Y)) - { - addclipline(x1 + v.X, y1 + v.Y, x2 + v.Y, y2 - v.X, obj, false); - } - else - { - if ((cstat & CSTAT_SPRITE_ONE_SIDE) != 0) - continue; - addclipline(x2 - v.X, y2 - v.Y, x1 - v.Y, y1 + v.X, obj, false); - } - } - } - break; - } + processClipSlopeSprite(clip, actor); } } } while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 76c575b71..5e53f4154 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -1403,14 +1403,13 @@ void processClipWallSprite(MoveClipper& clip, DCoreActor* actor) } } - //========================================================================== // // // //========================================================================== -bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) +bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points, double* heights) { int heinum = spriteGetSlope(actor); double sprz = spriteGetZOfSlopef(&actor->spr, actor->spr.pos.XY(), heinum); @@ -1422,8 +1421,9 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) if ((clip.pos.Z > sprz) == ((actor->spr.cstat & CSTAT_SPRITE_YFLIP) == 0)) return false; } - DVector2 points[4]; - GetFlatSpritePosition(actor, actor->spr.pos.XY(), points, nullptr); + DVector2 opoints[4]; + if (!points) points = opoints; + GetFlatSpritePosition(actor, actor->spr.pos.XY(), points, heights); auto offset = (actor->spr.Angles.Yaw - DAngle45).ToVector() * clip.walldist; @@ -1464,6 +1464,55 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) // //========================================================================== +void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor) +{ + auto spos = actor->spr.pos; + DVector2 points[4]; + double heights[4]; + DVector2 lpoints[2]; + + if (!processClipFloorSprite(clip, actor, points, heights)) return; + int heinum = spriteGetSlope(actor); + if (heinum == 0) return; + + double zz[3] = { clip.pos.Z, clip.pos.Z + clip.floordist, clip.pos.Z - clip.ceilingdist }; + + CollisionBase objtype; + objtype.setSprite(actor); + + for (int k = 0; k < 3; k++) + { + double factor = (zz[k] - heights[0]) / (heights[1] - heights[0]); + if (factor < 0 || factor > 1) continue; // sprite never hits the desired height. + auto dist = (points[1] - points[0]) * factor; + lpoints[0] = points[0] + dist; + lpoints[1] = points[3] + dist; + + // The rest is just the same as the main part of the wall sprite collector. + if (IsCloseToLine(clip.center, lpoints[0], lpoints[1], clip.movedist) == EClose::Outside) continue; // out of reach + + auto offset = (actor->spr.angle - DAngle45).ToVector() * clip.walldist; + auto d = lpoints[1] - lpoints[0]; + + if (PointOnLineSide(clip.center.X, clip.center.Y, lpoints[0].X, lpoints[0].Y, d.X, d.Y) <= 0) + { + // in front + addClipLine(clip, lpoints[0] + offset, lpoints[1] + offset.Rotated90CW(), objtype); + } + else if (!(actor->spr.cstat & CSTAT_SPRITE_ONE_SIDE)) + { + // behind + addClipLine(clip, lpoints[0] - offset, lpoints[1] + offset.Rotated90CCW(), objtype); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + int FindBestSector(const DVector3& pos) { int bestnum = -1; diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index cd8768d6e..024e553c9 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -261,7 +261,8 @@ void processClipWalls(MoveClipper& clip, sectortype* sec); void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor); void processClipWallSprite(MoveClipper& clip, DCoreActor* actor); -bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor); +bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points = nullptr, double* heights = nullptr); +void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor); int FindBestSector(const DVector3& pos);