p_map.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include <stdlib.h>
  23. #include "m_bbox.h"
  24. #include "m_random.h"
  25. #include "i_system.h"
  26. #include "doomdef.h"
  27. #include "p_local.h"
  28. #include "s_sound.h"
  29. // State.
  30. #include "doomstat.h"
  31. #include "r_state.h"
  32. // Data.
  33. #include "sounds.h"
  34. #include "Main.h"
  35. // If "floatok" true, move would be ok
  36. // if within "tmfloorz - tmceilingz".
  37. // keep track of the line that lowers the ceiling,
  38. // so missiles don't explode against sky hack walls
  39. // keep track of special ::g->lines as they are hit,
  40. // but don't process them until the move is proven valid
  41. //
  42. // TELEPORT MOVE
  43. //
  44. //
  45. // PIT_StompThing
  46. //
  47. qboolean PIT_StompThing (mobj_t* thing)
  48. {
  49. fixed_t blockdist;
  50. if (!(thing->flags & MF_SHOOTABLE) )
  51. return true;
  52. blockdist = thing->radius + ::g->tmthing->radius;
  53. if ( abs(thing->x - ::g->tmx) >= blockdist
  54. || abs(thing->y - ::g->tmy) >= blockdist )
  55. {
  56. // didn't hit it
  57. return true;
  58. }
  59. // don't clip against self
  60. if (thing == ::g->tmthing)
  61. return true;
  62. // monsters don't stomp things except on boss level
  63. if ( !::g->tmthing->player && ::g->gamemap != 30)
  64. return false;
  65. P_DamageMobj (thing, ::g->tmthing, ::g->tmthing, 10000);
  66. return true;
  67. }
  68. //
  69. // P_TeleportMove
  70. //
  71. qboolean
  72. P_TeleportMove
  73. ( mobj_t* thing,
  74. fixed_t x,
  75. fixed_t y )
  76. {
  77. int xl;
  78. int xh;
  79. int yl;
  80. int yh;
  81. int bx;
  82. int by;
  83. subsector_t* newsubsec;
  84. // kill anything occupying the position
  85. ::g->tmthing = thing;
  86. ::g->tmflags = thing->flags;
  87. ::g->tmx = x;
  88. ::g->tmy = y;
  89. ::g->tmbbox[BOXTOP] = y + ::g->tmthing->radius;
  90. ::g->tmbbox[BOXBOTTOM] = y - ::g->tmthing->radius;
  91. ::g->tmbbox[BOXRIGHT] = x + ::g->tmthing->radius;
  92. ::g->tmbbox[BOXLEFT] = x - ::g->tmthing->radius;
  93. newsubsec = R_PointInSubsector (x,y);
  94. ::g->ceilingline = NULL;
  95. // The base floor/ceiling is from the subsector
  96. // that contains the point.
  97. // Any contacted ::g->lines the step closer together
  98. // will adjust them.
  99. ::g->tmfloorz = ::g->tmdropoffz = newsubsec->sector->floorheight;
  100. ::g->tmceilingz = newsubsec->sector->ceilingheight;
  101. ::g->validcount++;
  102. ::g->numspechit = 0;
  103. // stomp on any things contacted
  104. xl = (::g->tmbbox[BOXLEFT] - ::g->bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
  105. xh = (::g->tmbbox[BOXRIGHT] - ::g->bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
  106. yl = (::g->tmbbox[BOXBOTTOM] - ::g->bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
  107. yh = (::g->tmbbox[BOXTOP] - ::g->bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
  108. for (bx=xl ; bx<=xh ; bx++)
  109. for (by=yl ; by<=yh ; by++)
  110. if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
  111. return false;
  112. // the move is ok,
  113. // so link the thing into its new position
  114. P_UnsetThingPosition (thing);
  115. thing->floorz = ::g->tmfloorz;
  116. thing->ceilingz = ::g->tmceilingz;
  117. thing->x = x;
  118. thing->y = y;
  119. P_SetThingPosition (thing);
  120. return true;
  121. }
  122. //
  123. // MOVEMENT ITERATOR FUNCTIONS
  124. //
  125. //
  126. // PIT_CheckLine
  127. // Adjusts ::g->tmfloorz and ::g->tmceilingz as ::g->lines are contacted
  128. //
  129. qboolean PIT_CheckLine (line_t* ld)
  130. {
  131. if (::g->tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
  132. || ::g->tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
  133. || ::g->tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
  134. || ::g->tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
  135. return true;
  136. if (P_BoxOnLineSide (::g->tmbbox, ld) != -1)
  137. return true;
  138. // A line has been hit
  139. // The moving thing's destination position will cross
  140. // the given line.
  141. // If this should not be allowed, return false.
  142. // If the line is special, keep track of it
  143. // to process later if the move is proven ok.
  144. // NOTE: specials are NOT sorted by order,
  145. // so two special ::g->lines that are only 8 pixels apart
  146. // could be crossed in either order.
  147. if (!ld->backsector)
  148. return false; // one sided line
  149. if (!(::g->tmthing->flags & MF_MISSILE) )
  150. {
  151. if ( ld->flags & ML_BLOCKING )
  152. return false; // explicitly blocking everything
  153. if ( !::g->tmthing->player && ld->flags & ML_BLOCKMONSTERS )
  154. return false; // block monsters only
  155. }
  156. // set ::g->openrange, ::g->opentop, ::g->openbottom
  157. P_LineOpening (ld);
  158. // adjust floor / ceiling heights
  159. if (::g->opentop < ::g->tmceilingz)
  160. {
  161. ::g->tmceilingz = ::g->opentop;
  162. ::g->ceilingline = ld;
  163. }
  164. if (::g->openbottom > ::g->tmfloorz)
  165. ::g->tmfloorz = ::g->openbottom;
  166. if (::g->lowfloor < ::g->tmdropoffz)
  167. ::g->tmdropoffz = ::g->lowfloor;
  168. // if contacted a special line, add it to the list
  169. if (ld->special && ::g->numspechit < MAXSPECIALCROSS )
  170. {
  171. ::g->spechit[::g->numspechit] = ld;
  172. ::g->numspechit++;
  173. }
  174. return true;
  175. }
  176. //
  177. // PIT_CheckThing
  178. //
  179. qboolean PIT_CheckThing (mobj_t* thing)
  180. {
  181. fixed_t blockdist;
  182. qboolean solid;
  183. int damage;
  184. if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
  185. return true;
  186. blockdist = thing->radius + ::g->tmthing->radius;
  187. if ( abs(thing->x - ::g->tmx) >= blockdist
  188. || abs(thing->y - ::g->tmy) >= blockdist )
  189. {
  190. // didn't hit it
  191. return true;
  192. }
  193. // don't clip against self
  194. if (thing == ::g->tmthing)
  195. return true;
  196. // check for skulls slamming into things
  197. if (::g->tmthing->flags & MF_SKULLFLY)
  198. {
  199. damage = ((P_Random()%8)+1)*::g->tmthing->info->damage;
  200. P_DamageMobj (thing, ::g->tmthing, ::g->tmthing, damage);
  201. ::g->tmthing->flags &= ~MF_SKULLFLY;
  202. ::g->tmthing->momx = ::g->tmthing->momy = ::g->tmthing->momz = 0;
  203. P_SetMobjState (::g->tmthing, (statenum_t)::g->tmthing->info->spawnstate);
  204. return false; // stop moving
  205. }
  206. // missiles can hit other things
  207. if (::g->tmthing->flags & MF_MISSILE)
  208. {
  209. // see if it went over / under
  210. if (::g->tmthing->z > thing->z + thing->height)
  211. return true; // overhead
  212. if (::g->tmthing->z+::g->tmthing->height < thing->z)
  213. return true; // underneath
  214. if (::g->tmthing->target && (
  215. ::g->tmthing->target->type == thing->type ||
  216. (::g->tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
  217. (::g->tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )
  218. {
  219. // Don't hit same species as originator.
  220. if (thing == ::g->tmthing->target)
  221. return true;
  222. if (thing->type != MT_PLAYER)
  223. {
  224. // Explode, but do no damage.
  225. // Let ::g->players missile other ::g->players.
  226. return false;
  227. }
  228. }
  229. if (! (thing->flags & MF_SHOOTABLE) )
  230. {
  231. // didn't do any damage
  232. return !(thing->flags & MF_SOLID);
  233. }
  234. // damage / explode
  235. damage = ((P_Random()%8)+1)*::g->tmthing->info->damage;
  236. P_DamageMobj (thing, ::g->tmthing, ::g->tmthing->target, damage);
  237. // don't traverse any more
  238. return false;
  239. }
  240. // check for special pickup
  241. if (thing->flags & MF_SPECIAL)
  242. {
  243. solid = thing->flags&MF_SOLID;
  244. if (::g->tmflags&MF_PICKUP)
  245. {
  246. // can remove thing
  247. P_TouchSpecialThing (thing, ::g->tmthing);
  248. }
  249. return !solid;
  250. }
  251. return !(thing->flags & MF_SOLID);
  252. }
  253. //
  254. // MOVEMENT CLIPPING
  255. //
  256. //
  257. // P_CheckPosition
  258. // This is purely informative, nothing is modified
  259. // (except things picked up).
  260. //
  261. // in:
  262. // a mobj_t (can be valid or invalid)
  263. // a position to be checked
  264. // (doesn't need to be related to the mobj_t->x,y)
  265. //
  266. // during:
  267. // special things are touched if MF_PICKUP
  268. // early out on solid lines?
  269. //
  270. // out:
  271. // newsubsec
  272. // floorz
  273. // ceilingz
  274. // ::g->tmdropoffz
  275. // the lowest point contacted
  276. // (monsters won't move to a dropoff)
  277. // speciallines[]
  278. // numspeciallines
  279. //
  280. qboolean
  281. P_CheckPosition
  282. ( mobj_t* thing,
  283. fixed_t x,
  284. fixed_t y )
  285. {
  286. int xl;
  287. int xh;
  288. int yl;
  289. int yh;
  290. int bx;
  291. int by;
  292. subsector_t* newsubsec;
  293. ::g->tmthing = thing;
  294. ::g->tmflags = thing->flags;
  295. ::g->tmx = x;
  296. ::g->tmy = y;
  297. ::g->tmbbox[BOXTOP] = y + ::g->tmthing->radius;
  298. ::g->tmbbox[BOXBOTTOM] = y - ::g->tmthing->radius;
  299. ::g->tmbbox[BOXRIGHT] = x + ::g->tmthing->radius;
  300. ::g->tmbbox[BOXLEFT] = x - ::g->tmthing->radius;
  301. newsubsec = R_PointInSubsector (x,y);
  302. ::g->ceilingline = NULL;
  303. // The base floor / ceiling is from the subsector
  304. // that contains the point.
  305. // Any contacted ::g->lines the step closer together
  306. // will adjust them.
  307. ::g->tmfloorz = ::g->tmdropoffz = newsubsec->sector->floorheight;
  308. ::g->tmceilingz = newsubsec->sector->ceilingheight;
  309. ::g->validcount++;
  310. ::g->numspechit = 0;
  311. if ( ::g->tmflags & MF_NOCLIP )
  312. return true;
  313. // Check things first, possibly picking things up.
  314. // The bounding box is extended by MAXRADIUS
  315. // because mobj_ts are grouped into mapblocks
  316. // based on their origin point, and can overlap
  317. // into adjacent blocks by up to MAXRADIUS units.
  318. xl = (::g->tmbbox[BOXLEFT] - ::g->bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
  319. xh = (::g->tmbbox[BOXRIGHT] - ::g->bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
  320. yl = (::g->tmbbox[BOXBOTTOM] - ::g->bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
  321. yh = (::g->tmbbox[BOXTOP] - ::g->bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
  322. for (bx=xl ; bx<=xh ; bx++)
  323. for (by=yl ; by<=yh ; by++)
  324. if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
  325. return false;
  326. // check ::g->lines
  327. xl = (::g->tmbbox[BOXLEFT] - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  328. xh = (::g->tmbbox[BOXRIGHT] - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  329. yl = (::g->tmbbox[BOXBOTTOM] - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  330. yh = (::g->tmbbox[BOXTOP] - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  331. for (bx=xl ; bx<=xh ; bx++)
  332. for (by=yl ; by<=yh ; by++)
  333. if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
  334. return false;
  335. return true;
  336. }
  337. //
  338. // P_TryMove
  339. // Attempt to move to a new position,
  340. // crossing special ::g->lines unless MF_TELEPORT is set.
  341. //
  342. qboolean
  343. P_TryMove
  344. ( mobj_t* thing,
  345. fixed_t x,
  346. fixed_t y )
  347. {
  348. fixed_t oldx;
  349. fixed_t oldy;
  350. int side;
  351. int oldside;
  352. line_t* ld;
  353. ::g->floatok = false;
  354. if (!P_CheckPosition (thing, x, y))
  355. return false; // solid wall or thing
  356. if ( !(thing->flags & MF_NOCLIP) )
  357. {
  358. if (::g->tmceilingz - ::g->tmfloorz < thing->height)
  359. return false; // doesn't fit
  360. ::g->floatok = true;
  361. if ( !(thing->flags&MF_TELEPORT)
  362. &&::g->tmceilingz - thing->z < thing->height)
  363. return false; // mobj must lower itself to fit
  364. if ( !(thing->flags&MF_TELEPORT)
  365. && ::g->tmfloorz - thing->z > 24*FRACUNIT )
  366. return false; // too big a step up
  367. if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))
  368. && ::g->tmfloorz - ::g->tmdropoffz > 24*FRACUNIT )
  369. return false; // don't stand over a dropoff
  370. }
  371. // the move is ok,
  372. // so link the thing into its new position
  373. P_UnsetThingPosition (thing);
  374. oldx = thing->x;
  375. oldy = thing->y;
  376. thing->floorz = ::g->tmfloorz;
  377. thing->ceilingz = ::g->tmceilingz;
  378. thing->x = x;
  379. thing->y = y;
  380. P_SetThingPosition (thing);
  381. // if any special ::g->lines were hit, do the effect
  382. if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )
  383. {
  384. while (::g->numspechit--)
  385. {
  386. // see if the line was crossed
  387. ld = ::g->spechit[::g->numspechit];
  388. side = P_PointOnLineSide (thing->x, thing->y, ld);
  389. oldside = P_PointOnLineSide (oldx, oldy, ld);
  390. if (side != oldside)
  391. {
  392. if (ld->special)
  393. P_CrossSpecialLine (ld-::g->lines, oldside, thing);
  394. }
  395. }
  396. }
  397. return true;
  398. }
  399. //
  400. // P_ThingHeightClip
  401. // Takes a valid thing and adjusts the thing->floorz,
  402. // thing->ceilingz, and possibly thing->z.
  403. // This is called for all nearby monsters
  404. // whenever a sector changes height.
  405. // If the thing doesn't fit,
  406. // the z will be set to the lowest value
  407. // and false will be returned.
  408. //
  409. qboolean P_ThingHeightClip (mobj_t* thing)
  410. {
  411. qboolean onfloor;
  412. onfloor = (thing->z == thing->floorz);
  413. P_CheckPosition (thing, thing->x, thing->y);
  414. // what about stranding a monster partially off an edge?
  415. thing->floorz = ::g->tmfloorz;
  416. thing->ceilingz = ::g->tmceilingz;
  417. if (onfloor)
  418. {
  419. // walking monsters rise and fall with the floor
  420. thing->z = thing->floorz;
  421. }
  422. else
  423. {
  424. // don't adjust a floating monster unless forced to
  425. if (thing->z+thing->height > thing->ceilingz)
  426. thing->z = thing->ceilingz - thing->height;
  427. }
  428. if (thing->ceilingz - thing->floorz < thing->height)
  429. return false;
  430. return true;
  431. }
  432. //
  433. // SLIDE MOVE
  434. // Allows the player to slide along any angled walls.
  435. //
  436. //
  437. // P_HitSlideLine
  438. // Adjusts the xmove / ymove
  439. // so that the next move will slide along the wall.
  440. //
  441. void P_HitSlideLine (line_t* ld)
  442. {
  443. int side;
  444. angle_t lineangle;
  445. angle_t moveangle;
  446. angle_t deltaangle;
  447. fixed_t movelen;
  448. fixed_t newlen;
  449. if (ld->slopetype == ST_HORIZONTAL)
  450. {
  451. ::g->tmymove = 0;
  452. return;
  453. }
  454. if (ld->slopetype == ST_VERTICAL)
  455. {
  456. ::g->tmxmove = 0;
  457. return;
  458. }
  459. side = P_PointOnLineSide (::g->slidemo->x, ::g->slidemo->y, ld);
  460. lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
  461. if (side == 1)
  462. lineangle += ANG180;
  463. moveangle = R_PointToAngle2 (0,0, ::g->tmxmove, ::g->tmymove);
  464. deltaangle = moveangle-lineangle;
  465. if (deltaangle > ANG180)
  466. deltaangle += ANG180;
  467. // I_Error ("SlideLine: ang>ANG180");
  468. lineangle >>= ANGLETOFINESHIFT;
  469. deltaangle >>= ANGLETOFINESHIFT;
  470. movelen = P_AproxDistance (::g->tmxmove, ::g->tmymove);
  471. newlen = FixedMul (movelen, finecosine[deltaangle]);
  472. ::g->tmxmove = FixedMul (newlen, finecosine[lineangle]);
  473. ::g->tmymove = FixedMul (newlen, finesine[lineangle]);
  474. }
  475. //
  476. // PTR_SlideTraverse
  477. //
  478. qboolean PTR_SlideTraverse (intercept_t* in)
  479. {
  480. line_t* li;
  481. if (!in->isaline)
  482. I_Error ("PTR_SlideTraverse: not a line?");
  483. li = in->d.line;
  484. if ( ! (li->flags & ML_TWOSIDED) )
  485. {
  486. if (P_PointOnLineSide (::g->slidemo->x, ::g->slidemo->y, li))
  487. {
  488. // don't hit the back side
  489. return true;
  490. }
  491. goto isblocking;
  492. }
  493. // set ::g->openrange, ::g->opentop, ::g->openbottom
  494. P_LineOpening (li);
  495. if (::g->openrange < ::g->slidemo->height)
  496. goto isblocking; // doesn't fit
  497. if (::g->opentop - ::g->slidemo->z < ::g->slidemo->height)
  498. goto isblocking; // mobj is too high
  499. if (::g->openbottom - ::g->slidemo->z > 24*FRACUNIT )
  500. goto isblocking; // too big a step up
  501. // this line doesn't block movement
  502. return true;
  503. // the line does block movement,
  504. // see if it is closer than best so far
  505. isblocking:
  506. if (in->frac < ::g->bestslidefrac)
  507. {
  508. ::g->secondslidefrac = ::g->bestslidefrac;
  509. ::g->secondslideline = ::g->bestslideline;
  510. ::g->bestslidefrac = in->frac;
  511. ::g->bestslideline = li;
  512. }
  513. return false; // stop
  514. }
  515. //
  516. // P_SlideMove
  517. // The momx / momy move is bad, so try to slide
  518. // along a wall.
  519. // Find the first line hit, move flush to it,
  520. // and slide along it
  521. //
  522. // This is a kludgy mess.
  523. //
  524. void P_SlideMove (mobj_t* mo)
  525. {
  526. fixed_t leadx;
  527. fixed_t leady;
  528. fixed_t trailx;
  529. fixed_t traily;
  530. fixed_t newx;
  531. fixed_t newy;
  532. int hitcount;
  533. ::g->slidemo = mo;
  534. hitcount = 0;
  535. retry:
  536. if (++hitcount == 3)
  537. goto stairstep; // don't loop forever
  538. // ::g->trace along the three leading corners
  539. if (mo->momx > 0)
  540. {
  541. leadx = mo->x + mo->radius;
  542. trailx = mo->x - mo->radius;
  543. }
  544. else
  545. {
  546. leadx = mo->x - mo->radius;
  547. trailx = mo->x + mo->radius;
  548. }
  549. if (mo->momy > 0)
  550. {
  551. leady = mo->y + mo->radius;
  552. traily = mo->y - mo->radius;
  553. }
  554. else
  555. {
  556. leady = mo->y - mo->radius;
  557. traily = mo->y + mo->radius;
  558. }
  559. ::g->bestslidefrac = FRACUNIT+1;
  560. P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy,
  561. PT_ADDLINES, PTR_SlideTraverse );
  562. P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy,
  563. PT_ADDLINES, PTR_SlideTraverse );
  564. P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy,
  565. PT_ADDLINES, PTR_SlideTraverse );
  566. // move up to the wall
  567. if (::g->bestslidefrac == FRACUNIT+1)
  568. {
  569. // the move most have hit the middle, so stairstep
  570. stairstep:
  571. if (!P_TryMove (mo, mo->x, mo->y + mo->momy))
  572. P_TryMove (mo, mo->x + mo->momx, mo->y);
  573. return;
  574. }
  575. // fudge a bit to make sure it doesn't hit
  576. ::g->bestslidefrac -= 0x800;
  577. if (::g->bestslidefrac > 0)
  578. {
  579. newx = FixedMul (mo->momx, ::g->bestslidefrac);
  580. newy = FixedMul (mo->momy, ::g->bestslidefrac);
  581. if (!P_TryMove (mo, mo->x+newx, mo->y+newy))
  582. goto stairstep;
  583. }
  584. // Now continue along the wall.
  585. // First calculate remainder.
  586. ::g->bestslidefrac = FRACUNIT-(::g->bestslidefrac+0x800);
  587. if (::g->bestslidefrac > FRACUNIT)
  588. ::g->bestslidefrac = FRACUNIT;
  589. if (::g->bestslidefrac <= 0)
  590. return;
  591. ::g->tmxmove = FixedMul (mo->momx, ::g->bestslidefrac);
  592. ::g->tmymove = FixedMul (mo->momy, ::g->bestslidefrac);
  593. P_HitSlideLine (::g->bestslideline); // clip the moves
  594. mo->momx = ::g->tmxmove;
  595. mo->momy = ::g->tmymove;
  596. if (!P_TryMove (mo, mo->x+::g->tmxmove, mo->y+::g->tmymove))
  597. {
  598. goto retry;
  599. }
  600. }
  601. //
  602. // P_LineAttack
  603. //
  604. // Height if not aiming up or down
  605. // ???: use slope for monsters?
  606. // slopes to top and bottom of target
  607. //
  608. // PTR_AimTraverse
  609. // Sets linetaget and ::g->aimslope when a target is aimed at.
  610. //
  611. qboolean
  612. PTR_AimTraverse (intercept_t* in)
  613. {
  614. line_t* li;
  615. mobj_t* th;
  616. fixed_t slope;
  617. fixed_t thingtopslope;
  618. fixed_t thingbottomslope;
  619. fixed_t dist;
  620. if (in->isaline)
  621. {
  622. li = in->d.line;
  623. if ( !(li->flags & ML_TWOSIDED) )
  624. return false; // stop
  625. // Crosses a two sided line.
  626. // A two sided line will restrict
  627. // the possible target ranges.
  628. P_LineOpening (li);
  629. if (::g->openbottom >= ::g->opentop)
  630. return false; // stop
  631. dist = FixedMul (::g->attackrange, in->frac);
  632. if (li->frontsector->floorheight != li->backsector->floorheight)
  633. {
  634. slope = FixedDiv (::g->openbottom - ::g->shootz , dist);
  635. if (slope > ::g->bottomslope)
  636. ::g->bottomslope = slope;
  637. }
  638. if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
  639. {
  640. slope = FixedDiv (::g->opentop - ::g->shootz , dist);
  641. if (slope < ::g->topslope)
  642. ::g->topslope = slope;
  643. }
  644. if (::g->topslope <= ::g->bottomslope)
  645. return false; // stop
  646. return true; // shot continues
  647. }
  648. // shoot a thing
  649. th = in->d.thing;
  650. if (th == ::g->shootthing)
  651. return true; // can't shoot self
  652. if (!(th->flags&MF_SHOOTABLE))
  653. return true; // corpse or something
  654. // check angles to see if the thing can be aimed at
  655. dist = FixedMul (::g->attackrange, in->frac);
  656. thingtopslope = FixedDiv (th->z+th->height - ::g->shootz , dist);
  657. if (thingtopslope < ::g->bottomslope)
  658. return true; // shot over the thing
  659. thingbottomslope = FixedDiv (th->z - ::g->shootz, dist);
  660. if (thingbottomslope > ::g->topslope)
  661. return true; // shot under the thing
  662. // this thing can be hit!
  663. if (thingtopslope > ::g->topslope)
  664. thingtopslope = ::g->topslope;
  665. if (thingbottomslope < ::g->bottomslope)
  666. thingbottomslope = ::g->bottomslope;
  667. ::g->aimslope = (thingtopslope+thingbottomslope)/2;
  668. ::g->linetarget = th;
  669. return false; // don't go any farther
  670. }
  671. //
  672. // PTR_ShootTraverse
  673. //
  674. qboolean PTR_ShootTraverse (intercept_t* in)
  675. {
  676. fixed_t x;
  677. fixed_t y;
  678. fixed_t z;
  679. fixed_t frac;
  680. line_t* li;
  681. mobj_t* th;
  682. fixed_t slope;
  683. fixed_t dist;
  684. fixed_t thingtopslope;
  685. fixed_t thingbottomslope;
  686. if (in->isaline)
  687. {
  688. li = in->d.line;
  689. if (li->special)
  690. P_ShootSpecialLine (::g->shootthing, li);
  691. if ( !(li->flags & ML_TWOSIDED) )
  692. goto hitline;
  693. // crosses a two sided line
  694. P_LineOpening (li);
  695. dist = FixedMul (::g->attackrange, in->frac);
  696. if (li->frontsector->floorheight != li->backsector->floorheight)
  697. {
  698. slope = FixedDiv (::g->openbottom - ::g->shootz , dist);
  699. if (slope > ::g->aimslope)
  700. goto hitline;
  701. }
  702. if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
  703. {
  704. slope = FixedDiv (::g->opentop - ::g->shootz , dist);
  705. if (slope < ::g->aimslope)
  706. goto hitline;
  707. }
  708. // shot continues
  709. return true;
  710. // hit line
  711. hitline:
  712. // position a bit closer
  713. frac = in->frac - FixedDiv (4*FRACUNIT,::g->attackrange);
  714. x = ::g->trace.x + FixedMul (::g->trace.dx, frac);
  715. y = ::g->trace.y + FixedMul (::g->trace.dy, frac);
  716. z = ::g->shootz + FixedMul (::g->aimslope, FixedMul(frac, ::g->attackrange));
  717. if (li->frontsector->ceilingpic == ::g->skyflatnum)
  718. {
  719. // don't shoot the sky!
  720. if (z > li->frontsector->ceilingheight)
  721. return false;
  722. // it's a sky hack wall
  723. if (li->backsector && li->backsector->ceilingpic == ::g->skyflatnum)
  724. return false;
  725. }
  726. mobj_t * sourceObject = ::g->shootthing;
  727. if( sourceObject ) {
  728. if( ( sourceObject->player) == &(::g->players[DoomLib::GetPlayer()]) ) {
  729. // Fist Punch.
  730. if( ::g->attackrange == MELEERANGE ) {
  731. }
  732. }
  733. }
  734. // Spawn bullet puffs.
  735. P_SpawnPuff (x,y,z);
  736. // don't go any farther
  737. return false;
  738. }
  739. // shoot a thing
  740. th = in->d.thing;
  741. if (th == ::g->shootthing)
  742. return true; // can't shoot self
  743. if (!(th->flags&MF_SHOOTABLE))
  744. return true; // corpse or something
  745. // check angles to see if the thing can be aimed at
  746. dist = FixedMul (::g->attackrange, in->frac);
  747. thingtopslope = FixedDiv (th->z+th->height - ::g->shootz , dist);
  748. if (thingtopslope < ::g->aimslope)
  749. return true; // shot over the thing
  750. thingbottomslope = FixedDiv (th->z - ::g->shootz, dist);
  751. if (thingbottomslope > ::g->aimslope)
  752. return true; // shot under the thing
  753. // hit thing
  754. // position a bit closer
  755. frac = in->frac - FixedDiv (10*FRACUNIT,::g->attackrange);
  756. x = ::g->trace.x + FixedMul (::g->trace.dx, frac);
  757. y = ::g->trace.y + FixedMul (::g->trace.dy, frac);
  758. z = ::g->shootz + FixedMul (::g->aimslope, FixedMul(frac, ::g->attackrange));
  759. // check for friendly fire.
  760. #ifdef ID_ENABLE_DOOM_CLASSIC_NETWORKING
  761. if( th && gameLocal->GetMatchParms().GetGameType() != GAME_TYPE_PVP ) {
  762. player_t * hitPlayer = th->player;
  763. if( hitPlayer ) {
  764. mobj_t * sourceObject = ::g->shootthing;
  765. if( sourceObject ) {
  766. player_t* sourcePlayer = sourceObject->player;
  767. if( sourcePlayer != NULL && sourcePlayer != hitPlayer && !gameLocal->GetMatchParms().AllowFriendlyFire() ) {
  768. return true;
  769. }
  770. }
  771. }
  772. }
  773. #endif
  774. mobj_t * sourceObject = ::g->shootthing;
  775. if( sourceObject ) {
  776. if( ( sourceObject->player) == &(::g->players[DoomLib::GetPlayer()]) ) {
  777. // Fist Punch.
  778. if( ::g->attackrange == MELEERANGE ) {
  779. }
  780. }
  781. }
  782. // Spawn bullet puffs or blod spots,
  783. // depending on target type.
  784. if (in->d.thing->flags & MF_NOBLOOD)
  785. P_SpawnPuff (x,y,z);
  786. else
  787. P_SpawnBlood (x,y,z, ::g->la_damage);
  788. if (::g->la_damage)
  789. P_DamageMobj (th, ::g->shootthing, ::g->shootthing, ::g->la_damage);
  790. // don't go any farther
  791. return false;
  792. }
  793. //
  794. // P_AimLineAttack
  795. //
  796. fixed_t
  797. P_AimLineAttack
  798. ( mobj_t* t1,
  799. angle_t angle,
  800. fixed_t distance )
  801. {
  802. fixed_t x2;
  803. fixed_t y2;
  804. angle >>= ANGLETOFINESHIFT;
  805. ::g->shootthing = t1;
  806. x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
  807. y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
  808. ::g->shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
  809. // can't shoot outside view angles
  810. ::g->topslope = 100*FRACUNIT/160;
  811. ::g->bottomslope = -100*FRACUNIT/160;
  812. ::g->attackrange = distance;
  813. ::g->linetarget = NULL;
  814. P_PathTraverse ( t1->x, t1->y,
  815. x2, y2,
  816. PT_ADDLINES|PT_ADDTHINGS,
  817. PTR_AimTraverse );
  818. if (::g->linetarget)
  819. return ::g->aimslope;
  820. return 0;
  821. }
  822. //
  823. // P_LineAttack
  824. // If damage == 0, it is just a test ::g->trace
  825. // that will leave ::g->linetarget set.
  826. //
  827. void
  828. P_LineAttack
  829. ( mobj_t* t1,
  830. angle_t angle,
  831. fixed_t distance,
  832. fixed_t slope,
  833. int damage )
  834. {
  835. fixed_t x2;
  836. fixed_t y2;
  837. angle >>= ANGLETOFINESHIFT;
  838. ::g->shootthing = t1;
  839. ::g->la_damage = damage;
  840. x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
  841. y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
  842. ::g->shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
  843. ::g->attackrange = distance;
  844. ::g->aimslope = slope;
  845. P_PathTraverse ( t1->x, t1->y,
  846. x2, y2,
  847. PT_ADDLINES|PT_ADDTHINGS,
  848. PTR_ShootTraverse );
  849. }
  850. //
  851. // USE LINES
  852. //
  853. qboolean PTR_UseTraverse (intercept_t* in)
  854. {
  855. int side;
  856. if (!in->d.line->special)
  857. {
  858. P_LineOpening (in->d.line);
  859. if (::g->openrange <= 0)
  860. {
  861. S_StartSound (::g->usething, sfx_noway);
  862. // can't use through a wall
  863. return false;
  864. }
  865. // not a special line, but keep checking
  866. return true ;
  867. }
  868. side = 0;
  869. if (P_PointOnLineSide (::g->usething->x, ::g->usething->y, in->d.line) == 1)
  870. side = 1;
  871. // return false; // don't use back side
  872. P_UseSpecialLine (::g->usething, in->d.line, side);
  873. // can't use for than one special line in a row
  874. return false;
  875. }
  876. //
  877. // P_UseLines
  878. // Looks for special ::g->lines in front of the player to activate.
  879. //
  880. void P_UseLines (player_t* player)
  881. {
  882. int angle;
  883. fixed_t x1;
  884. fixed_t y1;
  885. fixed_t x2;
  886. fixed_t y2;
  887. ::g->usething = player->mo;
  888. angle = player->mo->angle >> ANGLETOFINESHIFT;
  889. x1 = player->mo->x;
  890. y1 = player->mo->y;
  891. x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
  892. y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
  893. P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
  894. }
  895. //
  896. // RADIUS ATTACK
  897. //
  898. //
  899. // PIT_RadiusAttack
  900. // "bombsource" is the creature
  901. // that caused the explosion at "bombspot".
  902. //
  903. qboolean PIT_RadiusAttack (mobj_t* thing)
  904. {
  905. fixed_t dx;
  906. fixed_t dy;
  907. fixed_t dist;
  908. if (!(thing->flags & MF_SHOOTABLE) )
  909. return true;
  910. // Boss spider and cyborg
  911. // take no damage from concussion.
  912. if (thing->type == MT_CYBORG
  913. || thing->type == MT_SPIDER)
  914. return true;
  915. dx = abs(thing->x - ::g->bombspot->x);
  916. dy = abs(thing->y - ::g->bombspot->y);
  917. dist = dx>dy ? dx : dy;
  918. dist = (dist - thing->radius) >> FRACBITS;
  919. if (dist < 0)
  920. dist = 0;
  921. if (dist >= ::g->bombdamage)
  922. return true; // out of range
  923. if ( P_CheckSight (thing, ::g->bombspot) )
  924. {
  925. // must be in direct path
  926. P_DamageMobj (thing, ::g->bombspot, ::g->bombsource, ::g->bombdamage - dist);
  927. }
  928. return true;
  929. }
  930. //
  931. // P_RadiusAttack
  932. // Source is the creature that caused the explosion at spot.
  933. //
  934. void
  935. P_RadiusAttack
  936. ( mobj_t* spot,
  937. mobj_t* source,
  938. int damage )
  939. {
  940. int x;
  941. int y;
  942. int xl;
  943. int xh;
  944. int yl;
  945. int yh;
  946. fixed_t dist;
  947. dist = (damage+MAXRADIUS)<<FRACBITS;
  948. yh = (spot->y + dist - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  949. yl = (spot->y - dist - ::g->bmaporgy)>>MAPBLOCKSHIFT;
  950. xh = (spot->x + dist - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  951. xl = (spot->x - dist - ::g->bmaporgx)>>MAPBLOCKSHIFT;
  952. ::g->bombspot = spot;
  953. ::g->bombsource = source;
  954. ::g->bombdamage = damage;
  955. for (y=yl ; y<=yh ; y++)
  956. for (x=xl ; x<=xh ; x++)
  957. P_BlockThingsIterator (x, y, PIT_RadiusAttack );
  958. }
  959. //
  960. // SECTOR HEIGHT CHANGING
  961. // After modifying a ::g->sectors floor or ceiling height,
  962. // call this routine to adjust the positions
  963. // of all things that touch the sector.
  964. //
  965. // If anything doesn't fit anymore, true will be returned.
  966. // If crunch is true, they will take damage
  967. // as they are being crushed.
  968. // If Crunch is false, you should set the sector height back
  969. // the way it was and call P_ChangeSector again
  970. // to undo the changes.
  971. //
  972. //
  973. // PIT_ChangeSector
  974. //
  975. qboolean PIT_ChangeSector (mobj_t* thing)
  976. {
  977. mobj_t* mo;
  978. if (P_ThingHeightClip (thing))
  979. {
  980. // keep checking
  981. return true;
  982. }
  983. // crunch bodies to giblets
  984. if (thing->health <= 0)
  985. {
  986. P_SetMobjState (thing, S_GIBS);
  987. thing->flags &= ~MF_SOLID;
  988. thing->height = 0;
  989. thing->radius = 0;
  990. // keep checking
  991. return true;
  992. }
  993. // crunch dropped items
  994. if (thing->flags & MF_DROPPED)
  995. {
  996. P_RemoveMobj (thing);
  997. // keep checking
  998. return true;
  999. }
  1000. if (! (thing->flags & MF_SHOOTABLE) )
  1001. {
  1002. // assume it is bloody gibs or something
  1003. return true;
  1004. }
  1005. ::g->nofit = true;
  1006. if (::g->crushchange && !(::g->leveltime&3) )
  1007. {
  1008. P_DamageMobj(thing,NULL,NULL,10);
  1009. // spray blood in a random direction
  1010. mo = P_SpawnMobj (thing->x,
  1011. thing->y,
  1012. thing->z + thing->height/2, MT_BLOOD);
  1013. mo->momx = (P_Random() - P_Random ())<<12;
  1014. mo->momy = (P_Random() - P_Random ())<<12;
  1015. }
  1016. // keep checking (crush other things)
  1017. return true;
  1018. }
  1019. //
  1020. // P_ChangeSector
  1021. //
  1022. qboolean
  1023. P_ChangeSector
  1024. ( sector_t* sector,
  1025. qboolean crunch )
  1026. {
  1027. int x;
  1028. int y;
  1029. ::g->nofit = false;
  1030. ::g->crushchange = crunch;
  1031. // re-check heights for all things near the moving sector
  1032. for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
  1033. for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
  1034. P_BlockThingsIterator (x, y, PIT_ChangeSector);
  1035. return ::g->nofit;
  1036. }