1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
18 // Revision 1.1 2000/02/29 18:21:04 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
23 // Movement, collision handling.
24 // Shooting and aiming.
26 //-----------------------------------------------------------------------------
56 // If "floatok" true, move would be ok
57 // if within "tmfloorz - tmceilingz".
64 // keep track of the line that lowers the ceiling,
65 // so missiles don't explode against sky hack walls
68 // keep track of special lines as they are hit,
69 // but don't process them until the move is proven valid
70 #define MAXSPECIALCROSS 20 /* was 8 */
72 line_t
* spechit
[MAXSPECIALCROSS
];
84 boolean
PIT_StompThing (mobj_t
* thing
)
88 if (!(thing
->flags
& MF_SHOOTABLE
) )
91 blockdist
= thing
->radius
+ tmthing
->radius
;
93 if ( iabs(thing
->x
- tmx
) >= blockdist
94 || iabs(thing
->y
- tmy
) >= blockdist
)
100 // don't clip against self
101 if (thing
== tmthing
)
104 // monsters don't stomp things except on boss level
105 if ( !tmthing
->player
&& gamemap
!= 30)
108 P_DamageMobj (thing
, tmthing
, tmthing
, 10000);
130 subsector_t
* newsubsec
;
132 // kill anything occupying the position
134 tmflags
= thing
->flags
;
139 tmbbox
[BOXTOP
] = y
+ tmthing
->radius
;
140 tmbbox
[BOXBOTTOM
] = y
- tmthing
->radius
;
141 tmbbox
[BOXRIGHT
] = x
+ tmthing
->radius
;
142 tmbbox
[BOXLEFT
] = x
- tmthing
->radius
;
144 newsubsec
= R_PointInSubsector (x
,y
);
147 // The base floor/ceiling is from the subsector
148 // that contains the point.
149 // Any contacted lines the step closer together
151 tmfloorz
= tmdropoffz
= newsubsec
->sector
->floorheight
;
152 tmceilingz
= newsubsec
->sector
->ceilingheight
;
157 // stomp on any things contacted
158 xl
= (tmbbox
[BOXLEFT
] - bmaporgx
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
159 xh
= (tmbbox
[BOXRIGHT
] - bmaporgx
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
160 yl
= (tmbbox
[BOXBOTTOM
] - bmaporgy
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
161 yh
= (tmbbox
[BOXTOP
] - bmaporgy
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
163 for (bx
=xl
; bx
<=xh
; bx
++)
164 for (by
=yl
; by
<=yh
; by
++)
165 if (!P_BlockThingsIterator(bx
,by
,PIT_StompThing
))
169 // so link the thing into its new position
170 P_UnsetThingPosition (thing
);
172 thing
->floorz
= tmfloorz
;
173 thing
->ceilingz
= tmceilingz
;
177 P_SetThingPosition (thing
);
184 // MOVEMENT ITERATOR FUNCTIONS
190 // Adjusts tmfloorz and tmceilingz as lines are contacted
192 boolean
PIT_CheckLine (line_t
* ld
)
194 if (tmbbox
[BOXRIGHT
] <= ld
->bbox
[BOXLEFT
]
195 || tmbbox
[BOXLEFT
] >= ld
->bbox
[BOXRIGHT
]
196 || tmbbox
[BOXTOP
] <= ld
->bbox
[BOXBOTTOM
]
197 || tmbbox
[BOXBOTTOM
] >= ld
->bbox
[BOXTOP
] )
200 if (P_BoxOnLineSide (tmbbox
, ld
) != -1)
203 // A line has been hit
205 // The moving thing's destination position will cross
207 // If this should not be allowed, return false.
208 // If the line is special, keep track of it
209 // to process later if the move is proven ok.
210 // NOTE: specials are NOT sorted by order,
211 // so two special lines that are only 8 pixels apart
212 // could be crossed in either order.
215 return false; // one sided line
217 if (!(tmthing
->flags
& MF_MISSILE
) )
219 if ( ld
->flags
& ML_BLOCKING
)
220 return false; // explicitly blocking everything
222 if ( !tmthing
->player
&& ld
->flags
& ML_BLOCKMONSTERS
)
223 return false; // block monsters only
226 // set openrange, opentop, openbottom
229 // adjust floor / ceiling heights
230 if (opentop
< tmceilingz
)
232 tmceilingz
= opentop
;
236 if (openbottom
> tmfloorz
)
237 tmfloorz
= openbottom
;
239 if (lowfloor
< tmdropoffz
)
240 tmdropoffz
= lowfloor
;
242 // if contacted a special line, add it to the list
243 if (ld
->special
/* && numspechit < MAXSPECIALCROSS */ )
245 spechit
[numspechit
] = ld
;
255 boolean
PIT_CheckThing (mobj_t
* thing
)
261 if (!(thing
->flags
& (MF_SOLID
|MF_SPECIAL
|MF_SHOOTABLE
) ))
264 blockdist
= thing
->radius
+ tmthing
->radius
;
266 if ( iabs(thing
->x
- tmx
) >= blockdist
267 || iabs(thing
->y
- tmy
) >= blockdist
)
273 // don't clip against self
274 if (thing
== tmthing
)
277 // check for skulls slamming into things
278 if (tmthing
->flags
& MF_SKULLFLY
)
280 damage
= ((P_Random()%8)+1)*tmthing
->info
->damage
;
282 P_DamageMobj (thing
, tmthing
, tmthing
, damage
);
284 tmthing
->flags
&= ~MF_SKULLFLY
;
285 tmthing
->momx
= tmthing
->momy
= tmthing
->momz
= 0;
287 P_SetMobjState (tmthing
, tmthing
->info
->spawnstate
);
289 return false; // stop moving
293 // missiles can hit other things
294 if (tmthing
->flags
& MF_MISSILE
)
296 // see if it went over / under
297 if (tmthing
->z
> thing
->z
+ thing
->height
)
298 return true; // overhead
299 if (tmthing
->z
+tmthing
->height
< thing
->z
)
300 return true; // underneath
302 if (tmthing
->target
&& (
303 tmthing
->target
->type
== thing
->type
||
304 (tmthing
->target
->type
== MT_KNIGHT
&& thing
->type
== MT_BRUISER
)||
305 (tmthing
->target
->type
== MT_BRUISER
&& thing
->type
== MT_KNIGHT
) ) )
307 // Don't hit same species as originator.
308 if (thing
== tmthing
->target
)
311 if (thing
->type
!= MT_PLAYER
)
313 // Explode, but do no damage.
314 // Let players missile other players.
319 if (! (thing
->flags
& MF_SHOOTABLE
) )
321 // didn't do any damage
322 return !(thing
->flags
& MF_SOLID
);
326 damage
= ((P_Random()%8)+1)*tmthing
->info
->damage
;
327 P_DamageMobj (thing
, tmthing
, tmthing
->target
, damage
);
329 // don't traverse any more
333 // check for special pickup
334 if (thing
->flags
& MF_SPECIAL
)
336 solid
= thing
->flags
&MF_SOLID
;
337 if (tmflags
&MF_PICKUP
)
340 P_TouchSpecialThing (thing
, tmthing
);
345 return !(thing
->flags
& MF_SOLID
);
355 // This is purely informative, nothing is modified
356 // (except things picked up).
359 // a mobj_t (can be valid or invalid)
360 // a position to be checked
361 // (doesn't need to be related to the mobj_t->x,y)
364 // special things are touched if MF_PICKUP
365 // early out on solid lines?
372 // the lowest point contacted
373 // (monsters won't move to a dropoff)
389 subsector_t
* newsubsec
;
392 tmflags
= thing
->flags
;
397 tmbbox
[BOXTOP
] = y
+ tmthing
->radius
;
398 tmbbox
[BOXBOTTOM
] = y
- tmthing
->radius
;
399 tmbbox
[BOXRIGHT
] = x
+ tmthing
->radius
;
400 tmbbox
[BOXLEFT
] = x
- tmthing
->radius
;
402 newsubsec
= R_PointInSubsector (x
,y
);
405 // The base floor / ceiling is from the subsector
406 // that contains the point.
407 // Any contacted lines the step closer together
409 tmfloorz
= tmdropoffz
= newsubsec
->sector
->floorheight
;
410 tmceilingz
= newsubsec
->sector
->ceilingheight
;
415 if ( tmflags
& MF_NOCLIP
)
418 // Check things first, possibly picking things up.
419 // The bounding box is extended by MAXRADIUS
420 // because mobj_ts are grouped into mapblocks
421 // based on their origin point, and can overlap
422 // into adjacent blocks by up to MAXRADIUS units.
423 xl
= (tmbbox
[BOXLEFT
] - bmaporgx
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
424 xh
= (tmbbox
[BOXRIGHT
] - bmaporgx
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
425 yl
= (tmbbox
[BOXBOTTOM
] - bmaporgy
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
426 yh
= (tmbbox
[BOXTOP
] - bmaporgy
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
428 for (bx
=xl
; bx
<=xh
; bx
++)
429 for (by
=yl
; by
<=yh
; by
++)
430 if (!P_BlockThingsIterator(bx
,by
,PIT_CheckThing
))
434 xl
= (tmbbox
[BOXLEFT
] - bmaporgx
)>>MAPBLOCKSHIFT
;
435 xh
= (tmbbox
[BOXRIGHT
] - bmaporgx
)>>MAPBLOCKSHIFT
;
436 yl
= (tmbbox
[BOXBOTTOM
] - bmaporgy
)>>MAPBLOCKSHIFT
;
437 yh
= (tmbbox
[BOXTOP
] - bmaporgy
)>>MAPBLOCKSHIFT
;
439 for (bx
=xl
; bx
<=xh
; bx
++)
440 for (by
=yl
; by
<=yh
; by
++)
441 if (!P_BlockLinesIterator (bx
,by
,PIT_CheckLine
))
450 // Attempt to move to a new position,
451 // crossing special lines unless MF_TELEPORT is set.
466 if (!P_CheckPosition (thing
, x
, y
))
467 return false; // solid wall or thing
469 if ( !(thing
->flags
& MF_NOCLIP
) )
471 if (tmceilingz
- tmfloorz
< thing
->height
)
472 return false; // doesn't fit
476 if ( !(thing
->flags
&MF_TELEPORT
)
477 &&tmceilingz
- thing
->z
< thing
->height
)
478 return false; // mobj must lower itself to fit
480 if ( !(thing
->flags
&MF_TELEPORT
)
481 && tmfloorz
- thing
->z
> 24*FRACUNIT
)
482 return false; // too big a step up
484 if ( !(thing
->flags
&(MF_DROPOFF
|MF_FLOAT
))
485 && tmfloorz
- tmdropoffz
> 24*FRACUNIT
)
486 return false; // don't stand over a dropoff
490 // so link the thing into its new position
491 P_UnsetThingPosition (thing
);
495 thing
->floorz
= tmfloorz
;
496 thing
->ceilingz
= tmceilingz
;
500 P_SetThingPosition (thing
);
502 // if any special lines were hit, do the effect
503 if (! (thing
->flags
&(MF_TELEPORT
|MF_NOCLIP
)) )
507 // see if the line was crossed
508 ld
= spechit
[numspechit
];
509 side
= P_PointOnLineSide (thing
->x
, thing
->y
, ld
);
510 oldside
= P_PointOnLineSide (oldx
, oldy
, ld
);
514 P_CrossSpecialLine (ld
-lines
, oldside
, thing
);
525 // Takes a valid thing and adjusts the thing->floorz,
526 // thing->ceilingz, and possibly thing->z.
527 // This is called for all nearby monsters
528 // whenever a sector changes height.
529 // If the thing doesn't fit,
530 // the z will be set to the lowest value
531 // and false will be returned.
533 boolean
P_ThingHeightClip (mobj_t
* thing
)
537 onfloor
= (thing
->z
== thing
->floorz
);
539 P_CheckPosition (thing
, thing
->x
, thing
->y
);
540 // what about stranding a monster partially off an edge?
542 thing
->floorz
= tmfloorz
;
543 thing
->ceilingz
= tmceilingz
;
547 // walking monsters rise and fall with the floor
548 thing
->z
= thing
->floorz
;
552 // don't adjust a floating monster unless forced to
553 if (thing
->z
+thing
->height
> thing
->ceilingz
)
554 thing
->z
= thing
->ceilingz
- thing
->height
;
557 if (thing
->ceilingz
- thing
->floorz
< thing
->height
)
567 // Allows the player to slide along any angled walls.
569 fixed_t bestslidefrac
;
570 fixed_t secondslidefrac
;
572 line_t
* bestslideline
;
573 line_t
* secondslideline
;
584 // Adjusts the xmove / ymove
585 // so that the next move will slide along the wall.
587 void P_HitSlideLine (line_t
* ld
)
599 if (ld
->slopetype
== ST_HORIZONTAL
)
605 if (ld
->slopetype
== ST_VERTICAL
)
611 side
= P_PointOnLineSide (slidemo
->x
, slidemo
->y
, ld
);
613 lineangle
= R_PointToAngle2 (0,0, ld
->dx
, ld
->dy
);
618 moveangle
= R_PointToAngle2 (0,0, tmxmove
, tmymove
);
619 deltaangle
= moveangle
-lineangle
;
621 if (deltaangle
> ANG180
)
622 deltaangle
+= ANG180
;
623 // I_Error ("SlideLine: ang>ANG180");
625 lineangle
>>= ANGLETOFINESHIFT
;
626 deltaangle
>>= ANGLETOFINESHIFT
;
628 movelen
= P_AproxDistance (tmxmove
, tmymove
);
629 newlen
= FixedMul (movelen
, finecosine
[deltaangle
]);
631 tmxmove
= FixedMul (newlen
, finecosine
[lineangle
]);
632 tmymove
= FixedMul (newlen
, finesine
[lineangle
]);
639 boolean
PTR_SlideTraverse (intercept_t
* in
)
644 I_Error ("PTR_SlideTraverse: not a line?");
648 if ( ! (li
->flags
& ML_TWOSIDED
) )
650 if (P_PointOnLineSide (slidemo
->x
, slidemo
->y
, li
))
652 // don't hit the back side
658 // set openrange, opentop, openbottom
661 if (openrange
< slidemo
->height
)
662 goto isblocking
; // doesn't fit
664 if (opentop
- slidemo
->z
< slidemo
->height
)
665 goto isblocking
; // mobj is too high
667 if (openbottom
- slidemo
->z
> 24*FRACUNIT
)
668 goto isblocking
; // too big a step up
670 // this line doesn't block movement
673 // the line does block movement,
674 // see if it is closer than best so far
676 if (in
->frac
< bestslidefrac
)
678 secondslidefrac
= bestslidefrac
;
679 secondslideline
= bestslideline
;
680 bestslidefrac
= in
->frac
;
684 return false; // stop
691 // The momx / momy move is bad, so try to slide
693 // Find the first line hit, move flush to it,
694 // and slide along it
696 // This is a kludgy mess.
698 void P_SlideMove (mobj_t
* mo
)
713 goto stairstep
; // don't loop forever
716 // trace along the three leading corners
719 leadx
= mo
->x
+ mo
->radius
;
720 trailx
= mo
->x
- mo
->radius
;
724 leadx
= mo
->x
- mo
->radius
;
725 trailx
= mo
->x
+ mo
->radius
;
730 leady
= mo
->y
+ mo
->radius
;
731 traily
= mo
->y
- mo
->radius
;
735 leady
= mo
->y
- mo
->radius
;
736 traily
= mo
->y
+ mo
->radius
;
739 bestslidefrac
= FRACUNIT
+1;
741 P_PathTraverse ( leadx
, leady
, leadx
+mo
->momx
, leady
+mo
->momy
,
742 PT_ADDLINES
, PTR_SlideTraverse
);
743 P_PathTraverse ( trailx
, leady
, trailx
+mo
->momx
, leady
+mo
->momy
,
744 PT_ADDLINES
, PTR_SlideTraverse
);
745 P_PathTraverse ( leadx
, traily
, leadx
+mo
->momx
, traily
+mo
->momy
,
746 PT_ADDLINES
, PTR_SlideTraverse
);
748 // move up to the wall
749 if (bestslidefrac
== FRACUNIT
+1)
751 // the move most have hit the middle, so stairstep
753 if (!P_TryMove (mo
, mo
->x
, mo
->y
+ mo
->momy
))
754 P_TryMove (mo
, mo
->x
+ mo
->momx
, mo
->y
);
758 // fudge a bit to make sure it doesn't hit
759 bestslidefrac
-= 0x800;
760 if (bestslidefrac
> 0)
762 newx
= FixedMul (mo
->momx
, bestslidefrac
);
763 newy
= FixedMul (mo
->momy
, bestslidefrac
);
765 if (!P_TryMove (mo
, mo
->x
+newx
, mo
->y
+newy
))
769 // Now continue along the wall.
770 // First calculate remainder.
771 bestslidefrac
= FRACUNIT
-(bestslidefrac
+0x800);
773 if (bestslidefrac
> FRACUNIT
)
774 bestslidefrac
= FRACUNIT
;
776 if (bestslidefrac
<= 0)
779 tmxmove
= FixedMul (mo
->momx
, bestslidefrac
);
780 tmymove
= FixedMul (mo
->momy
, bestslidefrac
);
782 P_HitSlideLine (bestslideline
); // clip the moves
787 if (!P_TryMove (mo
, mo
->x
+tmxmove
, mo
->y
+tmymove
))
797 mobj_t
* linetarget
; // who got hit (or NULL)
800 // Height if not aiming up or down
801 // ???: use slope for monsters?
809 // slopes to top and bottom of target
810 extern fixed_t topslope
;
811 extern fixed_t bottomslope
;
816 // Sets linetaget and aimslope when a target is aimed at.
819 PTR_AimTraverse (intercept_t
* in
)
824 fixed_t thingtopslope
;
825 fixed_t thingbottomslope
;
832 if ( !(li
->flags
& ML_TWOSIDED
) )
833 return false; // stop
835 // Crosses a two sided line.
836 // A two sided line will restrict
837 // the possible target ranges.
840 if (openbottom
>= opentop
)
841 return false; // stop
843 dist
= FixedMul (attackrange
, in
->frac
);
845 if (li
->frontsector
->floorheight
!= li
->backsector
->floorheight
)
847 slope
= FixedDiv (openbottom
- shootz
, dist
);
848 if (slope
> bottomslope
)
852 if (li
->frontsector
->ceilingheight
!= li
->backsector
->ceilingheight
)
854 slope
= FixedDiv (opentop
- shootz
, dist
);
855 if (slope
< topslope
)
859 if (topslope
<= bottomslope
)
860 return false; // stop
862 return true; // shot continues
867 if (th
== shootthing
)
868 return true; // can't shoot self
870 if (!(th
->flags
&MF_SHOOTABLE
))
871 return true; // corpse or something
873 // check angles to see if the thing can be aimed at
874 dist
= FixedMul (attackrange
, in
->frac
);
875 thingtopslope
= FixedDiv (th
->z
+th
->height
- shootz
, dist
);
877 if (thingtopslope
< bottomslope
)
878 return true; // shot over the thing
880 thingbottomslope
= FixedDiv (th
->z
- shootz
, dist
);
882 if (thingbottomslope
> topslope
)
883 return true; // shot under the thing
885 // this thing can be hit!
886 if (thingtopslope
> topslope
)
887 thingtopslope
= topslope
;
889 if (thingbottomslope
< bottomslope
)
890 thingbottomslope
= bottomslope
;
892 aimslope
= (thingtopslope
+thingbottomslope
)/2;
895 return false; // don't go any farther
902 boolean
PTR_ShootTraverse (intercept_t
* in
)
915 fixed_t thingtopslope
;
916 fixed_t thingbottomslope
;
923 P_ShootSpecialLine (shootthing
, li
);
925 if ( !(li
->flags
& ML_TWOSIDED
) )
928 // crosses a two sided line
931 dist
= FixedMul (attackrange
, in
->frac
);
933 if (li
->frontsector
->floorheight
!= li
->backsector
->floorheight
)
935 slope
= FixedDiv (openbottom
- shootz
, dist
);
936 if (slope
> aimslope
)
940 if (li
->frontsector
->ceilingheight
!= li
->backsector
->ceilingheight
)
942 slope
= FixedDiv (opentop
- shootz
, dist
);
943 if (slope
< aimslope
)
953 // position a bit closer
954 frac
= in
->frac
- FixedDiv (4*FRACUNIT
,attackrange
);
955 x
= trace
.x
+ FixedMul (trace
.dx
, frac
);
956 y
= trace
.y
+ FixedMul (trace
.dy
, frac
);
957 z
= shootz
+ FixedMul (aimslope
, FixedMul(frac
, attackrange
));
959 if (li
->frontsector
->ceilingpic
== skyflatnum
)
961 // don't shoot the sky!
962 if (z
> li
->frontsector
->ceilingheight
)
965 // it's a sky hack wall
966 if (li
->backsector
&& li
->backsector
->ceilingpic
== skyflatnum
)
970 // Spawn bullet puffs.
973 // don't go any farther
979 if (th
== shootthing
)
980 return true; // can't shoot self
982 if (!(th
->flags
&MF_SHOOTABLE
))
983 return true; // corpse or something
985 // check angles to see if the thing can be aimed at
986 dist
= FixedMul (attackrange
, in
->frac
);
987 thingtopslope
= FixedDiv (th
->z
+th
->height
- shootz
, dist
);
989 if (thingtopslope
< aimslope
)
990 return true; // shot over the thing
992 thingbottomslope
= FixedDiv (th
->z
- shootz
, dist
);
994 if (thingbottomslope
> aimslope
)
995 return true; // shot under the thing
999 // position a bit closer
1000 frac
= in
->frac
- FixedDiv (10*FRACUNIT
,attackrange
);
1002 x
= trace
.x
+ FixedMul (trace
.dx
, frac
);
1003 y
= trace
.y
+ FixedMul (trace
.dy
, frac
);
1004 z
= shootz
+ FixedMul (aimslope
, FixedMul(frac
, attackrange
));
1006 // Spawn bullet puffs or blod spots,
1007 // depending on target type.
1008 if (in
->d
.thing
->flags
& MF_NOBLOOD
)
1009 P_SpawnPuff (x
,y
,z
);
1011 P_SpawnBlood (x
,y
,z
, la_damage
);
1014 P_DamageMobj (th
, shootthing
, shootthing
, la_damage
);
1016 // don't go any farther
1034 angle
>>= ANGLETOFINESHIFT
;
1037 x2
= t1
->x
+ (distance
>>FRACBITS
)*finecosine
[angle
];
1038 y2
= t1
->y
+ (distance
>>FRACBITS
)*finesine
[angle
];
1039 shootz
= t1
->z
+ (t1
->height
>>1) + 8*FRACUNIT
;
1041 // can't shoot outside view angles
1042 topslope
= 100*FRACUNIT
/160;
1043 bottomslope
= -100*FRACUNIT
/160;
1045 attackrange
= distance
;
1048 P_PathTraverse ( t1
->x
, t1
->y
,
1050 PT_ADDLINES
|PT_ADDTHINGS
,
1062 // If damage == 0, it is just a test trace
1063 // that will leave linetarget set.
1076 angle
>>= ANGLETOFINESHIFT
;
1079 x2
= t1
->x
+ (distance
>>FRACBITS
)*finecosine
[angle
];
1080 y2
= t1
->y
+ (distance
>>FRACBITS
)*finesine
[angle
];
1081 shootz
= t1
->z
+ (t1
->height
>>1) + 8*FRACUNIT
;
1082 attackrange
= distance
;
1085 P_PathTraverse ( t1
->x
, t1
->y
,
1087 PT_ADDLINES
|PT_ADDTHINGS
,
1088 PTR_ShootTraverse
);
1098 boolean
PTR_UseTraverse (intercept_t
* in
)
1102 if (!in
->d
.line
->special
)
1104 P_LineOpening (in
->d
.line
);
1107 S_StartSound (usething
, sfx_noway
);
1109 // can't use through a wall
1112 // not a special line, but keep checking
1117 if (P_PointOnLineSide (usething
->x
, usething
->y
, in
->d
.line
) == 1)
1120 // return false; // don't use back side
1122 P_UseSpecialLine (usething
, in
->d
.line
, side
);
1124 // can't use for than one special line in a row
1131 // Looks for special lines in front of the player to activate.
1133 void P_UseLines (player_t
* player
)
1141 usething
= player
->mo
;
1143 angle
= player
->mo
->angle
>> ANGLETOFINESHIFT
;
1147 x2
= x1
+ (USERANGE
>>FRACBITS
)*finecosine
[angle
];
1148 y2
= y1
+ (USERANGE
>>FRACBITS
)*finesine
[angle
];
1150 P_PathTraverse ( x1
, y1
, x2
, y2
, PT_ADDLINES
, PTR_UseTraverse
);
1164 // "bombsource" is the creature
1165 // that caused the explosion at "bombspot".
1167 boolean
PIT_RadiusAttack (mobj_t
* thing
)
1173 if (!(thing
->flags
& MF_SHOOTABLE
) )
1176 // Boss spider and cyborg
1177 // take no damage from concussion.
1178 if (thing
->type
== MT_CYBORG
1179 || thing
->type
== MT_SPIDER
)
1182 dx
= iabs(thing
->x
- bombspot
->x
);
1183 dy
= iabs(thing
->y
- bombspot
->y
);
1185 dist
= dx
>dy
? dx
: dy
;
1186 dist
= (dist
- thing
->radius
) >> FRACBITS
;
1191 if (dist
>= bombdamage
)
1192 return true; // out of range
1194 if ( P_CheckSight (thing
, bombspot
) )
1196 // must be in direct path
1197 P_DamageMobj (thing
, bombspot
, bombsource
, bombdamage
- dist
);
1206 // Source is the creature that caused the explosion at spot.
1224 dist
= (damage
+MAXRADIUS
)<<FRACBITS
;
1225 yh
= (spot
->y
+ dist
- bmaporgy
)>>MAPBLOCKSHIFT
;
1226 yl
= (spot
->y
- dist
- bmaporgy
)>>MAPBLOCKSHIFT
;
1227 xh
= (spot
->x
+ dist
- bmaporgx
)>>MAPBLOCKSHIFT
;
1228 xl
= (spot
->x
- dist
- bmaporgx
)>>MAPBLOCKSHIFT
;
1230 bombsource
= source
;
1231 bombdamage
= damage
;
1233 for (y
=yl
; y
<=yh
; y
++)
1234 for (x
=xl
; x
<=xh
; x
++)
1235 P_BlockThingsIterator (x
, y
, PIT_RadiusAttack
);
1241 // SECTOR HEIGHT CHANGING
1242 // After modifying a sectors floor or ceiling height,
1243 // call this routine to adjust the positions
1244 // of all things that touch the sector.
1246 // If anything doesn't fit anymore, true will be returned.
1247 // If crunch is true, they will take damage
1248 // as they are being crushed.
1249 // If Crunch is false, you should set the sector height back
1250 // the way it was and call P_ChangeSector again
1251 // to undo the changes.
1253 boolean crushchange
;
1260 boolean
PIT_ChangeSector (mobj_t
* thing
)
1264 if (P_ThingHeightClip (thing
))
1271 // crunch bodies to giblets
1272 if (thing
->health
<= 0)
1274 P_SetMobjState (thing
, S_GIBS
);
1276 thing
->flags
&= ~MF_SOLID
;
1284 // crunch dropped items
1285 if (thing
->flags
& MF_DROPPED
)
1287 P_RemoveMobj (thing
);
1293 if (! (thing
->flags
& MF_SHOOTABLE
) )
1295 // assume it is bloody gibs or something
1301 if (crushchange
&& !(leveltime
&3) )
1303 P_DamageMobj(thing
,NULL
,NULL
,10);
1305 // spray blood in a random direction
1306 mo
= P_SpawnMobj (thing
->x
,
1308 thing
->z
+ thing
->height
/2, MT_BLOOD
);
1310 mo
->momx
= (P_Random() - P_Random ())<<12;
1311 mo
->momy
= (P_Random() - P_Random ())<<12;
1314 // keep checking (crush other things)
1332 crushchange
= crunch
;
1334 // re-check heights for all things near the moving sector
1335 for (x
=sector
->blockbox
[BOXLEFT
] ; x
<= sector
->blockbox
[BOXRIGHT
] ; x
++)
1336 for (y
=sector
->blockbox
[BOXBOTTOM
];y
<= sector
->blockbox
[BOXTOP
] ; y
++)
1337 P_BlockThingsIterator (x
, y
, PIT_ChangeSector
);