DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

p_slide.c (16109B)


      1 #include "doomdef.h"
      2 #include "p_local.h"
      3 
      4 #define	CLIPRADIUS	23
      5 #define SIDE_ON	0
      6 #define	SIDE_FRONT	1
      7 #define	SIDE_BACK	-1
      8 
      9 fixed_t bestslidefrac;  // 800A5728
     10 line_t  *bestslideline; // 800A572C
     11 mobj_t  *slidemo;       // 800A5730
     12 
     13 /*
     14 ====================
     15 =
     16 = PTR_SlideTraverse
     17 =
     18 ====================
     19 */
     20 
     21 boolean PTR_SlideTraverse(intercept_t* in) // 800170AC
     22 {
     23     line_t* li;
     24 
     25     li = in->d.line;
     26 
     27     if(!(li->flags & ML_TWOSIDED))
     28     {
     29         if(P_PointOnLineSide(slidemo->x, slidemo->y, li))
     30             return true; /* don't hit the back side */
     31 
     32         goto isblocking;
     33     }
     34 
     35     /* set openrange, opentop, openbottom */
     36     P_LineOpening(li);
     37 
     38     if(openrange < slidemo->height)
     39     {
     40         goto isblocking;    /* doesn't fit */
     41     }
     42 
     43     if(opentop - slidemo->z < slidemo->height)
     44     {
     45         goto isblocking;    /* mobj is too high */
     46     }
     47 
     48     if(openbottom - slidemo->z > 24*FRACUNIT)
     49     {
     50         goto isblocking;    /* too big a step up */
     51     }
     52 
     53     /* this line doesn't block movement */
     54     return true;
     55 
     56     /* the line does block movement, */
     57     /* see if it is closer than best so far */
     58 
     59 isblocking:
     60 
     61     if(in->frac < bestslidefrac)
     62     {
     63         bestslidefrac = in->frac;
     64         bestslideline = li;
     65     }
     66 
     67     return false;       /* stop */
     68 }
     69 
     70 /*
     71 ===============================================
     72 = P_SlideMove
     73 = The momx / momy move is bad, so try to slide
     74 = along a wall.
     75 = Find the first line hit, move flush to it,
     76 = and slide along it
     77 =
     78 = This is a kludgy mess.
     79 ===============================================
     80 */
     81 
     82 void P_SlideMove(mobj_t* mo) // 800171B0
     83 {
     84     fixed_t tmxmove;
     85     fixed_t tmymove;
     86     fixed_t leadx;
     87     fixed_t leady;
     88     fixed_t trailx;
     89     fixed_t traily;
     90     fixed_t newx;
     91     fixed_t newy;
     92     int     hitcount;
     93     line_t* ld;
     94     int     an1;
     95     int     an2;
     96 
     97     slidemo = mo;
     98     hitcount = 0;
     99 
    100 retry:
    101     hitcount++;
    102 
    103     if(hitcount == 3)
    104     {
    105         goto stairstep;    // don't loop forever
    106     }
    107 
    108     // trace along the three leading corners
    109     if(mo->momx > 0)
    110     {
    111         leadx = mo->x + mo->radius;
    112         trailx = mo->x - mo->radius;
    113     }
    114     else
    115     {
    116         leadx = mo->x - mo->radius;
    117         trailx = mo->x + mo->radius;
    118     }
    119 
    120     if(mo->momy > 0)
    121     {
    122         leady = mo->y + mo->radius;
    123         traily = mo->y - mo->radius;
    124     }
    125     else
    126     {
    127         leady = mo->y - mo->radius;
    128         traily = mo->y + mo->radius;
    129     }
    130 
    131     bestslidefrac = FRACUNIT+1;
    132 
    133     P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy,
    134                    PT_ADDLINES, PTR_SlideTraverse);
    135     P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy,
    136                    PT_ADDLINES, PTR_SlideTraverse);
    137     P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
    138                    PT_ADDLINES, PTR_SlideTraverse);
    139 
    140     // move up to the wall
    141     if(bestslidefrac == FRACUNIT+1)
    142     {
    143         // the move most have hit the middle, so stairstep
    144 stairstep:
    145         if(!P_TryMove(mo, mo->x, mo->y + mo->momy))
    146         {
    147             if(!P_TryMove(mo, mo->x + mo->momx, mo->y))
    148             {
    149                 // [d64] set momx and momy to 0
    150                 mo->momx = 0;
    151                 mo->momy = 0;
    152             }
    153         }
    154         return;
    155     }
    156 
    157     // fudge a bit to make sure it doesn't hit
    158     bestslidefrac -= 0x800;
    159     if(bestslidefrac > 0)
    160     {
    161         newx = FixedMul(mo->momx, bestslidefrac);
    162         newy = FixedMul(mo->momy, bestslidefrac);
    163 
    164         if(!P_TryMove(mo, mo->x + newx, mo->y + newy))
    165         {
    166             bestslidefrac = FRACUNIT;
    167 
    168             // [d64] jump to hitslideline instead of stairstep
    169             goto hitslideline;
    170         }
    171     }
    172 
    173     // Now continue along the wall.
    174     // First calculate remainder.
    175     bestslidefrac = 0xf800 - bestslidefrac;
    176     //bestslidefrac = FRACUNIT - (bestslidefrac + 0x800);
    177 
    178     if(bestslidefrac > FRACUNIT)
    179     {
    180         bestslidefrac = FRACUNIT;
    181     }
    182 
    183     if(bestslidefrac <= 0)
    184     {
    185         return;
    186     }
    187 
    188     //
    189     // [d64] code below is loosely based on P_HitSlideLine
    190     //
    191 hitslideline:
    192 
    193     ld = bestslideline;
    194 
    195     if(ld->slopetype == ST_HORIZONTAL)
    196     {
    197         tmymove = 0;
    198     }
    199     else
    200     {
    201         tmymove = FixedMul(mo->momy, bestslidefrac);
    202     }
    203 
    204     if(ld->slopetype == ST_VERTICAL)
    205     {
    206         tmxmove = 0;
    207     }
    208     else
    209     {
    210         tmxmove = FixedMul(mo->momx, bestslidefrac);
    211     }
    212 
    213     //
    214     // [d64] this new algorithm seems to reduce the chances
    215     // of boosting the player's speed when wall running
    216     //
    217 
    218     an1 = finecosine[ld->fineangle];
    219     an2 = finesine[ld->fineangle];
    220 
    221     if(P_PointOnLineSide(mo->x, mo->y, bestslideline))
    222     {
    223         //
    224         // [d64] same as deltaangle += ANG180 ?
    225         //
    226         an1 = -an1;
    227         an2 = -an2;
    228     }
    229 
    230     newx = FixedMul(tmxmove, an1);
    231     newy = FixedMul(tmymove, an2);
    232 
    233     mo->momx = FixedMul(newx + newy, an1);
    234     mo->momy = FixedMul(newx + newy, an2);
    235 
    236     if(!P_TryMove(mo, mo->x + mo->momx, mo->y + mo->momy))
    237     {
    238         goto retry;
    239     }
    240 }
    241 
    242 //----------------------
    243 
    244 #if 0
    245 
    246 fixed_t slidex, slidey;		// the final position       //80077DBC|fGp000009ac, 80077DC0|fGp000009b0
    247 line_t *specialline;		//80077DC8, uGp000009b8
    248 
    249 fixed_t		slidedx, slidedy;		// current move for completablefrac //80077E9C|fGp00000a8c, 80077EA0|fGp00000a90
    250 
    251 fixed_t		endbox[4];				// final proposed position //800979d0
    252 
    253 fixed_t blockfrac;			// the fraction of move that gets completed //8007804C|iGp00000c3c
    254 fixed_t blocknvx, blocknvy;	// the vector of the line that blocks move //80077FD0|fGp00000bc0, 80077FD8|fGp00000bc8
    255 
    256 // p1, p2 are line endpoints
    257 // p3, p4 are move endpoints
    258 /*iGp00000ae4, iGp00000aec*///p1x, p1y
    259 /*iGp00000ae8, iGp00000af8*///p2x, p2y
    260 /*iGp00000af4, iGp00000b0c*///p3x, p3y
    261 /*iGp00000b08, iGp00000b14*///p4x, p4y
    262 
    263 int p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
    264 fixed_t	nvx, nvy;				// normalized line vector //fGp00000b70, fGp00000b74
    265 
    266 extern mobj_t *slidething;//80077D04
    267 
    268 
    269 fixed_t P_CompletableFrac(fixed_t dx, fixed_t dy);
    270 int SL_PointOnSide(fixed_t x, fixed_t y);
    271 fixed_t SL_CrossFrac (void);
    272 boolean CheckLineEnds (void);
    273 void SL_ClipToLine( void );
    274 boolean SL_CheckLine(line_t *ld);
    275 int	SL_PointOnSide2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, fixed_t x3, fixed_t y3);
    276 void SL_CheckSpecialLines (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
    277 
    278 /*
    279 ===================
    280 =
    281 = P_SlideMove
    282 =
    283 ===================
    284 */
    285 
    286 void P_SlideMove(void)//L8002553C()
    287 {
    288     fixed_t dx, dy, rx, ry;
    289     fixed_t frac, slide;
    290     int i;
    291 
    292 	dx = slidething->momx;
    293 	dy = slidething->momy;
    294 	slidex = slidething->x;
    295 	slidey = slidething->y;
    296 
    297 	if (slidething->flags & MF_NOCLIP)//Psx Doom
    298     {
    299         frac = FRACUNIT;
    300         goto Skip_P_CompletableFrac;
    301     }
    302 
    303     // perform a maximum of three bumps
    304     for (i = 0; i < 3; i++)
    305     {
    306         frac = P_CompletableFrac(dx, dy);
    307 
    308         if (frac != FRACUNIT)
    309             frac -= 0x1000;
    310 
    311         if (frac < 0)
    312             frac = 0;
    313 
    314     Skip_P_CompletableFrac:
    315         rx = FixedMul(frac, dx);
    316         ry = FixedMul(frac, dy);
    317 
    318         slidex += rx;
    319         slidey += ry;
    320 
    321         // made it the entire way
    322         if (frac == FRACUNIT)
    323         {
    324             slidething->momx = dx;
    325             slidething->momy = dy;
    326             SL_CheckSpecialLines(slidething->x, slidething->y, slidex, slidey);
    327             return;
    328         }
    329 
    330         // project the remaining move along the line that blocked movement
    331         dx -= rx;
    332         dy -= ry;
    333         slide = FixedMul(dx, blocknvx) + FixedMul(dy, blocknvy);
    334 
    335         dx = FixedMul(slide, blocknvx);
    336         dy = FixedMul(slide, blocknvy);
    337     }
    338 
    339 	// some hideous situation has happened that won't let the player slide
    340 	slidex = slidething->x;
    341 	slidey = slidething->y;
    342 	slidething->momx = slidething->momy = 0;
    343 }
    344 
    345 
    346 /*
    347 ===================
    348 =
    349 = P_CompletableFrac
    350 =
    351 = Returns the fraction of the move that is completable
    352 ===================
    353 */
    354 
    355 fixed_t P_CompletableFrac(fixed_t dx, fixed_t dy)//L800256CC()
    356 {
    357 	int	xl,xh,yl,yh,bx,by;
    358 	int			offset;
    359     short		*list;
    360     line_t		*ld;
    361 
    362 	blockfrac = FRACUNIT;		// the entire dist until shown otherwise
    363 	slidedx = dx;
    364 	slidedy = dy;
    365 
    366 	endbox[BOXTOP   ] = slidey + CLIPRADIUS*FRACUNIT;
    367 	endbox[BOXBOTTOM] = slidey - CLIPRADIUS*FRACUNIT;
    368 	endbox[BOXRIGHT ] = slidex + CLIPRADIUS*FRACUNIT;
    369 	endbox[BOXLEFT  ] = slidex - CLIPRADIUS*FRACUNIT;
    370 
    371 	if (dx > 0)
    372 		endbox[BOXRIGHT ] += dx;
    373 	else
    374 		endbox[BOXLEFT  ] += dx;
    375 
    376 	if (dy > 0)
    377 		endbox[BOXTOP   ] += dy;
    378 	else
    379 		endbox[BOXBOTTOM] += dy;
    380 
    381 	++validcount;
    382 
    383 	//
    384 	// check lines
    385 	//
    386 	xl = (endbox[BOXLEFT  ] - bmaporgx) >> MAPBLOCKSHIFT;
    387 	xh = (endbox[BOXRIGHT ] - bmaporgx) >> MAPBLOCKSHIFT;
    388 	yl = (endbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
    389 	yh = (endbox[BOXTOP   ] - bmaporgy) >> MAPBLOCKSHIFT;
    390 
    391 	if (xl<0)
    392 		xl = 0;
    393 	if (yl<0)
    394 		yl = 0;
    395 
    396 	if (xh>= bmapwidth)
    397 		xh = bmapwidth -1;
    398 
    399 	if (yh>= bmapheight)
    400 		yh = bmapheight -1;
    401 
    402 	for (bx = xl; bx <= xh; bx++)
    403 	{
    404 		for (by = yl; by <= yh; by++)
    405 		{
    406 		    /*inline ??*/
    407 			//P_BlockLinesIterator(bx, by, SL_CheckLine);
    408 
    409             offset = by*bmapwidth+bx;
    410 
    411             offset = *(blockmap+offset);
    412 
    413             for ( list = blockmaplump+offset ; *list != -1 ; list++)
    414             {
    415                 ld = &lines[*list];
    416 
    417                 if (ld->validcount != validcount)
    418                 {
    419                     ld->validcount = validcount;
    420                     SL_CheckLine(ld);
    421                 }
    422             }
    423 		}
    424 	}
    425 
    426 	//
    427 	// examine results
    428 	//
    429 	if (blockfrac < 0x1000)
    430 	{
    431 		blockfrac = 0;
    432 		specialline = 0;	// can't cross anything on a bad move
    433 		return 0;			// solid wall or thing
    434 	}
    435 
    436 	return blockfrac;
    437 }
    438 
    439 //inline
    440 int SL_PointOnSide(fixed_t x, fixed_t y)//L80025970()
    441 {
    442     //checked
    443     fixed_t	dx, dy, dist;
    444 
    445     dx = x - p1x;
    446     dy = y - p1y;
    447     dist = FixedMul(dx,nvx) + FixedMul(dy,nvy);
    448 
    449     if(dist > FRACUNIT)
    450         return SIDE_FRONT;
    451     else if(dist < -FRACUNIT)
    452         return SIDE_BACK;
    453     else
    454         return SIDE_ON;
    455 }
    456 
    457 //inline
    458 fixed_t SL_CrossFrac (void)//L800259E0()
    459 {
    460     //checked
    461     fixed_t	dx, dy, dist1, dist2, frac;
    462 
    463     // project move start and end points onto line normal
    464     dx = p3x - p1x;
    465     dy = p3y - p1y;
    466 
    467     dist1 = FixedMul(dx,nvx) + FixedMul(dy,nvy);
    468 
    469     dx = p4x - p1x;
    470     dy = p4y - p1y;
    471     dist2 = FixedMul(dx,nvx) + FixedMul(dy,nvy);
    472 
    473     if ((dist1 < 0) == (dist2 < 0))
    474 		return FRACUNIT;		// doesn't cross
    475 
    476 	frac = FixedDiv(dist1, dist1 - dist2 );
    477 
    478 	return frac;
    479 }
    480 
    481 
    482 boolean CheckLineEnds (void)//L80025A98()
    483 {
    484     //checked
    485     fixed_t		snx, sny;		// sight normals
    486     fixed_t		dist1, dist2;
    487     fixed_t		dx, dy;
    488 
    489     snx = p4y - p3y;
    490     sny = p3x - p4x;
    491 
    492     dx = p1x - p3x;
    493     dy = p1y - p3y;
    494 
    495     dist1 = FixedMul(dx,snx) + FixedMul(dy,sny);
    496 
    497     dx = p2x - p3x;
    498     dy = p2y - p3y;
    499 
    500     dist2 = FixedMul(dx,snx) + FixedMul(dy,sny);
    501 
    502     return ((dist1 < 0)^(dist2 < 0));
    503 
    504     /*
    505     if ( (dist1<0) == (dist2<0) )
    506 		return false;
    507 
    508 	return true;
    509     */
    510 }
    511 
    512 
    513 /*
    514 ====================
    515 =
    516 = SL_ClipToLine
    517 =
    518 = Call with p1 and p2 set to the endpoints
    519 = and nvx, nvy set to normalized vector
    520 = Assumes the start point is definately on the front side of the line
    521 = returns the fraction of the current move that crosses the line segment
    522 ====================
    523 */
    524 
    525 void SL_ClipToLine( void )//L80025B58()
    526 {
    527     fixed_t frac;
    528     int     side2, side3;
    529 
    530     // adjust start so it will be the first point contacted on the player circle
    531     // p3, p4 are move endpoints
    532 
    533     p3x = slidex - CLIPRADIUS * nvx;
    534     p3y = slidey - CLIPRADIUS * nvy;
    535     p4x = p3x + slidedx;
    536     p4y = p3y + slidedy;
    537 
    538     // if the adjusted point is on the other side of the line, the endpoint must
    539     // be checked.
    540     side2 = SL_PointOnSide(p3x, p3y);
    541     if(side2 == SIDE_BACK)
    542         return; // ClipToPoint and slide along normal to line
    543 
    544     side3 = SL_PointOnSide(p4x, p4y);
    545     if(side3 == SIDE_ON)
    546         return; // the move goes flush with the wall
    547     else if(side3 == SIDE_FRONT)
    548         return; // move doesn't cross line
    549 
    550     if(side2 == SIDE_ON)
    551     {
    552         frac = 0; // moves toward the line
    553         goto blockmove;
    554     }
    555 
    556     // the line endpoints must be on opposite sides of the move trace
    557 
    558     // find the fractional intercept
    559     frac = SL_CrossFrac();
    560 
    561     if(frac < blockfrac)
    562     {
    563         blockmove:
    564         blockfrac =  frac;
    565         blocknvx  = -nvy;
    566         blocknvy  =  nvx;
    567     }
    568 }
    569 
    570 /*
    571 ==================
    572 =
    573 = SL_CheckLine
    574 =
    575 ==================
    576 */
    577 
    578 
    579 boolean SL_CheckLine(line_t *ld)//L80025D50()
    580 {
    581 	fixed_t		opentop, openbottom;
    582 	sector_t	*front, *back;
    583 	int			side1, temp;
    584 
    585 	// check bbox first
    586 	if (endbox[BOXRIGHT ] < ld->bbox[BOXLEFT  ]
    587 	||	endbox[BOXLEFT  ] > ld->bbox[BOXRIGHT ]
    588 	||	endbox[BOXTOP   ] < ld->bbox[BOXBOTTOM]
    589 	||	endbox[BOXBOTTOM] > ld->bbox[BOXTOP   ] )
    590 		return true;
    591 
    592 	// see if it can possibly block movement
    593 	if (!ld->backsector || ld->flags & ML_BLOCKING)
    594 		goto findfrac;		// explicitly blocking
    595 
    596 	front = ld->frontsector;
    597 	back = ld->backsector;
    598 
    599 	if (front->floorheight > back->floorheight)
    600 		openbottom = front->floorheight;
    601 	else
    602 		openbottom = back->floorheight;
    603 
    604 	if (openbottom - slidething->z > 24*FRACUNIT)
    605 		goto findfrac;		// too big of a step up
    606 
    607 	if (front->ceilingheight < back->ceilingheight)
    608 		opentop = front->ceilingheight;
    609 	else
    610 		opentop = back->ceilingheight;
    611 
    612 	if (opentop - openbottom >= 56*FRACUNIT)
    613 		return true;		// the line doesn't block movement
    614 
    615 	// the line definately blocks movement
    616 findfrac:
    617 	// p1, p2 are line endpoints
    618 	p1x = ld->v1->x;
    619 	p1y = ld->v1->y;
    620 	p2x = ld->v2->x;
    621 	p2y = ld->v2->y;
    622 
    623 	nvx = finesine[ld->fineangle];
    624 	nvy = -finecosine[ld->fineangle];
    625 
    626 	side1 = SL_PointOnSide (slidex, slidey);
    627 	if (side1 == SIDE_ON)
    628 		return true;
    629 	if (side1 == SIDE_BACK)
    630 	{
    631 		if (!ld->backsector)
    632 			return true;			// don't clip to backs of one sided lines
    633 		temp = p1x;
    634 		p1x = p2x;
    635 		p2x = temp;
    636 		temp = p1y;
    637 		p1y = p2y;
    638 		p2y = temp;
    639 		nvx = -nvx;
    640 		nvy = -nvy;
    641 	}
    642 
    643 	SL_ClipToLine();
    644 	return true;
    645 }
    646 
    647 int	SL_PointOnSide2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, fixed_t x3, fixed_t y3)//L80025f9C()
    648 {
    649     //checked
    650 	fixed_t	nx, ny;
    651 	fixed_t dist;
    652 
    653 	x1 = (x1 - x2);
    654 	y1 = (y1 - y2);
    655 
    656 	nx = (y3 - y2);
    657 	ny = (x2 - x3);
    658 
    659 	dist = FixedMul(x1, nx) + FixedMul(y1, ny);
    660 
    661 	if (dist < 0)
    662 		return SIDE_BACK;
    663 	return SIDE_FRONT;
    664 }
    665 
    666 static short    *list_;     //80078074|psGp00000c64
    667 static line_t   *ld_;       //80077E48|plGp00000a38
    668 static int      offset_;    //80077DB0|iGp000009a0
    669 
    670 void SL_CheckSpecialLines (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)//L8002600C()
    671 {
    672 	fixed_t			bx, by, xl, xh, yl, yh, bxl, bxh, byl, byh;
    673 	fixed_t			x3,y3,x4,y4;
    674 	int			    side1, side2;
    675 
    676 	if (x1<x2) {
    677 		xl = x1;
    678 		xh = x2;
    679 	} else {
    680 		xl = x2;
    681 		xh = x1;
    682 	}
    683 	if (y1<y2) {
    684 		yl = y1;
    685 		yh = y2;
    686 	} else {
    687 		yl = y2;
    688 		yh = y1;
    689 	}
    690 
    691 	bxl = (xl - bmaporgx)>>MAPBLOCKSHIFT;
    692 	bxh = (xh - bmaporgx)>>MAPBLOCKSHIFT;
    693 	byl = (yl - bmaporgy)>>MAPBLOCKSHIFT;
    694 	byh = (yh - bmaporgy)>>MAPBLOCKSHIFT;
    695 
    696 	if (bxl<0)
    697 		bxl = 0;
    698 	if (byl<0)
    699 		byl = 0;
    700 	if (bxh>= bmapwidth)
    701 		bxh = bmapwidth -1;
    702 	if (byh>= bmapheight)
    703 		byh = bmapheight -1;
    704 
    705 	specialline = 0;
    706 	++validcount;
    707 
    708 	for (bx = bxl; bx <= bxh; bx++)
    709 	{
    710 		for (by = byl; by <= byh; by++)
    711 		{
    712 			offset_ = (by*bmapwidth) + bx;
    713 			offset_ = *(blockmap + offset_);
    714 
    715 			for (list_ = blockmaplump + offset_; *list_ != -1; list_++)
    716 			{
    717 				ld_ = &lines[*list_];
    718 
    719 				if (!ld_->special)
    720 					continue;
    721 				if (ld_->validcount == validcount)
    722 					continue;		// line has already been checked
    723 
    724 				ld_->validcount = validcount;
    725 
    726 				if (xh < ld_->bbox[BOXLEFT]
    727 					|| xl > ld_->bbox[BOXRIGHT]
    728 					|| yh < ld_->bbox[BOXBOTTOM]
    729 					|| yl > ld_->bbox[BOXTOP])
    730 					continue;
    731 
    732 				x3 = ld_->v1->x;
    733 				y3 = ld_->v1->y;
    734 				x4 = ld_->v2->x;
    735 				y4 = ld_->v2->y;
    736 
    737 				side1 = SL_PointOnSide2(x1, y1, x3, y3, x4, y4);
    738 				side2 = SL_PointOnSide2(x2, y2, x3, y3, x4, y4);
    739 
    740 				if (side1 == side2)
    741 					continue;		// move doesn't cross line
    742 
    743 				side1 = SL_PointOnSide2(x3, y3, x1, y1, x2, y2);
    744 				side2 = SL_PointOnSide2(x4, y4, x1, y1, x2, y2);
    745 
    746 				if (side1 == side2)
    747 					continue;		// line doesn't cross move
    748 
    749 				specialline = ld_;
    750 				return;
    751 			}
    752 		}
    753 	}
    754 }
    755 #endif // 0