- 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

@ -100,8 +100,6 @@ int tmceilingpic;
sector_t *tmceilingsector;
bool tmtouchmidtex;
static fixed_t tmfbbox[4];
static AActor *tmfthing;
fixed_t tmffloorz;
fixed_t tmfceilingz;
fixed_t tmfdropoffz;
@ -142,15 +140,15 @@ AActor *LastRipped;
//
//==========================================================================
static bool PIT_FindFloorCeiling (line_t *ld)
static bool PIT_FindFloorCeiling (line_t *ld, AActor *tmfthing, const FBoundingBox &box, fixed_t tmx, fixed_t tmy)
{
if (tmfbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|| tmfbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| tmfbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|| tmfbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
if (box.Right() <= ld->bbox[BOXLEFT]
|| box.Left() >= ld->bbox[BOXRIGHT]
|| box.Top() <= ld->bbox[BOXBOTTOM]
|| box.Bottom() >= ld->bbox[BOXTOP] )
return true;
if (P_BoxOnLineSide (tmfbbox, ld) != -1)
if (box.BoxOnLineSide (ld) != -1)
return true;
// A line has been hit
@ -223,17 +221,13 @@ static bool PIT_FindFloorCeiling (line_t *ld)
void P_FindFloorCeiling (AActor *actor)
{
int xl,xh,yl,yh,bx,by;
fixed_t x, y;
sector_t *sec;
x = actor->x;
y = actor->y;
tmfbbox[BOXTOP] = y + actor->radius;
tmfbbox[BOXBOTTOM] = y - actor->radius;
tmfbbox[BOXRIGHT] = x + actor->radius;
tmfbbox[BOXLEFT] = x - actor->radius;
FBoundingBox box(x, y, actor->radius);
sec = P_PointInSector (x, y);
tmffloorz = tmfdropoffz = sec->floorplane.ZatPoint (x, y);
@ -242,18 +236,15 @@ void P_FindFloorCeiling (AActor *actor)
tmffloorsector = sec;
tmfceilingpic = sec->ceilingpic;
tmfceilingsector = sec;
tmfthing = actor;
validcount++;
xl = (tmfbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT;
xh = (tmfbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT;
yl = (tmfbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
yh = (tmfbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT;
FBlockLinesIterator it(box);
line_t *ld;
for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++)
if (!P_BlockLinesIterator (bx, by, PIT_FindFloorCeiling))
return;
while ((ld = it.Next()))
{
PIT_FindFloorCeiling(ld, actor, box, x, y);
}
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
}
@ -340,10 +331,10 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
tmy = y;
tmz = z;
tmfbbox[BOXTOP] = tmbbox[BOXTOP] = y + tmthing->radius;
tmfbbox[BOXBOTTOM] = tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmfbbox[BOXRIGHT] = tmbbox[BOXRIGHT] = x + tmthing->radius;
tmfbbox[BOXLEFT] = tmbbox[BOXLEFT] = x - tmthing->radius;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmbbox[BOXRIGHT] = x + tmthing->radius;
tmbbox[BOXLEFT] = x - tmthing->radius;
newsec = P_PointInSector (x,y);
ceilingline = NULL;
@ -356,7 +347,6 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
tmffloorsector = newsec;
tmfceilingpic = newsec->ceilingpic;
tmfceilingsector = newsec;
tmfthing = tmthing;
validcount++;
spechit.Clear ();
@ -364,21 +354,13 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag;
// stomp on any things contacted
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
FBoundingBox box(x, y, thing->radius);
FBlockLinesIterator it(box);
line_t *ld;
for (bx=xl ; bx<=xh ; bx++)
while ((ld = it.Next()))
{
for (by=yl ; by<=yh ; by++)
{
if (!P_BlockLinesIterator(bx,by,PIT_FindFloorCeiling))
{
return false;
}
}
PIT_FindFloorCeiling(ld, thing, box, x, y);
}
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
@ -391,6 +373,13 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
int savecpic = tmffloorpic;
fixed_t savedropoff = tmfdropoffz;
// stomp on any things contacted
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
// stomp on any things contacted
for (bx=xl ; bx<=xh ; bx++)
{
for (by=yl ; by<=yh ; by++)
@ -609,54 +598,23 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp)
// MOVEMENT ITERATOR FUNCTIONS
//
// // phares
// PIT_CrossLine // |
// Checks to see if a PE->LS trajectory line crosses a blocking // V
// line. Returns false if it does.
//
// tmbbox holds the bounding box of the trajectory. If that box
// does not touch the bounding box of the line in question,
// then the trajectory is not blocked. If the PE is on one side
// of the line and the LS is on the other side, then the
// trajectory is blocked.
//
// Currently this assumes an infinite line, which is not quite
// correct. A more correct solution would be to check for an
// intersection of the trajectory and the line, but that takes
// longer and probably really isn't worth the effort.
//
static // killough 3/26/98: make static
bool PIT_CrossLine (line_t* ld)
{
if (!(ld->flags & ML_TWOSIDED) ||
(ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_BLOCKEVERYTHING)))
if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] ||
tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] ||
tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] ||
tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))
if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))
return(false); // line blocks trajectory // ^
return(true); // line doesn't block trajectory // |
} // phares
//
// PIT_CheckLine
// Adjusts tmfloorz and tmceilingz as lines are contacted
//
static // killough 3/26/98: make static
bool PIT_CheckLine (line_t *ld)
bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
{
bool rail = false;
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
if (box.Right() <= ld->bbox[BOXLEFT]
|| box.Left() >= ld->bbox[BOXRIGHT]
|| box.Top() <= ld->bbox[BOXBOTTOM]
|| box.Bottom() >= ld->bbox[BOXTOP] )
return true;
if (P_BoxOnLineSide (tmbbox, ld) != -1)
if (box.BoxOnLineSide (ld) != -1)
return true;
// A line has been hit
@ -1113,51 +1071,6 @@ bool PIT_CheckThing (AActor *thing)
// return !(thing->flags & MF_SOLID); // old code -- killough
}
// This routine checks for Lost Souls trying to be spawned // phares
// across 1-sided lines, impassible lines, or "monsters can't // |
// cross" lines. Draw an imaginary line between the PE // V
// and the new Lost Soul spawn spot. If that line crosses
// a 'blocking' line, then disallow the spawn. Only search
// lines in the blocks of the blockmap where the bounding box
// of the trajectory line resides. Then check bounding box
// of the trajectory vs. the bounding box of each blocking
// line to see if the trajectory and the blocking line cross.
// Then check the PE and LS to see if they're on different
// sides of the blocking line. If so, return true, otherwise
// false.
bool Check_Sides(AActor* actor, int x, int y)
{
int bx,by,xl,xh,yl,yh;
pe_x = actor->x;
pe_y = actor->y;
ls_x = x;
ls_y = y;
// Here is the bounding box of the trajectory
tmbbox[BOXLEFT] = pe_x < x ? pe_x : x;
tmbbox[BOXRIGHT] = pe_x > x ? pe_x : x;
tmbbox[BOXTOP] = pe_y > y ? pe_y : y;
tmbbox[BOXBOTTOM] = pe_y < y ? pe_y : y;
// Determine which blocks to look in for blocking lines
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
// xl->xh, yl->yh determine the mapblock set to search
validcount++; // prevents checking same line twice
for (bx = xl ; bx <= xh ; bx++)
for (by = yl ; by <= yh ; by++)
if (!P_BlockLinesIterator(bx,by,PIT_CrossLine))
return true; // ^
return(false); // |
} // phares
//---------------------------------------------------------------------------
//
@ -1286,10 +1199,12 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
tmx = x;
tmy = y;
tmbbox[BOXTOP] = y + thing->radius;
tmbbox[BOXBOTTOM] = y - thing->radius;
tmbbox[BOXRIGHT] = x + thing->radius;
tmbbox[BOXLEFT] = x - thing->radius;
FBoundingBox box(x, y, thing->radius);
tmbbox[BOXTOP] = box.Top();
tmbbox[BOXBOTTOM] = box.Bottom();
tmbbox[BOXRIGHT] = box.Right();
tmbbox[BOXLEFT] = box.Left();
newsec = P_PointInSector (x,y);
ceilingline = BlockingLine = NULL;
@ -1407,19 +1322,18 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
thing->height = realheight;
if (tmflags & MF_NOCLIP)
return (BlockingMobj = thingblocker) == NULL;
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
FBlockLinesIterator it(box);
line_t *ld;
fixed_t thingdropoffz = tmfloorz;
//bool onthing = (thingdropoffz != tmdropoffz);
tmfloorz = tmdropoffz;
for (bx=xl ; bx<=xh ; bx++)
for (by=yl ; by<=yh ; by++)
if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
return false;
while ((ld = it.Next()))
{
if (!PIT_CheckLine(ld, box)) return false;
}
if (tmceilingz - tmfloorz < thing->height)
return false;
@ -4713,50 +4627,6 @@ void P_DelSeclist (msecnode_t *node)
node = P_DelSecnode (node);
}
//=============================================================================
// phares 3/14/98
//
// PIT_GetSectors
//
// Locates all the sectors the object is in by looking at the lines that
// cross through it. You have already decided that the object is allowed
// at this location, so don't bother with checking impassable or
// blocking lines.
//=============================================================================
bool PIT_GetSectors (line_t *ld)
{
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] ||
tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
return true;
if (P_BoxOnLineSide (tmbbox, ld) != -1)
return true;
// This line crosses through the object.
// Collect the sector(s) from the line and add to the
// sector_list you're examining. If the Thing ends up being
// allowed to move to this position, then the sector_list
// will be attached to the Thing's AActor at touching_sectorlist.
sector_list = P_AddSecnode (ld->frontsector,tmthing,sector_list);
// Don't assume all lines are 2-sided, since some Things
// like MT_TFOG are allowed regardless of whether their radius takes
// them beyond an impassable linedef.
// killough 3/27/98, 4/4/98:
// Use sidedefs instead of 2s flag to determine two-sidedness.
if (ld->backsector)
sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list);
return true;
}
//=============================================================================
// phares 3/14/98
//
@ -4768,18 +4638,8 @@ bool PIT_GetSectors (line_t *ld)
void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
{
int xl, xh, yl, yh, bx, by;
msecnode_t *node;
// [RH] Save old tm* values.
AActor *thingsave = tmthing;
int flagssave = tmflags;
fixed_t xsave = tmx;
fixed_t ysave = tmy;
fixed_t bboxsave[4];
memcpy (bboxsave, tmbbox, sizeof(bboxsave));
// First, clear out the existing m_thing fields. As each node is
// added or verified as needed, m_thing will be set properly. When
// finished, delete all nodes where m_thing is still NULL. These
@ -4792,27 +4652,40 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
node = node->m_tnext;
}
tmthing = thing;
tmflags = thing->flags;
FBoundingBox box(thing->x, thing->y, thing->radius);
FBlockLinesIterator it(box);
line_t *ld;
tmx = x;
tmy = y;
while ((ld = it.Next()))
{
if (box.Right() <= ld->bbox[BOXLEFT] ||
box.Left() >= ld->bbox[BOXRIGHT] ||
box.Top() <= ld->bbox[BOXBOTTOM] ||
box.Bottom() >= ld->bbox[BOXTOP])
continue;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmbbox[BOXRIGHT] = x + tmthing->radius;
tmbbox[BOXLEFT] = x - tmthing->radius;
if (box.BoxOnLineSide (ld) != -1)
continue;
validcount++; // used to make sure we only process a line once
// This line crosses through the object.
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
// Collect the sector(s) from the line and add to the
// sector_list you're examining. If the Thing ends up being
// allowed to move to this position, then the sector_list
// will be attached to the Thing's AActor at touching_sectorlist.
for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++)
P_BlockLinesIterator (bx,by,PIT_GetSectors);
sector_list = P_AddSecnode (ld->frontsector,thing,sector_list);
// Don't assume all lines are 2-sided, since some Things
// like MT_TFOG are allowed regardless of whether their radius takes
// them beyond an impassable linedef.
// killough 3/27/98, 4/4/98:
// Use sidedefs instead of 2s flag to determine two-sidedness.
if (ld->backsector)
sector_list = P_AddSecnode(ld->backsector, thing, sector_list);
}
// Add the sector of the (x,y) point to sector_list.
@ -4835,13 +4708,6 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
node = node->m_tnext;
}
}
// [RH] Restore old tm* values.
tmthing = thingsave;
tmflags = flagssave;
tmx = xsave;
tmy = ysave;
memcpy (tmbbox, bboxsave, sizeof(bboxsave));
}
void SpawnShootDecal (AActor *t1, const FTraceResults &trace)