mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-20 08:20:52 +00:00
Merge branch 'checksector-refactor' into 'next'
Refactor P_CheckSector Closes #870 See merge request STJr/SRB2!1946
This commit is contained in:
commit
d5a3f10a4d
1 changed files with 165 additions and 253 deletions
418
src/p_map.c
418
src/p_map.c
|
@ -4256,13 +4256,11 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
|
||||||
// the way it was and call P_CheckSector (? was P_ChangeSector - Graue) again
|
// the way it was and call P_CheckSector (? was P_ChangeSector - Graue) again
|
||||||
// to undo the changes.
|
// to undo the changes.
|
||||||
//
|
//
|
||||||
static boolean crushchange;
|
|
||||||
static boolean nofit;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// PIT_ChangeSector
|
// PIT_ChangeSector
|
||||||
//
|
//
|
||||||
static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch)
|
||||||
{
|
{
|
||||||
mobj_t *killer = NULL;
|
mobj_t *killer = NULL;
|
||||||
//If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed.
|
//If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed.
|
||||||
|
@ -4286,11 +4284,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
||||||
if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz)
|
if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz)
|
||||||
{
|
{
|
||||||
if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight)
|
if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight)
|
||||||
{
|
return false; //Thing is a pushable and blocks the moving ceiling
|
||||||
//Thing is a pushable and blocks the moving ceiling
|
|
||||||
nofit = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check FOFs in the sector
|
//Check FOFs in the sector
|
||||||
if (thing->subsector->sector->ffloors && (realcrush || immunepushable))
|
if (thing->subsector->sector->ffloors && (realcrush || immunepushable))
|
||||||
|
@ -4302,47 +4296,54 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
||||||
|
|
||||||
for (rover = thing->subsector->sector->ffloors; rover; rover = rover->next)
|
for (rover = thing->subsector->sector->ffloors; rover; rover = rover->next)
|
||||||
{
|
{
|
||||||
if (!(((rover->fofflags & FOF_BLOCKPLAYER) && thing->player)
|
thinker_t *think;
|
||||||
|| ((rover->fofflags & FOF_BLOCKOTHERS) && !thing->player)) || !(rover->fofflags & FOF_EXISTS))
|
|
||||||
|
if (!(rover->fofflags & FOF_EXISTS))
|
||||||
|
continue;
|
||||||
|
if (thing->player && !(rover->fofflags & FOF_BLOCKPLAYER))
|
||||||
|
continue;
|
||||||
|
if (!thing->player && !(rover->fofflags & FOF_BLOCKOTHERS))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = *rover->topheight;
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = *rover->bottomheight;
|
||||||
//topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y);
|
|
||||||
//bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y);
|
if (bottomheight > thing->ceilingz)
|
||||||
|
continue;
|
||||||
|
|
||||||
delta1 = thing->z - (bottomheight + topheight)/2;
|
delta1 = thing->z - (bottomheight + topheight)/2;
|
||||||
delta2 = thingtop - (bottomheight + topheight)/2;
|
delta2 = thingtop - (bottomheight + topheight)/2;
|
||||||
if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
|
if (abs(delta1) < abs(delta2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (immunepushable)
|
||||||
|
return false; //FOF is blocked by pushable
|
||||||
|
|
||||||
|
if (!realcrush)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//If the thing was crushed by a crumbling FOF, reward the player who made it crumble!
|
||||||
|
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
|
||||||
{
|
{
|
||||||
if (immunepushable)
|
crumble_t *crumbler;
|
||||||
{
|
|
||||||
//FOF is blocked by pushable
|
|
||||||
nofit = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//If the thing was crushed by a crumbling FOF, reward the player who made it crumble!
|
|
||||||
thinker_t *think;
|
|
||||||
crumble_t *crumbler;
|
|
||||||
|
|
||||||
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
|
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
|
||||||
{
|
continue;
|
||||||
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
crumbler = (crumble_t *)think;
|
crumbler = (crumble_t *)think;
|
||||||
|
|
||||||
if (crumbler->player && crumbler->player->mo
|
if (!crumbler->player)
|
||||||
&& crumbler->player->mo != thing
|
continue;
|
||||||
&& crumbler->actionsector == thing->subsector->sector
|
if (!crumbler->player->mo)
|
||||||
&& crumbler->sector == rover->master->frontsector)
|
continue;
|
||||||
{
|
if (crumbler->player->mo == thing)
|
||||||
killer = crumbler->player->mo;
|
continue;
|
||||||
}
|
if (crumbler->actionsector != thing->subsector->sector)
|
||||||
}
|
continue;
|
||||||
}
|
if (crumbler->sector != rover->master->frontsector)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
killer = crumbler->player->mo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4358,24 +4359,139 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realcrush && crushchange)
|
if (realcrush && crunch)
|
||||||
P_DamageMobj(thing, NULL, NULL, 1, 0);
|
P_DamageMobj(thing, NULL, NULL, 1, 0);
|
||||||
|
|
||||||
// keep checking (crush other things)
|
// keep checking (crush other things)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boolean crunch)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
// Sal: This stupid function chain is required to fix polyobjects not being able to crush.
|
||||||
|
// Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead
|
||||||
|
validcount++;
|
||||||
|
|
||||||
|
for (i = 0; i < sector->linecount; i++)
|
||||||
|
{
|
||||||
|
INT32 x, y;
|
||||||
|
polyobj_t *po = sector->lines[i]->polyobj;
|
||||||
|
|
||||||
|
if (!po)
|
||||||
|
continue;
|
||||||
|
if (po->validcount == validcount)
|
||||||
|
continue; // skip if already checked
|
||||||
|
if (!(po->flags & POF_SOLID))
|
||||||
|
continue;
|
||||||
|
if (po->lines[0]->backsector != sector) // Make sure you're currently checking the control sector
|
||||||
|
continue;
|
||||||
|
|
||||||
|
po->validcount = validcount;
|
||||||
|
|
||||||
|
for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y)
|
||||||
|
{
|
||||||
|
for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x)
|
||||||
|
{
|
||||||
|
mobj_t *mo;
|
||||||
|
|
||||||
|
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mo = blocklinks[y * bmapwidth + x];
|
||||||
|
|
||||||
|
for (; mo; mo = mo->bnext)
|
||||||
|
{
|
||||||
|
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
|
||||||
|
|
||||||
|
if (!P_MobjInsidePolyobj(po, mo))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!PIT_ChangeSector(mo, realcrush, crunch) && !realcrush)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean P_CheckTouchingThinglist(sector_t *sector, boolean realcrush, boolean crunch)
|
||||||
|
{
|
||||||
|
msecnode_t *n;
|
||||||
|
|
||||||
|
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next)
|
||||||
|
n->visited = false;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list
|
||||||
|
{
|
||||||
|
if (n->visited)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
n->visited = true; // mark thing as processed
|
||||||
|
|
||||||
|
if (n->m_thing->flags & MF_NOBLOCKMAP) //jff 4/7/98 don't do these
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) // process it
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break; // exit and start over
|
||||||
|
}
|
||||||
|
} while (n); // repeat from scratch until all things left are marked valid
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean P_CheckSectorFFloors(sector_t *sector, boolean realcrush, boolean crunch)
|
||||||
|
{
|
||||||
|
sector_t *sec;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!sector->numattached)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (i = 0; i < sector->numattached; i++)
|
||||||
|
{
|
||||||
|
sec = §ors[sector->attached[i]];
|
||||||
|
|
||||||
|
sec->moved = true;
|
||||||
|
|
||||||
|
P_RecalcPrecipInSector(sec);
|
||||||
|
|
||||||
|
if (!sector->attachedsolid[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!P_CheckTouchingThinglist(sec, realcrush, crunch))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean crunch)
|
||||||
|
{
|
||||||
|
if (!P_CheckSectorPolyObjects(sector, realcrush, crunch))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!P_CheckSectorFFloors(sector, realcrush, crunch))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Mark all things invalid
|
||||||
|
sector->moved = true;
|
||||||
|
|
||||||
|
return P_CheckTouchingThinglist(sector, realcrush, crunch);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_CheckSector
|
// P_CheckSector
|
||||||
//
|
//
|
||||||
boolean P_CheckSector(sector_t *sector, boolean crunch)
|
boolean P_CheckSector(sector_t *sector, boolean crunch)
|
||||||
{
|
{
|
||||||
msecnode_t *n;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
nofit = false;
|
|
||||||
crushchange = crunch;
|
|
||||||
|
|
||||||
// killough 4/4/98: scan list front-to-back until empty or exhausted,
|
// killough 4/4/98: scan list front-to-back until empty or exhausted,
|
||||||
// restarting from beginning after each thing is processed. Avoids
|
// restarting from beginning after each thing is processed. Avoids
|
||||||
// crashes, and is sure to examine all things in the sector, and only
|
// crashes, and is sure to examine all things in the sector, and only
|
||||||
|
@ -4384,218 +4500,14 @@ boolean P_CheckSector(sector_t *sector, boolean crunch)
|
||||||
//
|
//
|
||||||
// killough 4/7/98: simplified to avoid using complicated counter
|
// killough 4/7/98: simplified to avoid using complicated counter
|
||||||
|
|
||||||
|
|
||||||
// First, let's see if anything will keep it from crushing.
|
// First, let's see if anything will keep it from crushing.
|
||||||
|
if (!P_CheckSectorHelper(sector, false, crunch))
|
||||||
// Sal: This stupid function chain is required to fix polyobjects not being able to crush.
|
return true;
|
||||||
// Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead
|
|
||||||
validcount++;
|
|
||||||
|
|
||||||
for (i = 0; i < sector->linecount; i++)
|
|
||||||
{
|
|
||||||
if (sector->lines[i]->polyobj)
|
|
||||||
{
|
|
||||||
polyobj_t *po = sector->lines[i]->polyobj;
|
|
||||||
if (po->validcount == validcount)
|
|
||||||
continue; // skip if already checked
|
|
||||||
if (!(po->flags & POF_SOLID))
|
|
||||||
continue;
|
|
||||||
if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector
|
|
||||||
{
|
|
||||||
INT32 x, y;
|
|
||||||
po->validcount = validcount;
|
|
||||||
|
|
||||||
for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y)
|
|
||||||
{
|
|
||||||
for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x)
|
|
||||||
{
|
|
||||||
mobj_t *mo;
|
|
||||||
|
|
||||||
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo = blocklinks[y * bmapwidth + x];
|
|
||||||
|
|
||||||
for (; mo; mo = mo->bnext)
|
|
||||||
{
|
|
||||||
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
|
|
||||||
|
|
||||||
if (!P_MobjInsidePolyobj(po, mo))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!PIT_ChangeSector(mo, false))
|
|
||||||
{
|
|
||||||
nofit = true;
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sector->numattached)
|
|
||||||
{
|
|
||||||
sector_t *sec;
|
|
||||||
for (i = 0; i < sector->numattached; i++)
|
|
||||||
{
|
|
||||||
sec = §ors[sector->attached[i]];
|
|
||||||
for (n = sec->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
n->visited = false;
|
|
||||||
|
|
||||||
sec->moved = true;
|
|
||||||
|
|
||||||
P_RecalcPrecipInSector(sec);
|
|
||||||
|
|
||||||
if (!sector->attachedsolid[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (n = sec->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
if (!n->visited)
|
|
||||||
{
|
|
||||||
n->visited = true;
|
|
||||||
if (!(n->m_thing->flags & MF_NOBLOCKMAP))
|
|
||||||
{
|
|
||||||
if (!PIT_ChangeSector(n->m_thing, false))
|
|
||||||
{
|
|
||||||
nofit = true;
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark all things invalid
|
|
||||||
sector->moved = true;
|
|
||||||
|
|
||||||
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
n->visited = false;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list
|
|
||||||
if (!n->visited) // unprocessed thing found
|
|
||||||
{
|
|
||||||
n->visited = true; // mark thing as processed
|
|
||||||
if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
|
|
||||||
{
|
|
||||||
if (!PIT_ChangeSector(n->m_thing, false)) // process it
|
|
||||||
{
|
|
||||||
nofit = true;
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break; // exit and start over
|
|
||||||
}
|
|
||||||
} while (n); // repeat from scratch until all things left are marked valid
|
|
||||||
|
|
||||||
// Nothing blocked us, so lets crush for real!
|
// Nothing blocked us, so lets crush for real!
|
||||||
|
P_CheckSectorHelper(sector, true, crunch);
|
||||||
|
|
||||||
// Sal: This stupid function chain is required to fix polyobjects not being able to crush.
|
return false;
|
||||||
// Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead
|
|
||||||
validcount++;
|
|
||||||
|
|
||||||
for (i = 0; i < sector->linecount; i++)
|
|
||||||
{
|
|
||||||
if (sector->lines[i]->polyobj)
|
|
||||||
{
|
|
||||||
polyobj_t *po = sector->lines[i]->polyobj;
|
|
||||||
if (po->validcount == validcount)
|
|
||||||
continue; // skip if already checked
|
|
||||||
if (!(po->flags & POF_SOLID))
|
|
||||||
continue;
|
|
||||||
if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector
|
|
||||||
{
|
|
||||||
INT32 x, y;
|
|
||||||
po->validcount = validcount;
|
|
||||||
|
|
||||||
for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y)
|
|
||||||
{
|
|
||||||
for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x)
|
|
||||||
{
|
|
||||||
mobj_t *mo;
|
|
||||||
|
|
||||||
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo = blocklinks[y * bmapwidth + x];
|
|
||||||
|
|
||||||
for (; mo; mo = mo->bnext)
|
|
||||||
{
|
|
||||||
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
|
|
||||||
|
|
||||||
if (!P_MobjInsidePolyobj(po, mo))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
PIT_ChangeSector(mo, true);
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sector->numattached)
|
|
||||||
{
|
|
||||||
sector_t *sec;
|
|
||||||
for (i = 0; i < sector->numattached; i++)
|
|
||||||
{
|
|
||||||
sec = §ors[sector->attached[i]];
|
|
||||||
for (n = sec->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
n->visited = false;
|
|
||||||
|
|
||||||
sec->moved = true;
|
|
||||||
|
|
||||||
P_RecalcPrecipInSector(sec);
|
|
||||||
|
|
||||||
if (!sector->attachedsolid[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (n = sec->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
if (!n->visited)
|
|
||||||
{
|
|
||||||
n->visited = true;
|
|
||||||
if (!(n->m_thing->flags & MF_NOBLOCKMAP))
|
|
||||||
{
|
|
||||||
PIT_ChangeSector(n->m_thing, true);
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark all things invalid
|
|
||||||
sector->moved = true;
|
|
||||||
|
|
||||||
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next)
|
|
||||||
n->visited = false;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list
|
|
||||||
if (!n->visited) // unprocessed thing found
|
|
||||||
{
|
|
||||||
n->visited = true; // mark thing as processed
|
|
||||||
if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
|
|
||||||
{
|
|
||||||
PIT_ChangeSector(n->m_thing, true); // process it
|
|
||||||
return nofit;
|
|
||||||
}
|
|
||||||
break; // exit and start over
|
|
||||||
}
|
|
||||||
} while (n); // repeat from scratch until all things left are marked valid
|
|
||||||
|
|
||||||
return nofit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue