doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

p_map.c (18661B)


      1 #include <stdlib.h>
      2 
      3 #include "m_bbox.h"
      4 #include "m_random.h"
      5 #include "i_system.h"
      6 #include "doomdef.h"
      7 #include "p_local.h"
      8 #include "s_sound.h"
      9 #include "doomstat.h"
     10 #include "r_state.h"
     11 #include "sounds.h"
     12 
     13 #define MAXSPECIALCROSS		8
     14 
     15 fixed_t		tmbbox[4];
     16 mobj_t*		tmthing;
     17 int		tmflags;
     18 fixed_t		tmx;
     19 fixed_t		tmy;
     20 boolean		floatok;
     21 fixed_t		tmfloorz;
     22 fixed_t		tmceilingz;
     23 fixed_t		tmdropoffz;
     24 line_t*		ceilingline;
     25 line_t*		spechit[MAXSPECIALCROSS];
     26 int		numspechit;
     27 
     28 boolean
     29 PIT_StompThing (mobj_t* thing)
     30 {
     31 	fixed_t	blockdist;
     32 
     33 	if (!(thing->flags & MF_SHOOTABLE)) return true;
     34 	blockdist = thing->radius + tmthing->radius;
     35 	if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist )
     36 	{
     37 
     38 	return true;
     39 	}
     40 
     41 
     42 	if (thing == tmthing)
     43 	return true;
     44 
     45 
     46 	if ( !tmthing->player && gamemap != 30)
     47 	return false;
     48 
     49 	P_DamageMobj (thing, tmthing, tmthing, 10000);
     50 
     51 	return true;
     52 }
     53 
     54 
     55 
     56 
     57 
     58 boolean
     59 P_TeleportMove
     60 ( mobj_t*	thing,
     61   fixed_t	x,
     62   fixed_t	y )
     63 {
     64 	int			xl;
     65 	int			xh;
     66 	int			yl;
     67 	int			yh;
     68 	int			bx;
     69 	int			by;
     70 
     71 	subsector_t*	newsubsec;
     72 
     73 
     74 	tmthing = thing;
     75 	tmflags = thing->flags;
     76 
     77 	tmx = x;
     78 	tmy = y;
     79 
     80 	tmbbox[BOXTOP] = y + tmthing->radius;
     81 	tmbbox[BOXBOTTOM] = y - tmthing->radius;
     82 	tmbbox[BOXRIGHT] = x + tmthing->radius;
     83 	tmbbox[BOXLEFT] = x - tmthing->radius;
     84 
     85 	newsubsec = R_PointInSubsector (x,y);
     86 	ceilingline = NULL;
     87 
     88 
     89 
     90 
     91 
     92 	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
     93 	tmceilingz = newsubsec->sector->ceilingheight;
     94 
     95 	validcount++;
     96 	numspechit = 0;
     97 
     98 
     99 	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
    100 	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
    101 	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
    102 	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
    103 
    104 	for (bx=xl ; bx<=xh ; bx++)
    105 	for (by=yl ; by<=yh ; by++)
    106 	    if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
    107 		return false;
    108 
    109 
    110 
    111 	P_UnsetThingPosition (thing);
    112 
    113 	thing->floorz = tmfloorz;
    114 	thing->ceilingz = tmceilingz;
    115 	thing->x = x;
    116 	thing->y = y;
    117 
    118 	P_SetThingPosition (thing);
    119 
    120 	return true;
    121 }
    122 
    123 
    124 
    125 
    126 
    127 
    128 
    129 
    130 
    131 
    132 
    133 boolean PIT_CheckLine (line_t* ld)
    134 {
    135 	if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
    136 	|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
    137 	|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
    138 	|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
    139 	return true;
    140 
    141 	if (P_BoxOnLineSide (tmbbox, ld) != -1)
    142 	return true;
    143 
    144 
    145 
    146 
    147 
    148 
    149 
    150 
    151 
    152 
    153 
    154 
    155 	if (!ld->backsector)
    156 	return false;
    157 
    158 	if (!(tmthing->flags & MF_MISSILE) )
    159 	{
    160 	if ( ld->flags & ML_BLOCKING )
    161 	    return false;
    162 
    163 	if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS )
    164 	    return false;
    165 	}
    166 
    167 
    168 	P_LineOpening (ld);
    169 
    170 
    171 	if (opentop < tmceilingz)
    172 	{
    173 	tmceilingz = opentop;
    174 	ceilingline = ld;
    175 	}
    176 
    177 	if (openbottom > tmfloorz)
    178 	tmfloorz = openbottom;
    179 
    180 	if (lowfloor < tmdropoffz)
    181 	tmdropoffz = lowfloor;
    182 
    183 
    184 	if (ld->special)
    185 	{
    186 	spechit[numspechit] = ld;
    187 	numspechit++;
    188 	}
    189 
    190 	return true;
    191 }
    192 
    193 
    194 
    195 
    196 boolean PIT_CheckThing (mobj_t* thing)
    197 {
    198 	fixed_t		blockdist;
    199 	boolean		solid;
    200 	int			damage;
    201 
    202 	if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
    203 	return true;
    204 
    205 	blockdist = thing->radius + tmthing->radius;
    206 
    207 	if ( abs(thing->x - tmx) >= blockdist
    208 	 || abs(thing->y - tmy) >= blockdist )
    209 	{
    210 
    211 	return true;
    212 	}
    213 
    214 
    215 	if (thing == tmthing)
    216 	return true;
    217 
    218 
    219 	if (tmthing->flags & MF_SKULLFLY)
    220 	{
    221 	damage = ((P_Random()%8)+1)*tmthing->info->damage;
    222 
    223 	P_DamageMobj (thing, tmthing, tmthing, damage);
    224 
    225 	tmthing->flags &= ~MF_SKULLFLY;
    226 	tmthing->momx = tmthing->momy = tmthing->momz = 0;
    227 
    228 	P_SetMobjState (tmthing, tmthing->info->spawnstate);
    229 
    230 	return false;
    231 	}
    232 
    233 
    234 
    235 	if (tmthing->flags & MF_MISSILE)
    236 	{
    237 
    238 	if (tmthing->z > thing->z + thing->height)
    239 	    return true;
    240 	if (tmthing->z+tmthing->height < thing->z)
    241 	    return true;
    242 
    243 	if (tmthing->target && (
    244 	    tmthing->target->type == thing->type ||
    245 	    (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
    246 	    (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )
    247 	{
    248 
    249 	    if (thing == tmthing->target)
    250 		return true;
    251 
    252 	    if (thing->type != MT_PLAYER)
    253 	    {
    254 
    255 
    256 		return false;
    257 	    }
    258 	}
    259 
    260 	if (! (thing->flags & MF_SHOOTABLE) )
    261 	{
    262 
    263 	    return !(thing->flags & MF_SOLID);
    264 	}
    265 
    266 
    267 	damage = ((P_Random()%8)+1)*tmthing->info->damage;
    268 	P_DamageMobj (thing, tmthing, tmthing->target, damage);
    269 
    270 
    271 	return false;
    272 	}
    273 
    274 
    275 	if (thing->flags & MF_SPECIAL)
    276 	{
    277 	solid = thing->flags&MF_SOLID;
    278 	if (tmflags&MF_PICKUP)
    279 	{
    280 
    281 	    P_TouchSpecialThing (thing, tmthing);
    282 	}
    283 	return !solid;
    284 	}
    285 
    286 	return !(thing->flags & MF_SOLID);
    287 }
    288 
    289 
    290 
    291 
    292 
    293 
    294 
    295 
    296 
    297 
    298 
    299 
    300 
    301 
    302 
    303 
    304 
    305 
    306 
    307 
    308 
    309 
    310 
    311 
    312 
    313 
    314 
    315 
    316 
    317 
    318 boolean
    319 P_CheckPosition
    320 ( mobj_t*	thing,
    321   fixed_t	x,
    322   fixed_t	y )
    323 {
    324 	int			xl;
    325 	int			xh;
    326 	int			yl;
    327 	int			yh;
    328 	int			bx;
    329 	int			by;
    330 	subsector_t*	newsubsec;
    331 
    332 	tmthing = thing;
    333 	tmflags = thing->flags;
    334 
    335 	tmx = x;
    336 	tmy = y;
    337 
    338 	tmbbox[BOXTOP] = y + tmthing->radius;
    339 	tmbbox[BOXBOTTOM] = y - tmthing->radius;
    340 	tmbbox[BOXRIGHT] = x + tmthing->radius;
    341 	tmbbox[BOXLEFT] = x - tmthing->radius;
    342 
    343 	newsubsec = R_PointInSubsector (x,y);
    344 	ceilingline = NULL;
    345 
    346 
    347 
    348 
    349 
    350 	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
    351 	tmceilingz = newsubsec->sector->ceilingheight;
    352 
    353 	validcount++;
    354 	numspechit = 0;
    355 
    356 	if ( tmflags & MF_NOCLIP )
    357 	return true;
    358 
    359 
    360 
    361 
    362 
    363 
    364 	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
    365 	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
    366 	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
    367 	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
    368 
    369 	for (bx=xl ; bx<=xh ; bx++)
    370 	for (by=yl ; by<=yh ; by++)
    371 	    if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
    372 		return false;
    373 
    374 
    375 	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
    376 	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
    377 	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
    378 	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
    379 
    380 	for (bx=xl ; bx<=xh ; bx++)
    381 	for (by=yl ; by<=yh ; by++)
    382 	    if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
    383 		return false;
    384 
    385 	return true;
    386 }
    387 
    388 
    389 
    390 
    391 
    392 
    393 
    394 boolean
    395 P_TryMove
    396 ( mobj_t*	thing,
    397   fixed_t	x,
    398   fixed_t	y )
    399 {
    400 	fixed_t	oldx;
    401 	fixed_t	oldy;
    402 	int		side;
    403 	int		oldside;
    404 	line_t*	ld;
    405 
    406 	floatok = false;
    407 	if (!P_CheckPosition (thing, x, y))
    408 	return false;
    409 
    410 	if ( !(thing->flags & MF_NOCLIP) )
    411 	{
    412 	if (tmceilingz - tmfloorz < thing->height)
    413 	    return false;
    414 
    415 	floatok = true;
    416 
    417 	if ( !(thing->flags&MF_TELEPORT)
    418 	     &&tmceilingz - thing->z < thing->height)
    419 	    return false;
    420 
    421 	if ( !(thing->flags&MF_TELEPORT)
    422 	     && tmfloorz - thing->z > 24*FRACUNIT )
    423 	    return false;
    424 
    425 	if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))
    426 	     && tmfloorz - tmdropoffz > 24*FRACUNIT )
    427 	    return false;
    428 	}
    429 
    430 
    431 
    432 	P_UnsetThingPosition (thing);
    433 
    434 	oldx = thing->x;
    435 	oldy = thing->y;
    436 	thing->floorz = tmfloorz;
    437 	thing->ceilingz = tmceilingz;
    438 	thing->x = x;
    439 	thing->y = y;
    440 
    441 	P_SetThingPosition (thing);
    442 
    443 
    444 	if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )
    445 	{
    446 	while (numspechit--)
    447 	{
    448 
    449 	    ld = spechit[numspechit];
    450 	    side = P_PointOnLineSide (thing->x, thing->y, ld);
    451 	    oldside = P_PointOnLineSide (oldx, oldy, ld);
    452 	    if (side != oldside)
    453 	    {
    454 		if (ld->special)
    455 		    P_CrossSpecialLine (ld-lines, oldside, thing);
    456 	    }
    457 	}
    458 	}
    459 
    460 	return true;
    461 }
    462 
    463 
    464 
    465 
    466 
    467 
    468 
    469 
    470 
    471 
    472 
    473 
    474 boolean P_ThingHeightClip (mobj_t* thing)
    475 {
    476 	boolean		onfloor;
    477 
    478 	onfloor = (thing->z == thing->floorz);
    479 
    480 	P_CheckPosition (thing, thing->x, thing->y);
    481 
    482 
    483 	thing->floorz = tmfloorz;
    484 	thing->ceilingz = tmceilingz;
    485 
    486 	if (onfloor)
    487 	{
    488 
    489 	thing->z = thing->floorz;
    490 	}
    491 	else
    492 	{
    493 
    494 	if (thing->z+thing->height > thing->ceilingz)
    495 	    thing->z = thing->ceilingz - thing->height;
    496 	}
    497 
    498 	if (thing->ceilingz - thing->floorz < thing->height)
    499 	return false;
    500 
    501 	return true;
    502 }
    503 
    504 
    505 
    506 
    507 
    508 
    509 
    510 fixed_t		bestslidefrac;
    511 fixed_t		secondslidefrac;
    512 
    513 line_t*		bestslideline;
    514 line_t*		secondslideline;
    515 
    516 mobj_t*		slidemo;
    517 
    518 fixed_t		tmxmove;
    519 fixed_t		tmymove;
    520 
    521 
    522 
    523 
    524 
    525 
    526 
    527 
    528 void P_HitSlideLine (line_t* ld)
    529 {
    530 	int			side;
    531 
    532 	angle_t		lineangle;
    533 	angle_t		moveangle;
    534 	angle_t		deltaangle;
    535 
    536 	fixed_t		movelen;
    537 	fixed_t		newlen;
    538 
    539 
    540 	if (ld->slopetype == ST_HORIZONTAL)
    541 	{
    542 	tmymove = 0;
    543 	return;
    544 	}
    545 
    546 	if (ld->slopetype == ST_VERTICAL)
    547 	{
    548 	tmxmove = 0;
    549 	return;
    550 	}
    551 
    552 	side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);
    553 
    554 	lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
    555 
    556 	if (side == 1)
    557 	lineangle += ANG180;
    558 
    559 	moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);
    560 	deltaangle = moveangle-lineangle;
    561 
    562 	if (deltaangle > ANG180)
    563 	deltaangle += ANG180;
    564 
    565 
    566 	lineangle >>= ANGLETOFINESHIFT;
    567 	deltaangle >>= ANGLETOFINESHIFT;
    568 
    569 	movelen = P_AproxDistance (tmxmove, tmymove);
    570 	newlen = FixedMul (movelen, finecosine[deltaangle]);
    571 
    572 	tmxmove = FixedMul (newlen, finecosine[lineangle]);
    573 	tmymove = FixedMul (newlen, finesine[lineangle]);
    574 }
    575 
    576 
    577 
    578 
    579 
    580 boolean PTR_SlideTraverse (intercept_t* in)
    581 {
    582 	line_t*	li;
    583 
    584 	if (!in->isaline)
    585 	I_Error ("PTR_SlideTraverse: not a line?");
    586 
    587 	li = in->d.line;
    588 
    589 	if ( ! (li->flags & ML_TWOSIDED) )
    590 	{
    591 	if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
    592 	{
    593 
    594 	    return true;
    595 	}
    596 	goto isblocking;
    597 	}
    598 
    599 
    600 	P_LineOpening (li);
    601 
    602 	if (openrange < slidemo->height)
    603 	goto isblocking;
    604 
    605 	if (opentop - slidemo->z < slidemo->height)
    606 	goto isblocking;
    607 
    608 	if (openbottom - slidemo->z > 24*FRACUNIT )
    609 	goto isblocking;
    610 
    611 
    612 	return true;
    613 
    614 
    615 
    616   isblocking:
    617 	if (in->frac < bestslidefrac)
    618 	{
    619 	secondslidefrac = bestslidefrac;
    620 	secondslideline = bestslideline;
    621 	bestslidefrac = in->frac;
    622 	bestslideline = li;
    623 	}
    624 
    625 	return false;
    626 }
    627 
    628 
    629 
    630 
    631 
    632 
    633 
    634 
    635 
    636 
    637 
    638 
    639 void P_SlideMove (mobj_t* mo)
    640 {
    641 	fixed_t		leadx;
    642 	fixed_t		leady;
    643 	fixed_t		trailx;
    644 	fixed_t		traily;
    645 	fixed_t		newx;
    646 	fixed_t		newy;
    647 	int			hitcount;
    648 
    649 	slidemo = mo;
    650 	hitcount = 0;
    651 
    652   retry:
    653 	if (++hitcount == 3)
    654 	goto stairstep;
    655 
    656 
    657 
    658 	if (mo->momx > 0)
    659 	{
    660 	leadx = mo->x + mo->radius;
    661 	trailx = mo->x - mo->radius;
    662 	}
    663 	else
    664 	{
    665 	leadx = mo->x - mo->radius;
    666 	trailx = mo->x + mo->radius;
    667 	}
    668 
    669 	if (mo->momy > 0)
    670 	{
    671 	leady = mo->y + mo->radius;
    672 	traily = mo->y - mo->radius;
    673 	}
    674 	else
    675 	{
    676 	leady = mo->y - mo->radius;
    677 	traily = mo->y + mo->radius;
    678 	}
    679 
    680 	bestslidefrac = FRACUNIT+1;
    681 
    682 	P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy,
    683 		     PT_ADDLINES, PTR_SlideTraverse );
    684 	P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy,
    685 		     PT_ADDLINES, PTR_SlideTraverse );
    686 	P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy,
    687 		     PT_ADDLINES, PTR_SlideTraverse );
    688 
    689 
    690 	if (bestslidefrac == FRACUNIT+1)
    691 	{
    692 
    693 	  stairstep:
    694 	if (!P_TryMove (mo, mo->x, mo->y + mo->momy))
    695 	    P_TryMove (mo, mo->x + mo->momx, mo->y);
    696 	return;
    697 	}
    698 
    699 
    700 	bestslidefrac -= 0x800;
    701 	if (bestslidefrac > 0)
    702 	{
    703 	newx = FixedMul (mo->momx, bestslidefrac);
    704 	newy = FixedMul (mo->momy, bestslidefrac);
    705 
    706 	if (!P_TryMove (mo, mo->x+newx, mo->y+newy))
    707 	    goto stairstep;
    708 	}
    709 
    710 
    711 
    712 	bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
    713 
    714 	if (bestslidefrac > FRACUNIT)
    715 	bestslidefrac = FRACUNIT;
    716 
    717 	if (bestslidefrac <= 0)
    718 	return;
    719 
    720 	tmxmove = FixedMul (mo->momx, bestslidefrac);
    721 	tmymove = FixedMul (mo->momy, bestslidefrac);
    722 
    723 	P_HitSlideLine (bestslideline);
    724 
    725 	mo->momx = tmxmove;
    726 	mo->momy = tmymove;
    727 
    728 	if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove))
    729 	{
    730 	goto retry;
    731 	}
    732 }
    733 
    734 
    735 
    736 
    737 
    738 mobj_t*		linetarget;
    739 mobj_t*		shootthing;
    740 
    741 
    742 
    743 fixed_t		shootz;
    744 
    745 int		la_damage;
    746 fixed_t		attackrange;
    747 
    748 fixed_t		aimslope;
    749 
    750 
    751 extern fixed_t	topslope;
    752 extern fixed_t	bottomslope;
    753 
    754 
    755 
    756 
    757 
    758 
    759 boolean
    760 PTR_AimTraverse (intercept_t* in)
    761 {
    762 	line_t*		li;
    763 	mobj_t*		th;
    764 	fixed_t		slope;
    765 	fixed_t		thingtopslope;
    766 	fixed_t		thingbottomslope;
    767 	fixed_t		dist;
    768 
    769 	if (in->isaline)
    770 	{
    771 	li = in->d.line;
    772 
    773 	if ( !(li->flags & ML_TWOSIDED) )
    774 	    return false;
    775 
    776 
    777 
    778 
    779 	P_LineOpening (li);
    780 
    781 	if (openbottom >= opentop)
    782 	    return false;
    783 
    784 	dist = FixedMul (attackrange, in->frac);
    785 
    786 	if (li->frontsector->floorheight != li->backsector->floorheight)
    787 	{
    788 	    slope = FixedDiv (openbottom - shootz , dist);
    789 	    if (slope > bottomslope)
    790 		bottomslope = slope;
    791 	}
    792 
    793 	if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
    794 	{
    795 	    slope = FixedDiv (opentop - shootz , dist);
    796 	    if (slope < topslope)
    797 		topslope = slope;
    798 	}
    799 
    800 	if (topslope <= bottomslope)
    801 	    return false;
    802 
    803 	return true;
    804 	}
    805 
    806 
    807 	th = in->d.thing;
    808 	if (th == shootthing)
    809 	return true;
    810 
    811 	if (!(th->flags&MF_SHOOTABLE))
    812 	return true;
    813 
    814 
    815 	dist = FixedMul (attackrange, in->frac);
    816 	thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
    817 
    818 	if (thingtopslope < bottomslope)
    819 	return true;
    820 
    821 	thingbottomslope = FixedDiv (th->z - shootz, dist);
    822 
    823 	if (thingbottomslope > topslope)
    824 	return true;
    825 
    826 
    827 	if (thingtopslope > topslope)
    828 	thingtopslope = topslope;
    829 
    830 	if (thingbottomslope < bottomslope)
    831 	thingbottomslope = bottomslope;
    832 
    833 	aimslope = (thingtopslope+thingbottomslope)/2;
    834 	linetarget = th;
    835 
    836 	return false;
    837 }
    838 
    839 
    840 
    841 
    842 
    843 boolean PTR_ShootTraverse (intercept_t* in)
    844 {
    845 	fixed_t		x;
    846 	fixed_t		y;
    847 	fixed_t		z;
    848 	fixed_t		frac;
    849 
    850 	line_t*		li;
    851 
    852 	mobj_t*		th;
    853 
    854 	fixed_t		slope;
    855 	fixed_t		dist;
    856 	fixed_t		thingtopslope;
    857 	fixed_t		thingbottomslope;
    858 
    859 	if (in->isaline)
    860 	{
    861 	li = in->d.line;
    862 
    863 	if (li->special)
    864 	    P_ShootSpecialLine (shootthing, li);
    865 
    866 	if ( !(li->flags & ML_TWOSIDED) )
    867 	    goto hitline;
    868 
    869 
    870 	P_LineOpening (li);
    871 
    872 	dist = FixedMul (attackrange, in->frac);
    873 
    874 	if (li->frontsector->floorheight != li->backsector->floorheight)
    875 	{
    876 	    slope = FixedDiv (openbottom - shootz , dist);
    877 	    if (slope > aimslope)
    878 		goto hitline;
    879 	}
    880 
    881 	if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
    882 	{
    883 	    slope = FixedDiv (opentop - shootz , dist);
    884 	    if (slope < aimslope)
    885 		goto hitline;
    886 	}
    887 
    888 
    889 	return true;
    890 
    891 
    892 
    893 	  hitline:
    894 
    895 	frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
    896 	x = trace.x + FixedMul (trace.dx, frac);
    897 	y = trace.y + FixedMul (trace.dy, frac);
    898 	z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
    899 
    900 	if (li->frontsector->ceilingpic == skyflatnum)
    901 	{
    902 
    903 	    if (z > li->frontsector->ceilingheight)
    904 		return false;
    905 
    906 
    907 	    if	(li->backsector && li->backsector->ceilingpic == skyflatnum)
    908 		return false;
    909 	}
    910 
    911 
    912 	P_SpawnPuff (x,y,z);
    913 
    914 
    915 	return false;
    916 	}
    917 
    918 
    919 	th = in->d.thing;
    920 	if (th == shootthing)
    921 	return true;
    922 
    923 	if (!(th->flags&MF_SHOOTABLE))
    924 	return true;
    925 
    926 
    927 	dist = FixedMul (attackrange, in->frac);
    928 	thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
    929 
    930 	if (thingtopslope < aimslope)
    931 	return true;
    932 
    933 	thingbottomslope = FixedDiv (th->z - shootz, dist);
    934 
    935 	if (thingbottomslope > aimslope)
    936 	return true;
    937 
    938 
    939 
    940 
    941 	frac = in->frac - FixedDiv (10*FRACUNIT,attackrange);
    942 
    943 	x = trace.x + FixedMul (trace.dx, frac);
    944 	y = trace.y + FixedMul (trace.dy, frac);
    945 	z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
    946 
    947 
    948 
    949 	if (in->d.thing->flags & MF_NOBLOOD)
    950 	P_SpawnPuff (x,y,z);
    951 	else
    952 	P_SpawnBlood (x,y,z, la_damage);
    953 
    954 	if (la_damage)
    955 	P_DamageMobj (th, shootthing, shootthing, la_damage);
    956 
    957 
    958 	return false;
    959 
    960 }
    961 
    962 
    963 
    964 
    965 
    966 fixed_t
    967 P_AimLineAttack
    968 ( mobj_t*	t1,
    969   angle_t	angle,
    970   fixed_t	distance )
    971 {
    972 	fixed_t	x2;
    973 	fixed_t	y2;
    974 
    975 	angle >>= ANGLETOFINESHIFT;
    976 	shootthing = t1;
    977 
    978 	x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
    979 	y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
    980 	shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
    981 
    982 
    983 	topslope = 100*FRACUNIT/160;
    984 	bottomslope = -100*FRACUNIT/160;
    985 
    986 	attackrange = distance;
    987 	linetarget = NULL;
    988 
    989 	P_PathTraverse ( t1->x, t1->y,
    990 		     x2, y2,
    991 		     PT_ADDLINES|PT_ADDTHINGS,
    992 		     PTR_AimTraverse );
    993 
    994 	if (linetarget)
    995 	return aimslope;
    996 
    997 	return 0;
    998 }
    999 
   1000 
   1001 
   1002 
   1003 
   1004 
   1005 
   1006 void
   1007 P_LineAttack
   1008 ( mobj_t*	t1,
   1009   angle_t	angle,
   1010   fixed_t	distance,
   1011   fixed_t	slope,
   1012   int		damage )
   1013 {
   1014 	fixed_t	x2;
   1015 	fixed_t	y2;
   1016 
   1017 	angle >>= ANGLETOFINESHIFT;
   1018 	shootthing = t1;
   1019 	la_damage = damage;
   1020 	x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
   1021 	y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
   1022 	shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
   1023 	attackrange = distance;
   1024 	aimslope = slope;
   1025 
   1026 	P_PathTraverse ( t1->x, t1->y,
   1027 		     x2, y2,
   1028 		     PT_ADDLINES|PT_ADDTHINGS,
   1029 		     PTR_ShootTraverse );
   1030 }
   1031 
   1032 
   1033 
   1034 
   1035 
   1036 
   1037 mobj_t*		usething;
   1038 
   1039 boolean	PTR_UseTraverse (intercept_t* in)
   1040 {
   1041 	int		side;
   1042 
   1043 	if (!in->d.line->special)
   1044 	{
   1045 	P_LineOpening (in->d.line);
   1046 	if (openrange <= 0)
   1047 	{
   1048 	    S_StartSound (usething, sfx_noway);
   1049 
   1050 
   1051 	    return false;
   1052 	}
   1053 
   1054 	return true ;
   1055 	}
   1056 
   1057 	side = 0;
   1058 	if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)
   1059 	side = 1;
   1060 
   1061 
   1062 
   1063 	P_UseSpecialLine (usething, in->d.line, side);
   1064 
   1065 
   1066 	return false;
   1067 }
   1068 
   1069 
   1070 
   1071 
   1072 
   1073 
   1074 void P_UseLines (player_t*	player)
   1075 {
   1076 	int		angle;
   1077 	fixed_t	x1;
   1078 	fixed_t	y1;
   1079 	fixed_t	x2;
   1080 	fixed_t	y2;
   1081 
   1082 	usething = player->mo;
   1083 
   1084 	angle = player->mo->angle >> ANGLETOFINESHIFT;
   1085 
   1086 	x1 = player->mo->x;
   1087 	y1 = player->mo->y;
   1088 	x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
   1089 	y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
   1090 
   1091 	P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
   1092 }
   1093 
   1094 
   1095 
   1096 
   1097 
   1098 mobj_t*		bombsource;
   1099 mobj_t*		bombspot;
   1100 int		bombdamage;
   1101 
   1102 
   1103 
   1104 
   1105 
   1106 
   1107 
   1108 boolean PIT_RadiusAttack (mobj_t* thing)
   1109 {
   1110 	fixed_t	dx;
   1111 	fixed_t	dy;
   1112 	fixed_t	dist;
   1113 
   1114 	if (!(thing->flags & MF_SHOOTABLE) )
   1115 	return true;
   1116 
   1117 
   1118 
   1119 	if (thing->type == MT_CYBORG
   1120 	|| thing->type == MT_SPIDER)
   1121 	return true;
   1122 
   1123 	dx = abs(thing->x - bombspot->x);
   1124 	dy = abs(thing->y - bombspot->y);
   1125 
   1126 	dist = dx>dy ? dx : dy;
   1127 	dist = (dist - thing->radius) >> FRACBITS;
   1128 
   1129 	if (dist < 0)
   1130 	dist = 0;
   1131 
   1132 	if (dist >= bombdamage)
   1133 	return true;
   1134 
   1135 	if ( P_CheckSight (thing, bombspot) )
   1136 	{
   1137 
   1138 	P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
   1139 	}
   1140 
   1141 	return true;
   1142 }
   1143 
   1144 
   1145 
   1146 
   1147 
   1148 
   1149 void
   1150 P_RadiusAttack
   1151 ( mobj_t*	spot,
   1152   mobj_t*	source,
   1153   int		damage )
   1154 {
   1155 	int		x;
   1156 	int		y;
   1157 
   1158 	int		xl;
   1159 	int		xh;
   1160 	int		yl;
   1161 	int		yh;
   1162 
   1163 	fixed_t	dist;
   1164 
   1165 	dist = (damage+MAXRADIUS)<<FRACBITS;
   1166 	yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
   1167 	yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
   1168 	xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
   1169 	xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
   1170 	bombspot = spot;
   1171 	bombsource = source;
   1172 	bombdamage = damage;
   1173 
   1174 	for (y=yl ; y<=yh ; y++)
   1175 	for (x=xl ; x<=xh ; x++)
   1176 	    P_BlockThingsIterator (x, y, PIT_RadiusAttack );
   1177 }
   1178 
   1179 
   1180 
   1181 
   1182 
   1183 
   1184 
   1185 
   1186 
   1187 
   1188 
   1189 
   1190 
   1191 
   1192 
   1193 
   1194 boolean		crushchange;
   1195 boolean		nofit;
   1196 
   1197 
   1198 
   1199 
   1200 
   1201 boolean PIT_ChangeSector (mobj_t*	thing)
   1202 {
   1203 	mobj_t*	mo;
   1204 
   1205 	if (P_ThingHeightClip (thing))
   1206 	{
   1207 
   1208 	return true;
   1209 	}
   1210 
   1211 
   1212 
   1213 	if (thing->health <= 0)
   1214 	{
   1215 	P_SetMobjState (thing, S_GIBS);
   1216 
   1217 	thing->flags &= ~MF_SOLID;
   1218 	thing->height = 0;
   1219 	thing->radius = 0;
   1220 
   1221 
   1222 	return true;
   1223 	}
   1224 
   1225 
   1226 	if (thing->flags & MF_DROPPED)
   1227 	{
   1228 	P_RemoveMobj (thing);
   1229 
   1230 
   1231 	return true;
   1232 	}
   1233 
   1234 	if (! (thing->flags & MF_SHOOTABLE) )
   1235 	{
   1236 
   1237 	return true;
   1238 	}
   1239 
   1240 	nofit = true;
   1241 
   1242 	if (crushchange && !(leveltime&3) )
   1243 	{
   1244 	P_DamageMobj(thing,NULL,NULL,10);
   1245 
   1246 
   1247 	mo = P_SpawnMobj (thing->x,
   1248 			  thing->y,
   1249 			  thing->z + thing->height/2, MT_BLOOD);
   1250 
   1251 	mo->momx = (P_Random() - P_Random ())<<12;
   1252 	mo->momy = (P_Random() - P_Random ())<<12;
   1253 	}
   1254 
   1255 
   1256 	return true;
   1257 }
   1258 
   1259 
   1260 
   1261 
   1262 
   1263 
   1264 boolean
   1265 P_ChangeSector
   1266 ( sector_t*	sector,
   1267   boolean	crunch )
   1268 {
   1269 	int		x;
   1270 	int		y;
   1271 
   1272 	nofit = false;
   1273 	crushchange = crunch;
   1274 
   1275 
   1276 	for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
   1277 	for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
   1278 	    P_BlockThingsIterator (x, y, PIT_ChangeSector);
   1279 
   1280 
   1281 	return nofit;
   1282 }
   1283