This commit is contained in:
Christoph Oelckers 2016-03-10 15:15:59 +01:00
commit 7de2139e9f
12 changed files with 108 additions and 57 deletions

View file

@ -1973,7 +1973,7 @@ static void D_DoomInit()
// Set the FPU precision to 53 significant bits. This is the default
// for Visual C++, but not for GCC, so some slight math variances
// might crop up if we leave it alone.
#if defined(_FPU_GETCW)
#if defined(_FPU_GETCW) && defined(_FPU_EXTENDED) && defined(_FPU_DOUBLE)
{
int cw;
_FPU_GETCW(cw);

View file

@ -576,6 +576,6 @@ DThinker *FThinkerIterator::Next ()
ADD_STAT (think)
{
FString out;
out.Format ("Think time = %04.1f ms, Action = %04.1f ms", ThinkCycles.TimeMS(), ActionCycles.TimeMS());
out.Format ("Think time = %04.2f ms, Action = %04.2f ms", ThinkCycles.TimeMS(), ActionCycles.TimeMS());
return out;
}

View file

@ -1221,32 +1221,48 @@ void G_FinishTravel ()
}
}
if (start == NULL) start = G_PickPlayerStart(pnum, 0);
if (start == NULL)
{
start = G_PickPlayerStart(pnum, 0);
if (start == NULL)
{
Printf(TEXTCOLOR_RED "No player %d start to travel to!\n", pnum + 1);
// Move to the coordinates this player had when they left the level.
pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
}
}
oldpawn = pawndup;
// The player being spawned here is a short lived dummy and
// must not start any ENTER script or big problems will happen.
pawndup = P_SpawnPlayer(start, pnum, SPF_TEMPPLAYER);
if (!(changeflags & CHANGELEVEL_KEEPFACING))
if (pawndup != NULL)
{
pawn->angle = pawndup->angle;
pawn->pitch = pawndup->pitch;
if (!(changeflags & CHANGELEVEL_KEEPFACING))
{
pawn->angle = pawndup->angle;
pawn->pitch = pawndup->pitch;
}
pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
pawn->velx = pawndup->velx;
pawn->vely = pawndup->vely;
pawn->velz = pawndup->velz;
pawn->Sector = pawndup->Sector;
pawn->floorz = pawndup->floorz;
pawn->ceilingz = pawndup->ceilingz;
pawn->dropoffz = pawndup->dropoffz;
pawn->floorsector = pawndup->floorsector;
pawn->floorpic = pawndup->floorpic;
pawn->floorterrain = pawndup->floorterrain;
pawn->ceilingsector = pawndup->ceilingsector;
pawn->ceilingpic = pawndup->ceilingpic;
pawn->floorclip = pawndup->floorclip;
pawn->waterlevel = pawndup->waterlevel;
}
else
{
P_FindFloorCeiling(pawn);
}
pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
pawn->velx = pawndup->velx;
pawn->vely = pawndup->vely;
pawn->velz = pawndup->velz;
pawn->Sector = pawndup->Sector;
pawn->floorz = pawndup->floorz;
pawn->ceilingz = pawndup->ceilingz;
pawn->dropoffz = pawndup->dropoffz;
pawn->floorsector = pawndup->floorsector;
pawn->floorpic = pawndup->floorpic;
pawn->floorterrain = pawndup->floorterrain;
pawn->ceilingsector = pawndup->ceilingsector;
pawn->ceilingpic = pawndup->ceilingpic;
pawn->floorclip = pawndup->floorclip;
pawn->waterlevel = pawndup->waterlevel;
pawn->target = NULL;
pawn->lastenemy = NULL;
pawn->player->mo = pawn;
@ -1255,7 +1271,10 @@ void G_FinishTravel ()
pawn->flags2 &= ~MF2_BLASTED;
DObject::StaticPointerSubstitution (oldpawn, pawn);
oldpawn->Destroy();
pawndup->Destroy ();
if (pawndup != NULL)
{
pawndup->Destroy();
}
pawn->LinkToWorld ();
pawn->ClearInterpolation();
pawn->AddToHash ();

View file

@ -2607,7 +2607,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
FMultiBlockThingsIterator it(check, viletry.x, viletry.y, self->Z() - 64* FRACUNIT, self->Top() + 64 * FRACUNIT, 32 * FRACUNIT);
FMultiBlockThingsIterator it(check, viletry.x, viletry.y, self->Z() - 64* FRACUNIT, self->Top() + 64 * FRACUNIT, 32 * FRACUNIT, false, NULL);
FMultiBlockThingsIterator::CheckResult cres;
while (it.Next(&cres))
{
@ -2618,8 +2618,8 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
// use the current actor's radius instead of the Arch Vile's default.
fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius;
if (abs(cres.position.x - viletry.x) > maxdist ||
abs(cres.position.y - viletry.y) > maxdist)
if (abs(corpsehit->Pos().x - cres.position.x) > maxdist ||
abs(corpsehit->Pos().y - cres.position.y) > maxdist)
continue; // not actually touching
// Let's check if there are floors in between the archvile and its target

View file

@ -431,9 +431,10 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
// P_LineOpening requires the thing's z to be the destination z in order to work.
fixed_t savedz = thing->Z();
thing->SetZ(z);
sector_t *sector = P_PointInSector(x, y);
FPortalGroupArray grouplist;
FMultiBlockLinesIterator mit(grouplist, x, y, z, thing->height, thing->radius);
FMultiBlockLinesIterator mit(grouplist, x, y, z, thing->height, thing->radius, sector);
FMultiBlockLinesIterator::CheckResult cres;
while (mit.Next(&cres))
@ -444,7 +445,7 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
FMultiBlockThingsIterator mit2(grouplist, x, y, z, thing->height, thing->radius);
FMultiBlockThingsIterator mit2(grouplist, x, y, z, thing->height, thing->radius, false, sector);
FMultiBlockThingsIterator::CheckResult cres2;
while (mit2.Next(&cres2))
@ -1670,7 +1671,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
FBoundingBox box(x, y, thing->radius);
FPortalGroupArray pcheck;
FMultiBlockThingsIterator it2(pcheck, x, y, thing->Z(), thing->height, thing->radius);
FMultiBlockThingsIterator it2(pcheck, x, y, thing->Z(), thing->height, thing->radius, false, newsec);
FMultiBlockThingsIterator::CheckResult tcres;
while ((it2.Next(&tcres)))
@ -1740,7 +1741,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo
spechit.Clear();
portalhit.Clear();
FMultiBlockLinesIterator it(pcheck, x, y, thing->Z(), thing->height, thing->radius);
FMultiBlockLinesIterator it(pcheck, x, y, thing->Z(), thing->height, thing->radius, newsec);
FMultiBlockLinesIterator::CheckResult lcres;
fixed_t thingdropoffz = tm.floorz;
@ -2405,11 +2406,18 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP)))
{
spechit_t spec;
fixedvec3 lastpos = thing->Pos();
while (spechit.Pop(spec))
{
line_t *ld = spec.line;
// see if the line was crossed
side = P_PointOnLineSide(spec.refpos.x, spec.refpos.y, ld);
// One more case of trying to preserve some side effects from the original:
// If the reference position is the same as the actor's position before checking the spechits,
// we use the thing's actual position, including all the side effects of the original.
// If some portal transition has to be considered here, we cannot do that and use the reference position stored with the spechit.
bool posisoriginal = (spec.refpos.x == lastpos.x && spec.refpos.y == lastpos.y);
side = posisoriginal? P_PointOnLineSide(thing->X(), thing->Y(), ld) : P_PointOnLineSide(spec.refpos.x, spec.refpos.y, ld);
oldside = P_PointOnLineSide(spec.oldrefpos.x, spec.oldrefpos.y, ld);
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
{
@ -5251,7 +5259,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
double bombdamagefloat = (double)bombdamage;
FPortalGroupArray grouplist(FPortalGroupArray::PGA_Full3d);
FMultiBlockThingsIterator it(grouplist, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistfix, bombspot->height + bombdistfix*2, bombdistfix);
FMultiBlockThingsIterator it(grouplist, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistfix, bombspot->height + bombdistfix*2, bombdistfix, false, bombspot->Sector);
FMultiBlockThingsIterator::CheckResult cres;
if (flags & RADF_SOURCEISSPOT)

View file

@ -741,16 +741,19 @@ FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AAc
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
startsector = origin->Sector;
Reset();
}
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius)
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, sector_t *newsec)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
startsector = newsec;
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
Reset();
@ -766,10 +769,9 @@ bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
{
if (continueup)
{
sector_t *sector = P_PointInSector(x, y);
if (!sector->PortalBlocksMovement(sector_t::ceiling))
if (!cursector->PortalBlocksMovement(sector_t::ceiling))
{
startIteratorForGroup(sector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
startIteratorForGroup(cursector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
portalflags = FFCF_NOFLOOR;
return true;
}
@ -788,10 +790,9 @@ bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
{
if (continuedown)
{
sector_t *sector = P_PointInSector(x, y);
if (!sector->PortalBlocksMovement(sector_t::floor))
if (!cursector->PortalBlocksMovement(sector_t::floor))
{
startIteratorForGroup(sector->SkyBoxes[sector_t::floor]->Sector->PortalGroup);
startIteratorForGroup(cursector->SkyBoxes[sector_t::floor]->Sector->PortalGroup);
portalflags = FFCF_NOCEILING;
return true;
}
@ -871,6 +872,7 @@ void FMultiBlockLinesIterator::startIteratorForGroup(int group)
offset = Displacements.getOffset(basegroup, group);
offset.x += checkpoint.x;
offset.y += checkpoint.y;
cursector = group == startsector->PortalGroup ? startsector : P_PointInSector(offset.x, offset.y);
bbox.setBox(offset.x, offset.y, checkpoint.z);
blockIterator.init(bbox);
}
@ -1076,13 +1078,14 @@ FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, A
Reset();
}
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted)
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted, sector_t *newsec)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
Reset();

View file

@ -218,6 +218,8 @@ class FMultiBlockLinesIterator
FPortalGroupArray &checklist;
fixedvec3 checkpoint;
fixedvec2 offset;
sector_t *startsector;
sector_t *cursector;
short basegroup;
short portalflags;
short index;
@ -240,7 +242,7 @@ public:
};
FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1);
FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius);
FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, sector_t *newsec);
bool Next(CheckResult *item);
void Reset();
// for stopping group traversal through portals. Only the calling code can decide whether this is needed so this needs to be set from the outside.
@ -325,7 +327,7 @@ public:
};
FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted, sector_t *newsec);
bool Next(CheckResult *item);
void Reset();
const FBoundingBox &Box() const

View file

@ -1983,7 +1983,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
FCheckPosition tm(!!(mo->flags2 & MF2_RIP));
angle_t oldangle = mo->angle;
do
{
if (i_compatflags & COMPATF_WALLRUN) pushtime++;
@ -2213,13 +2213,25 @@ explode:
// If the new position does not match the desired position, the player
// must have gone through a teleporter, so stop moving right now if it
// was a regular teleporter. If it was a line-to-line or fogless teleporter,
// the move should continue, but startx and starty need to change.
// the move should continue, but startx, starty and xmove, ymove need to change.
if (mo->velx == 0 && mo->vely == 0)
{
step = steps;
}
else
{
angle_t anglediff = (mo->angle - oldangle) >> ANGLETOFINESHIFT;
if (anglediff != 0)
{
fixed_t xnew = FixedMul(xmove, finecosine[anglediff]) - FixedMul(ymove, finesine[anglediff]);
fixed_t ynew = FixedMul(xmove, finesine[anglediff]) + FixedMul(ymove, finecosine[anglediff]);
xmove = xnew;
ymove = ynew;
oldangle = mo->angle; // in case more moves are needed this needs to be updated.
}
startx = mo->X() - Scale (xmove, step, steps);
starty = mo->Y() - Scale (ymove, step, steps);
}
@ -4603,6 +4615,10 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
fixed_t spawn_x, spawn_y, spawn_z;
angle_t spawn_angle;
if (mthing == NULL)
{
return NULL;
}
// not playing?
if ((unsigned)playernum >= (unsigned)MAXPLAYERS || !playeringame[playernum])
return NULL;

View file

@ -940,12 +940,13 @@ fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flag
while (true)
{
// Looking through planes from bottom to top
fixed_t realceil = sec->ceilingplane.ZatPoint(x, y);
for (int i = sec->e->XFloor.ffloors.Size() - 1; i >= 0; --i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
fixed_t ffz = ff->bottom.plane->ZatPoint(x, y);
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) && z <= ffz)
if (ffz < realceil && ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) && z <= ffz))
{ // This floor is above our eyes.
if (resultsec) *resultsec = sec;
if (resultffloor) *resultffloor = ff;
@ -956,7 +957,7 @@ fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flag
{ // Use sector's floor
if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec;
return sec->ceilingplane.ZatPoint(x, y);
return realceil;
}
else
{
@ -977,17 +978,19 @@ fixed_t sector_t::NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags,
{
// Looking through planes from top to bottom
unsigned numff = sec->e->XFloor.ffloors.Size();
fixed_t realfloor = sec->floorplane.ZatPoint(x, y);
for (unsigned i = 0; i < numff; ++i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
fixed_t ffz = ff->top.plane->ZatPoint(x, y);
fixed_t ffb = ff->bottom.plane->ZatPoint(x, y);
// either with feet above the 3D floor or feet with less than 'stepheight' map units inside
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID))
{
if (z >= ffz || (!(flags & FFCF_3DRESTRICT) && (ffb < z && ffz < z + steph)))
fixed_t ffz = ff->top.plane->ZatPoint(x, y);
fixed_t ffb = ff->bottom.plane->ZatPoint(x, y);
if (ffz > realfloor && (z >= ffz || (!(flags & FFCF_3DRESTRICT) && (ffb < z && ffz < z + steph))))
{ // This floor is beneath our feet.
if (resultsec) *resultsec = sec;
if (resultffloor) *resultffloor = ff;
@ -999,7 +1002,7 @@ fixed_t sector_t::NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags,
{ // Use sector's floor
if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec;
return sec->floorplane.ZatPoint(x, y);
return realfloor;
}
else
{

View file

@ -2277,7 +2277,7 @@ void DPusher::Tick ()
// point pusher. Crosses sectors, so use blockmap.
FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals); // no sector portals because this thing is utterly z-unaware.
FMultiBlockThingsIterator it(check, m_X, m_Y, 0, 0, m_Radius);
FMultiBlockThingsIterator it(check, m_X, m_Y, 0, 0, m_Radius, false, m_Source->Sector);
FMultiBlockThingsIterator::CheckResult cres;

View file

@ -2643,12 +2643,12 @@ void R_StoreWallRange (int start, int stop)
{
if (pds.ceilingclip[i] < 0)
pds.ceilingclip[i] = 0;
if (pds.ceilingclip[i] >= RenderTarget->GetHeight())
pds.ceilingclip[i] = RenderTarget->GetHeight()-1;
if (pds.ceilingclip[i] >= viewheight)
pds.ceilingclip[i] = viewheight-1;
if (pds.floorclip[i] < 0)
pds.floorclip[i] = 0;
if (pds.floorclip[i] >= RenderTarget->GetHeight())
pds.floorclip[i] = RenderTarget->GetHeight()-1;
if (pds.floorclip[i] >= viewheight)
pds.floorclip[i] = viewheight-1;
}
pds.mirror = curline->linedef->special == Line_Mirror;

View file

@ -5583,7 +5583,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
{
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
fixed_t mid = self->Z() + self->height / 2;
FMultiBlockThingsIterator it(check, self->X(), self->Y(), mid-distance, mid+distance, distance);
FMultiBlockThingsIterator it(check, self->X(), self->Y(), mid-distance, mid+distance, distance, false, self->Sector);
FMultiBlockThingsIterator::CheckResult cres;
while ((it.Next(&cres)))