mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-15 16:51:31 +00:00
- Fixed: The game would lockup when using the override polyobject specials with cyclical chains
of mirrored polyobjects. Fixing this has also removed lots of duplicated code for mirrored polyobjects. SVN r3400 (trunk)
This commit is contained in:
parent
f6c1c0e2df
commit
676ce338b1
1 changed files with 137 additions and 162 deletions
299
src/po_man.cpp
299
src/po_man.cpp
|
@ -154,6 +154,17 @@ private:
|
|||
DPolyDoor ();
|
||||
};
|
||||
|
||||
class FPolyMirrorIterator
|
||||
{
|
||||
FPolyObj *CurPoly;
|
||||
int UsedPolys[100]; // tracks mirrored polyobjects we've seen
|
||||
int NumUsedPolys;
|
||||
|
||||
public:
|
||||
FPolyMirrorIterator(FPolyObj *poly);
|
||||
FPolyObj *NextMirror();
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
void PO_Init (void);
|
||||
|
@ -402,57 +413,25 @@ void DRotatePoly::Tick ()
|
|||
bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle,
|
||||
int direction, bool overRide)
|
||||
{
|
||||
int mirror;
|
||||
DRotatePoly *pe;
|
||||
DRotatePoly *pe = NULL;
|
||||
FPolyObj *poly;
|
||||
|
||||
if ( (poly = PO_GetPolyobj(polyNum)) )
|
||||
{
|
||||
if (poly->specialdata && !overRide)
|
||||
{ // poly is already moving
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((poly = PO_GetPolyobj(polyNum)) == NULL)
|
||||
{
|
||||
Printf("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum);
|
||||
return false;
|
||||
}
|
||||
pe = new DRotatePoly (polyNum);
|
||||
if (byteAngle)
|
||||
FPolyMirrorIterator it(poly);
|
||||
|
||||
while ((poly = it.NextMirror()) != NULL)
|
||||
{
|
||||
if (byteAngle == 255)
|
||||
{
|
||||
pe->m_Dist = ~0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->m_Dist = byteAngle*(ANGLE_90/64); // Angle
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->m_Dist = ANGLE_MAX-1;
|
||||
}
|
||||
pe->m_Speed = (speed*direction*(ANGLE_90/64))>>3;
|
||||
poly->specialdata = pe;
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
|
||||
while ( (mirror = poly->GetMirror()) )
|
||||
{
|
||||
poly = PO_GetPolyobj(mirror);
|
||||
if (poly == NULL)
|
||||
{
|
||||
Printf ("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum);
|
||||
if (poly->specialdata != NULL && !overRide)
|
||||
{ // poly is already in motion
|
||||
break;
|
||||
}
|
||||
if (poly->specialdata && !overRide)
|
||||
{ // mirroring poly is already in motion
|
||||
break;
|
||||
}
|
||||
pe = new DRotatePoly (mirror);
|
||||
pe = new DRotatePoly(poly->tag);
|
||||
poly->specialdata = pe;
|
||||
if (byteAngle)
|
||||
if (byteAngle != 0)
|
||||
{
|
||||
if (byteAngle == 255)
|
||||
{
|
||||
|
@ -467,12 +446,11 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle,
|
|||
{
|
||||
pe->m_Dist = ANGLE_MAX-1;
|
||||
}
|
||||
direction = -direction;
|
||||
pe->m_Speed = (speed*direction*(ANGLE_90/64))>>3;
|
||||
polyNum = mirror;
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
direction = -direction; // Reverse the direction
|
||||
}
|
||||
return true;
|
||||
return pe != NULL; // Return true if something started moving.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -515,67 +493,44 @@ void DMovePoly::Tick ()
|
|||
bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle,
|
||||
fixed_t dist, bool overRide)
|
||||
{
|
||||
int mirror;
|
||||
DMovePoly *pe;
|
||||
DMovePoly *pe = NULL;
|
||||
FPolyObj *poly;
|
||||
angle_t an;
|
||||
angle_t an = angle;
|
||||
|
||||
if ( (poly = PO_GetPolyobj(polyNum)) )
|
||||
{
|
||||
if (poly->specialdata && !overRide)
|
||||
{ // poly is already moving
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((poly = PO_GetPolyobj(polyNum)) == NULL)
|
||||
{
|
||||
Printf("EV_MovePoly: Invalid polyobj num: %d\n", polyNum);
|
||||
return false;
|
||||
}
|
||||
pe = new DMovePoly (polyNum);
|
||||
pe->m_Dist = dist; // Distance
|
||||
pe->m_Speed = speed;
|
||||
poly->specialdata = pe;
|
||||
FPolyMirrorIterator it(poly);
|
||||
|
||||
an = angle;
|
||||
|
||||
pe->m_Angle = an>>ANGLETOFINESHIFT;
|
||||
pe->m_xSpeed = FixedMul (pe->m_Speed, finecosine[pe->m_Angle]);
|
||||
pe->m_ySpeed = FixedMul (pe->m_Speed, finesine[pe->m_Angle]);
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
|
||||
// Do not interpolate very fast moving polyobjects. The minimum tic count is
|
||||
// 3 instead of 2, because the moving crate effect in Massmouth 2, Hostitality
|
||||
// that this fixes isn't quite fast enough to move the crate back to its start
|
||||
// in just 1 tic.
|
||||
if (dist/speed <= 2)
|
||||
while ((poly = it.NextMirror()) != NULL)
|
||||
{
|
||||
pe->StopInterpolation ();
|
||||
}
|
||||
|
||||
while ( (mirror = poly->GetMirror()) )
|
||||
{
|
||||
poly = PO_GetPolyobj(mirror);
|
||||
if (poly == NULL || (poly->specialdata != NULL && !overRide))
|
||||
{ // mirroring poly does not exist or is already in motion
|
||||
if (poly->specialdata != NULL && !overRide)
|
||||
{ // poly is already in motion
|
||||
break;
|
||||
}
|
||||
pe = new DMovePoly (mirror);
|
||||
pe = new DMovePoly(poly->tag);
|
||||
poly->specialdata = pe;
|
||||
pe->m_Dist = dist; // Distance
|
||||
pe->m_Speed = speed;
|
||||
an = an+ANGLE_180; // reverse the angle
|
||||
pe->m_Angle = an>>ANGLETOFINESHIFT;
|
||||
pe->m_Angle = an >> ANGLETOFINESHIFT;
|
||||
pe->m_xSpeed = FixedMul (pe->m_Speed, finecosine[pe->m_Angle]);
|
||||
pe->m_ySpeed = FixedMul (pe->m_Speed, finesine[pe->m_Angle]);
|
||||
polyNum = mirror;
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
|
||||
// Do not interpolate very fast moving polyobjects. The minimum tic count is
|
||||
// 3 instead of 2, because the moving crate effect in Massmouth 2, Hostitality
|
||||
// that this fixes isn't quite fast enough to move the crate back to its start
|
||||
// in just 1 tic.
|
||||
if (dist/speed <= 2)
|
||||
{
|
||||
pe->StopInterpolation ();
|
||||
}
|
||||
|
||||
an = an + ANGLE_180; // Reverse the angle.
|
||||
}
|
||||
return true;
|
||||
return pe != NULL; // Return true if something started moving.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -617,53 +572,28 @@ void DMovePolyTo::Tick ()
|
|||
|
||||
bool EV_MovePolyTo(line_t *line, int polyNum, int speed, fixed_t targx, fixed_t targy, bool overRide)
|
||||
{
|
||||
int mirror;
|
||||
DMovePolyTo *pe;
|
||||
DMovePolyTo *pe = NULL;
|
||||
FPolyObj *poly;
|
||||
TVector2<double> dist;
|
||||
double distlen;
|
||||
bool nointerp;
|
||||
|
||||
if ( (poly = PO_GetPolyobj(polyNum)) )
|
||||
{
|
||||
if (poly->specialdata && !overRide)
|
||||
{ // poly is already moving
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((poly = PO_GetPolyobj(polyNum)) == NULL)
|
||||
{
|
||||
Printf("EV_MovePolyTo: Invalid polyobj num: %d\n", polyNum);
|
||||
return false;
|
||||
}
|
||||
FPolyMirrorIterator it(poly);
|
||||
|
||||
dist.X = targx - poly->StartSpot.x;
|
||||
dist.Y = targy - poly->StartSpot.y;
|
||||
pe = new DMovePolyTo(polyNum);
|
||||
poly->specialdata = pe;
|
||||
pe->m_Dist = xs_RoundToInt(distlen = dist.MakeUnit());
|
||||
pe->m_Speed = speed;
|
||||
pe->m_xSpeed = xs_RoundToInt(speed * dist.X);
|
||||
pe->m_ySpeed = xs_RoundToInt(speed * dist.Y);
|
||||
pe->m_xTarget = targx;
|
||||
pe->m_yTarget = targy;
|
||||
|
||||
nointerp = (pe->m_Dist / pe->m_Speed) <= 2;
|
||||
if (nointerp)
|
||||
distlen = dist.MakeUnit();
|
||||
while ((poly = it.NextMirror()) != NULL)
|
||||
{
|
||||
pe->StopInterpolation();
|
||||
}
|
||||
|
||||
while ( (mirror = poly->GetMirror()) )
|
||||
{
|
||||
poly = PO_GetPolyobj(mirror);
|
||||
if (poly == NULL || (poly->specialdata != NULL && !overRide))
|
||||
{ // mirroring poly does not exist or is already in motion
|
||||
if (poly->specialdata != NULL && !overRide)
|
||||
{ // poly is already in motion
|
||||
break;
|
||||
}
|
||||
// reverse the direction
|
||||
dist.X = -dist.X;
|
||||
dist.Y = -dist.Y;
|
||||
pe = new DMovePolyTo(mirror);
|
||||
pe = new DMovePolyTo(poly->tag);
|
||||
poly->specialdata = pe;
|
||||
pe->m_Dist = xs_RoundToInt(distlen);
|
||||
pe->m_Speed = speed;
|
||||
|
@ -671,14 +601,13 @@ bool EV_MovePolyTo(line_t *line, int polyNum, int speed, fixed_t targx, fixed_t
|
|||
pe->m_ySpeed = xs_RoundToInt(speed * dist.Y);
|
||||
pe->m_xTarget = xs_RoundToInt(poly->StartSpot.x + distlen * dist.X);
|
||||
pe->m_yTarget = xs_RoundToInt(poly->StartSpot.y + distlen * dist.Y);
|
||||
polyNum = mirror;
|
||||
SN_StartSequence(poly, poly->seqType, SEQ_DOOR, 0);
|
||||
if (nointerp)
|
||||
if ((pe->m_Dist / pe->m_Speed) <= 2)
|
||||
{
|
||||
pe->StopInterpolation();
|
||||
}
|
||||
dist = -dist; // reverse the direction
|
||||
}
|
||||
return true;
|
||||
return pe != NULL; // Return true if something started moving.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -801,74 +730,48 @@ void DPolyDoor::Tick ()
|
|||
bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle,
|
||||
int delay, int distance, podoortype_t type)
|
||||
{
|
||||
int mirror;
|
||||
DPolyDoor *pd;
|
||||
DPolyDoor *pd = NULL;
|
||||
FPolyObj *poly;
|
||||
int swingdir = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR
|
||||
|
||||
if( (poly = PO_GetPolyobj(polyNum)) )
|
||||
{
|
||||
if (poly->specialdata)
|
||||
{ // poly is already moving
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((poly = PO_GetPolyobj(polyNum)) == NULL)
|
||||
{
|
||||
Printf("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum);
|
||||
return false;
|
||||
}
|
||||
pd = new DPolyDoor (polyNum, type);
|
||||
if (type == PODOOR_SLIDE)
|
||||
{
|
||||
pd->m_WaitTics = delay;
|
||||
pd->m_Speed = speed;
|
||||
pd->m_Dist = pd->m_TotalDist = distance; // Distance
|
||||
pd->m_Direction = angle >> ANGLETOFINESHIFT;
|
||||
pd->m_xSpeed = FixedMul (pd->m_Speed, finecosine[pd->m_Direction]);
|
||||
pd->m_ySpeed = FixedMul (pd->m_Speed, finesine[pd->m_Direction]);
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
}
|
||||
else if (type == PODOOR_SWING)
|
||||
{
|
||||
pd->m_WaitTics = delay;
|
||||
pd->m_Direction = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR
|
||||
pd->m_Speed = (speed*pd->m_Direction*(ANGLE_90/64))>>3;
|
||||
pd->m_Dist = pd->m_TotalDist = angle;
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
}
|
||||
FPolyMirrorIterator it(poly);
|
||||
|
||||
poly->specialdata = pd;
|
||||
|
||||
while ( (mirror = poly->GetMirror()) )
|
||||
while ((poly = it.NextMirror()) != NULL)
|
||||
{
|
||||
poly = PO_GetPolyobj (mirror);
|
||||
if (poly == NULL || poly->specialdata != NULL)
|
||||
{ // mirroring poly does not exist or is already in motion
|
||||
if (poly->specialdata != NULL)
|
||||
{ // poly is already moving
|
||||
break;
|
||||
}
|
||||
pd = new DPolyDoor (mirror, type);
|
||||
pd = new DPolyDoor(poly->tag, type);
|
||||
poly->specialdata = pd;
|
||||
if (type == PODOOR_SLIDE)
|
||||
{
|
||||
pd->m_WaitTics = delay;
|
||||
pd->m_Speed = speed;
|
||||
pd->m_Dist = pd->m_TotalDist = distance; // Distance
|
||||
pd->m_Direction = (angle + ANGLE_180) >> ANGLETOFINESHIFT; // reverse the angle
|
||||
pd->m_Direction = angle >> ANGLETOFINESHIFT;
|
||||
pd->m_xSpeed = FixedMul (pd->m_Speed, finecosine[pd->m_Direction]);
|
||||
pd->m_ySpeed = FixedMul (pd->m_Speed, finesine[pd->m_Direction]);
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
angle += ANGLE_180; // reverse the angle
|
||||
}
|
||||
else if (type == PODOOR_SWING)
|
||||
{
|
||||
pd->m_WaitTics = delay;
|
||||
pd->m_Direction = -1; // ADD: same as above
|
||||
pd->m_Direction = swingdir;
|
||||
pd->m_Speed = (speed*pd->m_Direction*(ANGLE_90/64))>>3;
|
||||
pd->m_Dist = pd->m_TotalDist = angle;
|
||||
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
|
||||
swingdir = -swingdir; // reverse the direction
|
||||
}
|
||||
polyNum = mirror;
|
||||
|
||||
}
|
||||
return true;
|
||||
return pd != NULL; // Return true if something started moving.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2342,3 +2245,75 @@ void ReleaseAllPolyNodes()
|
|||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPolyMirrorIterator Constructor
|
||||
//
|
||||
// This class is used to avoid infinitely looping on cyclical chains of
|
||||
// mirrored polyobjects.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPolyMirrorIterator::FPolyMirrorIterator(FPolyObj *poly)
|
||||
{
|
||||
CurPoly = poly;
|
||||
if (poly != NULL)
|
||||
{
|
||||
UsedPolys[0] = poly->tag;
|
||||
NumUsedPolys = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumUsedPolys = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FPolyMirrorIterator :: NextMirror
|
||||
//
|
||||
// Returns the polyobject that mirrors the current one, or NULL if there
|
||||
// is no mirroring polyobject, or there is a mirroring polyobject but it was
|
||||
// already returned.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPolyObj *FPolyMirrorIterator::NextMirror()
|
||||
{
|
||||
FPolyObj *poly = CurPoly, *nextpoly;
|
||||
|
||||
if (poly == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Do the work to decide which polyobject to return the next time this
|
||||
// function is called.
|
||||
int mirror = poly->GetMirror(), i;
|
||||
nextpoly = NULL;
|
||||
|
||||
// Is there a mirror and we have room to remember it?
|
||||
if (mirror != 0 && NumUsedPolys != countof(UsedPolys))
|
||||
{
|
||||
// Has this polyobject been returned already?
|
||||
for (i = 0; i < NumUsedPolys; ++i)
|
||||
{
|
||||
if (UsedPolys[i] == mirror)
|
||||
{
|
||||
break; // Yes, it has been returned.
|
||||
}
|
||||
}
|
||||
if (i == NumUsedPolys)
|
||||
{ // No, it has not been returned.
|
||||
UsedPolys[NumUsedPolys++] = mirror;
|
||||
nextpoly = PO_GetPolyobj(mirror);
|
||||
if (nextpoly == NULL)
|
||||
{
|
||||
Printf("Invalid mirror polyobj num %d for polyobj num %d\n", mirror, UsedPolys[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
CurPoly = nextpoly;
|
||||
return poly;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue