From 6c4d070095c3dfef557c081d0c34c4b307dae42f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 28 May 2010 21:07:45 +0000 Subject: [PATCH] - restored original Doom behavior for hitscans to only check actors which have their center in the blockmap cells being checked, compatibility optioned by COMPATF_HITSCAN. SVN r2341 (trunk) --- src/p_local.h | 5 ++- src/p_map.cpp | 15 +++---- src/p_maputl.cpp | 109 +++++++++++++++++++++++++++++------------------ src/p_setup.cpp | 20 --------- src/p_trace.cpp | 2 +- src/po_man.cpp | 8 ++-- 6 files changed, 83 insertions(+), 76 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index e42dc960d..fc9068cd0 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -292,7 +292,7 @@ class FBlockThingsIterator public: FBlockThingsIterator(int minx, int miny, int maxx, int maxy); FBlockThingsIterator(const FBoundingBox &box); - AActor *Next(); + AActor *Next(bool centeronly = false); void Reset() { StartBlock(minx, miny); } }; @@ -307,7 +307,7 @@ class FPathTraverse unsigned int count; void AddLineIntercepts(int bx, int by); - void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it); + void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it, bool compatible); public: intercept_t *Next(); @@ -320,6 +320,7 @@ public: #define PT_ADDLINES 1 #define PT_ADDTHINGS 2 +#define PT_COMPATIBLE 4 AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL); AActor *P_RoughMonsterSearch (AActor *mo, int distance); diff --git a/src/p_map.cpp b/src/p_map.cpp index 4e78227f5..d13a12c3f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1276,10 +1276,6 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm) return true; // Check things first, possibly picking things up. - // The bounding box is extended by MAXRADIUS - // because DActors are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. thing->BlockingMobj = NULL; thingblocker = NULL; fakedblocker = NULL; @@ -2943,7 +2939,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in) void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target) { - FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS); + FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS|PT_COMPATIBLE); intercept_t *in; while ((in = it.Next())) @@ -3426,9 +3422,12 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, (t1->player->ReadyWeapon->WeaponFlags & WIF_AXEBLOOD)); // Hit a thing, so it could be either a puff or blood - hitx = t1->x + FixedMul (vx, trace.Distance); - hity = t1->y + FixedMul (vy, trace.Distance); - hitz = shootz + FixedMul (vz, trace.Distance); + fixed_t dist = trace.Distance; + // position a bit closer for puffs/blood if using compatibility mode. + if (i_compatflags & COMPATF_HITSCAN) dist -= 10*FRACUNIT; + hitx = t1->x + FixedMul (vx, dist); + hity = t1->y + FixedMul (vy, dist); + hitz = shootz + FixedMul (vz, dist); // Spawn bullet puffs or blood spots, depending on target type. if ((puffDefaults->flags3 & MF3_PUFFONACTORS) || diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index fc0197183..14421fc50 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -825,7 +825,7 @@ void FBlockThingsIterator::SwitchBlock(int x, int y) // //=========================================================================== -AActor *FBlockThingsIterator::Next() +AActor *FBlockThingsIterator::Next(bool centeronly) { for (;;) { @@ -842,37 +842,55 @@ AActor *FBlockThingsIterator::Next() { // This actor doesn't span blocks, so we know it can only ever be checked once. return me; } - size_t hash = ((size_t)me >> 3) % countof(Buckets); - for (i = Buckets[hash]; i >= 0; ) + if (centeronly) { - entry = GetHashEntry(i); - if (entry->Actor == me) - { // I've already been checked. Skip to the next actor. - break; + // Block boundaries for compatibility mode + fixed_t blockleft = (curx << MAPBLOCKSHIFT) + bmaporgx; + fixed_t blockright = blockleft + MAPBLOCKSIZE; + fixed_t blockbottom = (cury << MAPBLOCKSHIFT) + bmaporgy; + fixed_t blocktop = blockbottom + MAPBLOCKSIZE; + + // only return actors with the center in this block + if (me->x >= blockleft && me->x < blockright && + me->y >= blockbottom && me->y < blocktop) + { + return me; } - i = entry->Next; } - if (i < 0) - { // Add me to the hash table and return me. - if (NumFixedHash < (int)countof(FixedHash)) + else + { + size_t hash = ((size_t)me >> 3) % countof(Buckets); + for (i = Buckets[hash]; i >= 0; ) { - entry = &FixedHash[NumFixedHash]; - entry->Next = Buckets[hash]; - Buckets[hash] = NumFixedHash++; - } - else - { - if (DynHash.Size() == 0) - { - DynHash.Grow(50); + entry = GetHashEntry(i); + if (entry->Actor == me) + { // I've already been checked. Skip to the next actor. + break; } - i = DynHash.Reserve(1); - entry = &DynHash[i]; - entry->Next = Buckets[hash]; - Buckets[hash] = i + countof(FixedHash); + i = entry->Next; + } + if (i < 0) + { // Add me to the hash table and return me. + if (NumFixedHash < (int)countof(FixedHash)) + { + entry = &FixedHash[NumFixedHash]; + entry->Next = Buckets[hash]; + Buckets[hash] = NumFixedHash++; + } + else + { + if (DynHash.Size() == 0) + { + DynHash.Grow(50); + } + i = DynHash.Reserve(1); + entry = &DynHash[i]; + entry->Next = Buckets[hash]; + Buckets[hash] = i + countof(FixedHash); + } + entry->Actor = me; + return me; } - entry->Actor = me; - return me; } } @@ -959,19 +977,19 @@ void FPathTraverse::AddLineIntercepts(int bx, int by) // //=========================================================================== -void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it) +void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it, bool compatible) { AActor *thing; it.SwitchBlock(bx, by); - while ((thing = it.Next())) + while ((thing = it.Next(compatible))) { int numfronts = 0; divline_t line; int i; - if (!(i_compatflags & COMPATF_HITSCAN)) + if (!compatible) { // [RH] Don't check a corner to corner crossection for hit. // Instead, check against the actual bounding box (but not if compatibility optioned.) @@ -1251,6 +1269,8 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in // from skipping the break statement. mapx = xt1; mapy = yt1; + + bool compatible = (flags & PT_COMPATIBLE) && (i_compatflags & COMPATF_HITSCAN); // we want to use one list of checked actors for the entire operation FBlockThingsIterator btit; @@ -1263,7 +1283,7 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in if (flags & PT_ADDTHINGS) { - AddThingIntercepts(mapx, mapy, btit); + AddThingIntercepts(mapx, mapy, btit, compatible); } if (mapx == xt2 && mapy == yt2) @@ -1293,21 +1313,28 @@ FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, in // being entered need to be checked (which will happen when this loop // continues), but the other two blocks adjacent to the corner also need to // be checked. - if (flags & PT_ADDLINES) + if (!compatible) { - AddLineIntercepts(mapx + mapxstep, mapy); - AddLineIntercepts(mapx, mapy + mapystep); + if (flags & PT_ADDLINES) + { + AddLineIntercepts(mapx + mapxstep, mapy); + AddLineIntercepts(mapx, mapy + mapystep); + } + + if (flags & PT_ADDTHINGS) + { + AddThingIntercepts(mapx + mapxstep, mapy, btit, false); + AddThingIntercepts(mapx, mapy + mapystep, btit, false); + } + xintercept += xstep; + yintercept += ystep; + mapx += mapxstep; + mapy += mapystep; } - - if (flags & PT_ADDTHINGS) + else { - AddThingIntercepts(mapx + mapxstep, mapy, btit); - AddThingIntercepts(mapx, mapy + mapystep, btit); + count = 100; // Doom originally did not handle this case so do the same in compatibility mode. } - xintercept += xstep; - yintercept += ystep; - mapx += mapxstep; - mapy += mapystep; break; } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 8c3f774d7..5efdac413 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3077,26 +3077,6 @@ static void P_GroupLines (bool buildmap) } } } -#if 0 - int block; - - // adjust bounding box to map blocks - block = (bbox.Top()-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapheight ? bmapheight-1 : block; - //sector->blockbox.Top()=block; - - block = (bbox.Bottom()-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - //sector->blockbox.Bottom()=block; - - block = (bbox.Right()-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapwidth ? bmapwidth-1 : block; - //sector->blockbox.Right()=block; - - block = (bbox.Left()-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - //sector->blockbox.Left()=block; -#endif } delete[] linesDoneInEachSector; times[3].Unclock(); diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 1f38cc694..bd00da36f 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -74,7 +74,7 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector, int ptflags; FTraceInfo inf; - ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS : PT_ADDLINES; + ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS|PT_COMPATIBLE : PT_ADDLINES; inf.StartX = x; inf.StartY = y; diff --git a/src/po_man.cpp b/src/po_man.cpp index 13a5bda91..12e3f57ca 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1156,10 +1156,10 @@ static bool CheckMobjBlocking (seg_t *seg, FPolyObj *po) ld = seg->linedef; - top = (ld->bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; - bottom = (ld->bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; - left = (ld->bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; - right = (ld->bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; + top = (ld->bbox[BOXTOP]-bmaporgy) >> MAPBLOCKSHIFT; + bottom = (ld->bbox[BOXBOTTOM]-bmaporgy) >> MAPBLOCKSHIFT; + left = (ld->bbox[BOXLEFT]-bmaporgx) >> MAPBLOCKSHIFT; + right = (ld->bbox[BOXRIGHT]-bmaporgx) >> MAPBLOCKSHIFT; blocked = false; checker.Clear();