Add thing argument to P_BlockThingsIterator and P_DoBlockThingsIterate

This commit is contained in:
MIDIMan 2024-12-11 14:34:52 -05:00
parent 9c74a73e57
commit f836f9e145
6 changed files with 116 additions and 43 deletions

View file

@ -5582,7 +5582,7 @@ void A_MinusDigging(mobj_t *actor)
minus = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry, minus);
}
else
{
@ -13726,7 +13726,7 @@ void A_DustDevilThink(mobj_t *actor)
dustdevil = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch, dustdevil);
//Whirlwind sound effect.
if (leveltime % 70 == 0)
@ -13842,7 +13842,7 @@ void A_TNTExplode(mobj_t *actor)
barrel = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode, barrel);
// cause a quake -- P_StartQuake does not exist yet
epicenter.x = actor->x;

View file

@ -2264,7 +2264,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++)
{
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing))
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing, tmthing))
blockval = false;
else
tmhitthing = tmfloorthing;
@ -2883,7 +2883,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
standx = x;
standy = y;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved, stand);
}
// Link the thing into its new position
@ -4229,7 +4229,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
bombdamagetype = damagetype;
bombsightcheck = sightcheck;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack, bombspot);
}
//

View file

@ -1050,10 +1050,14 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
//
// P_BlockThingsIterator
//
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *), mobj_t *thing)
{
mobj_t *bnext = NULL;
blocknode_t *block, *next = NULL;
boolean checkthing = false;
if (thing)
checkthing = true;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
return true;
@ -1071,7 +1075,7 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
return false;
}
if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue.
if ((checkthing && P_MobjWasRemoved(thing)) // func just popped our tmthing, cannot continue.
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
{
P_SetTarget(&bnext, NULL);
@ -1084,13 +1088,13 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
return true;
}
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *))
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing)
{
boolean status = true;
for (INT32 bx = x1; bx <= x2; bx++)
for (INT32 by = y1; by <= y2; by++)
if (!P_BlockThingsIterator(bx, by, func))
if (!P_BlockThingsIterator(bx, by, func, thing))
status = false;
return status;
@ -1463,7 +1467,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
INT32 flags, traverser_t trav)
{
fixed_t xt1, yt1, xt2, yt2;
fixed_t xstep, ystep, partial, xintercept, yintercept;
fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept;
INT32 mapx, mapy, mapxstep, mapystep, count;
earlyout = flags & PT_EARLYOUT;
@ -1481,57 +1485,83 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
trace.y = py1;
trace.dx = px2 - px1;
trace.dy = py2 - py1;
px1 -= bmaporgx;
py1 -= bmaporgy;
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
px2 -= bmaporgx;
py2 -= bmaporgy;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
xt1 = px1>>MAPBLOCKSHIFT;
yt1 = py2>>MAPBLOCKSHIFT;
px1 = (unsigned)(px1 - bmaporgx);
py1 = (unsigned)(py1 - bmaporgy);
xt2 = px2>>MAPBLOCKSHIFT;
yt2 = py2>>MAPBLOCKSHIFT;
px2 = (unsigned)(px2 - bmaporgx);
py2 = (unsigned)(py2 - bmaporgy);
if (xt2 > xt1)
{
mapxstep = 1;
partial = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK);
partialx = FRACUNIT - (((unsigned)px1>>MAPBTOFRAC) & FRACMASK);
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
}
else if (xt2 < xt1)
{
mapxstep = -1;
partial = (px1>>MAPBTOFRAC) & FRACMASK;
partialx = ((unsigned)px1>>MAPBTOFRAC) & FRACMASK;
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
}
else
{
mapxstep = 0;
partial = FRACUNIT;
partialx = FRACUNIT;
ystep = 256*FRACUNIT;
}
yintercept = (py1>>MAPBTOFRAC) + FixedMul(partial, ystep);
yintercept = ((unsigned)py1>>MAPBTOFRAC) + FixedMul(partialx, ystep);
if (yt2 > yt1)
{
mapystep = 1;
partial = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK);
partialy = FRACUNIT - (((unsigned)py1>>MAPBTOFRAC) & FRACMASK);
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
}
else if (yt2 < yt1)
{
mapystep = -1;
partial = (py1>>MAPBTOFRAC) & FRACMASK;
partialy = ((unsigned)py1>>MAPBTOFRAC) & FRACMASK;
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
}
else
{
mapystep = 0;
partial = FRACUNIT;
partialy = FRACUNIT;
xstep = 256*FRACUNIT;
}
xintercept = (px1>>MAPBTOFRAC) + FixedMul(partial, xstep);
xintercept = ((unsigned)px1>>MAPBTOFRAC) + FixedMul(partialy, xstep);
// [RH] Fix for traces that pass only through blockmap corners. In that case,
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
// for loop would never advance anywhere.
if (abs(xstep) == 1 && abs(ystep) == 1)
{
if (ystep < 0)
{
partialx = FRACUNIT - partialx;
}
if (xstep < 0)
{
partialy = FRACUNIT - partialy;
}
if (partialx == partialy)
{
xintercept = xt1;
yintercept = yt1;
}
}
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
// Step through map blocks.
// Count is present to prevent a round off error
@ -1546,21 +1576,64 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
return false; // early out
if (flags & PT_ADDTHINGS)
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts))
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out
if (mapx == xt2 && mapy == yt2)
// both coordinates reached the end, so end the traversing.
if ((mapxstep | mapystep) == 0)
break;
if ((yintercept >> FRACBITS) == mapy)
// [RH] Handle corner cases properly instead of pretending they don't exist.
switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
{
yintercept += ystep;
mapx += mapxstep;
}
else if ((xintercept >> FRACBITS) == mapx)
{
xintercept += xstep;
mapy += mapystep;
case 0: // neither xintercept nor yintercept match!
count = 64; // Stop traversing, because somebody screwed up.
break;
case 1: // xintercept matches
xintercept += xstep;
mapy += mapystep;
if (mapy == yt2)
mapystep = 0;
break;
case 2: // yintercept matches
yintercept += ystep;
mapx += mapxstep;
if (mapx == xt2)
mapxstep = 0;
break;
case 3: // xintercept and yintercept both match
// The trace is exiting a block through its corner. Not only does the block
// 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 (!P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts))
return false; // early out
if (!P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts))
return false; // early out
}
if (flags & PT_ADDTHINGS)
{
if (!P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out
if (!P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts, NULL))
return false; // early out
}
xintercept += xstep;
yintercept += ystep;
mapx += mapxstep;
mapy += mapystep;
if (mapx == xt2)
mapxstep = 0;
if (mapy == yt2)
mapystep = 0;
break;
}
}
// Go through the sorted list

View file

@ -61,7 +61,7 @@ extern ffloor_t *openfloorrover, *openceilingrover;
void P_LineOpening(line_t *plinedef, mobj_t *mobj);
boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *), mobj_t *thing);
void P_ClearBlockNodes(void);
@ -94,7 +94,7 @@ typedef struct bthingit_s
bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2);
mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly);
void P_FreeBlockThingsIterator(bthingit_t *it);
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *));
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing);
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2

View file

@ -9342,7 +9342,7 @@ static void P_PointPushThink(mobj_t *mobj)
yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing);
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing, pushmobj);
}
static boolean P_MobjRegularThink(mobj_t *mobj)

View file

@ -4126,7 +4126,7 @@ static void P_DoTeeter(player_t *player)
teeteryl = teeteryh = player->mo->y;
couldteeter = false;
solidteeter = teeter;
if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter))
if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter, tmthing))
goto teeterdone; // we've found something that stops us teetering at all
teeterdone:
teeter = solidteeter;