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
|
||||
// to undo the changes.
|
||||
//
|
||||
static boolean crushchange;
|
||||
static boolean nofit;
|
||||
|
||||
//
|
||||
// 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;
|
||||
//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 (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight)
|
||||
{
|
||||
//Thing is a pushable and blocks the moving ceiling
|
||||
nofit = true;
|
||||
return false;
|
||||
}
|
||||
return false; //Thing is a pushable and blocks the moving ceiling
|
||||
|
||||
//Check FOFs in the sector
|
||||
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)
|
||||
{
|
||||
if (!(((rover->fofflags & FOF_BLOCKPLAYER) && thing->player)
|
||||
|| ((rover->fofflags & FOF_BLOCKOTHERS) && !thing->player)) || !(rover->fofflags & FOF_EXISTS))
|
||||
thinker_t *think;
|
||||
|
||||
if (!(rover->fofflags & FOF_EXISTS))
|
||||
continue;
|
||||
if (thing->player && !(rover->fofflags & FOF_BLOCKPLAYER))
|
||||
continue;
|
||||
if (!thing->player && !(rover->fofflags & FOF_BLOCKOTHERS))
|
||||
continue;
|
||||
|
||||
topheight = *rover->topheight;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
//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;
|
||||
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
|
||||
&& crumbler->player->mo != thing
|
||||
&& crumbler->actionsector == thing->subsector->sector
|
||||
&& crumbler->sector == rover->master->frontsector)
|
||||
{
|
||||
killer = crumbler->player->mo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!crumbler->player)
|
||||
continue;
|
||||
if (!crumbler->player->mo)
|
||||
continue;
|
||||
if (crumbler->player->mo == thing)
|
||||
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);
|
||||
|
||||
// keep checking (crush other things)
|
||||
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
|
||||
//
|
||||
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,
|
||||
// restarting from beginning after each thing is processed. Avoids
|
||||
// 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
|
||||
|
||||
|
||||
// First, let's see if anything will keep it from crushing.
|
||||
|
||||
// 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++)
|
||||
{
|
||||
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
|
||||
if (!P_CheckSectorHelper(sector, false, crunch))
|
||||
return true;
|
||||
|
||||
// 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.
|
||||
// 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;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue