p_spec.c 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355
  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-2000 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. * -Loads and initializes texture and flat animation sequences
  31. * -Implements utility functions for all linedef/sector special handlers
  32. * -Dispatches walkover and gun line triggers
  33. * -Initializes and implements special sector types
  34. * -Implements donut linedef triggers
  35. * -Initializes and implements BOOM linedef triggers for
  36. * Scrollers/Conveyors
  37. * Friction
  38. * Wind/Current
  39. *
  40. *-----------------------------------------------------------------------------*/
  41. #include "doomstat.h"
  42. #include "p_spec.h"
  43. #include "p_tick.h"
  44. #include "p_setup.h"
  45. #include "m_random.h"
  46. #include "d_englsh.h"
  47. #include "m_argv.h"
  48. #include "w_wad.h"
  49. #include "r_main.h"
  50. #include "p_maputl.h"
  51. #include "p_map.h"
  52. #include "g_game.h"
  53. #include "p_inter.h"
  54. #include "s_sound.h"
  55. #include "sounds.h"
  56. #include "m_bbox.h" // phares 3/20/98
  57. #include "d_deh.h"
  58. #include "r_plane.h"
  59. #include "lprintf.h"
  60. //
  61. // Animating textures and planes
  62. // There is another anim_t used in wi_stuff, unrelated.
  63. //
  64. typedef struct
  65. {
  66. boolean istexture;
  67. int picnum;
  68. int basepic;
  69. int numpics;
  70. int speed;
  71. } anim_t;
  72. //
  73. // source animation definition
  74. //
  75. //
  76. #ifdef _MSC_VER // proff: This is the same as __attribute__ ((packed)) in GNUC
  77. #pragma pack(push)
  78. #pragma pack(1)
  79. #endif //_MSC_VER
  80. #if defined(__MWERKS__)
  81. #pragma options align=packed
  82. #endif
  83. typedef struct
  84. {
  85. signed char istexture; //jff 3/23/98 make char for comparison // cph - make signed
  86. char endname[9]; // if false, it is a flat
  87. char startname[9];
  88. int speed;
  89. } PACKEDATTR animdef_t; //jff 3/23/98 pack to read from memory
  90. #if defined(__MWERKS__)
  91. #pragma options align=reset
  92. #endif
  93. #ifdef _MSC_VER
  94. #pragma pack(pop)
  95. #endif //_MSC_VER
  96. #define MAXANIMS 32 // no longer a strict limit -- killough
  97. static anim_t* lastanim;
  98. static anim_t* anims; // new structure w/o limits -- killough
  99. static size_t maxanims;
  100. // killough 3/7/98: Initialize generalized scrolling
  101. static void P_SpawnScrollers(void);
  102. static void P_SpawnFriction(void); // phares 3/16/98
  103. static void P_SpawnPushers(void); // phares 3/20/98
  104. //
  105. // P_InitPicAnims
  106. //
  107. // Load the table of animation definitions, checking for existence of
  108. // the start and end of each frame. If the start doesn't exist the sequence
  109. // is skipped, if the last doesn't exist, BOOM exits.
  110. //
  111. // Wall/Flat animation sequences, defined by name of first and last frame,
  112. // The full animation sequence is given using all lumps between the start
  113. // and end entry, in the order found in the WAD file.
  114. //
  115. // This routine modified to read its data from a predefined lump or
  116. // PWAD lump called ANIMATED rather than a static table in this module to
  117. // allow wad designers to insert or modify animation sequences.
  118. //
  119. // Lump format is an array of byte packed animdef_t structures, terminated
  120. // by a structure with istexture == -1. The lump can be generated from a
  121. // text source file using SWANTBLS.EXE, distributed with the BOOM utils.
  122. // The standard list of switches and animations is contained in the example
  123. // source text file DEFSWANI.DAT also in the BOOM util distribution.
  124. //
  125. //
  126. void P_InitPicAnims (void)
  127. {
  128. int i;
  129. const animdef_t *animdefs; //jff 3/23/98 pointer to animation lump
  130. int lump = W_GetNumForName("ANIMATED"); // cph - new wad lump handling
  131. // Init animation
  132. //jff 3/23/98 read from predefined or wad lump instead of table
  133. animdefs = (const animdef_t *)W_CacheLumpNum(lump);
  134. lastanim = anims;
  135. for (i=0 ; animdefs[i].istexture != -1 ; i++)
  136. {
  137. // 1/11/98 killough -- removed limit by array-doubling
  138. if (lastanim >= anims + maxanims)
  139. {
  140. size_t newmax = maxanims ? maxanims*2 : MAXANIMS;
  141. anims = realloc(anims, newmax*sizeof(*anims)); // killough
  142. lastanim = anims + maxanims;
  143. maxanims = newmax;
  144. }
  145. if (animdefs[i].istexture)
  146. {
  147. // different episode ?
  148. if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
  149. continue;
  150. lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
  151. lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
  152. }
  153. else
  154. {
  155. if ((W_CheckNumForName)(animdefs[i].startname, ns_flats) == -1) // killough 4/17/98
  156. continue;
  157. lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
  158. lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
  159. }
  160. lastanim->istexture = animdefs[i].istexture;
  161. lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
  162. if (lastanim->numpics < 2)
  163. I_Error ("P_InitPicAnims: bad cycle from %s to %s",
  164. animdefs[i].startname,
  165. animdefs[i].endname);
  166. lastanim->speed = LONG(animdefs[i].speed); // killough 5/5/98: add LONG()
  167. lastanim++;
  168. }
  169. W_UnlockLumpNum(lump);
  170. }
  171. ///////////////////////////////////////////////////////////////
  172. //
  173. // Linedef and Sector Special Implementation Utility Functions
  174. //
  175. ///////////////////////////////////////////////////////////////
  176. //
  177. // getSide()
  178. //
  179. // Will return a side_t*
  180. // given the number of the current sector,
  181. // the line number, and the side (0/1) that you want.
  182. //
  183. // Note: if side=1 is specified, it must exist or results undefined
  184. //
  185. side_t* getSide
  186. ( int currentSector,
  187. int line,
  188. int side )
  189. {
  190. return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
  191. }
  192. //
  193. // getSector()
  194. //
  195. // Will return a sector_t*
  196. // given the number of the current sector,
  197. // the line number and the side (0/1) that you want.
  198. //
  199. // Note: if side=1 is specified, it must exist or results undefined
  200. //
  201. sector_t* getSector
  202. ( int currentSector,
  203. int line,
  204. int side )
  205. {
  206. return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
  207. }
  208. //
  209. // twoSided()
  210. //
  211. // Given the sector number and the line number,
  212. // it will tell you whether the line is two-sided or not.
  213. //
  214. // modified to return actual two-sidedness rather than presence
  215. // of 2S flag unless compatibility optioned
  216. //
  217. int twoSided
  218. ( int sector,
  219. int line )
  220. {
  221. //jff 1/26/98 return what is actually needed, whether the line
  222. //has two sidedefs, rather than whether the 2S flag is set
  223. return comp[comp_model] ?
  224. (sectors[sector].lines[line])->flags & ML_TWOSIDED
  225. :
  226. (sectors[sector].lines[line])->sidenum[1] != NO_INDEX;
  227. }
  228. //
  229. // getNextSector()
  230. //
  231. // Return sector_t * of sector next to current across line.
  232. //
  233. // Note: returns NULL if not two-sided line, or both sides refer to sector
  234. //
  235. sector_t* getNextSector
  236. ( line_t* line,
  237. sector_t* sec )
  238. {
  239. //jff 1/26/98 check unneeded since line->backsector already
  240. //returns NULL if the line is not two sided, and does so from
  241. //the actual two-sidedness of the line, rather than its 2S flag
  242. if (comp[comp_model])
  243. {
  244. if (!(line->flags & ML_TWOSIDED))
  245. return NULL;
  246. }
  247. if (line->frontsector == sec) {
  248. if (comp[comp_model] || line->backsector!=sec)
  249. return line->backsector; //jff 5/3/98 don't retn sec unless compatibility
  250. else // fixes an intra-sector line breaking functions
  251. return NULL; // like floor->highest floor
  252. }
  253. return line->frontsector;
  254. }
  255. //
  256. // P_FindLowestFloorSurrounding()
  257. //
  258. // Returns the fixed point value of the lowest floor height
  259. // in the sector passed or its surrounding sectors.
  260. //
  261. fixed_t P_FindLowestFloorSurrounding(sector_t* sec)
  262. {
  263. int i;
  264. line_t* check;
  265. sector_t* other;
  266. fixed_t floor = sec->floorheight;
  267. for (i=0 ;i < sec->linecount ; i++)
  268. {
  269. check = sec->lines[i];
  270. other = getNextSector(check,sec);
  271. if (!other)
  272. continue;
  273. if (other->floorheight < floor)
  274. floor = other->floorheight;
  275. }
  276. return floor;
  277. }
  278. //
  279. // P_FindHighestFloorSurrounding()
  280. //
  281. // Passed a sector, returns the fixed point value of the largest
  282. // floor height in the surrounding sectors, not including that passed
  283. //
  284. // NOTE: if no surrounding sector exists -32000*FRACUINT is returned
  285. // if compatibility then -500*FRACUNIT is the smallest return possible
  286. //
  287. fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
  288. {
  289. int i;
  290. line_t* check;
  291. sector_t* other;
  292. fixed_t floor = -500*FRACUNIT;
  293. //jff 1/26/98 Fix initial value for floor to not act differently
  294. //in sections of wad that are below -500 units
  295. if (!comp[comp_model]) /* jff 3/12/98 avoid ovf */
  296. floor = -32000*FRACUNIT; // in height calculations
  297. for (i=0 ;i < sec->linecount ; i++)
  298. {
  299. check = sec->lines[i];
  300. other = getNextSector(check,sec);
  301. if (!other)
  302. continue;
  303. if (other->floorheight > floor)
  304. floor = other->floorheight;
  305. }
  306. return floor;
  307. }
  308. //
  309. // P_FindNextHighestFloor()
  310. //
  311. // Passed a sector and a floor height, returns the fixed point value
  312. // of the smallest floor height in a surrounding sector larger than
  313. // the floor height passed. If no such height exists the floorheight
  314. // passed is returned.
  315. //
  316. // Rewritten by Lee Killough to avoid fixed array and to be faster
  317. //
  318. fixed_t P_FindNextHighestFloor(sector_t *sec, int currentheight)
  319. {
  320. sector_t *other;
  321. int i;
  322. for (i=0 ;i < sec->linecount ; i++)
  323. if ((other = getNextSector(sec->lines[i],sec)) &&
  324. other->floorheight > currentheight)
  325. {
  326. int height = other->floorheight;
  327. while (++i < sec->linecount)
  328. if ((other = getNextSector(sec->lines[i],sec)) &&
  329. other->floorheight < height &&
  330. other->floorheight > currentheight)
  331. height = other->floorheight;
  332. return height;
  333. }
  334. /* cph - my guess at doom v1.2 - 1.4beta compatibility here.
  335. * If there are no higher neighbouring sectors, Heretic just returned
  336. * heightlist[0] (local variable), i.e. noise off the stack. 0 is right for
  337. * RETURN01 E1M2, so let's take that. */
  338. return (compatibility_level < doom_1666_compatibility ? 0 : currentheight);
  339. }
  340. //
  341. // P_FindNextLowestFloor()
  342. //
  343. // Passed a sector and a floor height, returns the fixed point value
  344. // of the largest floor height in a surrounding sector smaller than
  345. // the floor height passed. If no such height exists the floorheight
  346. // passed is returned.
  347. //
  348. // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
  349. //
  350. fixed_t P_FindNextLowestFloor(sector_t *sec, int currentheight)
  351. {
  352. sector_t *other;
  353. int i;
  354. for (i=0 ;i < sec->linecount ; i++)
  355. if ((other = getNextSector(sec->lines[i],sec)) &&
  356. other->floorheight < currentheight)
  357. {
  358. int height = other->floorheight;
  359. while (++i < sec->linecount)
  360. if ((other = getNextSector(sec->lines[i],sec)) &&
  361. other->floorheight > height &&
  362. other->floorheight < currentheight)
  363. height = other->floorheight;
  364. return height;
  365. }
  366. return currentheight;
  367. }
  368. //
  369. // P_FindNextLowestCeiling()
  370. //
  371. // Passed a sector and a ceiling height, returns the fixed point value
  372. // of the largest ceiling height in a surrounding sector smaller than
  373. // the ceiling height passed. If no such height exists the ceiling height
  374. // passed is returned.
  375. //
  376. // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
  377. //
  378. fixed_t P_FindNextLowestCeiling(sector_t *sec, int currentheight)
  379. {
  380. sector_t *other;
  381. int i;
  382. for (i=0 ;i < sec->linecount ; i++)
  383. if ((other = getNextSector(sec->lines[i],sec)) &&
  384. other->ceilingheight < currentheight)
  385. {
  386. int height = other->ceilingheight;
  387. while (++i < sec->linecount)
  388. if ((other = getNextSector(sec->lines[i],sec)) &&
  389. other->ceilingheight > height &&
  390. other->ceilingheight < currentheight)
  391. height = other->ceilingheight;
  392. return height;
  393. }
  394. return currentheight;
  395. }
  396. //
  397. // P_FindNextHighestCeiling()
  398. //
  399. // Passed a sector and a ceiling height, returns the fixed point value
  400. // of the smallest ceiling height in a surrounding sector larger than
  401. // the ceiling height passed. If no such height exists the ceiling height
  402. // passed is returned.
  403. //
  404. // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
  405. //
  406. fixed_t P_FindNextHighestCeiling(sector_t *sec, int currentheight)
  407. {
  408. sector_t *other;
  409. int i;
  410. for (i=0 ;i < sec->linecount ; i++)
  411. if ((other = getNextSector(sec->lines[i],sec)) &&
  412. other->ceilingheight > currentheight)
  413. {
  414. int height = other->ceilingheight;
  415. while (++i < sec->linecount)
  416. if ((other = getNextSector(sec->lines[i],sec)) &&
  417. other->ceilingheight < height &&
  418. other->ceilingheight > currentheight)
  419. height = other->ceilingheight;
  420. return height;
  421. }
  422. return currentheight;
  423. }
  424. //
  425. // P_FindLowestCeilingSurrounding()
  426. //
  427. // Passed a sector, returns the fixed point value of the smallest
  428. // ceiling height in the surrounding sectors, not including that passed
  429. //
  430. // NOTE: if no surrounding sector exists 32000*FRACUINT is returned
  431. // but if compatibility then INT_MAX is the return
  432. //
  433. fixed_t P_FindLowestCeilingSurrounding(sector_t* sec)
  434. {
  435. int i;
  436. line_t* check;
  437. sector_t* other;
  438. fixed_t height = INT_MAX;
  439. /* jff 3/12/98 avoid ovf in height calculations */
  440. if (!comp[comp_model]) height = 32000*FRACUNIT;
  441. for (i=0 ;i < sec->linecount ; i++)
  442. {
  443. check = sec->lines[i];
  444. other = getNextSector(check,sec);
  445. if (!other)
  446. continue;
  447. if (other->ceilingheight < height)
  448. height = other->ceilingheight;
  449. }
  450. return height;
  451. }
  452. //
  453. // P_FindHighestCeilingSurrounding()
  454. //
  455. // Passed a sector, returns the fixed point value of the largest
  456. // ceiling height in the surrounding sectors, not including that passed
  457. //
  458. // NOTE: if no surrounding sector exists -32000*FRACUINT is returned
  459. // but if compatibility then 0 is the smallest return possible
  460. //
  461. fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
  462. {
  463. int i;
  464. line_t* check;
  465. sector_t* other;
  466. fixed_t height = 0;
  467. /* jff 1/26/98 Fix initial value for floor to not act differently
  468. * in sections of wad that are below 0 units
  469. * jff 3/12/98 avoid ovf in height calculations */
  470. if (!comp[comp_model]) height = -32000*FRACUNIT;
  471. for (i=0 ;i < sec->linecount ; i++)
  472. {
  473. check = sec->lines[i];
  474. other = getNextSector(check,sec);
  475. if (!other)
  476. continue;
  477. if (other->ceilingheight > height)
  478. height = other->ceilingheight;
  479. }
  480. return height;
  481. }
  482. //
  483. // P_FindShortestTextureAround()
  484. //
  485. // Passed a sector number, returns the shortest lower texture on a
  486. // linedef bounding the sector.
  487. //
  488. // Note: If no lower texture exists 32000*FRACUNIT is returned.
  489. // but if compatibility then INT_MAX is returned
  490. //
  491. // jff 02/03/98 Add routine to find shortest lower texture
  492. //
  493. fixed_t P_FindShortestTextureAround(int secnum)
  494. {
  495. int minsize = INT_MAX;
  496. side_t* side;
  497. int i;
  498. sector_t *sec = &sectors[secnum];
  499. if (!comp[comp_model])
  500. minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow in height calcs
  501. for (i = 0; i < sec->linecount; i++)
  502. {
  503. if (twoSided(secnum, i))
  504. {
  505. side = getSide(secnum,i,0);
  506. if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder
  507. if (textureheight[side->bottomtexture] < minsize)
  508. minsize = textureheight[side->bottomtexture];
  509. side = getSide(secnum,i,1);
  510. if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder
  511. if (textureheight[side->bottomtexture] < minsize)
  512. minsize = textureheight[side->bottomtexture];
  513. }
  514. }
  515. return minsize;
  516. }
  517. //
  518. // P_FindShortestUpperAround()
  519. //
  520. // Passed a sector number, returns the shortest upper texture on a
  521. // linedef bounding the sector.
  522. //
  523. // Note: If no upper texture exists 32000*FRACUNIT is returned.
  524. // but if compatibility then INT_MAX is returned
  525. //
  526. // jff 03/20/98 Add routine to find shortest upper texture
  527. //
  528. fixed_t P_FindShortestUpperAround(int secnum)
  529. {
  530. int minsize = INT_MAX;
  531. side_t* side;
  532. int i;
  533. sector_t *sec = &sectors[secnum];
  534. if (!comp[comp_model])
  535. minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow
  536. // in height calcs
  537. for (i = 0; i < sec->linecount; i++)
  538. {
  539. if (twoSided(secnum, i))
  540. {
  541. side = getSide(secnum,i,0);
  542. if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder
  543. if (textureheight[side->toptexture] < minsize)
  544. minsize = textureheight[side->toptexture];
  545. side = getSide(secnum,i,1);
  546. if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder
  547. if (textureheight[side->toptexture] < minsize)
  548. minsize = textureheight[side->toptexture];
  549. }
  550. }
  551. return minsize;
  552. }
  553. //
  554. // P_FindModelFloorSector()
  555. //
  556. // Passed a floor height and a sector number, return a pointer to a
  557. // a sector with that floor height across the lowest numbered two sided
  558. // line surrounding the sector.
  559. //
  560. // Note: If no sector at that height bounds the sector passed, return NULL
  561. //
  562. // jff 02/03/98 Add routine to find numeric model floor
  563. // around a sector specified by sector number
  564. // jff 3/14/98 change first parameter to plain height to allow call
  565. // from routine not using floormove_t
  566. //
  567. sector_t *P_FindModelFloorSector(fixed_t floordestheight,int secnum)
  568. {
  569. int i;
  570. sector_t *sec=NULL;
  571. int linecount;
  572. sec = &sectors[secnum]; //jff 3/2/98 woops! better do this
  573. //jff 5/23/98 don't disturb sec->linecount while searching
  574. // but allow early exit in old demos
  575. linecount = sec->linecount;
  576. for (i = 0; i < (demo_compatibility && sec->linecount<linecount?
  577. sec->linecount : linecount); i++)
  578. {
  579. if ( twoSided(secnum, i) )
  580. {
  581. if (getSide(secnum,i,0)->sector-sectors == secnum)
  582. sec = getSector(secnum,i,1);
  583. else
  584. sec = getSector(secnum,i,0);
  585. if (sec->floorheight == floordestheight)
  586. return sec;
  587. }
  588. }
  589. return NULL;
  590. }
  591. //
  592. // P_FindModelCeilingSector()
  593. //
  594. // Passed a ceiling height and a sector number, return a pointer to a
  595. // a sector with that ceiling height across the lowest numbered two sided
  596. // line surrounding the sector.
  597. //
  598. // Note: If no sector at that height bounds the sector passed, return NULL
  599. //
  600. // jff 02/03/98 Add routine to find numeric model ceiling
  601. // around a sector specified by sector number
  602. // used only from generalized ceiling types
  603. // jff 3/14/98 change first parameter to plain height to allow call
  604. // from routine not using ceiling_t
  605. //
  606. sector_t *P_FindModelCeilingSector(fixed_t ceildestheight,int secnum)
  607. {
  608. int i;
  609. sector_t *sec=NULL;
  610. int linecount;
  611. sec = &sectors[secnum]; //jff 3/2/98 woops! better do this
  612. //jff 5/23/98 don't disturb sec->linecount while searching
  613. // but allow early exit in old demos
  614. linecount = sec->linecount;
  615. for (i = 0; i < (demo_compatibility && sec->linecount<linecount?
  616. sec->linecount : linecount); i++)
  617. {
  618. if ( twoSided(secnum, i) )
  619. {
  620. if (getSide(secnum,i,0)->sector-sectors == secnum)
  621. sec = getSector(secnum,i,1);
  622. else
  623. sec = getSector(secnum,i,0);
  624. if (sec->ceilingheight == ceildestheight)
  625. return sec;
  626. }
  627. }
  628. return NULL;
  629. }
  630. //
  631. // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
  632. //
  633. // Find the next sector with the same tag as a linedef.
  634. // Rewritten by Lee Killough to use chained hashing to improve speed
  635. int P_FindSectorFromLineTag(const line_t *line, int start)
  636. {
  637. start = start >= 0 ? sectors[start].nexttag :
  638. sectors[(unsigned) line->tag % (unsigned) numsectors].firsttag;
  639. while (start >= 0 && sectors[start].tag != line->tag)
  640. start = sectors[start].nexttag;
  641. return start;
  642. }
  643. // killough 4/16/98: Same thing, only for linedefs
  644. int P_FindLineFromLineTag(const line_t *line, int start)
  645. {
  646. start = start >= 0 ? lines[start].nexttag :
  647. lines[(unsigned) line->tag % (unsigned) numlines].firsttag;
  648. while (start >= 0 && lines[start].tag != line->tag)
  649. start = lines[start].nexttag;
  650. return start;
  651. }
  652. // Hash the sector tags across the sectors and linedefs.
  653. static void P_InitTagLists(void)
  654. {
  655. register int i;
  656. for (i=numsectors; --i>=0; ) // Initially make all slots empty.
  657. sectors[i].firsttag = -1;
  658. for (i=numsectors; --i>=0; ) // Proceed from last to first sector
  659. { // so that lower sectors appear first
  660. int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func
  661. sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain
  662. sectors[j].firsttag = i;
  663. }
  664. // killough 4/17/98: same thing, only for linedefs
  665. for (i=numlines; --i>=0; ) // Initially make all slots empty.
  666. lines[i].firsttag = -1;
  667. for (i=numlines; --i>=0; ) // Proceed from last to first linedef
  668. { // so that lower linedefs appear first
  669. int j = (unsigned) lines[i].tag % (unsigned) numlines; // Hash func
  670. lines[i].nexttag = lines[j].firsttag; // Prepend linedef to chain
  671. lines[j].firsttag = i;
  672. }
  673. }
  674. //
  675. // P_FindMinSurroundingLight()
  676. //
  677. // Passed a sector and a light level, returns the smallest light level
  678. // in a surrounding sector less than that passed. If no smaller light
  679. // level exists, the light level passed is returned.
  680. //
  681. int P_FindMinSurroundingLight
  682. ( sector_t* sector,
  683. int max )
  684. {
  685. int i;
  686. int min;
  687. line_t* line;
  688. sector_t* check;
  689. min = max;
  690. for (i=0 ; i < sector->linecount ; i++)
  691. {
  692. line = sector->lines[i];
  693. check = getNextSector(line,sector);
  694. if (!check)
  695. continue;
  696. if (check->lightlevel < min)
  697. min = check->lightlevel;
  698. }
  699. return min;
  700. }
  701. //
  702. // P_CanUnlockGenDoor()
  703. //
  704. // Passed a generalized locked door linedef and a player, returns whether
  705. // the player has the keys necessary to unlock that door.
  706. //
  707. // Note: The linedef passed MUST be a generalized locked door type
  708. // or results are undefined.
  709. //
  710. // jff 02/05/98 routine added to test for unlockability of
  711. // generalized locked doors
  712. //
  713. boolean P_CanUnlockGenDoor
  714. ( line_t* line,
  715. player_t* player)
  716. {
  717. // does this line special distinguish between skulls and keys?
  718. int skulliscard = (line->special & LockedNKeys)>>LockedNKeysShift;
  719. // determine for each case of lock type if player's keys are adequate
  720. switch((line->special & LockedKey)>>LockedKeyShift)
  721. {
  722. case AnyKey:
  723. if
  724. (
  725. !player->cards[it_redcard] &&
  726. !player->cards[it_redskull] &&
  727. !player->cards[it_bluecard] &&
  728. !player->cards[it_blueskull] &&
  729. !player->cards[it_yellowcard] &&
  730. !player->cards[it_yellowskull]
  731. )
  732. {
  733. player->message = s_PD_ANY; // Ty 03/27/98 - externalized
  734. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  735. return false;
  736. }
  737. break;
  738. case RCard:
  739. if
  740. (
  741. !player->cards[it_redcard] &&
  742. (!skulliscard || !player->cards[it_redskull])
  743. )
  744. {
  745. player->message = skulliscard? s_PD_REDK : s_PD_REDC; // Ty 03/27/98 - externalized
  746. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  747. return false;
  748. }
  749. break;
  750. case BCard:
  751. if
  752. (
  753. !player->cards[it_bluecard] &&
  754. (!skulliscard || !player->cards[it_blueskull])
  755. )
  756. {
  757. player->message = skulliscard? s_PD_BLUEK : s_PD_BLUEC; // Ty 03/27/98 - externalized
  758. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  759. return false;
  760. }
  761. break;
  762. case YCard:
  763. if
  764. (
  765. !player->cards[it_yellowcard] &&
  766. (!skulliscard || !player->cards[it_yellowskull])
  767. )
  768. {
  769. player->message = skulliscard? s_PD_YELLOWK : s_PD_YELLOWC; // Ty 03/27/98 - externalized
  770. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  771. return false;
  772. }
  773. break;
  774. case RSkull:
  775. if
  776. (
  777. !player->cards[it_redskull] &&
  778. (!skulliscard || !player->cards[it_redcard])
  779. )
  780. {
  781. player->message = skulliscard? s_PD_REDK : s_PD_REDS; // Ty 03/27/98 - externalized
  782. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  783. return false;
  784. }
  785. break;
  786. case BSkull:
  787. if
  788. (
  789. !player->cards[it_blueskull] &&
  790. (!skulliscard || !player->cards[it_bluecard])
  791. )
  792. {
  793. player->message = skulliscard? s_PD_BLUEK : s_PD_BLUES; // Ty 03/27/98 - externalized
  794. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  795. return false;
  796. }
  797. break;
  798. case YSkull:
  799. if
  800. (
  801. !player->cards[it_yellowskull] &&
  802. (!skulliscard || !player->cards[it_yellowcard])
  803. )
  804. {
  805. player->message = skulliscard? s_PD_YELLOWK : s_PD_YELLOWS; // Ty 03/27/98 - externalized
  806. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  807. return false;
  808. }
  809. break;
  810. case AllKeys:
  811. if
  812. (
  813. !skulliscard &&
  814. (
  815. !player->cards[it_redcard] ||
  816. !player->cards[it_redskull] ||
  817. !player->cards[it_bluecard] ||
  818. !player->cards[it_blueskull] ||
  819. !player->cards[it_yellowcard] ||
  820. !player->cards[it_yellowskull]
  821. )
  822. )
  823. {
  824. player->message = s_PD_ALL6; // Ty 03/27/98 - externalized
  825. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  826. return false;
  827. }
  828. if
  829. (
  830. skulliscard &&
  831. (
  832. (!player->cards[it_redcard] &&
  833. !player->cards[it_redskull]) ||
  834. (!player->cards[it_bluecard] &&
  835. !player->cards[it_blueskull]) ||
  836. (!player->cards[it_yellowcard] &&
  837. !player->cards[it_yellowskull])
  838. )
  839. )
  840. {
  841. player->message = s_PD_ALL3; // Ty 03/27/98 - externalized
  842. S_StartSound(player->mo,sfx_oof); // killough 3/20/98
  843. return false;
  844. }
  845. break;
  846. }
  847. return true;
  848. }
  849. //
  850. // P_SectorActive()
  851. //
  852. // Passed a linedef special class (floor, ceiling, lighting) and a sector
  853. // returns whether the sector is already busy with a linedef special of the
  854. // same class. If old demo compatibility true, all linedef special classes
  855. // are the same.
  856. //
  857. // jff 2/23/98 added to prevent old demos from
  858. // succeeding in starting multiple specials on one sector
  859. //
  860. boolean PUREFUNC P_SectorActive(special_e t, const sector_t *sec)
  861. {
  862. if (demo_compatibility) // return whether any thinker is active
  863. return sec->floordata != NULL || sec->ceilingdata != NULL || sec->lightingdata != NULL;
  864. else
  865. switch (t) // return whether thinker of same type is active
  866. {
  867. case floor_special:
  868. return sec->floordata != NULL;
  869. case ceiling_special:
  870. return sec->ceilingdata != NULL;
  871. case lighting_special:
  872. return sec->lightingdata != NULL;
  873. }
  874. return true; // don't know which special, must be active, shouldn't be here
  875. }
  876. //
  877. // P_CheckTag()
  878. //
  879. // Passed a line, returns true if the tag is non-zero or the line special
  880. // allows no tag without harm. If compatibility, all linedef specials are
  881. // allowed to have zero tag.
  882. //
  883. // Note: Only line specials activated by walkover, pushing, or shooting are
  884. // checked by this routine.
  885. //
  886. // jff 2/27/98 Added to check for zero tag allowed for regular special types
  887. //
  888. int P_CheckTag(line_t *line)
  889. {
  890. /* tag not zero, allowed, or
  891. * killough 11/98: compatibility option */
  892. if (comp[comp_zerotags] || line->tag)
  893. return 1;
  894. switch(line->special)
  895. {
  896. case 1: // Manual door specials
  897. case 26:
  898. case 27:
  899. case 28:
  900. case 31:
  901. case 32:
  902. case 33:
  903. case 34:
  904. case 117:
  905. case 118:
  906. case 139: // Lighting specials
  907. case 170:
  908. case 79:
  909. case 35:
  910. case 138:
  911. case 171:
  912. case 81:
  913. case 13:
  914. case 192:
  915. case 169:
  916. case 80:
  917. case 12:
  918. case 194:
  919. case 173:
  920. case 157:
  921. case 104:
  922. case 193:
  923. case 172:
  924. case 156:
  925. case 17:
  926. case 195: // Thing teleporters
  927. case 174:
  928. case 97:
  929. case 39:
  930. case 126:
  931. case 125:
  932. case 210:
  933. case 209:
  934. case 208:
  935. case 207:
  936. case 11: // Exits
  937. case 52:
  938. case 197:
  939. case 51:
  940. case 124:
  941. case 198:
  942. case 48: // Scrolling walls
  943. case 85:
  944. return 1; // zero tag allowed
  945. default:
  946. break;
  947. }
  948. return 0; // zero tag not allowed
  949. }
  950. //
  951. // P_IsSecret()
  952. //
  953. // Passed a sector, returns if the sector secret type is still active, i.e.
  954. // secret type is set and the secret has not yet been obtained.
  955. //
  956. // jff 3/14/98 added to simplify checks for whether sector is secret
  957. // in automap and other places
  958. //
  959. boolean PUREFUNC P_IsSecret(const sector_t *sec)
  960. {
  961. return (sec->special==9 || (sec->special&SECRET_MASK));
  962. }
  963. //
  964. // P_WasSecret()
  965. //
  966. // Passed a sector, returns if the sector secret type is was active, i.e.
  967. // secret type was set and the secret has been obtained already.
  968. //
  969. // jff 3/14/98 added to simplify checks for whether sector is secret
  970. // in automap and other places
  971. //
  972. boolean PUREFUNC P_WasSecret(const sector_t *sec)
  973. {
  974. return (sec->oldspecial==9 || (sec->oldspecial&SECRET_MASK));
  975. }
  976. //////////////////////////////////////////////////////////////////////////
  977. //
  978. // Events
  979. //
  980. // Events are operations triggered by using, crossing,
  981. // or shooting special lines, or by timed thinkers.
  982. //
  983. /////////////////////////////////////////////////////////////////////////
  984. //
  985. // P_CrossSpecialLine - Walkover Trigger Dispatcher
  986. //
  987. // Called every time a thing origin is about
  988. // to cross a line with a non 0 special, whether a walkover type or not.
  989. //
  990. // jff 02/12/98 all W1 lines were fixed to check the result from the EV_
  991. // function before clearing the special. This avoids losing the function
  992. // of the line, should the sector already be active when the line is
  993. // crossed. Change is qualified by demo_compatibility.
  994. //
  995. // CPhipps - take a line_t pointer instead of a line number, as in MBF
  996. void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing)
  997. {
  998. int ok;
  999. // Things that should never trigger lines
  1000. if (!thing->player)
  1001. {
  1002. // Things that should NOT trigger specials...
  1003. switch(thing->type)
  1004. {
  1005. case MT_ROCKET:
  1006. case MT_PLASMA:
  1007. case MT_BFG:
  1008. case MT_TROOPSHOT:
  1009. case MT_HEADSHOT:
  1010. case MT_BRUISERSHOT:
  1011. return;
  1012. break;
  1013. default: break;
  1014. }
  1015. }
  1016. //jff 02/04/98 add check here for generalized lindef types
  1017. if (!demo_compatibility) // generalized types not recognized if old demo
  1018. {
  1019. // pointer to line function is NULL by default, set non-null if
  1020. // line special is walkover generalized linedef type
  1021. int (*linefunc)(line_t *line)=NULL;
  1022. // check each range of generalized linedefs
  1023. if ((unsigned)line->special >= GenEnd)
  1024. {
  1025. // Out of range for GenFloors
  1026. }
  1027. else if ((unsigned)line->special >= GenFloorBase)
  1028. {
  1029. if (!thing->player)
  1030. if ((line->special & FloorChange) || !(line->special & FloorModel))
  1031. return; // FloorModel is "Allow Monsters" if FloorChange is 0
  1032. if (!line->tag) //jff 2/27/98 all walk generalized types require tag
  1033. return;
  1034. linefunc = EV_DoGenFloor;
  1035. }
  1036. else if ((unsigned)line->special >= GenCeilingBase)
  1037. {
  1038. if (!thing->player)
  1039. if ((line->special & CeilingChange) || !(line->special & CeilingModel))
  1040. return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
  1041. if (!line->tag) //jff 2/27/98 all walk generalized types require tag
  1042. return;
  1043. linefunc = EV_DoGenCeiling;
  1044. }
  1045. else if ((unsigned)line->special >= GenDoorBase)
  1046. {
  1047. if (!thing->player)
  1048. {
  1049. if (!(line->special & DoorMonster))
  1050. return; // monsters disallowed from this door
  1051. if (line->flags & ML_SECRET) // they can't open secret doors either
  1052. return;
  1053. }
  1054. if (!line->tag) //3/2/98 move outside the monster check
  1055. return;
  1056. linefunc = EV_DoGenDoor;
  1057. }
  1058. else if ((unsigned)line->special >= GenLockedBase)
  1059. {
  1060. if (!thing->player)
  1061. return; // monsters disallowed from unlocking doors
  1062. if (((line->special&TriggerType)==WalkOnce) || ((line->special&TriggerType)==WalkMany))
  1063. { //jff 4/1/98 check for being a walk type before reporting door type
  1064. if (!P_CanUnlockGenDoor(line,thing->player))
  1065. return;
  1066. }
  1067. else
  1068. return;
  1069. linefunc = EV_DoGenLockedDoor;
  1070. }
  1071. else if ((unsigned)line->special >= GenLiftBase)
  1072. {
  1073. if (!thing->player)
  1074. if (!(line->special & LiftMonster))
  1075. return; // monsters disallowed
  1076. if (!line->tag) //jff 2/27/98 all walk generalized types require tag
  1077. return;
  1078. linefunc = EV_DoGenLift;
  1079. }
  1080. else if ((unsigned)line->special >= GenStairsBase)
  1081. {
  1082. if (!thing->player)
  1083. if (!(line->special & StairMonster))
  1084. return; // monsters disallowed
  1085. if (!line->tag) //jff 2/27/98 all walk generalized types require tag
  1086. return;
  1087. linefunc = EV_DoGenStairs;
  1088. }
  1089. if (linefunc) // if it was a valid generalized type
  1090. switch((line->special & TriggerType) >> TriggerTypeShift)
  1091. {
  1092. case WalkOnce:
  1093. if (linefunc(line))
  1094. line->special = 0; // clear special if a walk once type
  1095. return;
  1096. case WalkMany:
  1097. linefunc(line);
  1098. return;
  1099. default: // if not a walk type, do nothing here
  1100. return;
  1101. }
  1102. }
  1103. if (!thing->player)
  1104. {
  1105. ok = 0;
  1106. switch(line->special)
  1107. {
  1108. case 39: // teleport trigger
  1109. case 97: // teleport retrigger
  1110. case 125: // teleport monsteronly trigger
  1111. case 126: // teleport monsteronly retrigger
  1112. case 4: // raise door
  1113. case 10: // plat down-wait-up-stay trigger
  1114. case 88: // plat down-wait-up-stay retrigger
  1115. //jff 3/5/98 add ability of monsters etc. to use teleporters
  1116. case 208: //silent thing teleporters
  1117. case 207:
  1118. case 243: //silent line-line teleporter
  1119. case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
  1120. case 262: //jff 4/14/98 add monster only
  1121. case 263: //jff 4/14/98 silent thing,line,line rev types
  1122. case 264: //jff 4/14/98 plus player/monster silent line
  1123. case 265: // reversed types
  1124. case 266:
  1125. case 267:
  1126. case 268:
  1127. case 269:
  1128. ok = 1;
  1129. break;
  1130. }
  1131. if (!ok)
  1132. return;
  1133. }
  1134. if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types
  1135. return;
  1136. // Dispatch on the line special value to the line's action routine
  1137. // If a once only function, and successful, clear the line special
  1138. switch (line->special)
  1139. {
  1140. // Regular walk once triggers
  1141. case 2:
  1142. // Open Door
  1143. if (EV_DoDoor(line,open) || demo_compatibility)
  1144. line->special = 0;
  1145. break;
  1146. case 3:
  1147. // Close Door
  1148. if (EV_DoDoor(line,close) || demo_compatibility)
  1149. line->special = 0;
  1150. break;
  1151. case 4:
  1152. // Raise Door
  1153. if (EV_DoDoor(line,normal) || demo_compatibility)
  1154. line->special = 0;
  1155. break;
  1156. case 5:
  1157. // Raise Floor
  1158. if (EV_DoFloor(line,raiseFloor) || demo_compatibility)
  1159. line->special = 0;
  1160. break;
  1161. case 6:
  1162. // Fast Ceiling Crush & Raise
  1163. if (EV_DoCeiling(line,fastCrushAndRaise) || demo_compatibility)
  1164. line->special = 0;
  1165. break;
  1166. case 8:
  1167. // Build Stairs
  1168. if (EV_BuildStairs(line,build8) || demo_compatibility)
  1169. line->special = 0;
  1170. break;
  1171. case 10:
  1172. // PlatDownWaitUp
  1173. if (EV_DoPlat(line,downWaitUpStay,0) || demo_compatibility)
  1174. line->special = 0;
  1175. break;
  1176. case 12:
  1177. // Light Turn On - brightest near
  1178. if (EV_LightTurnOn(line,0) || demo_compatibility)
  1179. line->special = 0;
  1180. break;
  1181. case 13:
  1182. // Light Turn On 255
  1183. if (EV_LightTurnOn(line,255) || demo_compatibility)
  1184. line->special = 0;
  1185. break;
  1186. case 16:
  1187. // Close Door 30
  1188. if (EV_DoDoor(line,close30ThenOpen) || demo_compatibility)
  1189. line->special = 0;
  1190. break;
  1191. case 17:
  1192. // Start Light Strobing
  1193. if (EV_StartLightStrobing(line) || demo_compatibility)
  1194. line->special = 0;
  1195. break;
  1196. case 19:
  1197. // Lower Floor
  1198. if (EV_DoFloor(line,lowerFloor) || demo_compatibility)
  1199. line->special = 0;
  1200. break;
  1201. case 22:
  1202. // Raise floor to nearest height and change texture
  1203. if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility)
  1204. line->special = 0;
  1205. break;
  1206. case 25:
  1207. // Ceiling Crush and Raise
  1208. if (EV_DoCeiling(line,crushAndRaise) || demo_compatibility)
  1209. line->special = 0;
  1210. break;
  1211. case 30:
  1212. // Raise floor to shortest texture height
  1213. // on either side of lines.
  1214. if (EV_DoFloor(line,raiseToTexture) || demo_compatibility)
  1215. line->special = 0;
  1216. break;
  1217. case 35:
  1218. // Lights Very Dark
  1219. if (EV_LightTurnOn(line,35) || demo_compatibility)
  1220. line->special = 0;
  1221. break;
  1222. case 36:
  1223. // Lower Floor (TURBO)
  1224. if (EV_DoFloor(line,turboLower) || demo_compatibility)
  1225. line->special = 0;
  1226. break;
  1227. case 37:
  1228. // LowerAndChange
  1229. if (EV_DoFloor(line,lowerAndChange) || demo_compatibility)
  1230. line->special = 0;
  1231. break;
  1232. case 38:
  1233. // Lower Floor To Lowest
  1234. if (EV_DoFloor(line, lowerFloorToLowest) || demo_compatibility)
  1235. line->special = 0;
  1236. break;
  1237. case 39:
  1238. // TELEPORT! //jff 02/09/98 fix using up with wrong side crossing
  1239. if (EV_Teleport(line, side, thing) || demo_compatibility)
  1240. line->special = 0;
  1241. break;
  1242. case 40:
  1243. // RaiseCeilingLowerFloor
  1244. if (demo_compatibility)
  1245. {
  1246. EV_DoCeiling( line, raiseToHighest );
  1247. EV_DoFloor( line, lowerFloorToLowest ); //jff 02/12/98 doesn't work
  1248. line->special = 0;
  1249. }
  1250. else
  1251. if (EV_DoCeiling(line, raiseToHighest))
  1252. line->special = 0;
  1253. break;
  1254. case 44:
  1255. // Ceiling Crush
  1256. if (EV_DoCeiling(line, lowerAndCrush) || demo_compatibility)
  1257. line->special = 0;
  1258. break;
  1259. case 52:
  1260. // EXIT!
  1261. // killough 10/98: prevent zombies from exiting levels
  1262. if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie]))
  1263. G_ExitLevel ();
  1264. break;
  1265. case 53:
  1266. // Perpetual Platform Raise
  1267. if (EV_DoPlat(line,perpetualRaise,0) || demo_compatibility)
  1268. line->special = 0;
  1269. break;
  1270. case 54:
  1271. // Platform Stop
  1272. if (EV_StopPlat(line) || demo_compatibility)
  1273. line->special = 0;
  1274. break;
  1275. case 56:
  1276. // Raise Floor Crush
  1277. if (EV_DoFloor(line,raiseFloorCrush) || demo_compatibility)
  1278. line->special = 0;
  1279. break;
  1280. case 57:
  1281. // Ceiling Crush Stop
  1282. if (EV_CeilingCrushStop(line) || demo_compatibility)
  1283. line->special = 0;
  1284. break;
  1285. case 58:
  1286. // Raise Floor 24
  1287. if (EV_DoFloor(line,raiseFloor24) || demo_compatibility)
  1288. line->special = 0;
  1289. break;
  1290. case 59:
  1291. // Raise Floor 24 And Change
  1292. if (EV_DoFloor(line,raiseFloor24AndChange) || demo_compatibility)
  1293. line->special = 0;
  1294. break;
  1295. case 100:
  1296. // Build Stairs Turbo 16
  1297. if (EV_BuildStairs(line,turbo16) || demo_compatibility)
  1298. line->special = 0;
  1299. break;
  1300. case 104:
  1301. // Turn lights off in sector(tag)
  1302. if (EV_TurnTagLightsOff(line) || demo_compatibility)
  1303. line->special = 0;
  1304. break;
  1305. case 108:
  1306. // Blazing Door Raise (faster than TURBO!)
  1307. if (EV_DoDoor(line,blazeRaise) || demo_compatibility)
  1308. line->special = 0;
  1309. break;
  1310. case 109:
  1311. // Blazing Door Open (faster than TURBO!)
  1312. if (EV_DoDoor (line,blazeOpen) || demo_compatibility)
  1313. line->special = 0;
  1314. break;
  1315. case 110:
  1316. // Blazing Door Close (faster than TURBO!)
  1317. if (EV_DoDoor (line,blazeClose) || demo_compatibility)
  1318. line->special = 0;
  1319. break;
  1320. case 119:
  1321. // Raise floor to nearest surr. floor
  1322. if (EV_DoFloor(line,raiseFloorToNearest) || demo_compatibility)
  1323. line->special = 0;
  1324. break;
  1325. case 121:
  1326. // Blazing PlatDownWaitUpStay
  1327. if (EV_DoPlat(line,blazeDWUS,0) || demo_compatibility)
  1328. line->special = 0;
  1329. break;
  1330. case 124:
  1331. // Secret EXIT
  1332. // killough 10/98: prevent zombies from exiting levels
  1333. // CPhipps - change for lxdoom's compatibility handling
  1334. if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie]))
  1335. G_SecretExitLevel ();
  1336. break;
  1337. case 125:
  1338. // TELEPORT MonsterONLY
  1339. if (!thing->player &&
  1340. (EV_Teleport(line, side, thing) || demo_compatibility))
  1341. line->special = 0;
  1342. break;
  1343. case 130:
  1344. // Raise Floor Turbo
  1345. if (EV_DoFloor(line,raiseFloorTurbo) || demo_compatibility)
  1346. line->special = 0;
  1347. break;
  1348. case 141:
  1349. // Silent Ceiling Crush & Raise
  1350. if (EV_DoCeiling(line,silentCrushAndRaise) || demo_compatibility)
  1351. line->special = 0;
  1352. break;
  1353. // Regular walk many retriggerable
  1354. case 72:
  1355. // Ceiling Crush
  1356. EV_DoCeiling( line, lowerAndCrush );
  1357. break;
  1358. case 73:
  1359. // Ceiling Crush and Raise
  1360. EV_DoCeiling(line,crushAndRaise);
  1361. break;
  1362. case 74:
  1363. // Ceiling Crush Stop
  1364. EV_CeilingCrushStop(line);
  1365. break;
  1366. case 75:
  1367. // Close Door
  1368. EV_DoDoor(line,close);
  1369. break;
  1370. case 76:
  1371. // Close Door 30
  1372. EV_DoDoor(line,close30ThenOpen);
  1373. break;
  1374. case 77:
  1375. // Fast Ceiling Crush & Raise
  1376. EV_DoCeiling(line,fastCrushAndRaise);
  1377. break;
  1378. case 79:
  1379. // Lights Very Dark
  1380. EV_LightTurnOn(line,35);
  1381. break;
  1382. case 80:
  1383. // Light Turn On - brightest near
  1384. EV_LightTurnOn(line,0);
  1385. break;
  1386. case 81:
  1387. // Light Turn On 255
  1388. EV_LightTurnOn(line,255);
  1389. break;
  1390. case 82:
  1391. // Lower Floor To Lowest
  1392. EV_DoFloor( line, lowerFloorToLowest );
  1393. break;
  1394. case 83:
  1395. // Lower Floor
  1396. EV_DoFloor(line,lowerFloor);
  1397. break;
  1398. case 84:
  1399. // LowerAndChange
  1400. EV_DoFloor(line,lowerAndChange);
  1401. break;
  1402. case 86:
  1403. // Open Door
  1404. EV_DoDoor(line,open);
  1405. break;
  1406. case 87:
  1407. // Perpetual Platform Raise
  1408. EV_DoPlat(line,perpetualRaise,0);
  1409. break;
  1410. case 88:
  1411. // PlatDownWaitUp
  1412. EV_DoPlat(line,downWaitUpStay,0);
  1413. break;
  1414. case 89:
  1415. // Platform Stop
  1416. EV_StopPlat(line);
  1417. break;
  1418. case 90:
  1419. // Raise Door
  1420. EV_DoDoor(line,normal);
  1421. break;
  1422. case 91:
  1423. // Raise Floor
  1424. EV_DoFloor(line,raiseFloor);
  1425. break;
  1426. case 92:
  1427. // Raise Floor 24
  1428. EV_DoFloor(line,raiseFloor24);
  1429. break;
  1430. case 93:
  1431. // Raise Floor 24 And Change
  1432. EV_DoFloor(line,raiseFloor24AndChange);
  1433. break;
  1434. case 94:
  1435. // Raise Floor Crush
  1436. EV_DoFloor(line,raiseFloorCrush);
  1437. break;
  1438. case 95:
  1439. // Raise floor to nearest height
  1440. // and change texture.
  1441. EV_DoPlat(line,raiseToNearestAndChange,0);
  1442. break;
  1443. case 96:
  1444. // Raise floor to shortest texture height
  1445. // on either side of lines.
  1446. EV_DoFloor(line,raiseToTexture);
  1447. break;
  1448. case 97:
  1449. // TELEPORT!
  1450. EV_Teleport( line, side, thing );
  1451. break;
  1452. case 98:
  1453. // Lower Floor (TURBO)
  1454. EV_DoFloor(line,turboLower);
  1455. break;
  1456. case 105:
  1457. // Blazing Door Raise (faster than TURBO!)
  1458. EV_DoDoor (line,blazeRaise);
  1459. break;
  1460. case 106:
  1461. // Blazing Door Open (faster than TURBO!)
  1462. EV_DoDoor (line,blazeOpen);
  1463. break;
  1464. case 107:
  1465. // Blazing Door Close (faster than TURBO!)
  1466. EV_DoDoor (line,blazeClose);
  1467. break;
  1468. case 120:
  1469. // Blazing PlatDownWaitUpStay.
  1470. EV_DoPlat(line,blazeDWUS,0);
  1471. break;
  1472. case 126:
  1473. // TELEPORT MonsterONLY.
  1474. if (!thing->player)
  1475. EV_Teleport( line, side, thing );
  1476. break;
  1477. case 128:
  1478. // Raise To Nearest Floor
  1479. EV_DoFloor(line,raiseFloorToNearest);
  1480. break;
  1481. case 129:
  1482. // Raise Floor Turbo
  1483. EV_DoFloor(line,raiseFloorTurbo);
  1484. break;
  1485. // Extended walk triggers
  1486. // jff 1/29/98 added new linedef types to fill all functions out so that
  1487. // all have varieties SR, S1, WR, W1
  1488. // killough 1/31/98: "factor out" compatibility test, by
  1489. // adding inner switch qualified by compatibility flag.
  1490. // relax test to demo_compatibility
  1491. // killough 2/16/98: Fix problems with W1 types being cleared too early
  1492. default:
  1493. if (!demo_compatibility)
  1494. switch (line->special)
  1495. {
  1496. // Extended walk once triggers
  1497. case 142:
  1498. // Raise Floor 512
  1499. // 142 W1 EV_DoFloor(raiseFloor512)
  1500. if (EV_DoFloor(line,raiseFloor512))
  1501. line->special = 0;
  1502. break;
  1503. case 143:
  1504. // Raise Floor 24 and change
  1505. // 143 W1 EV_DoPlat(raiseAndChange,24)
  1506. if (EV_DoPlat(line,raiseAndChange,24))
  1507. line->special = 0;
  1508. break;
  1509. case 144:
  1510. // Raise Floor 32 and change
  1511. // 144 W1 EV_DoPlat(raiseAndChange,32)
  1512. if (EV_DoPlat(line,raiseAndChange,32))
  1513. line->special = 0;
  1514. break;
  1515. case 145:
  1516. // Lower Ceiling to Floor
  1517. // 145 W1 EV_DoCeiling(lowerToFloor)
  1518. if (EV_DoCeiling( line, lowerToFloor ))
  1519. line->special = 0;
  1520. break;
  1521. case 146:
  1522. // Lower Pillar, Raise Donut
  1523. // 146 W1 EV_DoDonut()
  1524. if (EV_DoDonut(line))
  1525. line->special = 0;
  1526. break;
  1527. case 199:
  1528. // Lower ceiling to lowest surrounding ceiling
  1529. // 199 W1 EV_DoCeiling(lowerToLowest)
  1530. if (EV_DoCeiling(line,lowerToLowest))
  1531. line->special = 0;
  1532. break;
  1533. case 200:
  1534. // Lower ceiling to highest surrounding floor
  1535. // 200 W1 EV_DoCeiling(lowerToMaxFloor)
  1536. if (EV_DoCeiling(line,lowerToMaxFloor))
  1537. line->special = 0;
  1538. break;
  1539. case 207:
  1540. // killough 2/16/98: W1 silent teleporter (normal kind)
  1541. if (EV_SilentTeleport(line, side, thing))
  1542. line->special = 0;
  1543. break;
  1544. //jff 3/16/98 renumber 215->153
  1545. case 153: //jff 3/15/98 create texture change no motion type
  1546. // Texture/Type Change Only (Trig)
  1547. // 153 W1 Change Texture/Type Only
  1548. if (EV_DoChange(line,trigChangeOnly))
  1549. line->special = 0;
  1550. break;
  1551. case 239: //jff 3/15/98 create texture change no motion type
  1552. // Texture/Type Change Only (Numeric)
  1553. // 239 W1 Change Texture/Type Only
  1554. if (EV_DoChange(line,numChangeOnly))
  1555. line->special = 0;
  1556. break;
  1557. case 219:
  1558. // Lower floor to next lower neighbor
  1559. // 219 W1 Lower Floor Next Lower Neighbor
  1560. if (EV_DoFloor(line,lowerFloorToNearest))
  1561. line->special = 0;
  1562. break;
  1563. case 227:
  1564. // Raise elevator next floor
  1565. // 227 W1 Raise Elevator next floor
  1566. if (EV_DoElevator(line,elevateUp))
  1567. line->special = 0;
  1568. break;
  1569. case 231:
  1570. // Lower elevator next floor
  1571. // 231 W1 Lower Elevator next floor
  1572. if (EV_DoElevator(line,elevateDown))
  1573. line->special = 0;
  1574. break;
  1575. case 235:
  1576. // Elevator to current floor
  1577. // 235 W1 Elevator to current floor
  1578. if (EV_DoElevator(line,elevateCurrent))
  1579. line->special = 0;
  1580. break;
  1581. case 243: //jff 3/6/98 make fit within DCK's 256 linedef types
  1582. // killough 2/16/98: W1 silent teleporter (linedef-linedef kind)
  1583. if (EV_SilentLineTeleport(line, side, thing, false))
  1584. line->special = 0;
  1585. break;
  1586. case 262: //jff 4/14/98 add silent line-line reversed
  1587. if (EV_SilentLineTeleport(line, side, thing, true))
  1588. line->special = 0;
  1589. break;
  1590. case 264: //jff 4/14/98 add monster-only silent line-line reversed
  1591. if (!thing->player &&
  1592. EV_SilentLineTeleport(line, side, thing, true))
  1593. line->special = 0;
  1594. break;
  1595. case 266: //jff 4/14/98 add monster-only silent line-line
  1596. if (!thing->player &&
  1597. EV_SilentLineTeleport(line, side, thing, false))
  1598. line->special = 0;
  1599. break;
  1600. case 268: //jff 4/14/98 add monster-only silent
  1601. if (!thing->player && EV_SilentTeleport(line, side, thing))
  1602. line->special = 0;
  1603. break;
  1604. //jff 1/29/98 end of added W1 linedef types
  1605. // Extended walk many retriggerable
  1606. //jff 1/29/98 added new linedef types to fill all functions
  1607. //out so that all have varieties SR, S1, WR, W1
  1608. case 147:
  1609. // Raise Floor 512
  1610. // 147 WR EV_DoFloor(raiseFloor512)
  1611. EV_DoFloor(line,raiseFloor512);
  1612. break;
  1613. case 148:
  1614. // Raise Floor 24 and Change
  1615. // 148 WR EV_DoPlat(raiseAndChange,24)
  1616. EV_DoPlat(line,raiseAndChange,24);
  1617. break;
  1618. case 149:
  1619. // Raise Floor 32 and Change
  1620. // 149 WR EV_DoPlat(raiseAndChange,32)
  1621. EV_DoPlat(line,raiseAndChange,32);
  1622. break;
  1623. case 150:
  1624. // Start slow silent crusher
  1625. // 150 WR EV_DoCeiling(silentCrushAndRaise)
  1626. EV_DoCeiling(line,silentCrushAndRaise);
  1627. break;
  1628. case 151:
  1629. // RaiseCeilingLowerFloor
  1630. // 151 WR EV_DoCeiling(raiseToHighest),
  1631. // EV_DoFloor(lowerFloortoLowest)
  1632. EV_DoCeiling( line, raiseToHighest );
  1633. EV_DoFloor( line, lowerFloorToLowest );
  1634. break;
  1635. case 152:
  1636. // Lower Ceiling to Floor
  1637. // 152 WR EV_DoCeiling(lowerToFloor)
  1638. EV_DoCeiling( line, lowerToFloor );
  1639. break;
  1640. //jff 3/16/98 renumber 153->256
  1641. case 256:
  1642. // Build stairs, step 8
  1643. // 256 WR EV_BuildStairs(build8)
  1644. EV_BuildStairs(line,build8);
  1645. break;
  1646. //jff 3/16/98 renumber 154->257
  1647. case 257:
  1648. // Build stairs, step 16
  1649. // 257 WR EV_BuildStairs(turbo16)
  1650. EV_BuildStairs(line,turbo16);
  1651. break;
  1652. case 155:
  1653. // Lower Pillar, Raise Donut
  1654. // 155 WR EV_DoDonut()
  1655. EV_DoDonut(line);
  1656. break;
  1657. case 156:
  1658. // Start lights strobing
  1659. // 156 WR Lights EV_StartLightStrobing()
  1660. EV_StartLightStrobing(line);
  1661. break;
  1662. case 157:
  1663. // Lights to dimmest near
  1664. // 157 WR Lights EV_TurnTagLightsOff()
  1665. EV_TurnTagLightsOff(line);
  1666. break;
  1667. case 201:
  1668. // Lower ceiling to lowest surrounding ceiling
  1669. // 201 WR EV_DoCeiling(lowerToLowest)
  1670. EV_DoCeiling(line,lowerToLowest);
  1671. break;
  1672. case 202:
  1673. // Lower ceiling to highest surrounding floor
  1674. // 202 WR EV_DoCeiling(lowerToMaxFloor)
  1675. EV_DoCeiling(line,lowerToMaxFloor);
  1676. break;
  1677. case 208:
  1678. // killough 2/16/98: WR silent teleporter (normal kind)
  1679. EV_SilentTeleport(line, side, thing);
  1680. break;
  1681. case 212: //jff 3/14/98 create instant toggle floor type
  1682. // Toggle floor between C and F instantly
  1683. // 212 WR Instant Toggle Floor
  1684. EV_DoPlat(line,toggleUpDn,0);
  1685. break;
  1686. //jff 3/16/98 renumber 216->154
  1687. case 154: //jff 3/15/98 create texture change no motion type
  1688. // Texture/Type Change Only (Trigger)
  1689. // 154 WR Change Texture/Type Only
  1690. EV_DoChange(line,trigChangeOnly);
  1691. break;
  1692. case 240: //jff 3/15/98 create texture change no motion type
  1693. // Texture/Type Change Only (Numeric)
  1694. // 240 WR Change Texture/Type Only
  1695. EV_DoChange(line,numChangeOnly);
  1696. break;
  1697. case 220:
  1698. // Lower floor to next lower neighbor
  1699. // 220 WR Lower Floor Next Lower Neighbor
  1700. EV_DoFloor(line,lowerFloorToNearest);
  1701. break;
  1702. case 228:
  1703. // Raise elevator next floor
  1704. // 228 WR Raise Elevator next floor
  1705. EV_DoElevator(line,elevateUp);
  1706. break;
  1707. case 232:
  1708. // Lower elevator next floor
  1709. // 232 WR Lower Elevator next floor
  1710. EV_DoElevator(line,elevateDown);
  1711. break;
  1712. case 236:
  1713. // Elevator to current floor
  1714. // 236 WR Elevator to current floor
  1715. EV_DoElevator(line,elevateCurrent);
  1716. break;
  1717. case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
  1718. // killough 2/16/98: WR silent teleporter (linedef-linedef kind)
  1719. EV_SilentLineTeleport(line, side, thing, false);
  1720. break;
  1721. case 263: //jff 4/14/98 add silent line-line reversed
  1722. EV_SilentLineTeleport(line, side, thing, true);
  1723. break;
  1724. case 265: //jff 4/14/98 add monster-only silent line-line reversed
  1725. if (!thing->player)
  1726. EV_SilentLineTeleport(line, side, thing, true);
  1727. break;
  1728. case 267: //jff 4/14/98 add monster-only silent line-line
  1729. if (!thing->player)
  1730. EV_SilentLineTeleport(line, side, thing, false);
  1731. break;
  1732. case 269: //jff 4/14/98 add monster-only silent
  1733. if (!thing->player)
  1734. EV_SilentTeleport(line, side, thing);
  1735. break;
  1736. //jff 1/29/98 end of added WR linedef types
  1737. }
  1738. break;
  1739. }
  1740. }
  1741. //
  1742. // P_ShootSpecialLine - Gun trigger special dispatcher
  1743. //
  1744. // Called when a thing shoots a special line with bullet, shell, saw, or fist.
  1745. //
  1746. // jff 02/12/98 all G1 lines were fixed to check the result from the EV_
  1747. // function before clearing the special. This avoids losing the function
  1748. // of the line, should the sector already be in motion when the line is
  1749. // impacted. Change is qualified by demo_compatibility.
  1750. //
  1751. void P_ShootSpecialLine
  1752. ( mobj_t* thing,
  1753. line_t* line )
  1754. {
  1755. //jff 02/04/98 add check here for generalized linedef
  1756. if (!demo_compatibility)
  1757. {
  1758. // pointer to line function is NULL by default, set non-null if
  1759. // line special is gun triggered generalized linedef type
  1760. int (*linefunc)(line_t *line)=NULL;
  1761. // check each range of generalized linedefs
  1762. if ((unsigned)line->special >= GenEnd)
  1763. {
  1764. // Out of range for GenFloors
  1765. }
  1766. else if ((unsigned)line->special >= GenFloorBase)
  1767. {
  1768. if (!thing->player)
  1769. if ((line->special & FloorChange) || !(line->special & FloorModel))
  1770. return; // FloorModel is "Allow Monsters" if FloorChange is 0
  1771. if (!line->tag) //jff 2/27/98 all gun generalized types require tag
  1772. return;
  1773. linefunc = EV_DoGenFloor;
  1774. }
  1775. else if ((unsigned)line->special >= GenCeilingBase)
  1776. {
  1777. if (!thing->player)
  1778. if ((line->special & CeilingChange) || !(line->special & CeilingModel))
  1779. return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
  1780. if (!line->tag) //jff 2/27/98 all gun generalized types require tag
  1781. return;
  1782. linefunc = EV_DoGenCeiling;
  1783. }
  1784. else if ((unsigned)line->special >= GenDoorBase)
  1785. {
  1786. if (!thing->player)
  1787. {
  1788. if (!(line->special & DoorMonster))
  1789. return; // monsters disallowed from this door
  1790. if (line->flags & ML_SECRET) // they can't open secret doors either
  1791. return;
  1792. }
  1793. if (!line->tag) //jff 3/2/98 all gun generalized types require tag
  1794. return;
  1795. linefunc = EV_DoGenDoor;
  1796. }
  1797. else if ((unsigned)line->special >= GenLockedBase)
  1798. {
  1799. if (!thing->player)
  1800. return; // monsters disallowed from unlocking doors
  1801. if (((line->special&TriggerType)==GunOnce) || ((line->special&TriggerType)==GunMany))
  1802. { //jff 4/1/98 check for being a gun type before reporting door type
  1803. if (!P_CanUnlockGenDoor(line,thing->player))
  1804. return;
  1805. }
  1806. else
  1807. return;
  1808. if (!line->tag) //jff 2/27/98 all gun generalized types require tag
  1809. return;
  1810. linefunc = EV_DoGenLockedDoor;
  1811. }
  1812. else if ((unsigned)line->special >= GenLiftBase)
  1813. {
  1814. if (!thing->player)
  1815. if (!(line->special & LiftMonster))
  1816. return; // monsters disallowed
  1817. linefunc = EV_DoGenLift;
  1818. }
  1819. else if ((unsigned)line->special >= GenStairsBase)
  1820. {
  1821. if (!thing->player)
  1822. if (!(line->special & StairMonster))
  1823. return; // monsters disallowed
  1824. if (!line->tag) //jff 2/27/98 all gun generalized types require tag
  1825. return;
  1826. linefunc = EV_DoGenStairs;
  1827. }
  1828. else if ((unsigned)line->special >= GenCrusherBase)
  1829. {
  1830. if (!thing->player)
  1831. if (!(line->special & StairMonster))
  1832. return; // monsters disallowed
  1833. if (!line->tag) //jff 2/27/98 all gun generalized types require tag
  1834. return;
  1835. linefunc = EV_DoGenCrusher;
  1836. }
  1837. if (linefunc)
  1838. switch((line->special & TriggerType) >> TriggerTypeShift)
  1839. {
  1840. case GunOnce:
  1841. if (linefunc(line))
  1842. P_ChangeSwitchTexture(line,0);
  1843. return;
  1844. case GunMany:
  1845. if (linefunc(line))
  1846. P_ChangeSwitchTexture(line,1);
  1847. return;
  1848. default: // if not a gun type, do nothing here
  1849. return;
  1850. }
  1851. }
  1852. // Impacts that other things can activate.
  1853. if (!thing->player)
  1854. {
  1855. int ok = 0;
  1856. switch(line->special)
  1857. {
  1858. case 46:
  1859. // 46 GR Open door on impact weapon is monster activatable
  1860. ok = 1;
  1861. break;
  1862. }
  1863. if (!ok)
  1864. return;
  1865. }
  1866. if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types
  1867. return;
  1868. switch(line->special)
  1869. {
  1870. case 24:
  1871. // 24 G1 raise floor to highest adjacent
  1872. if (EV_DoFloor(line,raiseFloor) || demo_compatibility)
  1873. P_ChangeSwitchTexture(line,0);
  1874. break;
  1875. case 46:
  1876. // 46 GR open door, stay open
  1877. EV_DoDoor(line,open);
  1878. P_ChangeSwitchTexture(line,1);
  1879. break;
  1880. case 47:
  1881. // 47 G1 raise floor to nearest and change texture and type
  1882. if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility)
  1883. P_ChangeSwitchTexture(line,0);
  1884. break;
  1885. //jff 1/30/98 added new gun linedefs here
  1886. // killough 1/31/98: added demo_compatibility check, added inner switch
  1887. default:
  1888. if (!demo_compatibility)
  1889. switch (line->special)
  1890. {
  1891. case 197:
  1892. // Exit to next level
  1893. // killough 10/98: prevent zombies from exiting levels
  1894. if(thing->player && thing->player->health<=0 && !comp[comp_zombie])
  1895. break;
  1896. P_ChangeSwitchTexture(line,0);
  1897. G_ExitLevel();
  1898. break;
  1899. case 198:
  1900. // Exit to secret level
  1901. // killough 10/98: prevent zombies from exiting levels
  1902. if(thing->player && thing->player->health<=0 && !comp[comp_zombie])
  1903. break;
  1904. P_ChangeSwitchTexture(line,0);
  1905. G_SecretExitLevel();
  1906. break;
  1907. //jff end addition of new gun linedefs
  1908. }
  1909. break;
  1910. }
  1911. }
  1912. //
  1913. // P_PlayerInSpecialSector()
  1914. //
  1915. // Called every tick frame
  1916. // that the player origin is in a special sector
  1917. //
  1918. // Changed to ignore sector types the engine does not recognize
  1919. //
  1920. void P_PlayerInSpecialSector (player_t* player)
  1921. {
  1922. sector_t* sector;
  1923. sector = player->mo->subsector->sector;
  1924. // Falling, not all the way down yet?
  1925. // Sector specials don't apply in mid-air
  1926. if (player->mo->z != sector->floorheight)
  1927. return;
  1928. // Has hit ground.
  1929. //jff add if to handle old vs generalized types
  1930. if (sector->special<32) // regular sector specials
  1931. {
  1932. switch (sector->special)
  1933. {
  1934. case 5:
  1935. // 5/10 unit damage per 31 ticks
  1936. if (!player->powers[pw_ironfeet])
  1937. if (!(leveltime&0x1f))
  1938. P_DamageMobj (player->mo, NULL, NULL, 10);
  1939. break;
  1940. case 7:
  1941. // 2/5 unit damage per 31 ticks
  1942. if (!player->powers[pw_ironfeet])
  1943. if (!(leveltime&0x1f))
  1944. P_DamageMobj (player->mo, NULL, NULL, 5);
  1945. break;
  1946. case 16:
  1947. // 10/20 unit damage per 31 ticks
  1948. case 4:
  1949. // 10/20 unit damage plus blinking light (light already spawned)
  1950. if (!player->powers[pw_ironfeet]
  1951. || (P_Random(pr_slimehurt)<5) ) // even with suit, take damage
  1952. {
  1953. if (!(leveltime&0x1f))
  1954. P_DamageMobj (player->mo, NULL, NULL, 20);
  1955. }
  1956. break;
  1957. case 9:
  1958. // Tally player in secret sector, clear secret special
  1959. player->secretcount++;
  1960. sector->special = 0;
  1961. break;
  1962. case 11:
  1963. // Exit on health < 11, take 10/20 damage per 31 ticks
  1964. if (comp[comp_god]) /* killough 2/21/98: add compatibility switch */
  1965. player->cheats &= ~CF_GODMODE; // on godmode cheat clearing
  1966. // does not affect invulnerability
  1967. if (!(leveltime&0x1f))
  1968. P_DamageMobj (player->mo, NULL, NULL, 20);
  1969. if (player->health <= 10)
  1970. G_ExitLevel();
  1971. break;
  1972. default:
  1973. //jff 1/24/98 Don't exit as DOOM2 did, just ignore
  1974. break;
  1975. };
  1976. }
  1977. else //jff 3/14/98 handle extended sector types for secrets and damage
  1978. {
  1979. switch ((sector->special&DAMAGE_MASK)>>DAMAGE_SHIFT)
  1980. {
  1981. case 0: // no damage
  1982. break;
  1983. case 1: // 2/5 damage per 31 ticks
  1984. if (!player->powers[pw_ironfeet])
  1985. if (!(leveltime&0x1f))
  1986. P_DamageMobj (player->mo, NULL, NULL, 5);
  1987. break;
  1988. case 2: // 5/10 damage per 31 ticks
  1989. if (!player->powers[pw_ironfeet])
  1990. if (!(leveltime&0x1f))
  1991. P_DamageMobj (player->mo, NULL, NULL, 10);
  1992. break;
  1993. case 3: // 10/20 damage per 31 ticks
  1994. if (!player->powers[pw_ironfeet]
  1995. || (P_Random(pr_slimehurt)<5)) // take damage even with suit
  1996. {
  1997. if (!(leveltime&0x1f))
  1998. P_DamageMobj (player->mo, NULL, NULL, 20);
  1999. }
  2000. break;
  2001. }
  2002. if (sector->special&SECRET_MASK)
  2003. {
  2004. player->secretcount++;
  2005. sector->special &= ~SECRET_MASK;
  2006. if (sector->special<32) // if all extended bits clear,
  2007. sector->special=0; // sector is not special anymore
  2008. }
  2009. // phares 3/19/98:
  2010. //
  2011. // If FRICTION_MASK or PUSH_MASK is set, we don't care at this
  2012. // point, since the code to deal with those situations is
  2013. // handled by Thinkers.
  2014. }
  2015. }
  2016. //
  2017. // P_UpdateSpecials()
  2018. //
  2019. // Check level timer, frag counter,
  2020. // animate flats, scroll walls,
  2021. // change button textures
  2022. //
  2023. // Reads and modifies globals:
  2024. // levelTimer, levelTimeCount,
  2025. // levelFragLimit, levelFragLimitCount
  2026. //
  2027. /* JDC static */boolean levelTimer;
  2028. /* JDC static */int levelTimeCount;
  2029. boolean levelFragLimit; // Ty 03/18/98 Added -frags support
  2030. int levelFragLimitCount; // Ty 03/18/98 Added -frags support
  2031. void P_UpdateSpecials (void)
  2032. {
  2033. anim_t* anim;
  2034. int pic;
  2035. int i;
  2036. // Downcount level timer, exit level if elapsed
  2037. if (levelTimer == true)
  2038. {
  2039. levelTimeCount--;
  2040. if (!levelTimeCount)
  2041. G_ExitLevel();
  2042. }
  2043. // Check frag counters, if frag limit reached, exit level // Ty 03/18/98
  2044. // Seems like the total frags should be kept in a simple
  2045. // array somewhere, but until they are...
  2046. if (levelFragLimit == true) // we used -frags so compare count
  2047. {
  2048. int k,m,fragcount,exitflag=false;
  2049. for (k=0;k<MAXPLAYERS;k++)
  2050. {
  2051. if (!playeringame[k]) continue;
  2052. fragcount = 0;
  2053. for (m=0;m<MAXPLAYERS;m++)
  2054. {
  2055. if (!playeringame[m]) continue;
  2056. fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
  2057. }
  2058. if (fragcount >= levelFragLimitCount) exitflag = true;
  2059. if (exitflag == true) break; // skip out of the loop--we're done
  2060. }
  2061. if (exitflag == true)
  2062. G_ExitLevel();
  2063. }
  2064. // Animate flats and textures globally
  2065. for (anim = anims ; anim < lastanim ; anim++)
  2066. {
  2067. for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
  2068. {
  2069. pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
  2070. if (anim->istexture)
  2071. texturetranslation[i] = pic;
  2072. else
  2073. flattranslation[i] = pic;
  2074. }
  2075. }
  2076. // Check buttons (retriggerable switches) and change texture on timeout
  2077. for (i = 0; i < MAXBUTTONS; i++)
  2078. if (buttonlist[i].btimer)
  2079. {
  2080. buttonlist[i].btimer--;
  2081. if (!buttonlist[i].btimer)
  2082. {
  2083. switch(buttonlist[i].where)
  2084. {
  2085. case top:
  2086. sides[buttonlist[i].line->sidenum[0]].toptexture =
  2087. buttonlist[i].btexture;
  2088. break;
  2089. case middle:
  2090. sides[buttonlist[i].line->sidenum[0]].midtexture =
  2091. buttonlist[i].btexture;
  2092. break;
  2093. case bottom:
  2094. sides[buttonlist[i].line->sidenum[0]].bottomtexture =
  2095. buttonlist[i].btexture;
  2096. break;
  2097. }
  2098. {
  2099. /* don't take the address of the switch's sound origin,
  2100. * unless in a compatibility mode. */
  2101. mobj_t *so = (mobj_t *)buttonlist[i].soundorg;
  2102. if (comp[comp_sound] || compatibility_level < prboom_6_compatibility)
  2103. /* since the buttonlist array is usually zeroed out,
  2104. * button popouts generally appear to come from (0,0) */
  2105. so = (mobj_t *)&buttonlist[i].soundorg;
  2106. S_StartSound(so, sfx_swtchn);
  2107. }
  2108. memset(&buttonlist[i],0,sizeof(button_t));
  2109. }
  2110. }
  2111. }
  2112. //////////////////////////////////////////////////////////////////////
  2113. //
  2114. // Sector and Line special thinker spawning at level startup
  2115. //
  2116. //////////////////////////////////////////////////////////////////////
  2117. //
  2118. // P_SpawnSpecials
  2119. // After the map has been loaded,
  2120. // scan for specials that spawn thinkers
  2121. //
  2122. // Parses command line parameters.
  2123. void P_SpawnSpecials (void)
  2124. {
  2125. sector_t* sector;
  2126. int i;
  2127. int episode;
  2128. episode = 1;
  2129. if (W_CheckNumForName("texture2") >= 0)
  2130. episode = 2;
  2131. #ifndef IPHONE // JDC: we set these directly
  2132. // See if -timer needs to be used.
  2133. levelTimer = false;
  2134. i = M_CheckParm("-avg"); // Austin Virtual Gaming 20 min timer on DM play
  2135. if (i && deathmatch)
  2136. {
  2137. levelTimer = true;
  2138. levelTimeCount = 20 * 60 * TICRATE;
  2139. }
  2140. i = M_CheckParm("-timer"); // user defined timer on game play
  2141. if (i && deathmatch)
  2142. {
  2143. int time;
  2144. time = atoi(myargv[i+1]) * 60 * TICRATE;
  2145. levelTimer = true;
  2146. levelTimeCount = time;
  2147. }
  2148. // See if -frags has been used
  2149. levelFragLimit = false;
  2150. i = M_CheckParm("-frags"); // Ty 03/18/98 Added -frags support
  2151. if (i && deathmatch)
  2152. {
  2153. int frags;
  2154. frags = atoi(myargv[i+1]);
  2155. if (frags <= 0) frags = 10; // default 10 if no count provided
  2156. levelFragLimit = true;
  2157. levelFragLimitCount = frags;
  2158. }
  2159. #endif
  2160. // Init special sectors.
  2161. sector = sectors;
  2162. for (i=0 ; i<numsectors ; i++, sector++)
  2163. {
  2164. if (!sector->special)
  2165. continue;
  2166. if (sector->special&SECRET_MASK) //jff 3/15/98 count extended
  2167. totalsecret++; // secret sectors too
  2168. switch (sector->special&31)
  2169. {
  2170. case 1:
  2171. // random off
  2172. P_SpawnLightFlash (sector);
  2173. break;
  2174. case 2:
  2175. // strobe fast
  2176. P_SpawnStrobeFlash(sector,FASTDARK,0);
  2177. break;
  2178. case 3:
  2179. // strobe slow
  2180. P_SpawnStrobeFlash(sector,SLOWDARK,0);
  2181. break;
  2182. case 4:
  2183. // strobe fast/death slime
  2184. P_SpawnStrobeFlash(sector,FASTDARK,0);
  2185. sector->special |= 3<<DAMAGE_SHIFT; //jff 3/14/98 put damage bits in
  2186. break;
  2187. case 8:
  2188. // glowing light
  2189. P_SpawnGlowingLight(sector);
  2190. break;
  2191. case 9:
  2192. // secret sector
  2193. if (sector->special<32) //jff 3/14/98 bits don't count unless not
  2194. totalsecret++; // a generalized sector type
  2195. break;
  2196. case 10:
  2197. // door close in 30 seconds
  2198. P_SpawnDoorCloseIn30 (sector);
  2199. break;
  2200. case 12:
  2201. // sync strobe slow
  2202. P_SpawnStrobeFlash (sector, SLOWDARK, 1);
  2203. break;
  2204. case 13:
  2205. // sync strobe fast
  2206. P_SpawnStrobeFlash (sector, FASTDARK, 1);
  2207. break;
  2208. case 14:
  2209. // door raise in 5 minutes
  2210. P_SpawnDoorRaiseIn5Mins (sector, i);
  2211. break;
  2212. case 17:
  2213. // fire flickering
  2214. P_SpawnFireFlicker(sector);
  2215. break;
  2216. }
  2217. }
  2218. P_RemoveAllActiveCeilings(); // jff 2/22/98 use killough's scheme
  2219. P_RemoveAllActivePlats(); // killough
  2220. for (i = 0;i < MAXBUTTONS;i++)
  2221. memset(&buttonlist[i],0,sizeof(button_t));
  2222. // P_InitTagLists() must be called before P_FindSectorFromLineTag()
  2223. // or P_FindLineFromLineTag() can be called.
  2224. P_InitTagLists(); // killough 1/30/98: Create xref tables for tags
  2225. P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
  2226. P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs
  2227. P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
  2228. for (i=0; i<numlines; i++)
  2229. switch (lines[i].special)
  2230. {
  2231. int s, sec;
  2232. // killough 3/7/98:
  2233. // support for drawn heights coming from different sector
  2234. case 242:
  2235. sec = sides[*lines[i].sidenum].sector-sectors;
  2236. for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
  2237. sectors[s].heightsec = sec;
  2238. break;
  2239. // killough 3/16/98: Add support for setting
  2240. // floor lighting independently (e.g. lava)
  2241. case 213:
  2242. sec = sides[*lines[i].sidenum].sector-sectors;
  2243. for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
  2244. sectors[s].floorlightsec = sec;
  2245. break;
  2246. // killough 4/11/98: Add support for setting
  2247. // ceiling lighting independently
  2248. case 261:
  2249. sec = sides[*lines[i].sidenum].sector-sectors;
  2250. for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
  2251. sectors[s].ceilinglightsec = sec;
  2252. break;
  2253. // killough 10/98:
  2254. //
  2255. // Support for sky textures being transferred from sidedefs.
  2256. // Allows scrolling and other effects (but if scrolling is
  2257. // used, then the same sector tag needs to be used for the
  2258. // sky sector, the sky-transfer linedef, and the scroll-effect
  2259. // linedef). Still requires user to use F_SKY1 for the floor
  2260. // or ceiling texture, to distinguish floor and ceiling sky.
  2261. case 271: // Regular sky
  2262. case 272: // Same, only flipped
  2263. for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;)
  2264. sectors[s].sky = i | PL_SKYFLAT;
  2265. break;
  2266. }
  2267. }
  2268. // killough 2/28/98:
  2269. //
  2270. // This function, with the help of r_plane.c and r_bsp.c, supports generalized
  2271. // scrolling floors and walls, with optional mobj-carrying properties, e.g.
  2272. // conveyor belts, rivers, etc. A linedef with a special type affects all
  2273. // tagged sectors the same way, by creating scrolling and/or object-carrying
  2274. // properties. Multiple linedefs may be used on the same sector and are
  2275. // cumulative, although the special case of scrolling a floor and carrying
  2276. // things on it, requires only one linedef. The linedef's direction determines
  2277. // the scrolling direction, and the linedef's length determines the scrolling
  2278. // speed. This was designed so that an edge around the sector could be used to
  2279. // control the direction of the sector's scrolling, which is usually what is
  2280. // desired.
  2281. //
  2282. // Process the active scrollers.
  2283. //
  2284. // This is the main scrolling code
  2285. // killough 3/7/98
  2286. void T_Scroll(scroll_t *s)
  2287. {
  2288. fixed_t dx = s->dx, dy = s->dy;
  2289. if (s->control != -1)
  2290. { // compute scroll amounts based on a sector's height changes
  2291. fixed_t height = sectors[s->control].floorheight +
  2292. sectors[s->control].ceilingheight;
  2293. fixed_t delta = height - s->last_height;
  2294. s->last_height = height;
  2295. dx = FixedMul(dx, delta);
  2296. dy = FixedMul(dy, delta);
  2297. }
  2298. // killough 3/14/98: Add acceleration
  2299. if (s->accel)
  2300. {
  2301. s->vdx = dx += s->vdx;
  2302. s->vdy = dy += s->vdy;
  2303. }
  2304. if (!(dx | dy)) // no-op if both (x,y) offsets 0
  2305. return;
  2306. switch (s->type)
  2307. {
  2308. side_t *side;
  2309. sector_t *sec;
  2310. fixed_t height, waterheight; // killough 4/4/98: add waterheight
  2311. msecnode_t *node;
  2312. mobj_t *thing;
  2313. case sc_side: // killough 3/7/98: Scroll wall texture
  2314. side = sides + s->affectee;
  2315. side->textureoffset += dx;
  2316. side->rowoffset += dy;
  2317. break;
  2318. case sc_floor: // killough 3/7/98: Scroll floor texture
  2319. sec = sectors + s->affectee;
  2320. sec->floor_xoffs += dx;
  2321. sec->floor_yoffs += dy;
  2322. break;
  2323. case sc_ceiling: // killough 3/7/98: Scroll ceiling texture
  2324. sec = sectors + s->affectee;
  2325. sec->ceiling_xoffs += dx;
  2326. sec->ceiling_yoffs += dy;
  2327. break;
  2328. case sc_carry:
  2329. // killough 3/7/98: Carry things on floor
  2330. // killough 3/20/98: use new sector list which reflects true members
  2331. // killough 3/27/98: fix carrier bug
  2332. // killough 4/4/98: Underwater, carry things even w/o gravity
  2333. sec = sectors + s->affectee;
  2334. height = sec->floorheight;
  2335. waterheight = sec->heightsec != -1 &&
  2336. sectors[sec->heightsec].floorheight > height ?
  2337. sectors[sec->heightsec].floorheight : INT_MIN;
  2338. for (node = sec->touching_thinglist; node; node = node->m_snext)
  2339. if (!((thing = node->m_thing)->flags & MF_NOCLIP) &&
  2340. (!(thing->flags & MF_NOGRAVITY || thing->z > height) ||
  2341. thing->z < waterheight))
  2342. {
  2343. // Move objects only if on floor or underwater,
  2344. // non-floating, and clipped.
  2345. thing->momx += dx;
  2346. thing->momy += dy;
  2347. }
  2348. break;
  2349. case sc_carry_ceiling: // to be added later
  2350. break;
  2351. }
  2352. }
  2353. //
  2354. // Add_Scroller()
  2355. //
  2356. // Add a generalized scroller to the thinker list.
  2357. //
  2358. // type: the enumerated type of scrolling: floor, ceiling, floor carrier,
  2359. // wall, floor carrier & scroller
  2360. //
  2361. // (dx,dy): the direction and speed of the scrolling or its acceleration
  2362. //
  2363. // control: the sector whose heights control this scroller's effect
  2364. // remotely, or -1 if no control sector
  2365. //
  2366. // affectee: the index of the affected object (sector or sidedef)
  2367. //
  2368. // accel: non-zero if this is an accelerative effect
  2369. //
  2370. static void Add_Scroller(int type, fixed_t dx, fixed_t dy,
  2371. int control, int affectee, int accel)
  2372. {
  2373. scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0);
  2374. s->thinker.function = T_Scroll;
  2375. s->type = type;
  2376. s->dx = dx;
  2377. s->dy = dy;
  2378. s->accel = accel;
  2379. s->vdx = s->vdy = 0;
  2380. if ((s->control = control) != -1)
  2381. s->last_height =
  2382. sectors[control].floorheight + sectors[control].ceilingheight;
  2383. s->affectee = affectee;
  2384. P_AddThinker(&s->thinker);
  2385. }
  2386. // Adds wall scroller. Scroll amount is rotated with respect to wall's
  2387. // linedef first, so that scrolling towards the wall in a perpendicular
  2388. // direction is translated into vertical motion, while scrolling along
  2389. // the wall in a parallel direction is translated into horizontal motion.
  2390. //
  2391. // killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff
  2392. //
  2393. // killough 10/98:
  2394. // fix scrolling aliasing problems, caused by long linedefs causing overflowing
  2395. static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l,
  2396. int control, int accel)
  2397. {
  2398. fixed_t x = D_abs(l->dx), y = D_abs(l->dy), d;
  2399. if (y > x)
  2400. d = x, x = y, y = d;
  2401. d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90)
  2402. >> ANGLETOFINESHIFT]);
  2403. // CPhipps - Import scroller calc overflow fix, compatibility optioned
  2404. if (compatibility_level >= lxdoom_1_compatibility) {
  2405. x = (fixed_t)(((int_64_t)dy * -(int_64_t)l->dy - (int_64_t)dx * (int_64_t)l->dx) / (int_64_t)d); // killough 10/98:
  2406. y = (fixed_t)(((int_64_t)dy * (int_64_t)l->dx - (int_64_t)dx * (int_64_t)l->dy) / (int_64_t)d); // Use long long arithmetic
  2407. } else {
  2408. x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d);
  2409. y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d);
  2410. }
  2411. Add_Scroller(sc_side, x, y, control, *l->sidenum, accel);
  2412. }
  2413. // Amount (dx,dy) vector linedef is shifted right to get scroll amount
  2414. #define SCROLL_SHIFT 5
  2415. // Factor to scale scrolling effect into mobj-carrying properties = 3/32.
  2416. // (This is so scrolling floors and objects on them can move at same speed.)
  2417. #define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375))
  2418. // Initialize the scrollers
  2419. static void P_SpawnScrollers(void)
  2420. {
  2421. int i;
  2422. line_t *l = lines;
  2423. for (i=0;i<numlines;i++,l++)
  2424. {
  2425. fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
  2426. fixed_t dy = l->dy >> SCROLL_SHIFT;
  2427. int control = -1, accel = 0; // no control sector or acceleration
  2428. int special = l->special;
  2429. // killough 3/7/98: Types 245-249 are same as 250-254 except that the
  2430. // first side's sector's heights cause scrolling when they change, and
  2431. // this linedef controls the direction and speed of the scrolling. The
  2432. // most complicated linedef since donuts, but powerful :)
  2433. //
  2434. // killough 3/15/98: Add acceleration. Types 214-218 are the same but
  2435. // are accelerative.
  2436. if (special >= 245 && special <= 249) // displacement scrollers
  2437. {
  2438. special += 250-245;
  2439. control = sides[*l->sidenum].sector - sectors;
  2440. }
  2441. else
  2442. if (special >= 214 && special <= 218) // accelerative scrollers
  2443. {
  2444. accel = 1;
  2445. special += 250-214;
  2446. control = sides[*l->sidenum].sector - sectors;
  2447. }
  2448. switch (special)
  2449. {
  2450. register int s;
  2451. case 250: // scroll effect ceiling
  2452. for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
  2453. Add_Scroller(sc_ceiling, -dx, dy, control, s, accel);
  2454. break;
  2455. case 251: // scroll effect floor
  2456. case 253: // scroll and carry objects on floor
  2457. for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
  2458. Add_Scroller(sc_floor, -dx, dy, control, s, accel);
  2459. if (special != 253)
  2460. break;
  2461. case 252: // carry objects on floor
  2462. dx = FixedMul(dx,CARRYFACTOR);
  2463. dy = FixedMul(dy,CARRYFACTOR);
  2464. for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;)
  2465. Add_Scroller(sc_carry, dx, dy, control, s, accel);
  2466. break;
  2467. // killough 3/1/98: scroll wall according to linedef
  2468. // (same direction and speed as scrolling floors)
  2469. case 254:
  2470. for (s=-1; (s = P_FindLineFromLineTag(l,s)) >= 0;)
  2471. if (s != i)
  2472. Add_WallScroller(dx, dy, lines+s, control, accel);
  2473. break;
  2474. case 255: // killough 3/2/98: scroll according to sidedef offsets
  2475. s = lines[i].sidenum[0];
  2476. Add_Scroller(sc_side, -sides[s].textureoffset,
  2477. sides[s].rowoffset, -1, s, accel);
  2478. break;
  2479. case 48: // scroll first side
  2480. Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
  2481. break;
  2482. case 85: // jff 1/30/98 2-way scroll
  2483. Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
  2484. break;
  2485. }
  2486. }
  2487. }
  2488. // e6y
  2489. // restored boom's friction code
  2490. /////////////////////////////
  2491. //
  2492. // Add a friction thinker to the thinker list
  2493. //
  2494. // Add_Friction adds a new friction thinker to the list of active thinkers.
  2495. //
  2496. static void Add_Friction(int friction, int movefactor, int affectee)
  2497. {
  2498. friction_t *f = Z_Malloc(sizeof *f, PU_LEVSPEC, 0);
  2499. f->thinker.function/*.acp1*/ = /*(actionf_p1) */T_Friction;
  2500. f->friction = friction;
  2501. f->movefactor = movefactor;
  2502. f->affectee = affectee;
  2503. P_AddThinker(&f->thinker);
  2504. }
  2505. /////////////////////////////
  2506. //
  2507. // This is where abnormal friction is applied to objects in the sectors.
  2508. // A friction thinker has been spawned for each sector where less or
  2509. // more friction should be applied. The amount applied is proportional to
  2510. // the length of the controlling linedef.
  2511. void T_Friction(friction_t *f)
  2512. {
  2513. sector_t *sec;
  2514. mobj_t *thing;
  2515. msecnode_t* node;
  2516. if (compatibility || !variable_friction)
  2517. return;
  2518. sec = sectors + f->affectee;
  2519. // Be sure the special sector type is still turned on. If so, proceed.
  2520. // Else, bail out; the sector type has been changed on us.
  2521. if (!(sec->special & FRICTION_MASK))
  2522. return;
  2523. // Assign the friction value to players on the floor, non-floating,
  2524. // and clipped. Normally the object's friction value is kept at
  2525. // ORIG_FRICTION and this thinker changes it for icy or muddy floors.
  2526. // In Phase II, you can apply friction to Things other than players.
  2527. // When the object is straddling sectors with the same
  2528. // floorheight that have different frictions, use the lowest
  2529. // friction value (muddy has precedence over icy).
  2530. node = sec->touching_thinglist; // things touching this sector
  2531. while (node)
  2532. {
  2533. thing = node->m_thing;
  2534. if (thing->player &&
  2535. !(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) &&
  2536. thing->z <= sec->floorheight)
  2537. {
  2538. if ((thing->friction == ORIG_FRICTION) || // normal friction?
  2539. (f->friction < thing->friction))
  2540. {
  2541. thing->friction = f->friction;
  2542. thing->movefactor = f->movefactor;
  2543. }
  2544. }
  2545. node = node->m_snext;
  2546. }
  2547. }
  2548. // killough 3/7/98 -- end generalized scroll effects
  2549. ////////////////////////////////////////////////////////////////////////////
  2550. //
  2551. // FRICTION EFFECTS
  2552. //
  2553. // phares 3/12/98: Start of friction effects
  2554. //
  2555. // As the player moves, friction is applied by decreasing the x and y
  2556. // momentum values on each tic. By varying the percentage of decrease,
  2557. // we can simulate muddy or icy conditions. In mud, the player slows
  2558. // down faster. In ice, the player slows down more slowly.
  2559. //
  2560. // The amount of friction change is controlled by the length of a linedef
  2561. // with type 223. A length < 100 gives you mud. A length > 100 gives you ice.
  2562. //
  2563. // Also, each sector where these effects are to take place is given a
  2564. // new special type _______. Changing the type value at runtime allows
  2565. // these effects to be turned on or off.
  2566. //
  2567. // Sector boundaries present problems. The player should experience these
  2568. // friction changes only when his feet are touching the sector floor. At
  2569. // sector boundaries where floor height changes, the player can find
  2570. // himself still 'in' one sector, but with his feet at the floor level
  2571. // of the next sector (steps up or down). To handle this, Thinkers are used
  2572. // in icy/muddy sectors. These thinkers examine each object that is touching
  2573. // their sectors, looking for players whose feet are at the same level as
  2574. // their floors. Players satisfying this condition are given new friction
  2575. // values that are applied by the player movement code later.
  2576. //
  2577. // killough 8/28/98:
  2578. //
  2579. // Completely redid code, which did not need thinkers, and which put a heavy
  2580. // drag on CPU. Friction is now a property of sectors, NOT objects inside
  2581. // them. All objects, not just players, are affected by it, if they touch
  2582. // the sector's floor. Code simpler and faster, only calling on friction
  2583. // calculations when an object needs friction considered, instead of doing
  2584. // friction calculations on every sector during every tic.
  2585. //
  2586. // Although this -might- ruin Boom demo sync involving friction, it's the only
  2587. // way, short of code explosion, to fix the original design bug. Fixing the
  2588. // design bug in Boom's original friction code, while maintaining demo sync
  2589. // under every conceivable circumstance, would double or triple code size, and
  2590. // would require maintenance of buggy legacy code which is only useful for old
  2591. // demos. Doom demos, which are more important IMO, are not affected by this
  2592. // change.
  2593. //
  2594. /////////////////////////////
  2595. //
  2596. // Initialize the sectors where friction is increased or decreased
  2597. static void P_SpawnFriction(void)
  2598. {
  2599. int i;
  2600. line_t *l = lines;
  2601. // killough 8/28/98: initialize all sectors to normal friction first
  2602. for (i = 0; i < numsectors; i++)
  2603. {
  2604. sectors[i].friction = ORIG_FRICTION;
  2605. sectors[i].movefactor = ORIG_FRICTION_FACTOR;
  2606. }
  2607. for (i = 0 ; i < numlines ; i++,l++)
  2608. if (l->special == 223)
  2609. {
  2610. int length = P_AproxDistance(l->dx,l->dy)>>FRACBITS;
  2611. int friction = (0x1EB8*length)/0x80 + 0xD000;
  2612. int movefactor, s;
  2613. // The following check might seem odd. At the time of movement,
  2614. // the move distance is multiplied by 'friction/0x10000', so a
  2615. // higher friction value actually means 'less friction'.
  2616. if (friction > ORIG_FRICTION) // ice
  2617. movefactor = ((0x10092 - friction)*(0x70))/0x158;
  2618. else
  2619. movefactor = ((friction - 0xDB34)*(0xA))/0x80;
  2620. if (mbf_features)
  2621. { // killough 8/28/98: prevent odd situations
  2622. if (friction > FRACUNIT)
  2623. friction = FRACUNIT;
  2624. if (friction < 0)
  2625. friction = 0;
  2626. if (movefactor < 32)
  2627. movefactor = 32;
  2628. }
  2629. for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
  2630. {
  2631. // killough 8/28/98:
  2632. //
  2633. // Instead of spawning thinkers, which are slow and expensive,
  2634. // modify the sector's own friction values. Friction should be
  2635. // a property of sectors, not objects which reside inside them.
  2636. // Original code scanned every object in every friction sector
  2637. // on every tic, adjusting its friction, putting unnecessary
  2638. // drag on CPU. New code adjusts friction of sector only once
  2639. // at level startup, and then uses this friction value.
  2640. //e6y: boom's friction code for boom compatibility
  2641. if (!demo_compatibility && !mbf_features)
  2642. Add_Friction(friction,movefactor,s);
  2643. sectors[s].friction = friction;
  2644. sectors[s].movefactor = movefactor;
  2645. }
  2646. }
  2647. }
  2648. //
  2649. // phares 3/12/98: End of friction effects
  2650. //
  2651. ////////////////////////////////////////////////////////////////////////////
  2652. ////////////////////////////////////////////////////////////////////////////
  2653. //
  2654. // PUSH/PULL EFFECT
  2655. //
  2656. // phares 3/20/98: Start of push/pull effects
  2657. //
  2658. // This is where push/pull effects are applied to objects in the sectors.
  2659. //
  2660. // There are four kinds of push effects
  2661. //
  2662. // 1) Pushing Away
  2663. //
  2664. // Pushes you away from a point source defined by the location of an
  2665. // MT_PUSH Thing. The force decreases linearly with distance from the
  2666. // source. This force crosses sector boundaries and is felt w/in a circle
  2667. // whose center is at the MT_PUSH. The force is felt only if the point
  2668. // MT_PUSH can see the target object.
  2669. //
  2670. // 2) Pulling toward
  2671. //
  2672. // Same as Pushing Away except you're pulled toward an MT_PULL point
  2673. // source. This force crosses sector boundaries and is felt w/in a circle
  2674. // whose center is at the MT_PULL. The force is felt only if the point
  2675. // MT_PULL can see the target object.
  2676. //
  2677. // 3) Wind
  2678. //
  2679. // Pushes you in a constant direction. Full force above ground, half
  2680. // force on the ground, nothing if you're below it (water).
  2681. //
  2682. // 4) Current
  2683. //
  2684. // Pushes you in a constant direction. No force above ground, full
  2685. // force if on the ground or below it (water).
  2686. //
  2687. // The magnitude of the force is controlled by the length of a controlling
  2688. // linedef. The force vector for types 3 & 4 is determined by the angle
  2689. // of the linedef, and is constant.
  2690. //
  2691. // For each sector where these effects occur, the sector special type has
  2692. // to have the PUSH_MASK bit set. If this bit is turned off by a switch
  2693. // at run-time, the effect will not occur. The controlling sector for
  2694. // types 1 & 2 is the sector containing the MT_PUSH/MT_PULL Thing.
  2695. #define PUSH_FACTOR 7
  2696. /////////////////////////////
  2697. //
  2698. // Add a push thinker to the thinker list
  2699. static void Add_Pusher(int type, int x_mag, int y_mag, mobj_t* source, int affectee)
  2700. {
  2701. pusher_t *p = Z_Malloc(sizeof *p, PU_LEVSPEC, 0);
  2702. p->thinker.function = T_Pusher;
  2703. p->source = source;
  2704. p->type = type;
  2705. p->x_mag = x_mag>>FRACBITS;
  2706. p->y_mag = y_mag>>FRACBITS;
  2707. p->magnitude = P_AproxDistance(p->x_mag,p->y_mag);
  2708. if (source) // point source exist?
  2709. {
  2710. p->radius = (p->magnitude)<<(FRACBITS+1); // where force goes to zero
  2711. p->x = p->source->x;
  2712. p->y = p->source->y;
  2713. }
  2714. p->affectee = affectee;
  2715. P_AddThinker(&p->thinker);
  2716. }
  2717. /////////////////////////////
  2718. //
  2719. // PIT_PushThing determines the angle and magnitude of the effect.
  2720. // The object's x and y momentum values are changed.
  2721. //
  2722. // tmpusher belongs to the point source (MT_PUSH/MT_PULL).
  2723. //
  2724. // killough 10/98: allow to affect things besides players
  2725. pusher_t* tmpusher; // pusher structure for blockmap searches
  2726. static boolean PIT_PushThing(mobj_t* thing)
  2727. {
  2728. /* killough 10/98: made more general */
  2729. if (!mbf_features ?
  2730. thing->player && !(thing->flags & (MF_NOCLIP | MF_NOGRAVITY)) :
  2731. (sentient(thing) || thing->flags & MF_SHOOTABLE) &&
  2732. !(thing->flags & MF_NOCLIP))
  2733. {
  2734. angle_t pushangle;
  2735. fixed_t speed;
  2736. fixed_t sx = tmpusher->x;
  2737. fixed_t sy = tmpusher->y;
  2738. speed = (tmpusher->magnitude -
  2739. ((P_AproxDistance(thing->x - sx,thing->y - sy)
  2740. >>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1);
  2741. // killough 10/98: make magnitude decrease with square
  2742. // of distance, making it more in line with real nature,
  2743. // so long as it's still in range with original formula.
  2744. //
  2745. // Removes angular distortion, and makes effort required
  2746. // to stay close to source, grow increasingly hard as you
  2747. // get closer, as expected. Still, it doesn't consider z :(
  2748. if (speed > 0 && mbf_features)
  2749. {
  2750. int x = (thing->x-sx) >> FRACBITS;
  2751. int y = (thing->y-sy) >> FRACBITS;
  2752. speed = (int)(((uint_64_t) tmpusher->magnitude << 23) / (x*x+y*y+1));
  2753. }
  2754. // If speed <= 0, you're outside the effective radius. You also have
  2755. // to be able to see the push/pull source point.
  2756. if (speed > 0 && P_CheckSight(thing,tmpusher->source))
  2757. {
  2758. pushangle = R_PointToAngle2(thing->x,thing->y,sx,sy);
  2759. if (tmpusher->source->type == MT_PUSH)
  2760. pushangle += ANG180; // away
  2761. pushangle >>= ANGLETOFINESHIFT;
  2762. thing->momx += FixedMul(speed,finecosine[pushangle]);
  2763. thing->momy += FixedMul(speed,finesine[pushangle]);
  2764. }
  2765. }
  2766. return true;
  2767. }
  2768. /////////////////////////////
  2769. //
  2770. // T_Pusher looks for all objects that are inside the radius of
  2771. // the effect.
  2772. //
  2773. void T_Pusher(pusher_t *p)
  2774. {
  2775. sector_t *sec;
  2776. mobj_t *thing;
  2777. msecnode_t* node;
  2778. int xspeed,yspeed;
  2779. int xl,xh,yl,yh,bx,by;
  2780. int radius;
  2781. int ht = 0;
  2782. if (!allow_pushers)
  2783. return;
  2784. sec = sectors + p->affectee;
  2785. // Be sure the special sector type is still turned on. If so, proceed.
  2786. // Else, bail out; the sector type has been changed on us.
  2787. if (!(sec->special & PUSH_MASK))
  2788. return;
  2789. // For constant pushers (wind/current) there are 3 situations:
  2790. //
  2791. // 1) Affected Thing is above the floor.
  2792. //
  2793. // Apply the full force if wind, no force if current.
  2794. //
  2795. // 2) Affected Thing is on the ground.
  2796. //
  2797. // Apply half force if wind, full force if current.
  2798. //
  2799. // 3) Affected Thing is below the ground (underwater effect).
  2800. //
  2801. // Apply no force if wind, full force if current.
  2802. if (p->type == p_push)
  2803. {
  2804. // Seek out all pushable things within the force radius of this
  2805. // point pusher. Crosses sectors, so use blockmap.
  2806. tmpusher = p; // MT_PUSH/MT_PULL point source
  2807. radius = p->radius; // where force goes to zero
  2808. tmbbox[BOXTOP] = p->y + radius;
  2809. tmbbox[BOXBOTTOM] = p->y - radius;
  2810. tmbbox[BOXRIGHT] = p->x + radius;
  2811. tmbbox[BOXLEFT] = p->x - radius;
  2812. xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
  2813. xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
  2814. yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
  2815. yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
  2816. for (bx=xl ; bx<=xh ; bx++)
  2817. for (by=yl ; by<=yh ; by++)
  2818. P_BlockThingsIterator(bx,by,PIT_PushThing);
  2819. return;
  2820. }
  2821. // constant pushers p_wind and p_current
  2822. if (sec->heightsec != -1) // special water sector?
  2823. ht = sectors[sec->heightsec].floorheight;
  2824. node = sec->touching_thinglist; // things touching this sector
  2825. for ( ; node ; node = node->m_snext)
  2826. {
  2827. thing = node->m_thing;
  2828. if (!thing->player || (thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
  2829. continue;
  2830. if (p->type == p_wind)
  2831. {
  2832. if (sec->heightsec == -1) // NOT special water sector
  2833. if (thing->z > thing->floorz) // above ground
  2834. {
  2835. xspeed = p->x_mag; // full force
  2836. yspeed = p->y_mag;
  2837. }
  2838. else // on ground
  2839. {
  2840. xspeed = (p->x_mag)>>1; // half force
  2841. yspeed = (p->y_mag)>>1;
  2842. }
  2843. else // special water sector
  2844. {
  2845. if (thing->z > ht) // above ground
  2846. {
  2847. xspeed = p->x_mag; // full force
  2848. yspeed = p->y_mag;
  2849. }
  2850. else if (thing->player->viewz < ht) // underwater
  2851. xspeed = yspeed = 0; // no force
  2852. else // wading in water
  2853. {
  2854. xspeed = (p->x_mag)>>1; // half force
  2855. yspeed = (p->y_mag)>>1;
  2856. }
  2857. }
  2858. }
  2859. else // p_current
  2860. {
  2861. if (sec->heightsec == -1) // NOT special water sector
  2862. if (thing->z > sec->floorheight) // above ground
  2863. xspeed = yspeed = 0; // no force
  2864. else // on ground
  2865. {
  2866. xspeed = p->x_mag; // full force
  2867. yspeed = p->y_mag;
  2868. }
  2869. else // special water sector
  2870. if (thing->z > ht) // above ground
  2871. xspeed = yspeed = 0; // no force
  2872. else // underwater
  2873. {
  2874. xspeed = p->x_mag; // full force
  2875. yspeed = p->y_mag;
  2876. }
  2877. }
  2878. thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR);
  2879. thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR);
  2880. }
  2881. }
  2882. /////////////////////////////
  2883. //
  2884. // P_GetPushThing() returns a pointer to an MT_PUSH or MT_PULL thing,
  2885. // NULL otherwise.
  2886. mobj_t* P_GetPushThing(int s)
  2887. {
  2888. mobj_t* thing;
  2889. sector_t* sec;
  2890. sec = sectors + s;
  2891. thing = sec->thinglist;
  2892. while (thing)
  2893. {
  2894. switch(thing->type)
  2895. {
  2896. case MT_PUSH:
  2897. case MT_PULL:
  2898. return thing;
  2899. default:
  2900. break;
  2901. }
  2902. thing = thing->snext;
  2903. }
  2904. return NULL;
  2905. }
  2906. /////////////////////////////
  2907. //
  2908. // Initialize the sectors where pushers are present
  2909. //
  2910. static void P_SpawnPushers(void)
  2911. {
  2912. int i;
  2913. line_t *l = lines;
  2914. register int s;
  2915. mobj_t* thing;
  2916. for (i = 0 ; i < numlines ; i++,l++)
  2917. switch(l->special)
  2918. {
  2919. case 224: // wind
  2920. for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
  2921. Add_Pusher(p_wind,l->dx,l->dy,NULL,s);
  2922. break;
  2923. case 225: // current
  2924. for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
  2925. Add_Pusher(p_current,l->dx,l->dy,NULL,s);
  2926. break;
  2927. case 226: // push/pull
  2928. for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; )
  2929. {
  2930. thing = P_GetPushThing(s);
  2931. if (thing) // No MT_P* means no effect
  2932. Add_Pusher(p_push,l->dx,l->dy,thing,s);
  2933. }
  2934. break;
  2935. }
  2936. }
  2937. //
  2938. // phares 3/20/98: End of Pusher effects
  2939. //
  2940. ////////////////////////////////////////////////////////////////////////////