/// <summary> /// Checks if this wall blocks a /// move between Start and End /// </summary> /// <param name="Start">A 3D location</param> /// <param name="End">A 2D location</param> /// <param name="PlayerHeight">Height of the player for ceiling collisions</param> /// <returns></returns> public bool IsBlocking(V3 Start, V2 End, Real PlayerHeight) { V2 P1 = GetP1(); V2 P2 = GetP2(); V2 Start2D = new V2(Start.X, Start.Z); // calculate the sides of the points (returns -1, 0 or 1) int startside = Start2D.GetSide(P1, P2); int endside = End.GetSide(P1, P2); // if points are not on same side // the infinite lines cross if (startside != endside) { // verify also the finite line segments cross V2 intersect; if (MathUtil.IntersectLineLine(Start2D, End, P1, P2, out intersect)) { // verify the side we've crossed is flaggged as "nonpassable" // if so, we actually have a collision if ((startside < 0 && LeftSide != null && !LeftSide.Flags.IsPassable) || (startside > 0 && RightSide != null && !RightSide.Flags.IsPassable)) { return(true); } // still check the stepheight from oldheight to new floor if passable // for too high steps Real endheight = 0.0f; Real diff; if (endside <= 0 && LeftSector != null) { endheight = LeftSector.CalculateFloorHeight((int)End.X, (int)End.Y, true); } else if (endside > 0 && RightSector != null) { endheight = RightSector.CalculateFloorHeight((int)End.X, (int)End.Y, true); } diff = endheight - Start.Y; // diff is bigger than max. step height, we have a collision if (diff > GeometryConstants.MAXSTEPHEIGHT) { return(true); } // check the ceiling heights if (endside <= 0 && LeftSector != null) { endheight = LeftSector.CalculateCeilingHeight((int)End.X, (int)End.Y); } else if (endside > 0 && RightSector != null) { endheight = RightSector.CalculateCeilingHeight((int)End.X, (int)End.Y); } // diff is bigger than max. step height, we have a collision if (endheight < Start.Y + PlayerHeight) { return(true); } } } return(false); }
/// <summary> /// Fills in the Z coordinates for the wall. /// Make sure to call "ResolveIndices" before! /// Taken from "SetWallHeights" in bspload.c /// </summary> public void CalculateWallSideHeights() { // no sectors? we're screwed, use defaults and return if (RightSector == null && LeftSector == null) { Z0 = Z1 = 0.0f; Z2 = Z3 = (Real)GeometryConstants.FINENESS; ZZ0 = ZZ1 = 0.0f; ZZ2 = ZZ3 = (Real)GeometryConstants.FINENESS; return; } // only left sector? use heights from there and return if (RightSector == null) { Z0 = Z1 = LeftSector.CalculateFloorHeight(X1, Y1); Z2 = Z3 = LeftSector.CalculateCeilingHeight(X1, Y1); ZZ0 = ZZ1 = LeftSector.CalculateFloorHeight(X2, Y2); ZZ2 = ZZ3 = LeftSector.CalculateCeilingHeight(X2, Y2); return; } // only right sector? use heights from there and return if (LeftSector == null) { Z0 = Z1 = RightSector.CalculateFloorHeight(X1, Y1); Z2 = Z3 = RightSector.CalculateCeilingHeight(X1, Y1); ZZ0 = ZZ1 = RightSector.CalculateFloorHeight(X2, Y2); ZZ2 = ZZ3 = RightSector.CalculateCeilingHeight(X2, Y2); return; } // -- finally, if there are both sectors available --- // start with the floor handling Real S1_height0 = RightSector.CalculateFloorHeight(X1, Y1); Real S2_height0 = LeftSector.CalculateFloorHeight(X1, Y1); Real S1_height1 = RightSector.CalculateFloorHeight(X2, Y2); Real S2_height1 = LeftSector.CalculateFloorHeight(X2, Y2); // S1 is above S2 at first endpoint if (S1_height0 > S2_height0) { if (S1_height1 >= S2_height1) { // normal wall - S1 higher at both ends BowtieFlags.Value = 0; Z1 = S1_height0; ZZ1 = S1_height1; Z0 = S2_height0; ZZ0 = S2_height1; } else { // bowtie handling BowtieFlags.IsBelowPos = true; // no extra zNeg here Z1 = S1_height0; ZZ1 = S2_height1; Z0 = S2_height0; ZZ0 = S1_height1; } } // S2 above S1 at first endpoint else { if (S2_height1 >= S1_height1) { // normal wall - S2 higher at both ends BowtieFlags.Value = 0; Z1 = S2_height0; ZZ1 = S2_height1; Z0 = S1_height0; ZZ0 = S1_height1; } else { // bowtie handling BowtieFlags.IsBelowNeg = true; // no extra zNeg here Z1 = S2_height0; ZZ1 = S1_height1; Z0 = S1_height0; ZZ0 = S2_height1; } } // start with ceiling handling S1_height0 = RightSector.CalculateCeilingHeight(X1, Y1); S2_height0 = LeftSector.CalculateCeilingHeight(X1, Y1); S1_height1 = RightSector.CalculateCeilingHeight(X2, Y2); S2_height1 = LeftSector.CalculateCeilingHeight(X2, Y2); if (S1_height0 > S2_height0) { if (S1_height1 >= S2_height1) { // normal wall - S1 higher at both ends //wall->bowtie_bits &= (BYTE)~BT_ABOVE_BOWTIE; // Clear above bowtie bits BowtieFlags.IsAboveBowtie = false; Z3 = S1_height0; ZZ3 = S1_height1; Z2 = S2_height0; ZZ2 = S2_height1; } else { // bowtie - see notes on bowties above //wall->bowtie_bits |= (BYTE)BT_ABOVE_POS; // positive sector is on top at endpoint 0 BowtieFlags.IsAbovePos = true; Z3 = S1_height0; ZZ3 = S2_height1; Z2 = S2_height0; ZZ2 = S1_height1; } } else { if (S2_height1 >= S1_height1) { // normal wall - S2 higher at both ends //wall->bowtie_bits &= (BYTE)~BT_ABOVE_BOWTIE; BowtieFlags.IsAboveBowtie = false; Z3 = S2_height0; ZZ3 = S2_height1; Z2 = S1_height0; ZZ2 = S1_height1; } else { // bowtie - see notes on bowties above //wall->bowtie_bits |= (BYTE)BT_ABOVE_NEG; // negative sector is on top at endpoint 0 BowtieFlags.IsAboveNeg = true; Z3 = S2_height0; ZZ3 = S1_height1; Z2 = S1_height0; ZZ2 = S2_height1; } } }