mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 08:31:23 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
This commit is contained in:
commit
6db95182cf
9 changed files with 295 additions and 310 deletions
182
src/p_effect.cpp
182
src/p_effect.cpp
|
@ -621,19 +621,65 @@ void P_DrawSplash2 (int count, const DVector3 &pos, DAngle angle, int updown, in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &portalhits, const DVector3 &end, int color1, int color2, double maxdiff_d, int flags, PClassActor *spawnclass, DAngle angle, int duration, double sparsity, double drift, int SpiralOffset)
|
struct TrailSegment
|
||||||
{
|
{
|
||||||
double length, lengthsquared;
|
DVector3 start;
|
||||||
|
DVector3 dir;
|
||||||
|
DVector3 extend;
|
||||||
|
DVector2 soundpos;
|
||||||
|
double length;
|
||||||
|
double sounddist;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &portalhits, int color1, int color2, double maxdiff, int flags, PClassActor *spawnclass, DAngle angle, int duration, double sparsity, double drift, int SpiralOffset)
|
||||||
|
{
|
||||||
|
double length = 0;
|
||||||
int steps, i;
|
int steps, i;
|
||||||
|
TArray<TrailSegment> trail;
|
||||||
TAngle<double> deg;
|
TAngle<double> deg;
|
||||||
DVector3 step, dir, pos, extend;
|
DVector3 pos;
|
||||||
bool fullbright;
|
bool fullbright;
|
||||||
float maxdiff = (float)maxdiff_d;
|
unsigned segment;
|
||||||
|
double lencount;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < portalhits.Size() - 1; i++)
|
||||||
|
{
|
||||||
|
TrailSegment seg;
|
||||||
|
|
||||||
|
seg.start = portalhits[i].ContPos;
|
||||||
|
seg.dir = portalhits[i].OutDir;
|
||||||
|
seg.length = (portalhits[i + 1].HitPos - seg.start).Length();
|
||||||
|
|
||||||
|
//Calculate PerpendicularVector (extend, dir):
|
||||||
|
double minelem = 1;
|
||||||
|
int epos;
|
||||||
|
int ii;
|
||||||
|
for (epos = 0, ii = 0; ii < 3; ++ii)
|
||||||
|
{
|
||||||
|
if (fabs(seg.dir[ii]) < minelem)
|
||||||
|
{
|
||||||
|
epos = ii;
|
||||||
|
minelem = fabs(seg.dir[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DVector3 tempvec(0, 0, 0);
|
||||||
|
tempvec[epos] = 1;
|
||||||
|
seg.extend = (tempvec - (seg.dir | tempvec) * seg.dir) * 3;
|
||||||
|
length += seg.length;
|
||||||
|
|
||||||
|
// Only consider sound in 2D (for now, anyway)
|
||||||
|
// [BB] You have to divide by lengthsquared here, not multiply with it.
|
||||||
|
AActor *mo = players[consoleplayer].camera;
|
||||||
|
|
||||||
|
double r = ((seg.start.Y - mo->Y()) * (-seg.dir.Y) - (seg.start.X - mo->X()) * (seg.dir.X)) / (seg.length * seg.length);
|
||||||
|
r = clamp<double>(r, 0., 1.);
|
||||||
|
seg.soundpos = seg.start + r * seg.dir;
|
||||||
|
seg.sounddist = (seg.soundpos - mo->Pos()).LengthSquared();
|
||||||
|
trail.Push(seg);
|
||||||
|
}
|
||||||
|
|
||||||
dir = end - start;
|
|
||||||
lengthsquared = dir | dir;
|
|
||||||
length = g_sqrt(lengthsquared);
|
|
||||||
steps = xs_FloorToInt(length / 3);
|
steps = xs_FloorToInt(length / 3);
|
||||||
fullbright = !!(flags & RAF_FULLBRIGHT);
|
fullbright = !!(flags & RAF_FULLBRIGHT);
|
||||||
|
|
||||||
|
@ -652,30 +698,19 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
// The railgun's sound is special. It gets played from the
|
// The railgun's sound is special. It gets played from the
|
||||||
// point on the slug's trail that is closest to the hearing player.
|
// point on the slug's trail that is closest to the hearing player.
|
||||||
AActor *mo = players[consoleplayer].camera;
|
AActor *mo = players[consoleplayer].camera;
|
||||||
DVector3 point;
|
|
||||||
double r;
|
|
||||||
double dirz;
|
|
||||||
|
|
||||||
if (fabs(mo->X() - start.X) < 20
|
if (fabs(mo->X() - trail[0].start.X) < 20 && fabs(mo->Y() - trail[0].start.Y) < 20)
|
||||||
&& fabs(mo->Y() - start.Y) < 20)
|
|
||||||
{ // This player (probably) fired the railgun
|
{ // This player (probably) fired the railgun
|
||||||
S_Sound (mo, CHAN_WEAPON, sound, 1, ATTN_NORM);
|
S_Sound (mo, CHAN_WEAPON, sound, 1, ATTN_NORM);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TrailSegment *shortest = NULL;
|
||||||
// Only consider sound in 2D (for now, anyway)
|
for (auto &seg : trail)
|
||||||
// [BB] You have to divide by lengthsquared here, not multiply with it.
|
{
|
||||||
|
if (shortest == NULL || shortest->sounddist > seg.sounddist) shortest = &seg;
|
||||||
r = ((start.Y - mo->Y()) * (-dir.Y) - (start.X - mo->X()) * (dir.X)) / lengthsquared;
|
}
|
||||||
r = clamp<double>(r, 0., 1.);
|
S_Sound (DVector3(shortest->soundpos, ViewPos.Z), CHAN_WEAPON, sound, 1, ATTN_NORM);
|
||||||
|
|
||||||
dirz = dir.Z;
|
|
||||||
dir.Z = 0;
|
|
||||||
point = start + r * dir;
|
|
||||||
dir.Z = dirz;
|
|
||||||
|
|
||||||
S_Sound (DVector3(point.X, point.Y, ViewPos.Z), CHAN_WEAPON, sound, 1, ATTN_NORM);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,35 +720,16 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir /= length;
|
|
||||||
|
|
||||||
//Calculate PerpendicularVector (extend, dir):
|
|
||||||
double minelem = 1;
|
|
||||||
int epos;
|
|
||||||
for (epos = 0, i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
if (fabs(dir[i]) < minelem)
|
|
||||||
{
|
|
||||||
epos = i;
|
|
||||||
minelem = fabs(dir[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DVector3 tempvec(0, 0, 0);
|
|
||||||
tempvec[epos] = 1;
|
|
||||||
extend = tempvec - (dir | tempvec) * dir;
|
|
||||||
//
|
|
||||||
|
|
||||||
extend *= 3;
|
|
||||||
step = dir * 3;
|
|
||||||
|
|
||||||
// Create the outer spiral.
|
// Create the outer spiral.
|
||||||
if (color1 != -1 && (!r_rail_smartspiral || color2 == -1) && r_rail_spiralsparsity > 0 && (spawnclass == NULL))
|
if (color1 != -1 && (!r_rail_smartspiral || color2 == -1) && r_rail_spiralsparsity > 0 && (spawnclass == NULL))
|
||||||
{
|
{
|
||||||
DVector3 spiral_step = step * r_rail_spiralsparsity * sparsity;
|
double stepsize = 3 * r_rail_spiralsparsity * sparsity;
|
||||||
int spiral_steps = (int)(steps * r_rail_spiralsparsity / sparsity);
|
int spiral_steps = (int)(steps * r_rail_spiralsparsity / sparsity);
|
||||||
|
segment = 0;
|
||||||
|
lencount = trail[0].length;
|
||||||
|
|
||||||
color1 = color1 == 0 ? -1 : ParticleColor(color1);
|
color1 = color1 == 0 ? -1 : ParticleColor(color1);
|
||||||
pos = start;
|
pos = trail[0].start;
|
||||||
deg = (double)SpiralOffset;
|
deg = (double)SpiralOffset;
|
||||||
for (i = spiral_steps; i; i--)
|
for (i = spiral_steps; i; i--)
|
||||||
{
|
{
|
||||||
|
@ -731,12 +747,12 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
p->size = 3;
|
p->size = 3;
|
||||||
p->bright = fullbright;
|
p->bright = fullbright;
|
||||||
|
|
||||||
tempvec = DMatrix3x3(dir, deg) * extend;
|
tempvec = DMatrix3x3(trail[segment].dir, deg) * trail[segment].extend;
|
||||||
p->Vel = tempvec * drift / 16.;
|
p->Vel = tempvec * drift / 16.;
|
||||||
p->Pos = tempvec + pos;
|
p->Pos = tempvec + pos;
|
||||||
pos += spiral_step;
|
pos += trail[segment].dir * stepsize;
|
||||||
deg += double(r_rail_spiralsparsity * 14);
|
deg += double(r_rail_spiralsparsity * 14);
|
||||||
|
lencount -= stepsize;
|
||||||
if (color1 == -1)
|
if (color1 == -1)
|
||||||
{
|
{
|
||||||
int rand = M_Random();
|
int rand = M_Random();
|
||||||
|
@ -754,19 +770,36 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
{
|
{
|
||||||
p->color = color1;
|
p->color = color1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lencount <= 0)
|
||||||
|
{
|
||||||
|
segment++;
|
||||||
|
if (segment < trail.Size())
|
||||||
|
{
|
||||||
|
pos = trail[segment].start - trail[segment].dir * lencount;
|
||||||
|
lencount += trail[segment].length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// should never happen but if something goes wrong, just terminate the loop.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the inner trail.
|
// Create the inner trail.
|
||||||
if (color2 != -1 && r_rail_trailsparsity > 0 && spawnclass == NULL)
|
if (color2 != -1 && r_rail_trailsparsity > 0 && spawnclass == NULL)
|
||||||
{
|
{
|
||||||
DVector3 trail_step = step * r_rail_trailsparsity * sparsity;
|
double stepsize = 3 * r_rail_spiralsparsity * sparsity;
|
||||||
int trail_steps = xs_FloorToInt(steps * r_rail_trailsparsity / sparsity);
|
int trail_steps = xs_FloorToInt(steps * r_rail_trailsparsity / sparsity);
|
||||||
|
|
||||||
color2 = color2 == 0 ? -1 : ParticleColor(color2);
|
color2 = color2 == 0 ? -1 : ParticleColor(color2);
|
||||||
DVector3 diff(0, 0, 0);
|
DVector3 diff(0, 0, 0);
|
||||||
|
|
||||||
pos = start;
|
pos = trail[0].start;
|
||||||
|
lencount = trail[0].length;
|
||||||
|
segment = 0;
|
||||||
for (i = trail_steps; i; i--)
|
for (i = trail_steps; i; i--)
|
||||||
{
|
{
|
||||||
// [XA] inner trail uses a different default duration (33).
|
// [XA] inner trail uses a different default duration (33).
|
||||||
|
@ -793,8 +826,8 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
p->Pos = postmp;
|
p->Pos = postmp;
|
||||||
if (color1 != -1)
|
if (color1 != -1)
|
||||||
p->Acc.Z -= 1./4096;
|
p->Acc.Z -= 1./4096;
|
||||||
pos += trail_step;
|
pos += trail[segment].dir * stepsize;
|
||||||
|
lencount -= stepsize;
|
||||||
p->bright = fullbright;
|
p->bright = fullbright;
|
||||||
|
|
||||||
if (color2 == -1)
|
if (color2 == -1)
|
||||||
|
@ -812,6 +845,21 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
{
|
{
|
||||||
p->color = color2;
|
p->color = color2;
|
||||||
}
|
}
|
||||||
|
if (lencount <= 0)
|
||||||
|
{
|
||||||
|
segment++;
|
||||||
|
if (segment < trail.Size())
|
||||||
|
{
|
||||||
|
pos = trail[segment].start - trail[segment].dir * lencount;
|
||||||
|
lencount += trail[segment].length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// should never happen but if something goes wrong, just terminate the loop.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create actors
|
// create actors
|
||||||
|
@ -820,11 +868,14 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
if (sparsity < 1)
|
if (sparsity < 1)
|
||||||
sparsity = 32;
|
sparsity = 32;
|
||||||
|
|
||||||
DVector3 trail_step = (step / 3) * sparsity;
|
double stepsize = 3 * r_rail_spiralsparsity * sparsity;
|
||||||
int trail_steps = (int)((steps * 3) / sparsity);
|
int trail_steps = (int)((steps * 3) / sparsity);
|
||||||
DVector3 diff(0, 0, 0);
|
DVector3 diff(0, 0, 0);
|
||||||
|
|
||||||
pos = start;
|
pos = trail[0].start;
|
||||||
|
lencount = trail[0].length;
|
||||||
|
segment = 0;
|
||||||
|
|
||||||
for (i = trail_steps; i; i--)
|
for (i = trail_steps; i; i--)
|
||||||
{
|
{
|
||||||
if (maxdiff > 0)
|
if (maxdiff > 0)
|
||||||
|
@ -840,7 +891,22 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &
|
||||||
AActor *thing = Spawn (spawnclass, pos + diff, ALLOW_REPLACE);
|
AActor *thing = Spawn (spawnclass, pos + diff, ALLOW_REPLACE);
|
||||||
if (thing)
|
if (thing)
|
||||||
thing->Angles.Yaw = angle;
|
thing->Angles.Yaw = angle;
|
||||||
pos += trail_step;
|
pos += trail[segment].dir * stepsize;
|
||||||
|
lencount -= stepsize;
|
||||||
|
if (lencount <= 0)
|
||||||
|
{
|
||||||
|
segment++;
|
||||||
|
if (segment < trail.Size())
|
||||||
|
{
|
||||||
|
pos = trail[segment].start - trail[segment].dir * lencount;
|
||||||
|
lencount += trail[segment].length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// should never happen but if something goes wrong, just terminate the loop.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ struct SPortalHit
|
||||||
DVector3 OutDir;
|
DVector3 OutDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
void P_DrawRailTrail(AActor *source, const DVector3 &start, TArray<SPortalHit> &portalhits, const DVector3 &end, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = 0., int duration = 35, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270);
|
void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = 0., int duration = 35, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270);
|
||||||
void P_DrawSplash (int count, const DVector3 &pos, DAngle angle, int kind);
|
void P_DrawSplash (int count, const DVector3 &pos, DAngle angle, int kind);
|
||||||
void P_DrawSplash2 (int count, const DVector3 &pos, DAngle angle, int updown, int kind);
|
void P_DrawSplash2 (int count, const DVector3 &pos, DAngle angle, int updown, int kind);
|
||||||
void P_DisconnectEffect (AActor *actor);
|
void P_DisconnectEffect (AActor *actor);
|
||||||
|
|
|
@ -4598,15 +4598,8 @@ void P_RailAttack(FRailParams *p)
|
||||||
rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true;
|
rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true;
|
||||||
rail_data.ThruSpecies = (puffDefaults->flags6 & MF6_MTHRUSPECIES) ? true : false;
|
rail_data.ThruSpecies = (puffDefaults->flags6 & MF6_MTHRUSPECIES) ? true : false;
|
||||||
|
|
||||||
// to make things easier, push the start position and directional vector onto the PortalHits array as its first element
|
|
||||||
SPortalHit phit = { start, start, vec };
|
|
||||||
rail_data.PortalHits.Push(phit);
|
|
||||||
Trace(start, source->Sector, vec, p->distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data);
|
Trace(start, source->Sector, vec, p->distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data);
|
||||||
|
|
||||||
// and push the hit position, too, so that the array contains the entire trace with all transition points.
|
|
||||||
phit = { trace.HitPos, trace.HitPos, trace.HitVector };
|
|
||||||
rail_data.PortalHits.Push(phit);
|
|
||||||
|
|
||||||
// Hurt anything the trace hit
|
// Hurt anything the trace hit
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType;
|
FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType;
|
||||||
|
@ -4709,7 +4702,7 @@ void P_RailAttack(FRailParams *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the slug's trail.
|
// Draw the slug's trail.
|
||||||
P_DrawRailTrail(source, start, rail_data.PortalHits, trace.HitPos, p->color1, p->color2, p->maxdiff, p->flags, p->spawnclass, angle, p->duration, p->sparsity, p->drift, p->SpiralOffset);
|
P_DrawRailTrail(source, rail_data.PortalHits, p->color1, p->color2, p->maxdiff, p->flags, p->spawnclass, angle, p->duration, p->sparsity, p->drift, p->SpiralOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -450,13 +450,13 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
|
||||||
// link into blockmap (inert things don't need to be in the blockmap)
|
// link into blockmap (inert things don't need to be in the blockmap)
|
||||||
if (!(flags & MF_NOBLOCKMAP))
|
if (!(flags & MF_NOBLOCKMAP))
|
||||||
{
|
{
|
||||||
FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals);
|
FPortalGroupArray check;
|
||||||
|
|
||||||
P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check);
|
P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check);
|
||||||
|
|
||||||
for (int i = -1; i < (int)check.Size(); i++)
|
for (int i = -1; i < (int)check.Size(); i++)
|
||||||
{
|
{
|
||||||
DVector3 pos = i==-1? Pos() : PosRelative(check[i]);
|
DVector3 pos = i==-1? Pos() : PosRelative(check[i] & ~FPortalGroupArray::FLAT);
|
||||||
|
|
||||||
int x1 = GetBlockX(pos.X - radius);
|
int x1 = GetBlockX(pos.X - radius);
|
||||||
int x2 = GetBlockX(pos.X + radius);
|
int x2 = GetBlockX(pos.X + radius);
|
||||||
|
@ -1616,12 +1616,22 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, DVector3 *optpos)
|
||||||
P_TranslatePortalXY(in->d.line, optpos->X, optpos->Y);
|
P_TranslatePortalXY(in->d.line, optpos->X, optpos->Y);
|
||||||
P_TranslatePortalZ(in->d.line, optpos->Z);
|
P_TranslatePortalZ(in->d.line, optpos->Z);
|
||||||
}
|
}
|
||||||
line_t *saved = in->d.line; // this gets overwriitten by the init call.
|
line_t *saved = in->d.line; // this gets overwritten by the init call.
|
||||||
intercepts.Resize(intercept_index);
|
intercepts.Resize(intercept_index);
|
||||||
init(hitx, hity, endx, endy, flags, in->frac);
|
init(hitx, hity, endx, endy, flags, in->frac + EQUAL_EPSILON);
|
||||||
return saved->getPortal()->mType == PORTT_LINKED? 1:-1;
|
return saved->getPortal()->mType == PORTT_LINKED? 1:-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FPathTraverse::PortalRelocate(AActor *portalthing, int flags, double hitfrac)
|
||||||
|
{
|
||||||
|
double hitx = trace.x + portalthing->Scale.X;
|
||||||
|
double hity = trace.y + portalthing->Scale.Y;
|
||||||
|
double endx = hitx + trace.dx;
|
||||||
|
double endy = hity + trace.dy;
|
||||||
|
intercepts.Resize(intercept_index);
|
||||||
|
init(hitx, hity, endx, endy, flags, hitfrac);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -373,6 +373,7 @@ public:
|
||||||
}
|
}
|
||||||
void init(double x1, double y1, double x2, double y2, int flags, double startfrac = 0);
|
void init(double x1, double y1, double x2, double y2, int flags, double startfrac = 0);
|
||||||
int PortalRelocate(intercept_t *in, int flags, DVector3 *optpos = NULL);
|
int PortalRelocate(intercept_t *in, int flags, DVector3 *optpos = NULL);
|
||||||
|
void PortalRelocate(AActor *portalthing, int flags, double hitfrac);
|
||||||
virtual ~FPathTraverse();
|
virtual ~FPathTraverse();
|
||||||
const divline_t &Trace() const { return trace; }
|
const divline_t &Trace() const { return trace; }
|
||||||
|
|
||||||
|
|
356
src/p_trace.cpp
356
src/p_trace.cpp
|
@ -55,7 +55,6 @@ struct FTraceInfo
|
||||||
DWORD WallMask;
|
DWORD WallMask;
|
||||||
AActor *IgnoreThis;
|
AActor *IgnoreThis;
|
||||||
FTraceResults *Results;
|
FTraceResults *Results;
|
||||||
FTraceResults *TempResults;
|
|
||||||
sector_t *CurSector;
|
sector_t *CurSector;
|
||||||
double MaxDist;
|
double MaxDist;
|
||||||
double EnterDist;
|
double EnterDist;
|
||||||
|
@ -64,10 +63,8 @@ struct FTraceInfo
|
||||||
DWORD TraceFlags;
|
DWORD TraceFlags;
|
||||||
int inshootthrough;
|
int inshootthrough;
|
||||||
double startfrac;
|
double startfrac;
|
||||||
int aimdir;
|
|
||||||
double limitz;
|
double limitz;
|
||||||
double lastfloorportalheight;
|
int ptflags;
|
||||||
double lastceilingportalheight;
|
|
||||||
|
|
||||||
// These are required for 3D-floor checking
|
// These are required for 3D-floor checking
|
||||||
// to create a fake sector with a floor
|
// to create a fake sector with a floor
|
||||||
|
@ -76,12 +73,12 @@ struct FTraceInfo
|
||||||
int sectorsel;
|
int sectorsel;
|
||||||
|
|
||||||
void Setup3DFloors();
|
void Setup3DFloors();
|
||||||
bool LineCheck(intercept_t *in);
|
bool LineCheck(intercept_t *in, double dist, DVector3 hit);
|
||||||
bool ThingCheck(intercept_t *in);
|
bool ThingCheck(intercept_t *in, double dist, DVector3 hit);
|
||||||
bool TraceTraverse (int ptflags);
|
bool TraceTraverse (int ptflags);
|
||||||
bool CheckPlane(const secplane_t &plane);
|
bool CheckPlane(const secplane_t &plane);
|
||||||
int EnterLinePortal(line_t *li, double frac);
|
void EnterLinePortal(FPathTraverse &pt, intercept_t *in);
|
||||||
void EnterSectorPortal(int position, double frac, sector_t *entersec);
|
void EnterSectorPortal(FPathTraverse &pt, int position, double frac, sector_t *entersec);
|
||||||
|
|
||||||
|
|
||||||
bool CheckSectorPlane(const sector_t *sector, bool checkFloor)
|
bool CheckSectorPlane(const sector_t *sector, bool checkFloor)
|
||||||
|
@ -107,6 +104,38 @@ struct FTraceInfo
|
||||||
static bool EditTraceResult (DWORD flags, FTraceResults &res);
|
static bool EditTraceResult (DWORD flags, FTraceResults &res);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void GetPortalTransition(DVector3 &pos, sector_t *&sec)
|
||||||
|
{
|
||||||
|
bool moved = false;
|
||||||
|
double testz = pos.Z;
|
||||||
|
|
||||||
|
while (!sec->PortalBlocksMovement(sector_t::ceiling))
|
||||||
|
{
|
||||||
|
AActor *port = sec->SkyBoxes[sector_t::ceiling];
|
||||||
|
if (pos.Z > port->specialf1)
|
||||||
|
{
|
||||||
|
pos += port->Scale;
|
||||||
|
sec = P_PointInSector(pos);
|
||||||
|
moved = true;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
if (!moved)
|
||||||
|
{
|
||||||
|
while (!sec->PortalBlocksMovement(sector_t::floor))
|
||||||
|
{
|
||||||
|
AActor *port = sec->SkyBoxes[sector_t::floor];
|
||||||
|
if (pos.Z <= port->specialf1)
|
||||||
|
{
|
||||||
|
pos += port->Scale;
|
||||||
|
sec = P_PointInSector(pos);
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Trace entry point
|
// Trace entry point
|
||||||
|
@ -117,16 +146,15 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d
|
||||||
ActorFlags actorMask, DWORD wallMask, AActor *ignore, FTraceResults &res, DWORD flags,
|
ActorFlags actorMask, DWORD wallMask, AActor *ignore, FTraceResults &res, DWORD flags,
|
||||||
ETraceStatus(*callback)(FTraceResults &res, void *), void *callbackdata)
|
ETraceStatus(*callback)(FTraceResults &res, void *), void *callbackdata)
|
||||||
{
|
{
|
||||||
int ptflags;
|
|
||||||
FTraceInfo inf;
|
FTraceInfo inf;
|
||||||
FTraceResults tempResult;
|
FTraceResults tempResult;
|
||||||
|
|
||||||
memset(&tempResult, 0, sizeof(tempResult));
|
memset(&tempResult, 0, sizeof(tempResult));
|
||||||
tempResult.Fraction = tempResult.Distance = NO_VALUE;
|
tempResult.Fraction = tempResult.Distance = NO_VALUE;
|
||||||
|
|
||||||
ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS|PT_COMPATIBLE : PT_ADDLINES;
|
|
||||||
|
|
||||||
inf.Start = start;
|
inf.Start = start;
|
||||||
|
GetPortalTransition(inf.Start, sector);
|
||||||
|
inf.ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS|PT_COMPATIBLE : PT_ADDLINES;
|
||||||
inf.Vec = direction;
|
inf.Vec = direction;
|
||||||
inf.ActorMask = actorMask;
|
inf.ActorMask = actorMask;
|
||||||
inf.WallMask = wallMask;
|
inf.WallMask = wallMask;
|
||||||
|
@ -138,15 +166,30 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d
|
||||||
inf.TraceCallbackData = callbackdata;
|
inf.TraceCallbackData = callbackdata;
|
||||||
inf.TraceFlags = flags;
|
inf.TraceFlags = flags;
|
||||||
inf.Results = &res;
|
inf.Results = &res;
|
||||||
inf.TempResults = &tempResult;
|
|
||||||
inf.inshootthrough = true;
|
inf.inshootthrough = true;
|
||||||
inf.sectorsel=0;
|
inf.sectorsel=0;
|
||||||
inf.aimdir = -1;
|
|
||||||
inf.startfrac = 0;
|
inf.startfrac = 0;
|
||||||
inf.lastfloorportalheight = inf.lastceilingportalheight = start.Z;
|
inf.limitz = inf.Start.Z;
|
||||||
memset(&res, 0, sizeof(res));
|
memset(&res, 0, sizeof(res));
|
||||||
|
|
||||||
if (inf.TraceTraverse (ptflags))
|
if ((flags & TRACE_ReportPortals) && callback != NULL)
|
||||||
|
{
|
||||||
|
tempResult.HitType = TRACE_CrossingPortal;
|
||||||
|
tempResult.HitPos = tempResult.SrcFromTarget = inf.Start;
|
||||||
|
tempResult.HitVector = inf.Vec;
|
||||||
|
callback(tempResult, inf.TraceCallbackData);
|
||||||
|
}
|
||||||
|
bool reslt = inf.TraceTraverse(inf.ptflags);
|
||||||
|
|
||||||
|
if ((flags & TRACE_ReportPortals) && callback != NULL)
|
||||||
|
{
|
||||||
|
tempResult.HitType = TRACE_CrossingPortal;
|
||||||
|
tempResult.HitPos = tempResult.SrcFromTarget = inf.Results->HitPos;
|
||||||
|
tempResult.HitVector = inf.Vec;
|
||||||
|
callback(tempResult, inf.TraceCallbackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reslt)
|
||||||
{
|
{
|
||||||
return flags ? EditTraceResult(flags, res) : true;
|
return flags ? EditTraceResult(flags, res) : true;
|
||||||
}
|
}
|
||||||
|
@ -163,48 +206,32 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
void FTraceInfo::EnterSectorPortal(int position, double frac, sector_t *entersec)
|
void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac, sector_t *entersec)
|
||||||
{
|
{
|
||||||
if (aimdir != -1 && aimdir != position) return;
|
|
||||||
AActor *portal = entersec->SkyBoxes[position];
|
AActor *portal = entersec->SkyBoxes[position];
|
||||||
|
|
||||||
if (aimdir == sector_t::ceiling && portal->specialf1 < limitz) return;
|
|
||||||
else if (aimdir == sector_t::floor && portal->specialf1 > limitz) return;
|
|
||||||
|
|
||||||
FTraceInfo newtrace;
|
|
||||||
FTraceResults results;
|
|
||||||
|
|
||||||
memset(&results, 0, sizeof(results));
|
|
||||||
|
|
||||||
newtrace.Start += portal->Scale;
|
|
||||||
|
|
||||||
frac += 1 / MaxDist;
|
|
||||||
double enterdist = MaxDist * frac;
|
double enterdist = MaxDist * frac;
|
||||||
DVector2 enter = newtrace.Start.XY() + enterdist * Vec.XY();
|
DVector3 exit = Start + enterdist * Vec;
|
||||||
|
DVector3 enter = exit + portal->Scale;
|
||||||
|
|
||||||
newtrace.Vec = Vec;
|
Start += portal->Scale;
|
||||||
newtrace.ActorMask = ActorMask;
|
CurSector = P_PointInSector(enter);
|
||||||
newtrace.WallMask = WallMask;
|
inshootthrough = true;
|
||||||
newtrace.IgnoreThis = IgnoreThis;
|
startfrac = frac;
|
||||||
newtrace.Results = &results;
|
EnterDist = enterdist;
|
||||||
newtrace.TempResults = TempResults;
|
pt.PortalRelocate(portal, ptflags, frac);
|
||||||
newtrace.CurSector = P_PointInSector(enter);
|
|
||||||
newtrace.MaxDist = MaxDist;
|
|
||||||
newtrace.EnterDist = EnterDist;
|
|
||||||
newtrace.TraceCallback = TraceCallback;
|
|
||||||
newtrace.TraceCallbackData = TraceCallbackData;
|
|
||||||
newtrace.TraceFlags = TraceFlags;
|
|
||||||
newtrace.inshootthrough = true;
|
|
||||||
newtrace.startfrac = frac;
|
|
||||||
newtrace.aimdir = position;
|
|
||||||
newtrace.limitz = portal->specialf1;
|
|
||||||
newtrace.sectorsel = 0;
|
|
||||||
newtrace.lastfloorportalheight = newtrace.lastceilingportalheight = limitz;
|
|
||||||
|
|
||||||
if (newtrace.TraceTraverse(ActorMask ? PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE : PT_ADDLINES))
|
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
||||||
{
|
{
|
||||||
TempResults->CopyIfCloser(newtrace.Results);
|
enterdist = MaxDist * frac;
|
||||||
|
Results->HitType = TRACE_CrossingPortal;
|
||||||
|
Results->HitPos = exit;
|
||||||
|
Results->SrcFromTarget = enter;
|
||||||
|
Results->HitVector = Vec;
|
||||||
|
TraceCallback(*Results, TraceCallbackData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Setup3DFloors();
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
@ -213,59 +240,38 @@ void FTraceInfo::EnterSectorPortal(int position, double frac, sector_t *entersec
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
int FTraceInfo::EnterLinePortal(line_t *li, double frac)
|
void FTraceInfo::EnterLinePortal(FPathTraverse &pt, intercept_t *in)
|
||||||
{
|
{
|
||||||
|
line_t *li = in->d.line;
|
||||||
FLinePortal *port = li->getPortal();
|
FLinePortal *port = li->getPortal();
|
||||||
|
|
||||||
// The caller cannot handle portals without global offset.
|
double frac = in->frac + EQUAL_EPSILON;
|
||||||
if (port->mType != PORTT_LINKED && (TraceFlags & TRACE_PortalRestrict)) return -1;
|
double enterdist = MaxDist * frac;
|
||||||
|
DVector3 exit = Start + MaxDist * in->frac * Vec;
|
||||||
|
|
||||||
FTraceInfo newtrace;
|
P_TranslatePortalXY(li, Start.X, Start.Y);
|
||||||
|
P_TranslatePortalZ(li, Start.Z);
|
||||||
|
P_TranslatePortalVXVY(li, Vec.X, Vec.Y);
|
||||||
|
P_TranslatePortalZ(li, limitz);
|
||||||
|
|
||||||
newtrace.Start = Start;
|
CurSector = P_PointInSector(Start + enterdist * Vec);
|
||||||
newtrace.Vec = Vec;
|
EnterDist = enterdist;
|
||||||
|
inshootthrough = true;
|
||||||
P_TranslatePortalXY(li, newtrace.Start.X, newtrace.Start.Y);
|
startfrac = frac;
|
||||||
P_TranslatePortalZ(li, newtrace.Start.Z);
|
Results->unlinked |= (port->mType != PORTT_LINKED);
|
||||||
P_TranslatePortalVXVY(li, newtrace.Vec.X, newtrace.Vec.Y);
|
pt.PortalRelocate(in, ptflags);
|
||||||
|
|
||||||
frac += 1 / MaxDist;
|
|
||||||
double enterdist = MaxDist / frac;
|
|
||||||
DVector3 enter = newtrace.Start + enterdist * Vec;
|
|
||||||
|
|
||||||
newtrace.ActorMask = ActorMask;
|
|
||||||
newtrace.WallMask = WallMask;
|
|
||||||
newtrace.IgnoreThis = IgnoreThis;
|
|
||||||
newtrace.Results = Results;
|
|
||||||
newtrace.TempResults = TempResults;
|
|
||||||
newtrace.CurSector = P_PointInSector(enter);
|
|
||||||
newtrace.MaxDist = MaxDist;
|
|
||||||
newtrace.EnterDist = EnterDist;
|
|
||||||
newtrace.TraceCallback = TraceCallback;
|
|
||||||
newtrace.TraceCallbackData = TraceCallbackData;
|
|
||||||
newtrace.TraceFlags = TraceFlags;
|
|
||||||
newtrace.inshootthrough = true;
|
|
||||||
newtrace.startfrac = frac;
|
|
||||||
newtrace.aimdir = aimdir;
|
|
||||||
newtrace.limitz = limitz;
|
|
||||||
|
|
||||||
P_TranslatePortalZ(li, newtrace.limitz);
|
|
||||||
newtrace.lastfloorportalheight = newtrace.lastceilingportalheight = newtrace.limitz;
|
|
||||||
newtrace.sectorsel = 0;
|
|
||||||
Results->unlinked = true;
|
|
||||||
|
|
||||||
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
||||||
{
|
{
|
||||||
|
enterdist = MaxDist * in->frac;
|
||||||
Results->HitType = TRACE_CrossingPortal;
|
Results->HitType = TRACE_CrossingPortal;
|
||||||
Results->HitPos = enter;
|
Results->HitPos = exit;
|
||||||
P_TranslatePortalXY(li, enter.X, enter.Y);
|
P_TranslatePortalXY(li, exit.X, exit.Y);
|
||||||
P_TranslatePortalZ(li, enter.Z);
|
P_TranslatePortalZ(li, exit.Z);
|
||||||
Results->SrcFromTarget = enter;
|
Results->SrcFromTarget = exit;
|
||||||
Results->HitVector = newtrace.Vec;
|
Results->HitVector = Vec;
|
||||||
TraceCallback(*Results, TraceCallbackData);
|
TraceCallback(*Results, TraceCallbackData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newtrace.TraceTraverse(ActorMask ? PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE : PT_ADDLINES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -355,14 +361,6 @@ void FTraceInfo::Setup3DFloors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!CurSector->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
|
||||||
EnterSectorPortal(sector_t::ceiling, startfrac, CurSector);
|
|
||||||
}
|
|
||||||
if (!CurSector->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
|
||||||
EnterSectorPortal(sector_t::floor, startfrac, CurSector);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -372,14 +370,11 @@ void FTraceInfo::Setup3DFloors()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool FTraceInfo::LineCheck(intercept_t *in)
|
bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
||||||
{
|
{
|
||||||
int lineside;
|
int lineside;
|
||||||
sector_t *entersector;
|
sector_t *entersector;
|
||||||
|
|
||||||
double dist = MaxDist * in->frac;
|
|
||||||
DVector3 hit = Start + Vec * dist;
|
|
||||||
|
|
||||||
double ff, fc, bf = 0, bc = 0;
|
double ff, fc, bf = 0, bc = 0;
|
||||||
|
|
||||||
if (in->d.line->frontsector->sectornum == CurSector->sectornum)
|
if (in->d.line->frontsector->sectornum == CurSector->sectornum)
|
||||||
|
@ -453,80 +448,17 @@ bool FTraceInfo::LineCheck(intercept_t *in)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit.Z <= ff)
|
if (hit.Z <= ff)
|
||||||
{
|
|
||||||
if (CurSector->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
{
|
||||||
// hit floor in front of wall
|
// hit floor in front of wall
|
||||||
Results->HitType = TRACE_HitFloor;
|
Results->HitType = TRACE_HitFloor;
|
||||||
Results->HitTexture = CurSector->GetTexture(sector_t::floor);
|
Results->HitTexture = CurSector->GetTexture(sector_t::floor);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((TraceFlags & TRACE_ReportPortals) && lastfloorportalheight > fc)
|
|
||||||
{
|
|
||||||
lastfloorportalheight = fc;
|
|
||||||
if (TraceCallback != NULL)
|
|
||||||
{
|
|
||||||
Results->HitType = TRACE_CrossingPortal;
|
|
||||||
double hitz = CurSector->SkyBoxes[sector_t::floor]->specialf1;
|
|
||||||
Results->HitPos = Start + Vec * (hitz - Start.Z) / Vec.Z;
|
|
||||||
Results->SrcFromTarget = Results->HitPos + CurSector->SkyBoxes[sector_t::floor]->Scale;
|
|
||||||
Results->HitVector = Vec;
|
|
||||||
TraceCallback(*Results, TraceCallbackData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (entersector == NULL || entersector->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
|
||||||
// hit beyond a portal plane. This needs to be taken care of by the trace spawned on the other side.
|
|
||||||
Results->HitType = TRACE_HitNone;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (hit.Z >= fc)
|
else if (hit.Z >= fc)
|
||||||
{
|
|
||||||
if (CurSector->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
{
|
||||||
// hit ceiling in front of wall
|
// hit ceiling in front of wall
|
||||||
Results->HitType = TRACE_HitCeiling;
|
Results->HitType = TRACE_HitCeiling;
|
||||||
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((TraceFlags & TRACE_ReportPortals) && lastceilingportalheight < fc)
|
|
||||||
{
|
|
||||||
lastceilingportalheight = fc;
|
|
||||||
if (TraceCallback != NULL)
|
|
||||||
{
|
|
||||||
Results->HitType = TRACE_CrossingPortal;
|
|
||||||
double hitz = CurSector->SkyBoxes[sector_t::ceiling]->specialf1;
|
|
||||||
Results->HitPos = Start + Vec * (hitz - Start.Z) / Vec.Z;
|
|
||||||
Results->SrcFromTarget = Results->HitPos + CurSector->SkyBoxes[sector_t::ceiling]->Scale;
|
|
||||||
Results->HitVector = Vec;
|
|
||||||
TraceCallback(*Results, TraceCallbackData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (entersector == NULL || entersector->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
|
||||||
// hit beyond a portal plane. This needs to be taken care of by the trace spawned on the other side.
|
|
||||||
Results->HitType = TRACE_HitNone;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in->d.line->isLinePortal())
|
|
||||||
{
|
|
||||||
if (entersector == NULL || (hit.Z >= bf && hit.Z <= bc))
|
|
||||||
{
|
|
||||||
int res = EnterLinePortal(in->d.line, in->frac);
|
|
||||||
if (res != -1)
|
|
||||||
{
|
|
||||||
aimdir = INT_MAX; // flag for ending the traverse
|
|
||||||
return !!res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto normalline; // hit upper or lower tier.
|
|
||||||
}
|
|
||||||
else if (entersector == NULL ||
|
else if (entersector == NULL ||
|
||||||
hit.Z < bf || hit.Z > bc ||
|
hit.Z < bf || hit.Z > bc ||
|
||||||
in->d.line->flags & WallMask)
|
in->d.line->flags & WallMask)
|
||||||
|
@ -610,15 +542,6 @@ normalline:
|
||||||
// we need to as well, for compatibility
|
// we need to as well, for compatibility
|
||||||
P_ActivateLine(in->d.line, IgnoreThis, lineside, SPAC_Impact);
|
P_ActivateLine(in->d.line, IgnoreThis, lineside, SPAC_Impact);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entersector->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
|
||||||
EnterSectorPortal(sector_t::ceiling, in->frac, entersector);
|
|
||||||
}
|
|
||||||
if (!entersector->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
|
||||||
EnterSectorPortal(sector_t::floor, in->frac, entersector);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cont:
|
cont:
|
||||||
|
|
||||||
|
@ -696,11 +619,8 @@ cont:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool FTraceInfo::ThingCheck(intercept_t *in)
|
bool FTraceInfo::ThingCheck(intercept_t *in, double dist, DVector3 hit)
|
||||||
{
|
{
|
||||||
double dist = MaxDist * in->frac;
|
|
||||||
DVector3 hit = Start + Vec * dist;
|
|
||||||
|
|
||||||
if (hit.Z > in->d.thing->Top())
|
if (hit.Z > in->d.thing->Top())
|
||||||
{
|
{
|
||||||
// trace enters above actor
|
// trace enters above actor
|
||||||
|
@ -834,49 +754,59 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
||||||
lastsplashsector = CurSector->sectornum;
|
lastsplashsector = CurSector->sectornum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have something closer in the storage for portal subtraces.
|
double dist = MaxDist * in->frac;
|
||||||
if (TempResults->HitType != TRACE_HitNone && in->frac > TempResults->Fraction)
|
DVector3 hit = Start + Vec * dist;
|
||||||
|
|
||||||
|
// Crossed a floor portal?
|
||||||
|
if (Vec.Z < 0 && !CurSector->PortalBlocksMovement(sector_t::floor))
|
||||||
{
|
{
|
||||||
break;
|
// calculate position where the portal is crossed
|
||||||
|
double portz = CurSector->SkyBoxes[sector_t::floor]->specialf1;
|
||||||
|
if (hit.Z < portz && limitz > portz)
|
||||||
|
{
|
||||||
|
limitz = portz;
|
||||||
|
EnterSectorPortal(it, sector_t::floor, (portz - Start.Z) / (Vec.Z * MaxDist), CurSector);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (in->isaline)
|
}
|
||||||
|
// ... or a ceiling portal?
|
||||||
|
else if (Vec.Z > 0 && !CurSector->PortalBlocksMovement(sector_t::ceiling))
|
||||||
{
|
{
|
||||||
bool res = LineCheck(in);
|
// calculate position where the portal is crossed
|
||||||
if (aimdir == INT_MAX) return res; // signal for immediate abort
|
double portz = CurSector->SkyBoxes[sector_t::ceiling]->specialf1;
|
||||||
if (!res) break;
|
if (hit.Z > portz && limitz < portz)
|
||||||
|
{
|
||||||
|
limitz = portz;
|
||||||
|
EnterSectorPortal(it, sector_t::ceiling, (portz - Start.Z) / (Vec.Z * MaxDist), CurSector);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in->isaline)
|
||||||
|
{
|
||||||
|
if (in->d.line->isLinePortal() && P_PointOnLineSidePrecise(Start, in->d.line) == 0)
|
||||||
|
{
|
||||||
|
sector_t *entersector = in->d.line->backsector;
|
||||||
|
if (entersector == NULL || (hit.Z >= entersector->floorplane.ZatPoint(hit) && hit.Z <= entersector->ceilingplane.ZatPoint(hit)))
|
||||||
|
{
|
||||||
|
FLinePortal *port = in->d.line->getPortal();
|
||||||
|
// The caller cannot handle portals without global offset.
|
||||||
|
if (port->mType == PORTT_LINKED || !(TraceFlags & TRACE_PortalRestrict))
|
||||||
|
{
|
||||||
|
EnterLinePortal(it, in);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!LineCheck(in, dist, hit)) break;
|
||||||
}
|
}
|
||||||
else if ((in->d.thing->flags & ActorMask) && in->d.thing != IgnoreThis)
|
else if ((in->d.thing->flags & ActorMask) && in->d.thing != IgnoreThis)
|
||||||
{
|
{
|
||||||
if (!ThingCheck(in)) break;
|
if (!ThingCheck(in, dist, hit)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if one subtrace through a portal yielded a better result.
|
if (Results->HitType == TRACE_HitNone)
|
||||||
if (TempResults->HitType != TRACE_HitNone &&
|
|
||||||
(Results->HitType == TRACE_HitNone || Results->Fraction > TempResults->Fraction))
|
|
||||||
{
|
|
||||||
// We still need to do a water check here or this may get missed on occasion
|
|
||||||
if (Results->CrossedWater == NULL &&
|
|
||||||
CurSector->heightsec != NULL &&
|
|
||||||
CurSector->heightsec->floorplane.ZatPoint(Results->HitPos) >= Results->HitPos.Z)
|
|
||||||
{
|
|
||||||
// Save the result so that the water check doesn't destroy it.
|
|
||||||
FTraceResults *res = Results;
|
|
||||||
FTraceResults hsecResult;
|
|
||||||
Results = &hsecResult;
|
|
||||||
|
|
||||||
if (CheckSectorPlane(CurSector->heightsec, true))
|
|
||||||
{
|
|
||||||
Results->CrossedWater = §ors[CurSector->sectornum];
|
|
||||||
Results->CrossedWaterPos = Results->HitPos;
|
|
||||||
}
|
|
||||||
Results = res;
|
|
||||||
}
|
|
||||||
|
|
||||||
Results->CopyIfCloser(TempResults);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (Results->HitType == TRACE_HitNone)
|
|
||||||
{
|
{
|
||||||
if (CurSector->PortalBlocksMovement(sector_t::floor) && CheckSectorPlane(CurSector, true))
|
if (CurSector->PortalBlocksMovement(sector_t::floor) && CheckSectorPlane(CurSector, true))
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,24 +87,6 @@ struct FTraceResults
|
||||||
DVector3 CrossedWaterPos; // remember the position so that we can use it for spawning the splash
|
DVector3 CrossedWaterPos; // remember the position so that we can use it for spawning the splash
|
||||||
F3DFloor *Crossed3DWater; // For 3D floor-based deep water
|
F3DFloor *Crossed3DWater; // For 3D floor-based deep water
|
||||||
DVector3 Crossed3DWaterPos;
|
DVector3 Crossed3DWaterPos;
|
||||||
|
|
||||||
void CopyIfCloser(FTraceResults *other)
|
|
||||||
{
|
|
||||||
if (other->Distance < Distance || HitType == TRACE_HitNone)
|
|
||||||
{
|
|
||||||
memcpy(this, other, myoffsetof(FTraceResults, CrossedWater));
|
|
||||||
}
|
|
||||||
if (CrossedWater == NULL && other->CrossedWater != NULL)
|
|
||||||
{
|
|
||||||
CrossedWater = other->CrossedWater;
|
|
||||||
CrossedWaterPos = other->CrossedWaterPos;
|
|
||||||
}
|
|
||||||
if (Crossed3DWater == NULL && other->Crossed3DWater != NULL)
|
|
||||||
{
|
|
||||||
Crossed3DWater = other->Crossed3DWater;
|
|
||||||
Crossed3DWaterPos = other->Crossed3DWaterPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1157,7 +1157,8 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
|
||||||
performBlockingThrust = true;
|
performBlockingThrust = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FBoundingBox box(mobj->X(), mobj->Y(), mobj->radius);
|
DVector2 pos = mobj->PosRelative(ld);
|
||||||
|
FBoundingBox box(pos.X, pos.Y, mobj->radius);
|
||||||
|
|
||||||
if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1)
|
if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -661,10 +661,10 @@ DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy)
|
||||||
if (blockx < 0 || blocky < 0 || blockx >= bmapwidth || blocky >= bmapheight || !PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
|
if (blockx < 0 || blocky < 0 || blockx >= bmapwidth || blocky >= bmapheight || !PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLinePortalTraverse it;
|
|
||||||
bool repeat;
|
bool repeat;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
FLinePortalTraverse it;
|
||||||
it.init(actx, acty, dx, dy, PT_ADDLINES|PT_DELTA);
|
it.init(actx, acty, dx, dy, PT_ADDLINES|PT_DELTA);
|
||||||
intercept_t *in;
|
intercept_t *in;
|
||||||
|
|
||||||
|
@ -696,6 +696,8 @@ DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy)
|
||||||
// update the fields, end this trace and restart from the new position
|
// update the fields, end this trace and restart from the new position
|
||||||
dx = dest.X - hit.X;
|
dx = dest.X - hit.X;
|
||||||
dy = dest.Y - hit.Y;
|
dy = dest.Y - hit.Y;
|
||||||
|
actx = hit.X;
|
||||||
|
acty = hit.Y;
|
||||||
repeat = true;
|
repeat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue