private bool AddLineIntercepts(LineDef line) { int s1; int s2; // Avoid precision problems with two routines. if (trace.Dx > Fixed.FromInt(16) || trace.Dy > Fixed.FromInt(16) || trace.Dx < -Fixed.FromInt(16) || trace.Dy < -Fixed.FromInt(16)) { s1 = Geometry.PointOnDivLineSide(line.Vertex1.X, line.Vertex1.Y, trace); s2 = Geometry.PointOnDivLineSide(line.Vertex2.X, line.Vertex2.Y, trace); } else { s1 = Geometry.PointOnLineSide(trace.X, trace.Y, line); s2 = Geometry.PointOnLineSide(trace.X + trace.Dx, trace.Y + trace.Dy, line); } if (s1 == s2) { // Line isn't crossed. return(true); } // Hit the line. target.MakeFrom(line); var frac = InterceptVector(trace, target); if (frac < Fixed.Zero) { // Behind source. return(true); } // Try to early out the check. if (earlyOut && frac < Fixed.One && line.BackSector == null) { // Stop checking. return(false); } intercepts[interceptCount].Frac = frac; intercepts[interceptCount].Line = line; intercepts[interceptCount].Thing = null; interceptCount++; // Continue. return(true); }
/// <summary> /// Returns true if strace crosses the given subsector successfully. /// </summary> private bool CrossSubsector(int subsectorNumber, int validCount) { var map = world.Map; var subsector = map.Subsectors[subsectorNumber]; var count = subsector.SegCount; // Check lines. for (var i = 0; i < count; i++) { var seg = map.Segs[subsector.FirstSeg + i]; var line = seg.LineDef; // Allready checked other side? if (line.ValidCount == validCount) { continue; } line.ValidCount = validCount; var v1 = line.Vertex1; var v2 = line.Vertex2; var s1 = Geometry.DivLineSide(v1.X, v1.Y, trace); var s2 = Geometry.DivLineSide(v2.X, v2.Y, trace); // Line isn't crossed? if (s1 == s2) { continue; } occluder.MakeFrom(line); s1 = Geometry.DivLineSide(trace.X, trace.Y, occluder); s2 = Geometry.DivLineSide(targetX, targetY, occluder); // Line isn't crossed? if (s1 == s2) { continue; } // The check below is imported from Chocolate Doom to // avoid crash due to two-sided lines with no backsector. if (line.BackSector == null) { return(false); } // Stop because it is not two sided anyway. // Might do this after updating validcount? if ((line.Flags & LineFlags.TwoSided) == 0) { return(false); } // Crosses a two sided line. var front = seg.FrontSector; var back = seg.BackSector; // No wall to block sight with? if (front.FloorHeight == back.FloorHeight && front.CeilingHeight == back.CeilingHeight) { continue; } // Possible occluder because of ceiling height differences. Fixed openTop; if (front.CeilingHeight < back.CeilingHeight) { openTop = front.CeilingHeight; } else { openTop = back.CeilingHeight; } // Because of ceiling height differences. Fixed openBottom; if (front.FloorHeight > back.FloorHeight) { openBottom = front.FloorHeight; } else { openBottom = back.FloorHeight; } // Quick test for totally closed doors. if (openBottom >= openTop) { // Stop. return(false); } var frac = InterceptVector(trace, occluder); if (front.FloorHeight != back.FloorHeight) { var slope = (openBottom - sightZStart) / frac; if (slope > bottomSlope) { bottomSlope = slope; } } if (front.CeilingHeight != back.CeilingHeight) { var slope = (openTop - sightZStart) / frac; if (slope < topSlope) { topSlope = slope; } } if (topSlope <= bottomSlope) { // Stop. return(false); } } // Passed the subsector ok. return(true); }