p_map.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2004 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Movement, collision handling.
  31. * Shooting and aiming.
  32. *
  33. *-----------------------------------------------------------------------------*/
  34. #include "doomstat.h"
  35. #include "r_main.h"
  36. #include "p_mobj.h"
  37. #include "p_maputl.h"
  38. #include "p_map.h"
  39. #include "p_setup.h"
  40. #include "p_spec.h"
  41. #include "s_sound.h"
  42. #include "sounds.h"
  43. #include "p_inter.h"
  44. #include "m_random.h"
  45. #include "m_bbox.h"
  46. #include "lprintf.h"
  47. static mobj_t *tmthing;
  48. static fixed_t tmx;
  49. static fixed_t tmy;
  50. static int pe_x; // Pain Elemental position for Lost Soul checks // phares
  51. static int pe_y; // Pain Elemental position for Lost Soul checks // phares
  52. static int ls_x; // Lost Soul position for Lost Soul checks // phares
  53. static int ls_y; // Lost Soul position for Lost Soul checks // phares
  54. // If "floatok" true, move would be ok
  55. // if within "tmfloorz - tmceilingz".
  56. boolean floatok;
  57. /* killough 11/98: if "felldown" true, object was pushed down ledge */
  58. boolean felldown;
  59. // The tm* items are used to hold information globally, usually for
  60. // line or object intersection checking
  61. fixed_t tmbbox[4]; // bounding box for line intersection checks
  62. fixed_t tmfloorz; // floor you'd hit if free to fall
  63. fixed_t tmceilingz; // ceiling of sector you're in
  64. fixed_t tmdropoffz; // dropoff on other side of line you're crossing
  65. // keep track of the line that lowers the ceiling,
  66. // so missiles don't explode against sky hack walls
  67. line_t *ceilingline;
  68. line_t *blockline; /* killough 8/11/98: blocking linedef */
  69. line_t *floorline; /* killough 8/1/98: Highest touched floor */
  70. static int tmunstuck; /* killough 8/1/98: whether to allow unsticking */
  71. // keep track of special lines as they are hit,
  72. // but don't process them until the move is proven valid
  73. // 1/11/98 killough: removed limit on special lines crossed
  74. line_t **spechit; // new code -- killough
  75. static int spechit_max; // killough
  76. int numspechit;
  77. // Temporary holder for thing_sectorlist threads
  78. msecnode_t* sector_list = NULL; // phares 3/16/98
  79. //
  80. // TELEPORT MOVE
  81. //
  82. //
  83. // PIT_StompThing
  84. //
  85. static boolean telefrag; /* killough 8/9/98: whether to telefrag at exit */
  86. boolean PIT_StompThing (mobj_t* thing)
  87. {
  88. fixed_t blockdist;
  89. // phares 9/10/98: moved this self-check to start of routine
  90. // don't clip against self
  91. if (thing == tmthing)
  92. return true;
  93. if (!(thing->flags & MF_SHOOTABLE)) // Can't shoot it? Can't stomp it!
  94. return true;
  95. blockdist = thing->radius + tmthing->radius;
  96. if (D_abs(thing->x - tmx) >= blockdist || D_abs(thing->y - tmy) >= blockdist)
  97. return true; // didn't hit it
  98. // monsters don't stomp things except on boss level
  99. if (!telefrag) // killough 8/9/98: make consistent across all levels
  100. return false;
  101. P_DamageMobj (thing, tmthing, tmthing, 10000); // Stomp!
  102. return true;
  103. }
  104. /*
  105. * killough 8/28/98:
  106. *
  107. * P_GetFriction()
  108. *
  109. * Returns the friction associated with a particular mobj.
  110. */
  111. int P_GetFriction(const mobj_t *mo, int *frictionfactor)
  112. {
  113. int friction = ORIG_FRICTION;
  114. int movefactor = ORIG_FRICTION_FACTOR;
  115. const msecnode_t *m;
  116. const sector_t *sec;
  117. /* Assign the friction value to objects on the floor, non-floating,
  118. * and clipped. Normally the object's friction value is kept at
  119. * ORIG_FRICTION and this thinker changes it for icy or muddy floors.
  120. *
  121. * When the object is straddling sectors with the same
  122. * floorheight that have different frictions, use the lowest
  123. * friction value (muddy has precedence over icy).
  124. */
  125. if (!(mo->flags & (MF_NOCLIP|MF_NOGRAVITY))
  126. && (mbf_features || (mo->player && !compatibility)) &&
  127. variable_friction)
  128. for (m = mo->touching_sectorlist; m; m = m->m_tnext)
  129. if ((sec = m->m_sector)->special & FRICTION_MASK &&
  130. (sec->friction < friction || friction == ORIG_FRICTION) &&
  131. (mo->z <= sec->floorheight ||
  132. (sec->heightsec != -1 &&
  133. mo->z <= sectors[sec->heightsec].floorheight &&
  134. mbf_features)))
  135. friction = sec->friction, movefactor = sec->movefactor;
  136. if (frictionfactor)
  137. *frictionfactor = movefactor;
  138. return friction;
  139. }
  140. /* phares 3/19/98
  141. * P_GetMoveFactor() returns the value by which the x,y
  142. * movements are multiplied to add to player movement.
  143. *
  144. * killough 8/28/98: rewritten
  145. */
  146. int P_GetMoveFactor(const mobj_t *mo, int *frictionp)
  147. {
  148. int movefactor, friction;
  149. //e6y
  150. if (!mbf_features)
  151. {
  152. int momentum;
  153. movefactor = ORIG_FRICTION_FACTOR;
  154. if (!compatibility && variable_friction &&
  155. !(mo->flags & (MF_NOGRAVITY | MF_NOCLIP)))
  156. {
  157. friction = mo->friction;
  158. if (friction == ORIG_FRICTION) // normal floor
  159. ;
  160. else if (friction > ORIG_FRICTION) // ice
  161. {
  162. movefactor = mo->movefactor;
  163. ((mobj_t*)mo)->movefactor = ORIG_FRICTION_FACTOR; // reset
  164. }
  165. else // sludge
  166. {
  167. // phares 3/11/98: you start off slowly, then increase as
  168. // you get better footing
  169. momentum = (P_AproxDistance(mo->momx,mo->momy));
  170. movefactor = mo->movefactor;
  171. if (momentum > MORE_FRICTION_MOMENTUM<<2)
  172. movefactor <<= 3;
  173. else if (momentum > MORE_FRICTION_MOMENTUM<<1)
  174. movefactor <<= 2;
  175. else if (momentum > MORE_FRICTION_MOMENTUM)
  176. movefactor <<= 1;
  177. ((mobj_t*)mo)->movefactor = ORIG_FRICTION_FACTOR; // reset
  178. }
  179. } // ^
  180. return(movefactor); // |
  181. }
  182. // If the floor is icy or muddy, it's harder to get moving. This is where
  183. // the different friction factors are applied to 'trying to move'. In
  184. // p_mobj.c, the friction factors are applied as you coast and slow down.
  185. if ((friction = P_GetFriction(mo, &movefactor)) < ORIG_FRICTION)
  186. {
  187. // phares 3/11/98: you start off slowly, then increase as
  188. // you get better footing
  189. int momentum = P_AproxDistance(mo->momx,mo->momy);
  190. if (momentum > MORE_FRICTION_MOMENTUM<<2)
  191. movefactor <<= 3;
  192. else if (momentum > MORE_FRICTION_MOMENTUM<<1)
  193. movefactor <<= 2;
  194. else if (momentum > MORE_FRICTION_MOMENTUM)
  195. movefactor <<= 1;
  196. }
  197. if (frictionp)
  198. *frictionp = friction;
  199. return movefactor;
  200. }
  201. //
  202. // P_TeleportMove
  203. //
  204. boolean P_TeleportMove (mobj_t* thing,fixed_t x,fixed_t y, boolean boss)
  205. {
  206. int xl;
  207. int xh;
  208. int yl;
  209. int yh;
  210. int bx;
  211. int by;
  212. subsector_t* newsubsec;
  213. /* killough 8/9/98: make telefragging more consistent, preserve compatibility */
  214. telefrag = thing->player ||
  215. (!comp[comp_telefrag] ? boss : (gamemap==30));
  216. // kill anything occupying the position
  217. tmthing = thing;
  218. tmx = x;
  219. tmy = y;
  220. tmbbox[BOXTOP] = y + tmthing->radius;
  221. tmbbox[BOXBOTTOM] = y - tmthing->radius;
  222. tmbbox[BOXRIGHT] = x + tmthing->radius;
  223. tmbbox[BOXLEFT] = x - tmthing->radius;
  224. newsubsec = R_PointInSubsector (x,y);
  225. ceilingline = NULL;
  226. // The base floor/ceiling is from the subsector
  227. // that contains the point.
  228. // Any contacted lines the step closer together
  229. // will adjust them.
  230. tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
  231. tmceilingz = newsubsec->sector->ceilingheight;
  232. validcount++;
  233. numspechit = 0;
  234. // stomp on any things contacted
  235. xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
  236. xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
  237. yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
  238. yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
  239. for (bx=xl ; bx<=xh ; bx++)
  240. for (by=yl ; by<=yh ; by++)
  241. if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
  242. return false;
  243. // the move is ok,
  244. // so unlink from the old position & link into the new position
  245. P_UnsetThingPosition (thing);
  246. thing->floorz = tmfloorz;
  247. thing->ceilingz = tmceilingz;
  248. thing->dropoffz = tmdropoffz; // killough 11/98
  249. thing->x = x;
  250. thing->y = y;
  251. P_SetThingPosition (thing);
  252. thing->PrevX = x;
  253. thing->PrevY = y;
  254. thing->PrevZ = thing->floorz;
  255. return true;
  256. }
  257. //
  258. // MOVEMENT ITERATOR FUNCTIONS
  259. //
  260. // e6y: Spechits overrun emulation code
  261. static void SpechitOverrun(line_t *ld);
  262. // // phares
  263. // PIT_CrossLine // |
  264. // Checks to see if a PE->LS trajectory line crosses a blocking // V
  265. // line. Returns false if it does.
  266. //
  267. // tmbbox holds the bounding box of the trajectory. If that box
  268. // does not touch the bounding box of the line in question,
  269. // then the trajectory is not blocked. If the PE is on one side
  270. // of the line and the LS is on the other side, then the
  271. // trajectory is blocked.
  272. //
  273. // Currently this assumes an infinite line, which is not quite
  274. // correct. A more correct solution would be to check for an
  275. // intersection of the trajectory and the line, but that takes
  276. // longer and probably really isn't worth the effort.
  277. //
  278. static // killough 3/26/98: make static
  279. boolean PIT_CrossLine (line_t* ld)
  280. {
  281. if (!(ld->flags & ML_TWOSIDED) ||
  282. (ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS)))
  283. if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] ||
  284. tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] ||
  285. tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] ||
  286. tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))
  287. if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))
  288. return(false); // line blocks trajectory // ^
  289. return(true); // line doesn't block trajectory // |
  290. } // phares
  291. /* killough 8/1/98: used to test intersection between thing and line
  292. * assuming NO movement occurs -- used to avoid sticky situations.
  293. */
  294. static int untouched(line_t *ld)
  295. {
  296. fixed_t x, y, thetmbbox[4];
  297. return
  298. (thetmbbox[BOXRIGHT] = (x=tmthing->x)+tmthing->radius) <= ld->bbox[BOXLEFT] ||
  299. (thetmbbox[BOXLEFT] = x-tmthing->radius) >= ld->bbox[BOXRIGHT] ||
  300. (thetmbbox[BOXTOP] = (y=tmthing->y)+tmthing->radius) <= ld->bbox[BOXBOTTOM] ||
  301. (thetmbbox[BOXBOTTOM] = y-tmthing->radius) >= ld->bbox[BOXTOP] ||
  302. P_BoxOnLineSide(tmbbox, ld) != -1;
  303. }
  304. //
  305. // PIT_CheckLine
  306. // Adjusts tmfloorz and tmceilingz as lines are contacted
  307. //
  308. static // killough 3/26/98: make static
  309. boolean PIT_CheckLine (line_t* ld)
  310. {
  311. if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
  312. || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
  313. || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
  314. || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
  315. return true; // didn't hit it
  316. if (P_BoxOnLineSide(tmbbox, ld) != -1)
  317. return true; // didn't hit it
  318. // A line has been hit
  319. // The moving thing's destination position will cross the given line.
  320. // If this should not be allowed, return false.
  321. // If the line is special, keep track of it
  322. // to process later if the move is proven ok.
  323. // NOTE: specials are NOT sorted by order,
  324. // so two special lines that are only 8 pixels apart
  325. // could be crossed in either order.
  326. // killough 7/24/98: allow player to move out of 1s wall, to prevent sticking
  327. if (!ld->backsector) // one sided line
  328. {
  329. blockline = ld;
  330. return tmunstuck && !untouched(ld) &&
  331. FixedMul(tmx-tmthing->x,ld->dy) > FixedMul(tmy-tmthing->y,ld->dx);
  332. }
  333. // killough 8/10/98: allow bouncing objects to pass through as missiles
  334. if (!(tmthing->flags & (MF_MISSILE | MF_BOUNCES)))
  335. {
  336. if (ld->flags & ML_BLOCKING) // explicitly blocking everything
  337. return tmunstuck && !untouched(ld); // killough 8/1/98: allow escape
  338. // killough 8/9/98: monster-blockers don't affect friends
  339. if (!(tmthing->flags & MF_FRIEND || tmthing->player)
  340. && ld->flags & ML_BLOCKMONSTERS)
  341. return false; // block monsters only
  342. }
  343. // set openrange, opentop, openbottom
  344. // these define a 'window' from one sector to another across this line
  345. P_LineOpening (ld);
  346. // adjust floor & ceiling heights
  347. if (opentop < tmceilingz)
  348. {
  349. tmceilingz = opentop;
  350. ceilingline = ld;
  351. blockline = ld;
  352. }
  353. if (openbottom > tmfloorz)
  354. {
  355. tmfloorz = openbottom;
  356. floorline = ld; // killough 8/1/98: remember floor linedef
  357. blockline = ld;
  358. }
  359. if (lowfloor < tmdropoffz)
  360. tmdropoffz = lowfloor;
  361. // if contacted a special line, add it to the list
  362. if (ld->special)
  363. {
  364. // 1/11/98 killough: remove limit on lines hit, by array doubling
  365. if (numspechit >= spechit_max) {
  366. spechit_max = spechit_max ? spechit_max*2 : 8;
  367. spechit = realloc(spechit,sizeof *spechit*spechit_max); // killough
  368. }
  369. spechit[numspechit++] = ld;
  370. // e6y: Spechits overrun emulation code
  371. if (numspechit >= 8 && demo_compatibility)
  372. SpechitOverrun(ld);
  373. }
  374. return true;
  375. }
  376. //
  377. // PIT_CheckThing
  378. //
  379. static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static
  380. {
  381. fixed_t blockdist;
  382. int damage;
  383. // killough 11/98: add touchy things
  384. if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE|MF_TOUCHY)))
  385. return true;
  386. blockdist = thing->radius + tmthing->radius;
  387. if (D_abs(thing->x - tmx) >= blockdist || D_abs(thing->y - tmy) >= blockdist)
  388. return true; // didn't hit it
  389. // killough 11/98:
  390. //
  391. // This test has less information content (it's almost always false), so it
  392. // should not be moved up to first, as it adds more overhead than it removes.
  393. // don't clip against self
  394. if (thing == tmthing)
  395. return true;
  396. /* killough 11/98:
  397. *
  398. * TOUCHY flag, for mines or other objects which die on contact with solids.
  399. * If a solid object of a different type comes in contact with a touchy
  400. * thing, and the touchy thing is not the sole one moving relative to fixed
  401. * surroundings such as walls, then the touchy thing dies immediately.
  402. */
  403. if (thing->flags & MF_TOUCHY && // touchy object
  404. tmthing->flags & MF_SOLID && // solid object touches it
  405. thing->health > 0 && // touchy object is alive
  406. (thing->intflags & MIF_ARMED || // Thing is an armed mine
  407. sentient(thing)) && // ... or a sentient thing
  408. (thing->type != tmthing->type || // only different species
  409. thing->type == MT_PLAYER) && // ... or different players
  410. thing->z + thing->height >= tmthing->z && // touches vertically
  411. tmthing->z + tmthing->height >= thing->z &&
  412. (thing->type ^ MT_PAIN) | // PEs and lost souls
  413. (tmthing->type ^ MT_SKULL) && // are considered same
  414. (thing->type ^ MT_SKULL) | // (but Barons & Knights
  415. (tmthing->type ^ MT_PAIN)) // are intentionally not)
  416. {
  417. P_DamageMobj(thing, NULL, NULL, thing->health); // kill object
  418. return true;
  419. }
  420. // check for skulls slamming into things
  421. if (tmthing->flags & MF_SKULLFLY)
  422. {
  423. // A flying skull is smacking something.
  424. // Determine damage amount, and the skull comes to a dead stop.
  425. int skulldamage = ((P_Random(pr_skullfly)%8)+1)*tmthing->info->damage;
  426. P_DamageMobj (thing, tmthing, tmthing, skulldamage);
  427. tmthing->flags &= ~MF_SKULLFLY;
  428. tmthing->momx = tmthing->momy = tmthing->momz = 0;
  429. P_SetMobjState (tmthing, tmthing->info->spawnstate);
  430. return false; // stop moving
  431. }
  432. // missiles can hit other things
  433. // killough 8/10/98: bouncing non-solid things can hit other things too
  434. if (tmthing->flags & MF_MISSILE || (tmthing->flags & MF_BOUNCES &&
  435. !(tmthing->flags & MF_SOLID)))
  436. {
  437. // see if it went over / under
  438. if (tmthing->z > thing->z + thing->height)
  439. return true; // overhead
  440. if (tmthing->z+tmthing->height < thing->z)
  441. return true; // underneath
  442. if (tmthing->target && (tmthing->target->type == thing->type ||
  443. (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
  444. (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT)))
  445. {
  446. if (thing == tmthing->target)
  447. return true; // Don't hit same species as originator.
  448. else
  449. // e6y: Dehacked support - monsters infight
  450. if (thing->type != MT_PLAYER && !monsters_infight) // Explode, but do no damage.
  451. return false; // Let players missile other players.
  452. }
  453. // killough 8/10/98: if moving thing is not a missile, no damage
  454. // is inflicted, and momentum is reduced if object hit is solid.
  455. if (!(tmthing->flags & MF_MISSILE)) {
  456. if (!(thing->flags & MF_SOLID)) {
  457. return true;
  458. } else {
  459. tmthing->momx = -tmthing->momx;
  460. tmthing->momy = -tmthing->momy;
  461. if (!(tmthing->flags & MF_NOGRAVITY))
  462. {
  463. tmthing->momx >>= 2;
  464. tmthing->momy >>= 2;
  465. }
  466. return false;
  467. }
  468. }
  469. if (!(thing->flags & MF_SHOOTABLE))
  470. return !(thing->flags & MF_SOLID); // didn't do any damage
  471. // damage / explode
  472. damage = ((P_Random(pr_damage)%8)+1)*tmthing->info->damage;
  473. P_DamageMobj (thing, tmthing, tmthing->target, damage);
  474. // don't traverse any more
  475. return false;
  476. }
  477. // check for special pickup
  478. if (thing->flags & MF_SPECIAL)
  479. {
  480. uint_64_t solid = thing->flags & MF_SOLID;
  481. if (tmthing->flags & MF_PICKUP)
  482. P_TouchSpecialThing(thing, tmthing); // can remove thing
  483. return !solid;
  484. }
  485. // killough 3/16/98: Allow non-solid moving objects to move through solid
  486. // ones, by allowing the moving thing (tmthing) to move if it's non-solid,
  487. // despite another solid thing being in the way.
  488. // killough 4/11/98: Treat no-clipping things as not blocking
  489. // ...but not in demo_compatibility mode
  490. return !(thing->flags & MF_SOLID)
  491. || (!demo_compatibility
  492. && (thing->flags & MF_NOCLIP || !(tmthing->flags & MF_SOLID)));
  493. // return !(thing->flags & MF_SOLID); // old code -- killough
  494. }
  495. // This routine checks for Lost Souls trying to be spawned // phares
  496. // across 1-sided lines, impassible lines, or "monsters can't // |
  497. // cross" lines. Draw an imaginary line between the PE // V
  498. // and the new Lost Soul spawn spot. If that line crosses
  499. // a 'blocking' line, then disallow the spawn. Only search
  500. // lines in the blocks of the blockmap where the bounding box
  501. // of the trajectory line resides. Then check bounding box
  502. // of the trajectory vs. the bounding box of each blocking
  503. // line to see if the trajectory and the blocking line cross.
  504. // Then check the PE and LS to see if they're on different
  505. // sides of the blocking line. If so, return true, otherwise
  506. // false.
  507. boolean Check_Sides(mobj_t* actor, int x, int y)
  508. {
  509. int bx,by,xl,xh,yl,yh;
  510. pe_x = actor->x;
  511. pe_y = actor->y;
  512. ls_x = x;
  513. ls_y = y;
  514. // Here is the bounding box of the trajectory
  515. tmbbox[BOXLEFT] = pe_x < x ? pe_x : x;
  516. tmbbox[BOXRIGHT] = pe_x > x ? pe_x : x;
  517. tmbbox[BOXTOP] = pe_y > y ? pe_y : y;
  518. tmbbox[BOXBOTTOM] = pe_y < y ? pe_y : y;
  519. // Determine which blocks to look in for blocking lines
  520. xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
  521. xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
  522. yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
  523. yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
  524. // xl->xh, yl->yh determine the mapblock set to search
  525. validcount++; // prevents checking same line twice
  526. for (bx = xl ; bx <= xh ; bx++)
  527. for (by = yl ; by <= yh ; by++)
  528. if (!P_BlockLinesIterator(bx,by,PIT_CrossLine))
  529. return true; // ^
  530. return(false); // |
  531. } // phares
  532. //
  533. // MOVEMENT CLIPPING
  534. //
  535. //
  536. // P_CheckPosition
  537. // This is purely informative, nothing is modified
  538. // (except things picked up).
  539. //
  540. // in:
  541. // a mobj_t (can be valid or invalid)
  542. // a position to be checked
  543. // (doesn't need to be related to the mobj_t->x,y)
  544. //
  545. // during:
  546. // special things are touched if MF_PICKUP
  547. // early out on solid lines?
  548. //
  549. // out:
  550. // newsubsec
  551. // floorz
  552. // ceilingz
  553. // tmdropoffz
  554. // the lowest point contacted
  555. // (monsters won't move to a dropoff)
  556. // speciallines[]
  557. // numspeciallines
  558. //
  559. boolean P_CheckPosition (mobj_t* thing,fixed_t x,fixed_t y)
  560. {
  561. int xl;
  562. int xh;
  563. int yl;
  564. int yh;
  565. int bx;
  566. int by;
  567. subsector_t* newsubsec;
  568. tmthing = thing;
  569. tmx = x;
  570. tmy = y;
  571. tmbbox[BOXTOP] = y + tmthing->radius;
  572. tmbbox[BOXBOTTOM] = y - tmthing->radius;
  573. tmbbox[BOXRIGHT] = x + tmthing->radius;
  574. tmbbox[BOXLEFT] = x - tmthing->radius;
  575. newsubsec = R_PointInSubsector (x,y);
  576. floorline = blockline = ceilingline = NULL; // killough 8/1/98
  577. // Whether object can get out of a sticky situation:
  578. tmunstuck = thing->player && /* only players */
  579. thing->player->mo == thing && /* not voodoo dolls */
  580. mbf_features; /* not under old demos */
  581. // The base floor / ceiling is from the subsector
  582. // that contains the point.
  583. // Any contacted lines the step closer together
  584. // will adjust them.
  585. tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
  586. tmceilingz = newsubsec->sector->ceilingheight;
  587. validcount++;
  588. numspechit = 0;
  589. if ( tmthing->flags & MF_NOCLIP )
  590. return true;
  591. // Check things first, possibly picking things up.
  592. // The bounding box is extended by MAXRADIUS
  593. // because mobj_ts are grouped into mapblocks
  594. // based on their origin point, and can overlap
  595. // into adjacent blocks by up to MAXRADIUS units.
  596. xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
  597. xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
  598. yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
  599. yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
  600. for (bx=xl ; bx<=xh ; bx++)
  601. for (by=yl ; by<=yh ; by++)
  602. if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
  603. return false;
  604. // check lines
  605. xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
  606. xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
  607. yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
  608. yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
  609. for (bx=xl ; bx<=xh ; bx++)
  610. for (by=yl ; by<=yh ; by++)
  611. if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
  612. return false; // doesn't fit
  613. return true;
  614. }
  615. //
  616. // P_TryMove
  617. // Attempt to move to a new position,
  618. // crossing special lines unless MF_TELEPORT is set.
  619. //
  620. boolean P_TryMove(mobj_t* thing,fixed_t x,fixed_t y,
  621. boolean dropoff) // killough 3/15/98: allow dropoff as option
  622. {
  623. fixed_t oldx;
  624. fixed_t oldy;
  625. felldown = floatok = false; // killough 11/98
  626. if (!P_CheckPosition (thing, x, y))
  627. return false; // solid wall or thing
  628. if ( !(thing->flags & MF_NOCLIP) )
  629. {
  630. // killough 7/26/98: reformatted slightly
  631. // killough 8/1/98: Possibly allow escape if otherwise stuck
  632. if (tmceilingz - tmfloorz < thing->height || // doesn't fit
  633. // mobj must lower to fit
  634. (floatok = true, !(thing->flags & MF_TELEPORT) &&
  635. tmceilingz - thing->z < thing->height) ||
  636. // too big a step up
  637. (!(thing->flags & MF_TELEPORT) &&
  638. tmfloorz - thing->z > 24*FRACUNIT))
  639. return tmunstuck
  640. && !(ceilingline && untouched(ceilingline))
  641. && !( floorline && untouched( floorline));
  642. /* killough 3/15/98: Allow certain objects to drop off
  643. * killough 7/24/98, 8/1/98:
  644. * Prevent monsters from getting stuck hanging off ledges
  645. * killough 10/98: Allow dropoffs in controlled circumstances
  646. * killough 11/98: Improve symmetry of clipping on stairs
  647. */
  648. if (!(thing->flags & (MF_DROPOFF|MF_FLOAT))) {
  649. if (comp[comp_dropoff])
  650. {
  651. if ((compatibility || !dropoff
  652. // fix demosync bug in mbf compatibility mode
  653. || (mbf_features && compatibility_level <= prboom_2_compatibility))
  654. && (tmfloorz - tmdropoffz > 24*FRACUNIT))
  655. return false; // don't stand over a dropoff
  656. }
  657. else
  658. if (!dropoff || (dropoff==2 && // large jump down (e.g. dogs)
  659. (tmfloorz-tmdropoffz > 128*FRACUNIT ||
  660. !thing->target || thing->target->z >tmdropoffz)))
  661. {
  662. if (!monkeys || !mbf_features ?
  663. tmfloorz - tmdropoffz > 24*FRACUNIT :
  664. thing->floorz - tmfloorz > 24*FRACUNIT ||
  665. thing->dropoffz - tmdropoffz > 24*FRACUNIT)
  666. return false;
  667. }
  668. else { /* dropoff allowed -- check for whether it fell more than 24 */
  669. felldown = !(thing->flags & MF_NOGRAVITY) &&
  670. thing->z - tmfloorz > 24*FRACUNIT;
  671. }
  672. }
  673. if (thing->flags & MF_BOUNCES && // killough 8/13/98
  674. !(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) &&
  675. !sentient(thing) && tmfloorz - thing->z > 16*FRACUNIT)
  676. return false; // too big a step up for bouncers under gravity
  677. // killough 11/98: prevent falling objects from going up too many steps
  678. if (thing->intflags & MIF_FALLING && tmfloorz - thing->z >
  679. FixedMul(thing->momx,thing->momx)+FixedMul(thing->momy,thing->momy))
  680. return false;
  681. }
  682. // the move is ok,
  683. // so unlink from the old position and link into the new position
  684. P_UnsetThingPosition (thing);
  685. oldx = thing->x;
  686. oldy = thing->y;
  687. thing->floorz = tmfloorz;
  688. thing->ceilingz = tmceilingz;
  689. thing->dropoffz = tmdropoffz; // killough 11/98: keep track of dropoffs
  690. thing->x = x;
  691. thing->y = y;
  692. P_SetThingPosition (thing);
  693. // if any special lines were hit, do the effect
  694. if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )
  695. while (numspechit--)
  696. if (spechit[numspechit]->special) // see if the line was crossed
  697. {
  698. int oldside;
  699. if ((oldside = P_PointOnLineSide(oldx, oldy, spechit[numspechit])) !=
  700. P_PointOnLineSide(thing->x, thing->y, spechit[numspechit]))
  701. P_CrossSpecialLine(spechit[numspechit], oldside, thing);
  702. }
  703. return true;
  704. }
  705. /*
  706. * killough 9/12/98:
  707. *
  708. * Apply "torque" to objects hanging off of ledges, so that they
  709. * fall off. It's not really torque, since Doom has no concept of
  710. * rotation, but it's a convincing effect which avoids anomalies
  711. * such as lifeless objects hanging more than halfway off of ledges,
  712. * and allows objects to roll off of the edges of moving lifts, or
  713. * to slide up and then back down stairs, or to fall into a ditch.
  714. * If more than one linedef is contacted, the effects are cumulative,
  715. * so balancing is possible.
  716. */
  717. static boolean PIT_ApplyTorque(line_t *ld)
  718. {
  719. if (ld->backsector && // If thing touches two-sided pivot linedef
  720. tmbbox[BOXRIGHT] > ld->bbox[BOXLEFT] &&
  721. tmbbox[BOXLEFT] < ld->bbox[BOXRIGHT] &&
  722. tmbbox[BOXTOP] > ld->bbox[BOXBOTTOM] &&
  723. tmbbox[BOXBOTTOM] < ld->bbox[BOXTOP] &&
  724. P_BoxOnLineSide(tmbbox, ld) == -1)
  725. {
  726. mobj_t *mo = tmthing;
  727. fixed_t dist = // lever arm
  728. + (ld->dx >> FRACBITS) * (mo->y >> FRACBITS)
  729. - (ld->dy >> FRACBITS) * (mo->x >> FRACBITS)
  730. - (ld->dx >> FRACBITS) * (ld->v1->y >> FRACBITS)
  731. + (ld->dy >> FRACBITS) * (ld->v1->x >> FRACBITS);
  732. if (dist < 0 ? // dropoff direction
  733. ld->frontsector->floorheight < mo->z &&
  734. ld->backsector->floorheight >= mo->z :
  735. ld->backsector->floorheight < mo->z &&
  736. ld->frontsector->floorheight >= mo->z)
  737. {
  738. /* At this point, we know that the object straddles a two-sided
  739. * linedef, and that the object's center of mass is above-ground.
  740. */
  741. fixed_t x = D_abs(ld->dx), y = D_abs(ld->dy);
  742. if (y > x)
  743. {
  744. fixed_t t = x;
  745. x = y;
  746. y = t;
  747. }
  748. y = finesine[(tantoangle[FixedDiv(y,x)>>DBITS] +
  749. ANG90) >> ANGLETOFINESHIFT];
  750. /* Momentum is proportional to distance between the
  751. * object's center of mass and the pivot linedef.
  752. *
  753. * It is scaled by 2^(OVERDRIVE - gear). When gear is
  754. * increased, the momentum gradually decreases to 0 for
  755. * the same amount of pseudotorque, so that oscillations
  756. * are prevented, yet it has a chance to reach equilibrium.
  757. */
  758. dist = FixedDiv(FixedMul(dist, (mo->gear < OVERDRIVE) ?
  759. y << -(mo->gear - OVERDRIVE) :
  760. y >> +(mo->gear - OVERDRIVE)), x);
  761. /* Apply momentum away from the pivot linedef. */
  762. x = FixedMul(ld->dy, dist);
  763. y = FixedMul(ld->dx, dist);
  764. /* Avoid moving too fast all of a sudden (step into "overdrive") */
  765. dist = FixedMul(x,x) + FixedMul(y,y);
  766. while (dist > FRACUNIT*4 && mo->gear < MAXGEAR)
  767. ++mo->gear, x >>= 1, y >>= 1, dist >>= 1;
  768. mo->momx -= x;
  769. mo->momy += y;
  770. }
  771. }
  772. return true;
  773. }
  774. /*
  775. * killough 9/12/98
  776. *
  777. * Applies "torque" to objects, based on all contacted linedefs
  778. */
  779. void P_ApplyTorque(mobj_t *mo)
  780. {
  781. int xl = ((tmbbox[BOXLEFT] =
  782. mo->x - mo->radius) - bmaporgx) >> MAPBLOCKSHIFT;
  783. int xh = ((tmbbox[BOXRIGHT] =
  784. mo->x + mo->radius) - bmaporgx) >> MAPBLOCKSHIFT;
  785. int yl = ((tmbbox[BOXBOTTOM] =
  786. mo->y - mo->radius) - bmaporgy) >> MAPBLOCKSHIFT;
  787. int yh = ((tmbbox[BOXTOP] =
  788. mo->y + mo->radius) - bmaporgy) >> MAPBLOCKSHIFT;
  789. int bx,by,flags = mo->intflags; //Remember the current state, for gear-change
  790. tmthing = mo;
  791. validcount++; /* prevents checking same line twice */
  792. for (bx = xl ; bx <= xh ; bx++)
  793. for (by = yl ; by <= yh ; by++)
  794. P_BlockLinesIterator(bx, by, PIT_ApplyTorque);
  795. /* If any momentum, mark object as 'falling' using engine-internal flags */
  796. if (mo->momx | mo->momy)
  797. mo->intflags |= MIF_FALLING;
  798. else // Clear the engine-internal flag indicating falling object.
  799. mo->intflags &= ~MIF_FALLING;
  800. /* If the object has been moving, step up the gear.
  801. * This helps reach equilibrium and avoid oscillations.
  802. *
  803. * Doom has no concept of potential energy, much less
  804. * of rotation, so we have to creatively simulate these
  805. * systems somehow :)
  806. */
  807. if (!((mo->intflags | flags) & MIF_FALLING)) // If not falling for a while,
  808. mo->gear = 0; // Reset it to full strength
  809. else
  810. if (mo->gear < MAXGEAR) // Else if not at max gear,
  811. mo->gear++; // move up a gear
  812. }
  813. //
  814. // P_ThingHeightClip
  815. // Takes a valid thing and adjusts the thing->floorz,
  816. // thing->ceilingz, and possibly thing->z.
  817. // This is called for all nearby monsters
  818. // whenever a sector changes height.
  819. // If the thing doesn't fit,
  820. // the z will be set to the lowest value
  821. // and false will be returned.
  822. //
  823. boolean P_ThingHeightClip (mobj_t* thing)
  824. {
  825. boolean onfloor;
  826. onfloor = (thing->z == thing->floorz);
  827. P_CheckPosition (thing, thing->x, thing->y);
  828. /* what about stranding a monster partially off an edge?
  829. * killough 11/98: Answer: see below (upset balance if hanging off ledge)
  830. */
  831. thing->floorz = tmfloorz;
  832. thing->ceilingz = tmceilingz;
  833. thing->dropoffz = tmdropoffz; /* killough 11/98: remember dropoffs */
  834. if (onfloor)
  835. {
  836. // walking monsters rise and fall with the floor
  837. thing->z = thing->floorz;
  838. /* killough 11/98: Possibly upset balance of objects hanging off ledges */
  839. if (thing->intflags & MIF_FALLING && thing->gear >= MAXGEAR)
  840. thing->gear = 0;
  841. }
  842. else
  843. {
  844. // don't adjust a floating monster unless forced to
  845. if (thing->z+thing->height > thing->ceilingz)
  846. thing->z = thing->ceilingz - thing->height;
  847. }
  848. return thing->ceilingz - thing->floorz >= thing->height;
  849. }
  850. //
  851. // SLIDE MOVE
  852. // Allows the player to slide along any angled walls.
  853. //
  854. /* killough 8/2/98: make variables static */
  855. static fixed_t bestslidefrac;
  856. static line_t* bestslideline;
  857. static mobj_t* slidemo;
  858. static fixed_t tmxmove;
  859. static fixed_t tmymove;
  860. //
  861. // P_HitSlideLine
  862. // Adjusts the xmove / ymove
  863. // so that the next move will slide along the wall.
  864. // If the floor is icy, then you can bounce off a wall. // phares
  865. //
  866. void P_HitSlideLine (line_t* ld)
  867. {
  868. int side;
  869. angle_t lineangle;
  870. angle_t moveangle;
  871. angle_t deltaangle;
  872. fixed_t movelen;
  873. fixed_t newlen;
  874. boolean icyfloor; // is floor icy? // phares
  875. // |
  876. // Under icy conditions, if the angle of approach to the wall // V
  877. // is more than 45 degrees, then you'll bounce and lose half
  878. // your momentum. If less than 45 degrees, you'll slide along
  879. // the wall. 45 is arbitrary and is believable.
  880. // Check for the special cases of horz or vert walls.
  881. /* killough 10/98: only bounce if hit hard (prevents wobbling)
  882. * cph - DEMOSYNC - should only affect players in Boom demos? */
  883. //e6y
  884. if (mbf_features)
  885. {
  886. icyfloor =
  887. P_AproxDistance(tmxmove, tmymove) > 4*FRACUNIT &&
  888. variable_friction && // killough 8/28/98: calc friction on demand
  889. slidemo->z <= slidemo->floorz &&
  890. P_GetFriction(slidemo, NULL) > ORIG_FRICTION;
  891. }
  892. else
  893. {
  894. extern boolean onground;
  895. icyfloor = !compatibility &&
  896. variable_friction &&
  897. slidemo->player &&
  898. onground &&
  899. slidemo->friction > ORIG_FRICTION;
  900. }
  901. if (ld->slopetype == ST_HORIZONTAL)
  902. {
  903. if (icyfloor && (D_abs(tmymove) > D_abs(tmxmove)))
  904. {
  905. tmxmove /= 2; // absorb half the momentum
  906. tmymove = -tmymove/2;
  907. S_StartSound(slidemo,sfx_oof); // oooff!
  908. }
  909. else
  910. tmymove = 0; // no more movement in the Y direction
  911. return;
  912. }
  913. if (ld->slopetype == ST_VERTICAL)
  914. {
  915. if (icyfloor && (D_abs(tmxmove) > D_abs(tmymove)))
  916. {
  917. tmxmove = -tmxmove/2; // absorb half the momentum
  918. tmymove /= 2;
  919. S_StartSound(slidemo,sfx_oof); // oooff! // ^
  920. } // |
  921. else // phares
  922. tmxmove = 0; // no more movement in the X direction
  923. return;
  924. }
  925. // The wall is angled. Bounce if the angle of approach is // phares
  926. // less than 45 degrees. // phares
  927. side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);
  928. lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
  929. if (side == 1)
  930. lineangle += ANG180;
  931. moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);
  932. // killough 3/2/98:
  933. // The moveangle+=10 breaks v1.9 demo compatibility in
  934. // some demos, so it needs demo_compatibility switch.
  935. if (!demo_compatibility)
  936. moveangle += 10; // prevents sudden path reversal due to // phares
  937. // rounding error // |
  938. deltaangle = moveangle-lineangle; // V
  939. movelen = P_AproxDistance (tmxmove, tmymove);
  940. if (icyfloor && (deltaangle > ANG45) && (deltaangle < ANG90+ANG45))
  941. {
  942. moveangle = lineangle - deltaangle;
  943. movelen /= 2; // absorb
  944. S_StartSound(slidemo,sfx_oof); // oooff!
  945. moveangle >>= ANGLETOFINESHIFT;
  946. tmxmove = FixedMul (movelen, finecosine[moveangle]);
  947. tmymove = FixedMul (movelen, finesine[moveangle]);
  948. } // ^
  949. else // |
  950. { // phares
  951. if (deltaangle > ANG180)
  952. deltaangle += ANG180;
  953. // I_Error ("SlideLine: ang>ANG180");
  954. lineangle >>= ANGLETOFINESHIFT;
  955. deltaangle >>= ANGLETOFINESHIFT;
  956. newlen = FixedMul (movelen, finecosine[deltaangle]);
  957. tmxmove = FixedMul (newlen, finecosine[lineangle]);
  958. tmymove = FixedMul (newlen, finesine[lineangle]);
  959. } // phares
  960. }
  961. //
  962. // PTR_SlideTraverse
  963. //
  964. boolean PTR_SlideTraverse (intercept_t* in)
  965. {
  966. line_t* li;
  967. if (!in->isaline)
  968. I_Error ("PTR_SlideTraverse: not a line?");
  969. li = in->d.line;
  970. if ( ! (li->flags & ML_TWOSIDED) )
  971. {
  972. if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
  973. return true; // don't hit the back side
  974. goto isblocking;
  975. }
  976. // set openrange, opentop, openbottom.
  977. // These define a 'window' from one sector to another across a line
  978. P_LineOpening (li);
  979. if (openrange < slidemo->height)
  980. goto isblocking; // doesn't fit
  981. if (opentop - slidemo->z < slidemo->height)
  982. goto isblocking; // mobj is too high
  983. if (openbottom - slidemo->z > 24*FRACUNIT )
  984. goto isblocking; // too big a step up
  985. // this line doesn't block movement
  986. return true;
  987. // the line does block movement,
  988. // see if it is closer than best so far
  989. isblocking:
  990. if (in->frac < bestslidefrac)
  991. {
  992. bestslidefrac = in->frac;
  993. bestslideline = li;
  994. }
  995. return false; // stop
  996. }
  997. //
  998. // P_SlideMove
  999. // The momx / momy move is bad, so try to slide
  1000. // along a wall.
  1001. // Find the first line hit, move flush to it,
  1002. // and slide along it
  1003. //
  1004. // This is a kludgy mess.
  1005. //
  1006. // killough 11/98: reformatted
  1007. void P_SlideMove(mobj_t *mo)
  1008. {
  1009. int hitcount = 3;
  1010. slidemo = mo; // the object that's sliding
  1011. do
  1012. {
  1013. fixed_t leadx, leady, trailx, traily;
  1014. if (!--hitcount)
  1015. goto stairstep; // don't loop forever
  1016. // trace along the three leading corners
  1017. if (mo->momx > 0)
  1018. leadx = mo->x + mo->radius, trailx = mo->x - mo->radius;
  1019. else
  1020. leadx = mo->x - mo->radius, trailx = mo->x + mo->radius;
  1021. if (mo->momy > 0)
  1022. leady = mo->y + mo->radius, traily = mo->y - mo->radius;
  1023. else
  1024. leady = mo->y - mo->radius, traily = mo->y + mo->radius;
  1025. bestslidefrac = FRACUNIT+1;
  1026. P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy,
  1027. PT_ADDLINES, PTR_SlideTraverse);
  1028. P_PathTraverse(trailx, leady, trailx+mo->momx, leady+mo->momy,
  1029. PT_ADDLINES, PTR_SlideTraverse);
  1030. P_PathTraverse(leadx, traily, leadx+mo->momx, traily+mo->momy,
  1031. PT_ADDLINES, PTR_SlideTraverse);
  1032. // move up to the wall
  1033. if (bestslidefrac == FRACUNIT+1)
  1034. {
  1035. // the move must have hit the middle, so stairstep
  1036. stairstep:
  1037. /* killough 3/15/98: Allow objects to drop off ledges
  1038. *
  1039. * phares 5/4/98: kill momentum if you can't move at all
  1040. * This eliminates player bobbing if pressed against a wall
  1041. * while on ice.
  1042. *
  1043. * killough 10/98: keep buggy code around for old Boom demos
  1044. *
  1045. * cph 2000/09//23: buggy code was only in Boom v2.01
  1046. */
  1047. if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true))
  1048. if (!P_TryMove(mo, mo->x + mo->momx, mo->y, true))
  1049. if (compatibility_level == boom_201_compatibility)
  1050. mo->momx = mo->momy = 0;
  1051. break;
  1052. }
  1053. // fudge a bit to make sure it doesn't hit
  1054. if ((bestslidefrac -= 0x800) > 0)
  1055. {
  1056. fixed_t newx = FixedMul(mo->momx, bestslidefrac);
  1057. fixed_t newy = FixedMul(mo->momy, bestslidefrac);
  1058. // killough 3/15/98: Allow objects to drop off ledges
  1059. if (!P_TryMove(mo, mo->x+newx, mo->y+newy, true))
  1060. goto stairstep;
  1061. }
  1062. // Now continue along the wall.
  1063. // First calculate remainder.
  1064. bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
  1065. if (bestslidefrac > FRACUNIT)
  1066. bestslidefrac = FRACUNIT;
  1067. if (bestslidefrac <= 0)
  1068. break;
  1069. tmxmove = FixedMul(mo->momx, bestslidefrac);
  1070. tmymove = FixedMul(mo->momy, bestslidefrac);
  1071. P_HitSlideLine(bestslideline); // clip the moves
  1072. mo->momx = tmxmove;
  1073. mo->momy = tmymove;
  1074. /* killough 10/98: affect the bobbing the same way (but not voodoo dolls)
  1075. * cph - DEMOSYNC? */
  1076. if (mo->player && mo->player->mo == mo)
  1077. {
  1078. if (D_abs(mo->player->momx) > D_abs(tmxmove))
  1079. mo->player->momx = tmxmove;
  1080. if (D_abs(mo->player->momy) > D_abs(tmymove))
  1081. mo->player->momy = tmymove;
  1082. }
  1083. } // killough 3/15/98: Allow objects to drop off ledges:
  1084. while (!P_TryMove(mo, mo->x+tmxmove, mo->y+tmymove, true));
  1085. }
  1086. //
  1087. // P_LineAttack
  1088. //
  1089. mobj_t* linetarget; // who got hit (or NULL)
  1090. static mobj_t* shootthing;
  1091. /* killough 8/2/98: for more intelligent autoaiming */
  1092. static uint_64_t aim_flags_mask;
  1093. // Height if not aiming up or down
  1094. fixed_t shootz;
  1095. int la_damage;
  1096. fixed_t attackrange;
  1097. static fixed_t aimslope;
  1098. // slopes to top and bottom of target
  1099. // killough 4/20/98: make static instead of using ones in p_sight.c
  1100. static fixed_t topslope;
  1101. static fixed_t bottomslope;
  1102. //
  1103. // PTR_AimTraverse
  1104. // Sets linetaget and aimslope when a target is aimed at.
  1105. //
  1106. boolean PTR_AimTraverse (intercept_t* in)
  1107. {
  1108. line_t* li;
  1109. mobj_t* th;
  1110. fixed_t slope;
  1111. fixed_t thingtopslope;
  1112. fixed_t thingbottomslope;
  1113. fixed_t dist;
  1114. if (in->isaline)
  1115. {
  1116. li = in->d.line;
  1117. if ( !(li->flags & ML_TWOSIDED) )
  1118. return false; // stop
  1119. // Crosses a two sided line.
  1120. // A two sided line will restrict
  1121. // the possible target ranges.
  1122. P_LineOpening (li);
  1123. if (openbottom >= opentop)
  1124. return false; // stop
  1125. dist = FixedMul (attackrange, in->frac);
  1126. if (li->frontsector->floorheight != li->backsector->floorheight)
  1127. {
  1128. slope = FixedDiv (openbottom - shootz , dist);
  1129. if (slope > bottomslope)
  1130. bottomslope = slope;
  1131. }
  1132. if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
  1133. {
  1134. slope = FixedDiv (opentop - shootz , dist);
  1135. if (slope < topslope)
  1136. topslope = slope;
  1137. }
  1138. if (topslope <= bottomslope)
  1139. return false; // stop
  1140. return true; // shot continues
  1141. }
  1142. // shoot a thing
  1143. th = in->d.thing;
  1144. if (th == shootthing)
  1145. return true; // can't shoot self
  1146. if (!(th->flags&MF_SHOOTABLE))
  1147. return true; // corpse or something
  1148. /* killough 7/19/98, 8/2/98:
  1149. * friends don't aim at friends (except players), at least not first
  1150. */
  1151. if (th->flags & shootthing->flags & aim_flags_mask && !th->player)
  1152. return true;
  1153. // check angles to see if the thing can be aimed at
  1154. dist = FixedMul (attackrange, in->frac);
  1155. thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
  1156. if (thingtopslope < bottomslope)
  1157. return true; // shot over the thing
  1158. thingbottomslope = FixedDiv (th->z - shootz, dist);
  1159. if (thingbottomslope > topslope)
  1160. return true; // shot under the thing
  1161. // this thing can be hit!
  1162. if (thingtopslope > topslope)
  1163. thingtopslope = topslope;
  1164. if (thingbottomslope < bottomslope)
  1165. thingbottomslope = bottomslope;
  1166. aimslope = (thingtopslope+thingbottomslope)/2;
  1167. linetarget = th;
  1168. return false; // don't go any farther
  1169. }
  1170. //
  1171. // PTR_ShootTraverse
  1172. //
  1173. boolean PTR_ShootTraverse (intercept_t* in)
  1174. {
  1175. fixed_t x;
  1176. fixed_t y;
  1177. fixed_t z;
  1178. fixed_t frac;
  1179. mobj_t* th;
  1180. fixed_t slope;
  1181. fixed_t dist;
  1182. fixed_t thingtopslope;
  1183. fixed_t thingbottomslope;
  1184. if (in->isaline)
  1185. {
  1186. line_t *li = in->d.line;
  1187. if (li->special)
  1188. P_ShootSpecialLine (shootthing, li);
  1189. if (li->flags & ML_TWOSIDED)
  1190. { // crosses a two sided (really 2s) line
  1191. P_LineOpening (li);
  1192. dist = FixedMul(attackrange, in->frac);
  1193. // killough 11/98: simplify
  1194. if ((li->frontsector->floorheight==li->backsector->floorheight ||
  1195. (slope = FixedDiv(openbottom - shootz , dist)) <= aimslope) &&
  1196. (li->frontsector->ceilingheight==li->backsector->ceilingheight ||
  1197. (slope = FixedDiv (opentop - shootz , dist)) >= aimslope))
  1198. return true; // shot continues
  1199. }
  1200. // hit line
  1201. // position a bit closer
  1202. frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
  1203. x = trace.x + FixedMul (trace.dx, frac);
  1204. y = trace.y + FixedMul (trace.dy, frac);
  1205. z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
  1206. if (li->frontsector->ceilingpic == skyflatnum)
  1207. {
  1208. // don't shoot the sky!
  1209. if (z > li->frontsector->ceilingheight)
  1210. return false;
  1211. // it's a sky hack wall
  1212. if (li->backsector && li->backsector->ceilingpic == skyflatnum)
  1213. // fix bullet-eaters -- killough:
  1214. // WARNING: Almost all demos will lose sync without this
  1215. // demo_compatibility flag check!!! killough 1/18/98
  1216. if (demo_compatibility || li->backsector->ceilingheight < z)
  1217. return false;
  1218. }
  1219. // Spawn bullet puffs.
  1220. P_SpawnPuff (x,y,z);
  1221. // don't go any farther
  1222. return false;
  1223. }
  1224. // shoot a thing
  1225. th = in->d.thing;
  1226. if (th == shootthing)
  1227. return true; // can't shoot self
  1228. if (!(th->flags&MF_SHOOTABLE))
  1229. return true; // corpse or something
  1230. // check angles to see if the thing can be aimed at
  1231. dist = FixedMul (attackrange, in->frac);
  1232. thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
  1233. if (thingtopslope < aimslope)
  1234. return true; // shot over the thing
  1235. thingbottomslope = FixedDiv (th->z - shootz, dist);
  1236. if (thingbottomslope > aimslope)
  1237. return true; // shot under the thing
  1238. // hit thing
  1239. // position a bit closer
  1240. frac = in->frac - FixedDiv (10*FRACUNIT,attackrange);
  1241. x = trace.x + FixedMul (trace.dx, frac);
  1242. y = trace.y + FixedMul (trace.dy, frac);
  1243. z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
  1244. // Spawn bullet puffs or blod spots,
  1245. // depending on target type.
  1246. if (in->d.thing->flags & MF_NOBLOOD)
  1247. P_SpawnPuff (x,y,z);
  1248. else
  1249. P_SpawnBlood (x,y,z, la_damage);
  1250. if (la_damage)
  1251. P_DamageMobj (th, shootthing, shootthing, la_damage);
  1252. // don't go any farther
  1253. return false;
  1254. }
  1255. //
  1256. // P_AimLineAttack
  1257. //
  1258. fixed_t P_AimLineAttack(mobj_t* t1,angle_t angle,fixed_t distance, uint_64_t mask)
  1259. {
  1260. fixed_t x2;
  1261. fixed_t y2;
  1262. angle >>= ANGLETOFINESHIFT;
  1263. shootthing = t1;
  1264. x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
  1265. y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
  1266. shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
  1267. // can't shoot outside view angles
  1268. topslope = 100*FRACUNIT/160;
  1269. bottomslope = -100*FRACUNIT/160;
  1270. attackrange = distance;
  1271. linetarget = NULL;
  1272. /* killough 8/2/98: prevent friends from aiming at friends */
  1273. aim_flags_mask = mask;
  1274. P_PathTraverse(t1->x,t1->y,x2,y2,PT_ADDLINES|PT_ADDTHINGS,PTR_AimTraverse);
  1275. if (linetarget)
  1276. return aimslope;
  1277. return 0;
  1278. }
  1279. //
  1280. // P_LineAttack
  1281. // If damage == 0, it is just a test trace
  1282. // that will leave linetarget set.
  1283. //
  1284. void P_LineAttack
  1285. (mobj_t* t1,
  1286. angle_t angle,
  1287. fixed_t distance,
  1288. fixed_t slope,
  1289. int damage)
  1290. {
  1291. fixed_t x2;
  1292. fixed_t y2;
  1293. angle >>= ANGLETOFINESHIFT;
  1294. shootthing = t1;
  1295. la_damage = damage;
  1296. x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
  1297. y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
  1298. shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
  1299. attackrange = distance;
  1300. aimslope = slope;
  1301. P_PathTraverse(t1->x,t1->y,x2,y2,PT_ADDLINES|PT_ADDTHINGS,PTR_ShootTraverse);
  1302. }
  1303. //
  1304. // USE LINES
  1305. //
  1306. mobj_t* usething;
  1307. boolean PTR_UseTraverse (intercept_t* in)
  1308. {
  1309. int side;
  1310. if (!in->d.line->special)
  1311. {
  1312. P_LineOpening (in->d.line);
  1313. if (openrange <= 0)
  1314. {
  1315. S_StartSound (usething, sfx_noway);
  1316. // can't use through a wall
  1317. return false;
  1318. }
  1319. // not a special line, but keep checking
  1320. return true;
  1321. }
  1322. side = 0;
  1323. if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)
  1324. side = 1;
  1325. // return false; // don't use back side
  1326. P_UseSpecialLine (usething, in->d.line, side);
  1327. //WAS can't use for than one special line in a row
  1328. //jff 3/21/98 NOW multiple use allowed with enabling line flag
  1329. return (!demo_compatibility && (in->d.line->flags&ML_PASSUSE))?
  1330. true : false;
  1331. }
  1332. // Returns false if a "oof" sound should be made because of a blocking
  1333. // linedef. Makes 2s middles which are impassable, as well as 2s uppers
  1334. // and lowers which block the player, cause the sound effect when the
  1335. // player tries to activate them. Specials are excluded, although it is
  1336. // assumed that all special linedefs within reach have been considered
  1337. // and rejected already (see P_UseLines).
  1338. //
  1339. // by Lee Killough
  1340. //
  1341. boolean PTR_NoWayTraverse(intercept_t* in)
  1342. {
  1343. line_t *ld = in->d.line;
  1344. // This linedef
  1345. return ld->special || !( // Ignore specials
  1346. ld->flags & ML_BLOCKING || ( // Always blocking
  1347. P_LineOpening(ld), // Find openings
  1348. openrange <= 0 || // No opening
  1349. openbottom > usething->z+24*FRACUNIT || // Too high it blocks
  1350. opentop < usething->z+usething->height // Too low it blocks
  1351. )
  1352. );
  1353. }
  1354. //
  1355. // P_UseLines
  1356. // Looks for special lines in front of the player to activate.
  1357. //
  1358. void P_UseLines (player_t* player)
  1359. {
  1360. int angle;
  1361. fixed_t x1;
  1362. fixed_t y1;
  1363. fixed_t x2;
  1364. fixed_t y2;
  1365. usething = player->mo;
  1366. angle = player->mo->angle >> ANGLETOFINESHIFT;
  1367. x1 = player->mo->x;
  1368. y1 = player->mo->y;
  1369. x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
  1370. y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
  1371. // old code:
  1372. //
  1373. // P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
  1374. //
  1375. // This added test makes the "oof" sound work on 2s lines -- killough:
  1376. if (P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ))
  1377. if (!comp[comp_sound] && !P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_NoWayTraverse ))
  1378. S_StartSound (usething, sfx_noway);
  1379. }
  1380. //
  1381. // RADIUS ATTACK
  1382. //
  1383. static mobj_t *bombsource, *bombspot;
  1384. static int bombdamage;
  1385. //
  1386. // PIT_RadiusAttack
  1387. // "bombsource" is the creature
  1388. // that caused the explosion at "bombspot".
  1389. //
  1390. boolean PIT_RadiusAttack (mobj_t* thing)
  1391. {
  1392. fixed_t dx;
  1393. fixed_t dy;
  1394. fixed_t dist;
  1395. /* killough 8/20/98: allow bouncers to take damage
  1396. * (missile bouncers are already excluded with MF_NOBLOCKMAP)
  1397. */
  1398. if (!(thing->flags & (MF_SHOOTABLE | MF_BOUNCES)))
  1399. return true;
  1400. // Boss spider and cyborg
  1401. // take no damage from concussion.
  1402. // killough 8/10/98: allow grenades to hurt anyone, unless
  1403. // fired by Cyberdemons, in which case it won't hurt Cybers.
  1404. if (bombspot->flags & MF_BOUNCES ?
  1405. thing->type == MT_CYBORG && bombsource->type == MT_CYBORG :
  1406. thing->type == MT_CYBORG || thing->type == MT_SPIDER)
  1407. return true;
  1408. dx = D_abs(thing->x - bombspot->x);
  1409. dy = D_abs(thing->y - bombspot->y);
  1410. dist = dx>dy ? dx : dy;
  1411. dist = (dist - thing->radius) >> FRACBITS;
  1412. if (dist < 0)
  1413. dist = 0;
  1414. if (dist >= bombdamage)
  1415. return true; // out of range
  1416. if ( P_CheckSight (thing, bombspot) )
  1417. {
  1418. // must be in direct path
  1419. P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
  1420. }
  1421. return true;
  1422. }
  1423. //
  1424. // P_RadiusAttack
  1425. // Source is the creature that caused the explosion at spot.
  1426. //
  1427. void P_RadiusAttack(mobj_t* spot,mobj_t* source,int damage)
  1428. {
  1429. int x;
  1430. int y;
  1431. int xl;
  1432. int xh;
  1433. int yl;
  1434. int yh;
  1435. fixed_t dist;
  1436. dist = (damage+MAXRADIUS)<<FRACBITS;
  1437. yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
  1438. yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
  1439. xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
  1440. xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
  1441. bombspot = spot;
  1442. bombsource = source;
  1443. bombdamage = damage;
  1444. for (y=yl ; y<=yh ; y++)
  1445. for (x=xl ; x<=xh ; x++)
  1446. P_BlockThingsIterator (x, y, PIT_RadiusAttack );
  1447. }
  1448. //
  1449. // SECTOR HEIGHT CHANGING
  1450. // After modifying a sectors floor or ceiling height,
  1451. // call this routine to adjust the positions
  1452. // of all things that touch the sector.
  1453. //
  1454. // If anything doesn't fit anymore, true will be returned.
  1455. // If crunch is true, they will take damage
  1456. // as they are being crushed.
  1457. // If Crunch is false, you should set the sector height back
  1458. // the way it was and call P_ChangeSector again
  1459. // to undo the changes.
  1460. //
  1461. static boolean crushchange, nofit;
  1462. //
  1463. // PIT_ChangeSector
  1464. //
  1465. boolean PIT_ChangeSector (mobj_t* thing)
  1466. {
  1467. mobj_t* mo;
  1468. if (P_ThingHeightClip (thing))
  1469. return true; // keep checking
  1470. // crunch bodies to giblets
  1471. if (thing->health <= 0)
  1472. {
  1473. P_SetMobjState (thing, S_GIBS);
  1474. thing->flags &= ~MF_SOLID;
  1475. thing->height = 0;
  1476. thing->radius = 0;
  1477. return true; // keep checking
  1478. }
  1479. // crunch dropped items
  1480. if (thing->flags & MF_DROPPED)
  1481. {
  1482. P_RemoveMobj (thing);
  1483. // keep checking
  1484. return true;
  1485. }
  1486. /* killough 11/98: kill touchy things immediately */
  1487. if (thing->flags & MF_TOUCHY &&
  1488. (thing->intflags & MIF_ARMED || sentient(thing)))
  1489. {
  1490. P_DamageMobj(thing, NULL, NULL, thing->health); // kill object
  1491. return true; // keep checking
  1492. }
  1493. if (! (thing->flags & MF_SHOOTABLE) )
  1494. {
  1495. // assume it is bloody gibs or something
  1496. return true;
  1497. }
  1498. nofit = true;
  1499. if (crushchange && !(leveltime&3)) {
  1500. int t;
  1501. P_DamageMobj(thing,NULL,NULL,10);
  1502. // spray blood in a random direction
  1503. mo = P_SpawnMobj (thing->x,
  1504. thing->y,
  1505. thing->z + thing->height/2, MT_BLOOD);
  1506. /* killough 8/10/98: remove dependence on order of evaluation */
  1507. t = P_Random(pr_crush);
  1508. mo->momx = (t - P_Random (pr_crush))<<12;
  1509. t = P_Random(pr_crush);
  1510. mo->momy = (t - P_Random (pr_crush))<<12;
  1511. }
  1512. // keep checking (crush other things)
  1513. return true;
  1514. }
  1515. //
  1516. // P_ChangeSector
  1517. //
  1518. boolean P_ChangeSector(sector_t* sector,boolean crunch)
  1519. {
  1520. int x;
  1521. int y;
  1522. nofit = false;
  1523. crushchange = crunch;
  1524. // ARRGGHHH!!!!
  1525. // This is horrendously slow!!!
  1526. // killough 3/14/98
  1527. // re-check heights for all things near the moving sector
  1528. for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
  1529. for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
  1530. P_BlockThingsIterator (x, y, PIT_ChangeSector);
  1531. return nofit;
  1532. }
  1533. //
  1534. // P_CheckSector
  1535. // jff 3/19/98 added to just check monsters on the periphery
  1536. // of a moving sector instead of all in bounding box of the
  1537. // sector. Both more accurate and faster.
  1538. //
  1539. boolean P_CheckSector(sector_t* sector,boolean crunch)
  1540. {
  1541. msecnode_t *n;
  1542. if (comp[comp_floors]) /* use the old routine for old demos though */
  1543. return P_ChangeSector(sector,crunch);
  1544. nofit = false;
  1545. crushchange = crunch;
  1546. // killough 4/4/98: scan list front-to-back until empty or exhausted,
  1547. // restarting from beginning after each thing is processed. Avoids
  1548. // crashes, and is sure to examine all things in the sector, and only
  1549. // the things which are in the sector, until a steady-state is reached.
  1550. // Things can arbitrarily be inserted and removed and it won't mess up.
  1551. //
  1552. // killough 4/7/98: simplified to avoid using complicated counter
  1553. // Mark all things invalid
  1554. for (n=sector->touching_thinglist; n; n=n->m_snext)
  1555. n->visited = false;
  1556. do
  1557. for (n=sector->touching_thinglist; n; n=n->m_snext) // go through list
  1558. if (!n->visited) // unprocessed thing found
  1559. {
  1560. n->visited = true; // mark thing as processed
  1561. if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these
  1562. PIT_ChangeSector(n->m_thing); // process it
  1563. break; // exit and start over
  1564. }
  1565. while (n); // repeat from scratch until all things left are marked valid
  1566. return nofit;
  1567. }
  1568. // CPhipps -
  1569. // Use block memory allocator here
  1570. #include "z_bmalloc.h"
  1571. IMPLEMENT_BLOCK_MEMORY_ALLOC_ZONE(secnodezone, sizeof(msecnode_t), PU_LEVEL, 32, "SecNodes");
  1572. inline static msecnode_t* P_GetSecnode(void)
  1573. {
  1574. return (msecnode_t*)Z_BMalloc(&secnodezone);
  1575. }
  1576. // P_PutSecnode() returns a node to the freelist.
  1577. inline static void P_PutSecnode(msecnode_t* node)
  1578. {
  1579. Z_BFree(&secnodezone, node);
  1580. }
  1581. // phares 3/16/98
  1582. //
  1583. // P_AddSecnode() searches the current list to see if this sector is
  1584. // already there. If not, it adds a sector node at the head of the list of
  1585. // sectors this object appears in. This is called when creating a list of
  1586. // nodes that will get linked in later. Returns a pointer to the new node.
  1587. msecnode_t* P_AddSecnode(sector_t* s, mobj_t* thing, msecnode_t* nextnode)
  1588. {
  1589. msecnode_t* node;
  1590. node = nextnode;
  1591. while (node)
  1592. {
  1593. if (node->m_sector == s) // Already have a node for this sector?
  1594. {
  1595. node->m_thing = thing; // Yes. Setting m_thing says 'keep it'.
  1596. return(nextnode);
  1597. }
  1598. node = node->m_tnext;
  1599. }
  1600. // Couldn't find an existing node for this sector. Add one at the head
  1601. // of the list.
  1602. node = P_GetSecnode();
  1603. // killough 4/4/98, 4/7/98: mark new nodes unvisited.
  1604. node->visited = 0;
  1605. node->m_sector = s; // sector
  1606. node->m_thing = thing; // mobj
  1607. node->m_tprev = NULL; // prev node on Thing thread
  1608. node->m_tnext = nextnode; // next node on Thing thread
  1609. if (nextnode)
  1610. nextnode->m_tprev = node; // set back link on Thing
  1611. // Add new node at head of sector thread starting at s->touching_thinglist
  1612. node->m_sprev = NULL; // prev node on sector thread
  1613. node->m_snext = s->touching_thinglist; // next node on sector thread
  1614. if (s->touching_thinglist)
  1615. node->m_snext->m_sprev = node;
  1616. s->touching_thinglist = node;
  1617. return(node);
  1618. }
  1619. // P_DelSecnode() deletes a sector node from the list of
  1620. // sectors this object appears in. Returns a pointer to the next node
  1621. // on the linked list, or NULL.
  1622. msecnode_t* P_DelSecnode(msecnode_t* node)
  1623. {
  1624. msecnode_t* tp; // prev node on thing thread
  1625. msecnode_t* tn; // next node on thing thread
  1626. msecnode_t* sp; // prev node on sector thread
  1627. msecnode_t* sn; // next node on sector thread
  1628. if (node)
  1629. {
  1630. // Unlink from the Thing thread. The Thing thread begins at
  1631. // sector_list and not from mobj_t->touching_sectorlist.
  1632. tp = node->m_tprev;
  1633. tn = node->m_tnext;
  1634. if (tp)
  1635. tp->m_tnext = tn;
  1636. if (tn)
  1637. tn->m_tprev = tp;
  1638. // Unlink from the sector thread. This thread begins at
  1639. // sector_t->touching_thinglist.
  1640. sp = node->m_sprev;
  1641. sn = node->m_snext;
  1642. if (sp)
  1643. sp->m_snext = sn;
  1644. else
  1645. node->m_sector->touching_thinglist = sn;
  1646. if (sn)
  1647. sn->m_sprev = sp;
  1648. // Return this node to the freelist
  1649. P_PutSecnode(node);
  1650. return(tn);
  1651. }
  1652. return(NULL);
  1653. } // phares 3/13/98
  1654. // Delete an entire sector list
  1655. void P_DelSeclist(msecnode_t* node)
  1656. {
  1657. while (node)
  1658. node = P_DelSecnode(node);
  1659. }
  1660. // phares 3/14/98
  1661. //
  1662. // PIT_GetSectors
  1663. // Locates all the sectors the object is in by looking at the lines that
  1664. // cross through it. You have already decided that the object is allowed
  1665. // at this location, so don't bother with checking impassable or
  1666. // blocking lines.
  1667. boolean PIT_GetSectors(line_t* ld)
  1668. {
  1669. if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] ||
  1670. tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
  1671. tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
  1672. tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
  1673. return true;
  1674. if (P_BoxOnLineSide(tmbbox, ld) != -1)
  1675. return true;
  1676. // This line crosses through the object.
  1677. // Collect the sector(s) from the line and add to the
  1678. // sector_list you're examining. If the Thing ends up being
  1679. // allowed to move to this position, then the sector_list
  1680. // will be attached to the Thing's mobj_t at touching_sectorlist.
  1681. sector_list = P_AddSecnode(ld->frontsector,tmthing,sector_list);
  1682. /* Don't assume all lines are 2-sided, since some Things
  1683. * like MT_TFOG are allowed regardless of whether their radius takes
  1684. * them beyond an impassable linedef.
  1685. *
  1686. * killough 3/27/98, 4/4/98:
  1687. * Use sidedefs instead of 2s flag to determine two-sidedness.
  1688. * killough 8/1/98: avoid duplicate if same sector on both sides
  1689. * cph - DEMOSYNC? */
  1690. if (ld->backsector && ld->backsector != ld->frontsector)
  1691. sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list);
  1692. return true;
  1693. }
  1694. // phares 3/14/98
  1695. //
  1696. // P_CreateSecNodeList alters/creates the sector_list that shows what sectors
  1697. // the object resides in.
  1698. void P_CreateSecNodeList(mobj_t* thing,fixed_t x,fixed_t y)
  1699. {
  1700. int xl;
  1701. int xh;
  1702. int yl;
  1703. int yh;
  1704. int bx;
  1705. int by;
  1706. msecnode_t* node;
  1707. mobj_t* saved_tmthing = tmthing; /* cph - see comment at func end */
  1708. fixed_t saved_tmx = tmx, saved_tmy = tmy; /* ditto */
  1709. // First, clear out the existing m_thing fields. As each node is
  1710. // added or verified as needed, m_thing will be set properly. When
  1711. // finished, delete all nodes where m_thing is still NULL. These
  1712. // represent the sectors the Thing has vacated.
  1713. node = sector_list;
  1714. while (node)
  1715. {
  1716. node->m_thing = NULL;
  1717. node = node->m_tnext;
  1718. }
  1719. tmthing = thing;
  1720. tmx = x;
  1721. tmy = y;
  1722. tmbbox[BOXTOP] = y + tmthing->radius;
  1723. tmbbox[BOXBOTTOM] = y - tmthing->radius;
  1724. tmbbox[BOXRIGHT] = x + tmthing->radius;
  1725. tmbbox[BOXLEFT] = x - tmthing->radius;
  1726. validcount++; // used to make sure we only process a line once
  1727. xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
  1728. xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
  1729. yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
  1730. yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
  1731. for (bx=xl ; bx<=xh ; bx++)
  1732. for (by=yl ; by<=yh ; by++)
  1733. P_BlockLinesIterator(bx,by,PIT_GetSectors);
  1734. // Add the sector of the (x,y) point to sector_list.
  1735. sector_list = P_AddSecnode(thing->subsector->sector,thing,sector_list);
  1736. // Now delete any nodes that won't be used. These are the ones where
  1737. // m_thing is still NULL.
  1738. node = sector_list;
  1739. while (node)
  1740. {
  1741. if (node->m_thing == NULL)
  1742. {
  1743. if (node == sector_list)
  1744. sector_list = node->m_tnext;
  1745. node = P_DelSecnode(node);
  1746. }
  1747. else
  1748. node = node->m_tnext;
  1749. }
  1750. /* cph -
  1751. * This is the strife we get into for using global variables. tmthing
  1752. * is being used by several different functions calling
  1753. * P_BlockThingIterator, including functions that can be called *from*
  1754. * P_BlockThingIterator. Using a global tmthing is not reentrant.
  1755. * OTOH for Boom/MBF demos we have to preserve the buggy behavior.
  1756. * Fun. We restore its previous value unless we're in a Boom/MBF demo.
  1757. */
  1758. if ((compatibility_level < boom_compatibility_compatibility) ||
  1759. (compatibility_level >= prboom_3_compatibility))
  1760. tmthing = saved_tmthing;
  1761. /* And, duh, the same for tmx/y - cph 2002/09/22
  1762. * And for tmbbox - cph 2003/08/10 */
  1763. if ((compatibility_level < boom_compatibility_compatibility) /* ||
  1764. (compatibility_level >= prboom_4_compatibility) */) {
  1765. tmx = saved_tmx, tmy = saved_tmy;
  1766. if (tmthing) {
  1767. tmbbox[BOXTOP] = tmy + tmthing->radius;
  1768. tmbbox[BOXBOTTOM] = tmy - tmthing->radius;
  1769. tmbbox[BOXRIGHT] = tmx + tmthing->radius;
  1770. tmbbox[BOXLEFT] = tmx - tmthing->radius;
  1771. }
  1772. }
  1773. }
  1774. /* cphipps 2004/08/30 -
  1775. * Must clear tmthing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */
  1776. void P_MapStart(void) {
  1777. if (tmthing) I_Error("P_MapStart: tmthing set!");
  1778. }
  1779. void P_MapEnd(void) {
  1780. tmthing = NULL;
  1781. }
  1782. // e6y
  1783. // Code to emulate the behavior of Vanilla Doom when encountering an overrun
  1784. // of the spechit array.
  1785. // No more desyncs on compet-n\hr.wad\hr18*.lmp, all strain.wad\map07 demos etc.
  1786. // http://www.doomworld.com/vb/showthread.php?s=&threadid=35214
  1787. static void SpechitOverrun(line_t *ld)
  1788. {
  1789. //int addr = 0x01C09C98 + (ld - lines) * 0x3E;
  1790. int addr = 0x00C09C98 + (ld - lines) * 0x3E;
  1791. if (compatibility_level == dosdoom_compatibility || compatibility_level == tasdoom_compatibility)
  1792. {
  1793. // e6y
  1794. // There are no more desyncs in the following dosdoom demos:
  1795. // flsofdth.wad\fod3uv.lmp - http://www.doomworld.com/sda/flsofdth.htm
  1796. // hr.wad\hf181430.lmp - http://www.doomworld.com/tas/hf181430.zip
  1797. // hr.wad\hr181329.lmp - http://www.doomworld.com/tas/hr181329.zip
  1798. // icarus.wad\ic09uv.lmp - http://competn.doom2.net/pub/sda/i-o/icuvlmps.zip
  1799. switch(numspechit)
  1800. {
  1801. case 8: break; /* strange cph's code */
  1802. case 9:
  1803. tmfloorz = addr;
  1804. break;
  1805. case 10:
  1806. tmceilingz = addr;
  1807. break;
  1808. default:
  1809. lprintf(LO_ERROR, "SpechitOverrun: Warning: unable to emulate"
  1810. " an overrun where numspechit=%i\n",
  1811. numspechit);
  1812. break;
  1813. }
  1814. }
  1815. else
  1816. {
  1817. switch(numspechit)
  1818. {
  1819. case 8: break; /* numspechit, not significant it seems - cph */
  1820. case 9:
  1821. case 10:
  1822. case 11:
  1823. case 12:
  1824. tmbbox[numspechit-9] = addr;
  1825. break;
  1826. case 13:
  1827. nofit = addr;
  1828. break;
  1829. case 14:
  1830. crushchange = addr;
  1831. break;
  1832. default:
  1833. lprintf(LO_ERROR, "SpechitOverrun: Warning: unable to emulate"
  1834. " an overrun where numspechit=%i\n",
  1835. numspechit);
  1836. break;
  1837. }
  1838. }
  1839. }