- Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but

P_FindFloorCeiling never did that.
- Merged Check_Sides and PIT_CrossLine into A_PainShootSkull.
- Replaced P_BlockLinesIterator with FBlockLinesIterator in all places it was
  used. This also allowed to remove all the global variable saving in
  P_CreateSecNodeList.
- Added a new FBlockLinesIterator class that doesn't need a callback
  function because debugging the previous bug proved to be a bit annoying
  because it involved a P_BlockLinesIterator loop.
- Fixed: The MBF code to move monsters away from dropoffs did not work as 
  intended due to some random decisions in P_DoNewChaseDir. When in the
  avoiding dropoff mode these are ignored now. This should cure the problem
  that monsters hanging over a dropoff tended to drop down. 

SVN r887 (trunk)
This commit is contained in:
Christoph Oelckers 2008-04-06 17:33:43 +00:00
commit ebd17de30a
16 changed files with 393 additions and 424 deletions

View file

@ -677,75 +677,119 @@ void FBlockNode::Release ()
//
// P_BlockLinesIterator
// The validcount flags are used to avoid checking lines
// that are marked in multiple mapblocks,
// so increment validcount before the first call
// to P_BlockLinesIterator, then make one or more calls
// to it.
// FBlockLinesIterator
//
extern polyblock_t **PolyBlockMap;
bool P_BlockLinesIterator (int x, int y, bool(*func)(line_t*))
FBlockLinesIterator::FBlockLinesIterator(int _minx, int _miny, int _maxx, int _maxy, bool keepvalidcount)
{
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
if (!keepvalidcount) validcount++;
minx = _minx;
maxx = _maxx;
miny = _miny;
maxy = _maxy;
Reset();
}
FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
{
validcount++;
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
minx = (box.Left() - bmaporgx) >> MAPBLOCKSHIFT;
Reset();
}
void FBlockLinesIterator::StartBlock(int x, int y)
{
if (x >= 0 && y >= 0 && x < bmapwidth && y <bmapheight)
{
return true;
}
else
{
int offset;
int *list;
/* [RH] Polyobj stuff from Hexen --> */
polyblock_t *polyLink;
offset = y*bmapwidth + x;
if (PolyBlockMap)
{
polyLink = PolyBlockMap[offset];
while (polyLink)
{
if (polyLink->polyobj && polyLink->polyobj->validcount != validcount)
{
int i;
seg_t **tempSeg = polyLink->polyobj->segs;
polyLink->polyobj->validcount = validcount;
for (i = polyLink->polyobj->numsegs; i; i--, tempSeg++)
{
if ((*tempSeg)->linedef->validcount != validcount)
{
(*tempSeg)->linedef->validcount = validcount;
if (!func ((*tempSeg)->linedef))
return false;
}
}
}
polyLink = polyLink->next;
}
}
/* <-- Polyobj stuff from Hexen */
offset = *(blockmap + offset);
curx = x;
cury = y;
int offset = y*bmapwidth + x;
polyLink = PolyBlockMap? PolyBlockMap[offset] : NULL;
polyIndex = 0;
// There is an extra entry at the beginning of every block.
// Apparently, id had originally intended for it to be used
// to keep track of things, but the final code does not do that.
for (list = blockmaplump + offset + 1; *list != -1; list++)
{
line_t *ld = &lines[*list];
list = blockmaplump + *(blockmap + offset) + 1;
}
else
{
// invalid block
list = NULL;
polyLink = NULL;
}
}
if (ld->validcount != validcount)
line_t *FBlockLinesIterator::Next()
{
while (true)
{
while (polyLink != NULL)
{
if (polyLink->polyobj)
{
ld->validcount = validcount;
if ( !func(ld) )
return false;
if (polyIndex == 0)
{
if (polyLink->polyobj->validcount == validcount)
{
polyLink = polyLink->next;
continue;
}
polyLink->polyobj->validcount = validcount;
}
seg_t *seg = polyLink->polyobj->segs[polyIndex];
if (++polyIndex >= polyLink->polyobj->numsegs)
{
polyLink = polyLink->next;
polyIndex = 0;
}
line_t *ld = seg->linedef;
if (ld->validcount == validcount)
{
continue;
}
else
{
ld->validcount = validcount;
return ld;
}
}
else polyLink = polyLink->next;
}
if (list != NULL)
{
while (*list != -1)
{
line_t *ld = &lines[*list];
if (ld->validcount != validcount)
{
ld->validcount = validcount;
return ld;
}
else
{
list++;
}
}
}
if (++curx > maxx)
{
curx = minx;
if (++cury > maxy) return NULL;
}
StartBlock(curx, cury);
}
return true; // everything was checked
}
@ -829,59 +873,62 @@ int ptflags;
// are on opposite sides of the trace.
// Returns true if earlyout and a solid line hit.
//
bool PIT_AddLineIntercepts (line_t *ld)
void P_AddLineIntercepts(int bx, int by)
{
int s1;
int s2;
fixed_t frac;
divline_t dl;
FBlockLinesIterator it(bx, by, bx, by, true);
line_t *ld;
// avoid precision problems with two routines
if ( trace.dx > FRACUNIT*16
|| trace.dy > FRACUNIT*16
|| trace.dx < -FRACUNIT*16
|| trace.dy < -FRACUNIT*16)
while ((ld = it.Next()))
{
s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
}
else
{
s1 = P_PointOnLineSide (trace.x, trace.y, ld);
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
}
if (s1 == s2)
return true; // line isn't crossed
// hit the line
P_MakeDivline (ld, &dl);
frac = P_InterceptVector (&trace, &dl);
int s1;
int s2;
fixed_t frac;
divline_t dl;
if (frac < 0)
return true; // behind source
// avoid precision problems with two routines
if ( trace.dx > FRACUNIT*16
|| trace.dy > FRACUNIT*16
|| trace.dx < -FRACUNIT*16
|| trace.dy < -FRACUNIT*16)
{
s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
}
else
{
s1 = P_PointOnLineSide (trace.x, trace.y, ld);
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
}
// try to early out the check
if (earlyout
&& frac < FRACUNIT
&& !ld->backsector)
{
return false; // stop checking
if (s1 == s2) continue; // line isn't crossed
// hit the line
P_MakeDivline (ld, &dl);
frac = P_InterceptVector (&trace, &dl);
if (frac < 0) continue; // behind source
/* unused code
// try to early out the check
if (earlyout
&& frac < FRACUNIT
&& !ld->backsector)
{
return false; // stop checking
}
*/
intercept_t newintercept;
newintercept.frac = frac;
newintercept.isaline = true;
newintercept.d.line = ld;
intercepts.Push (newintercept);
}
intercept_t newintercept;
newintercept.frac = frac;
newintercept.isaline = true;
newintercept.d.line = ld;
intercepts.Push (newintercept);
return true; // continue
}
//
// PIT_AddThingIntercepts
//
@ -1145,8 +1192,7 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
{
if (flags & PT_ADDLINES)
{
if (!P_BlockLinesIterator (mapx, mapy, PIT_AddLineIntercepts))
return false; // early out
P_AddLineIntercepts(mapx, mapy);
}
if (flags & PT_ADDTHINGS)
@ -1184,9 +1230,8 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
// be checked.
if (flags & PT_ADDLINES)
{
if (!P_BlockLinesIterator (mapx + mapxstep, mapy, PIT_AddLineIntercepts) ||
!P_BlockLinesIterator (mapx, mapy + mapystep, PIT_AddLineIntercepts))
return false; // early out
P_AddLineIntercepts(mapx + mapxstep, mapy);
P_AddLineIntercepts(mapx, mapy + mapystep);
}
if (flags & PT_ADDTHINGS)
@ -1330,3 +1375,5 @@ static AActor *RoughBlockCheck (AActor *mo, int index)
}
return NULL;
}