diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index d05da2a99..4bb6481f3 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -639,8 +639,10 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) { - DVector2 v(vec.X* inttoworld, vec.Y* inttoworld); - clipupdatesector(v, sectnum, rad * inttoworld, clipsectormap); + DVector3 v(vec.X* inttoworld, vec.Y* inttoworld, 0); + sectortype* sect = §or[*sectnum]; + updatesectorneighbor(v, §, rad * inttoworld); + *sectnum = ::sectnum(sect); } pos->X = vec.X; @@ -697,93 +699,3 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect, } -// -// pushmove -// -int pushmove_(vec3_t *const vect, int *const sectnum, - int32_t const walldist, int32_t const ceildist, int32_t const flordist, uint32_t const cliptype, bool clear /*= true*/) -{ - int bad; - - const int32_t dawalclipmask = (cliptype&65535); - // const int32_t dasprclipmask = (cliptype >> 16); - - if (*sectnum < 0) - return -1; - - int32_t k = 32; - - int dir = 1; - do - { - int32_t clipsectcnt = 0; - - bad = 0; - - if (clear) - { - if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE && *sectnum < 0) - return 0; - clipsectorlist[0] = *sectnum; - clipsectnum = 1; - - clipsectormap.Zero(); - clipsectormap.Set(*sectnum); - } - - do - { - const walltype* wal; - int32_t startwall, endwall; - - auto sec = §or[clipsectorlist[clipsectcnt]]; - if (dir > 0) - startwall = sec->wallptr, endwall = startwall + sec->wallnum; - else - endwall = sec->wallptr, startwall = endwall + sec->wallnum - 1; - - int i; - - for (i=startwall, wal=&wall[startwall]; i!=endwall; i+=dir, wal+=dir) - if (IsCloseToWall(DVector2(vect->X * inttoworld, vect->Y * inttoworld), &wall[i], (walldist-4) * inttoworld) == EClose::InFront) - { - int j = 0; - if (wal->nextsector < 0 || wal->cstat & EWallFlags::FromInt(dawalclipmask)) j = 1; - else - { - auto pvect = NearestPointOnWall(vect->X * inttoworld, vect->Y * inttoworld, wal); - vec2_t closest = { int(pvect.X * worldtoint), int(pvect.Y * worldtoint) }; - - j = cliptestsector(clipsectorlist[clipsectcnt], wal->nextsector, flordist, ceildist, closest, vect->Z); - } - - if (j != 0) - { - DAngle jj = wal->delta().Angle(); - int32_t dx = -int(jj.Sin() * 8); - int32_t dy = int(jj.Cos() * 8); - int bad2 = 16; - do - { - vect->X = (vect->X) + dx; vect->Y = (vect->Y) + dy; - bad2--; if (bad2 == 0) break; - } while (IsCloseToWall(DVector2(vect->X * inttoworld, vect->Y * inttoworld), &wall[i], (walldist - 4) * inttoworld) != EClose::Outside); - bad = -1; - k--; if (k <= 0) return bad; - - DVector2 v(vect->vec2.X * inttoworld, vect->vec2.Y * inttoworld); - clipupdatesector(v, sectnum, walldist * inttoworld, clipsectormap); - - if (*sectnum < 0) return -1; - } - else if (!clipsectormap[wal->nextsector]) - addclipsect(wal->nextsector); - } - - clipsectcnt++; - } while (clipsectcnt < clipsectnum); - dir = -dir; - } while (bad != 0); - - return bad; -} diff --git a/source/core/coreactor.h b/source/core/coreactor.h index 89a77532a..4b00c66f4 100644 --- a/source/core/coreactor.h +++ b/source/core/coreactor.h @@ -447,19 +447,6 @@ inline int clipmove(DVector3& pos, sectortype** const sect, const DVector2& mvec return result.type; } -inline int pushmove(DVector3& pos, sectortype** const sect, double const walldist, double const ceildist, double const flordist, - uint32_t const cliptype, bool clear = true) -{ - auto vect = vec3_t(int(pos.X * worldtoint), int(pos.Y * worldtoint), int(pos.Z * zworldtoint)); - int sectno = *sect ? sector.IndexOf(*sect) : -1; - int res = pushmove_(&vect, §no, int(walldist * worldtoint), int(ceildist * zworldtoint), int(flordist * zworldtoint), cliptype, clear); - pos = { vect.X * inttoworld, vect.Y * inttoworld, vect.Z * zinttoworld }; - *sect = sectno == -1 ? nullptr : §or[sectno]; - return res; -} - - -tspritetype* renderAddTsprite(tspriteArray& tsprites, DCoreActor* actor); inline PClassActor* PClass::FindActor(FName name) { diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 3728a13e6..5b41bf07f 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -1177,6 +1177,84 @@ void neartag(const DVector3& pos, sectortype* startsect, DAngle angle, HitInfoBa } } +//========================================================================== +// +// +// +//========================================================================== + +bool checkOpening(const DVector3& pos, const sectortype* sec, const sectortype* nextsec, double ceilingdist, double floordist) +{ + double c1, c2, f1, f2; + calcSlope(sec, pos.X, pos.Y, &c1, &f1); + calcSlope(nextsec, pos.X, pos.Y, &c2, &f2); + + return ((f2 < f1 - 1 && (nextsec->floorstat & CSTAT_SECTOR_SKY) == 0 && pos.Z >= f2 - (floordist - zmaptoworld)) || + (c2 > c1 + 1 && (nextsec->ceilingstat & CSTAT_SECTOR_SKY) == 0 && pos.Z <= c2 + (ceilingdist - zmaptoworld))); +} + +//========================================================================== +// +// +// +//========================================================================== + +int pushmove(DVector3& pos, sectortype** pSect, double walldist, double ceildist, double floordist, unsigned cliptype) +{ + auto wallflags = EWallFlags::FromInt(cliptype & 65535); + int maxhitwalls = 0; + bool pushed = true; + + for(int direction = 1; pushed; direction = -direction) + { + pushed = false; + + if (*pSect == nullptr) + return -1; + + BFSSectorSearch search(*pSect); + + while (auto sec = search.GetNext()) + { + // this must go both forward and backward so we cannot use wallsofsector. Pity + for (int i = 0; i < sec->wallnum; i++) + { + auto wal = direction > 0 ? sec->firstWall() + i : sec->lastWall() - i; + + if (IsCloseToWall(pos.XY(), wal, walldist - 0.25) == EClose::InFront) + { + bool blocked = false; + if (!wal->twoSided() || wal->cstat & wallflags) blocked = true; + else + { + auto pvect = NearestPointOnWall(pos.X, pos.Y, wal); + blocked = checkOpening(DVector3(pvect, pos.Z), sec, wal->nextSector(), ceildist, floordist); + } + + if (blocked) + { + auto dv = wal->delta().Rotated90CCW().Unit() * 0.5; + for (int t = 0; t < 16; t++) + { + pos += dv; + if (IsCloseToWall(pos, wal, (walldist - 0.25)) == EClose::Outside) break; + } + pushed = true; + + updatesector(pos, pSect); + if (++maxhitwalls >= 32) return -1; + if (*pSect == nullptr) return -1; + } + else + search.Add(wal->nextSector()); + } + } + } + if (!pushed) return 0; + } + return -1; +} + //========================================================================== // // diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h index 099b03500..f47c40639 100644 --- a/source/core/gamefuncs.h +++ b/source/core/gamefuncs.h @@ -264,6 +264,9 @@ bool checkRangeOfWallSprite(DCoreActor* itActor, const DVector3& pos, double max bool checkRangeOfFloorSprite(DCoreActor* itActor, const DVector3& pos, double maxdist, double& theZ); void getzrange(const DVector3& pos, sectortype* sect, double* ceilz, CollisionBase& ceilhit, double* florz, CollisionBase& florhit, double walldist, uint32_t cliptype); +int pushmove(DVector3& pos, sectortype** pSect, double walldist, double ceildist, double flordist, unsigned cliptype); +tspritetype* renderAddTsprite(tspriteArray& tsprites, DCoreActor* actor); + diff --git a/source/core/updatesector.h b/source/core/updatesector.h index 549ac7537..3c194667b 100644 --- a/source/core/updatesector.h +++ b/source/core/updatesector.h @@ -61,7 +61,7 @@ void DoUpdateSector(double x, double y, double z, int* sectnum, double maxDistan for (auto& wal : wallsofsector(lsect)) { - if (wal.twoSided() && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToSector(x, y, wal.nextSector()) <= maxDistSq)) + if (wal.twoSided() && !search.Check(wal.nextsector) && (iter == 0 || SquareDistToWall(x, y, &wal) <= maxDistSq)) search.Add(wal.nextsector); } iter++; @@ -118,59 +118,3 @@ inline void updatesector(int x_, int y_, int* sectnum) DoUpdateSector(x, y, 0, sectnum, MAXUPDATESECTORDIST, inside0); } -// clipmove uses this. It's really just two loops nearly identical to DoUpdateSector with different checking conditions. -inline void clipupdatesector(const DVector2& pos, int* const sectnum, double walldist, BitArray& sectormap) -{ - assert(*sectnum >= 0); - sectortype* sect = §or[*sectnum]; - if (inside(pos.X, pos.Y, sect)) - return; - - double sdist = SquareDistToSector(pos.X, pos.Y, sect); - - double wd = (walldist + 8); - wd *= wd; - if (sdist > wd) - { - wd = 2048 * 2048; - } - - { - BFSSearch search(sector.Size(), *sectnum); - - for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;) - { - if (inside(pos.X, pos.Y, §or[secnum])) - { - *sectnum = secnum; - return; - } - - for (auto& wal : wallsofsector(secnum)) - { - if (wal.twoSided() && sectormap[wal.nextsector]) - search.Add(wal.nextsector); - } - } - } - - { - BFSSearch search(sector.Size(), *sectnum); - - for (unsigned secnum; (secnum = search.GetNext()) != BFSSearch::EOL;) - { - if (inside(pos.X, pos.Y, §or[secnum])) - { - *sectnum = secnum; - return; - } - for (auto& wal : wallsofsector(secnum)) - { - if (wal.twoSided() && SquareDistToWall(pos.X, pos.Y, &wal) < wd) - search.Add(wal.nextsector); - } - } - } - - *sectnum = -1; -}