C5_WIZ.C 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. // C3_WIZ.C
  19. #include "DEF.H"
  20. #include "gelib.h"
  21. #pragma hdrstop
  22. /*
  23. =============================================================================
  24. LOCAL CONSTANTS
  25. =============================================================================
  26. */
  27. ////////#define NUMSCROLLS 8
  28. #define SHOWITEMS 9
  29. #define NUKETIME 40
  30. #define NUMBOLTS 10
  31. #define BOLTTICS 6
  32. #define STATUSCOLOR 8
  33. #define TEXTCOLOR 14
  34. #define SIDEBARWIDTH 5
  35. #define BODYLINE 8
  36. #define POWERLINE 80
  37. #define SPECTILESTART 0 // 18
  38. #define SHOTDAMAGE 1
  39. #define BIGSHOTDAMAGE 3
  40. #define PLAYERSPEED 5120
  41. #define RUNSPEED (8192<<1)
  42. #define SHOTSPEED 10000
  43. //#define LASTWALLTILE 47
  44. //#define LASTSPECIALTILE 37
  45. #define LASTTILE (LASTWALLPIC-FIRSTWALLPIC) // 47
  46. #define FIRETIME 2
  47. #define HANDPAUSE 60
  48. #define RIGHTEDGE 205;
  49. #define LEFTEDGE 95;
  50. #define PRNY 32;
  51. #define WINX 10;
  52. #define WINY 32;
  53. /*
  54. =============================================================================
  55. GLOBAL VARIABLES
  56. =============================================================================
  57. */
  58. long lastnuke,lasthand;
  59. int lasttext;
  60. int handheight;
  61. int boltsleft,bolttimer;
  62. short RadarXY[MAX_RADAR_BLIPS][3]={-1,-1,-1};
  63. short radarx=RADARX,radary=RADARY,radar_xcenter=RADAR_XCENTER,radar_ycenter=RADAR_YCENTER;
  64. int key_x[4]={24,27,27,24},key_y[4]={30,57,30,57};
  65. boolean redraw_gems,button0down;
  66. /*
  67. =============================================================================
  68. LOCAL VARIABLES
  69. =============================================================================
  70. */
  71. int lastradar;
  72. unsigned lastfiretime;
  73. int strafeangle[9] = {0,90,180,270,45,135,225,315,0};
  74. short RotateAngle = -1; // -1 == No Angle to turn to...
  75. short FreezeTime = 0; // Stops all think (except player)
  76. short RotateSpeed; // Speed (and dir) to rotate..
  77. //===========================================================================
  78. void CalcBounds(objtype *ob);
  79. boolean VerifyGateExit(void);
  80. void DrawNSEWIcons(void);
  81. void DrawGems(void);
  82. void DrawRadar (void);
  83. void DrawChar (unsigned x, unsigned y, unsigned tile);
  84. void RedrawStatusWindow (void);
  85. void GiveBolt (void);
  86. void TakeBolt (void);
  87. void GiveNuke (void);
  88. void TakeNuke (void);
  89. void GivePotion (void);
  90. void TakePotion (void);
  91. void GiveKey (int keytype);
  92. void TakeKey (int keytype);
  93. ////////////void GiveScroll (int scrolltype,boolean show);
  94. ////////////void ReadScroll (int scroll);
  95. ////////////void DrawScrolls(void);
  96. void DrawNum(short x,short y,short value,short maxdigits);
  97. //----------
  98. void Shoot (void);
  99. void BigShoot (void);
  100. void CastBolt (void);
  101. void CastNuke (void);
  102. void DrinkPotion (void);
  103. //----------
  104. void DrawHealth(void);
  105. void SpawnPlayer (int tilex, int tiley, int dir);
  106. void Thrust (int angle, unsigned speed);
  107. void T_Player (objtype *ob);
  108. //void AddPoints (int points);
  109. void ClipMove (objtype *ob, long xmove, long ymove);
  110. boolean ShotClipMove (objtype *ob, long xmove, long ymove);
  111. //===========================================================================
  112. /*
  113. ===============
  114. =
  115. = DrawChar
  116. =
  117. ===============
  118. */
  119. void DrawChar (unsigned x, unsigned y, unsigned tile)
  120. {
  121. unsigned junk = latchpics[0];
  122. EGAWRITEMODE(1);
  123. asm mov bx,[y]
  124. asm shl bx,1
  125. asm mov di,[WORD PTR ylookup+bx]
  126. asm add di,[x]
  127. asm mov si,[tile]
  128. asm shl si,1
  129. asm shl si,1
  130. asm shl si,1
  131. asm add si,[junk] // the damn inline assembler won't reference latchpics
  132. asm mov ax,[screenseg]
  133. asm mov es,ax
  134. asm mov ds,ax
  135. asm mov dx,SCREENWIDTH-1
  136. asm movsb
  137. asm add di,dx
  138. asm movsb
  139. asm add di,dx
  140. asm movsb
  141. asm add di,dx
  142. asm movsb
  143. asm add di,dx
  144. asm movsb
  145. asm add di,dx
  146. asm movsb
  147. asm add di,dx
  148. asm movsb
  149. asm add di,dx
  150. asm movsb
  151. asm mov ax,ss
  152. asm mov ds,ax
  153. EGAWRITEMODE(0);
  154. }
  155. //===========================================================================
  156. /*
  157. ===============
  158. =
  159. = RedrawStatusWindow
  160. =
  161. ===============
  162. */
  163. void RedrawStatusWindow (void)
  164. {
  165. short keytype;
  166. EGABITMASK(0xff);
  167. for (keytype=0; keytype<4; keytype++)
  168. DrawNum(key_x[keytype],key_y[keytype],gamestate.keys[keytype],2);
  169. DrawNum(20,54,gamestate.potions,2);
  170. DrawNum(20,36,gamestate.nukes,2);
  171. DrawNum(20,18,gamestate.bolts,2);
  172. DrawHealth();
  173. DrawRadar();
  174. EGAWRITEMODE(0);
  175. DrawGems();
  176. //////// DrawScrolls();
  177. redraw_gems = false;
  178. }
  179. //===========================================================================
  180. /*
  181. ===============
  182. =
  183. = GiveBolt
  184. =
  185. ===============
  186. */
  187. void GiveBolt (void)
  188. {
  189. if (gamestate.bolts == 99)
  190. return;
  191. SD_PlaySound (GETBOLTSND);
  192. DrawNum(20,18,++gamestate.bolts,2);
  193. }
  194. /*
  195. ===============
  196. =
  197. = TakeBolt
  198. =
  199. ===============
  200. */
  201. void TakeBolt (void)
  202. {
  203. SD_PlaySound (USEBOLTSND);
  204. DrawNum(20,18,--gamestate.bolts,2);
  205. }
  206. //===========================================================================
  207. /*
  208. ===============
  209. =
  210. = GiveNuke
  211. =
  212. ===============
  213. */
  214. void GiveNuke (void)
  215. {
  216. if (gamestate.nukes == 99)
  217. return;
  218. SD_PlaySound (GETNUKESND);
  219. DrawNum(20,36,++gamestate.nukes,2);
  220. }
  221. /*
  222. ===============
  223. =
  224. = TakeNuke
  225. =
  226. ===============
  227. */
  228. void TakeNuke (void)
  229. {
  230. SD_PlaySound (USENUKESND);
  231. DrawNum(20,36,--gamestate.nukes,2);
  232. }
  233. //===========================================================================
  234. /*
  235. ===============
  236. =
  237. = GivePotion
  238. =
  239. ===============
  240. */
  241. void GivePotion (void)
  242. {
  243. if (gamestate.potions == 99)
  244. return;
  245. SD_PlaySound (GETPOTIONSND);
  246. DrawNum(20,54,++gamestate.potions,2);
  247. }
  248. /*
  249. ===============
  250. =
  251. = TakePotion
  252. =
  253. ===============
  254. */
  255. void TakePotion (void)
  256. {
  257. SD_PlaySound (USEPOTIONSND);
  258. DrawNum(20,54,--gamestate.potions,2);
  259. }
  260. //===========================================================================
  261. /*
  262. ===============
  263. =
  264. = GiveKey
  265. =
  266. ===============
  267. */
  268. void GiveKey (int keytype)
  269. {
  270. int i,j,x;
  271. if (gamestate.keys[keytype] == 99)
  272. return;
  273. SD_PlaySound (GETKEYSND);
  274. DrawNum(key_x[keytype],key_y[keytype],++gamestate.keys[keytype],2);
  275. }
  276. /*
  277. ===============
  278. =
  279. = TakeKey
  280. =
  281. ===============
  282. */
  283. void TakeKey (int keytype)
  284. {
  285. int i,j,x;
  286. char *key_colors[] = {"a RED key",
  287. "a YELLOW key",
  288. "a GREEN key",
  289. "a BLUE key"};
  290. SD_PlaySound (USEKEYSND);
  291. DrawNum(key_x[keytype],key_y[keytype],--gamestate.keys[keytype],2);
  292. displayofs = bufferofs = screenloc[screenpage];
  293. CenterWindow(20,5);
  294. US_CPrint("\nYou use\n");
  295. US_CPrint(key_colors[keytype]);
  296. VW_UpdateScreen();
  297. VW_WaitVBL(120);
  298. }
  299. //===========================================================================
  300. /*
  301. ===============
  302. =
  303. = GiveGem
  304. =
  305. ===============
  306. */
  307. void GiveGem (int gemtype)
  308. {
  309. #if 0
  310. int i,j,x;
  311. SD_PlaySound (GETKEYSND);
  312. DrawNum(key_x[keytype],key_y[keytype],++gamestate.keys[keytype],2);
  313. #endif
  314. }
  315. /*
  316. ===============
  317. =
  318. = TakeGem
  319. =
  320. ===============
  321. */
  322. void TakeGem (int gemtype)
  323. {
  324. #if 0
  325. int i,j,x;
  326. SD_PlaySound (USEKEYSND);
  327. DrawNum(key_x[keytype],key_y[keytype],--gamestate.keys[keytype],2);
  328. #endif
  329. }
  330. /*
  331. ===============
  332. =
  333. = DrawGem
  334. =
  335. ===============
  336. */
  337. void DrawGems()
  338. {
  339. short loop;
  340. redraw_gems = false;
  341. bufferofs = 0;
  342. LatchDrawPic (31,51,RADAR_BOTTOMPIC);
  343. for (loop=0; loop<5; loop++)
  344. if (gamestate.gems[loop])
  345. LatchDrawPic (32+loop,53,RADAR_RGEMPIC+loop);
  346. }
  347. //===========================================================================
  348. #if 0
  349. /*
  350. ===============
  351. =
  352. = GiveScroll
  353. =
  354. ===============
  355. */
  356. void GiveScroll (int scrolltype,boolean show)
  357. {
  358. int i,j,x,y,scrollnum;
  359. SD_PlaySound (GETSCROLLSND);
  360. gamestate.scrolls[scrolltype] = true;
  361. y = 30 + ((scrolltype > 3) * 10);
  362. x = 26 + (scrolltype % 4);
  363. DrawChar(x,y,SCROLLCHARS+scrolltype);
  364. if (show)
  365. ReadScroll(scrolltype);
  366. }
  367. /*
  368. ===============
  369. =
  370. = DrawScrolls
  371. =
  372. = Force draw of all scrolls
  373. =
  374. ===============
  375. */
  376. void DrawScrolls()
  377. {
  378. int loop,x,y;
  379. VW_Bar(210,30,30,18,0xf);
  380. for (loop=0;loop<8;loop++)
  381. if (gamestate.scrolls[loop])
  382. {
  383. y = 30 + ((loop > 3) * 10);
  384. x = 26 + (loop % 4);
  385. DrawChar(x,y,SCROLLCHARS+loop);
  386. }
  387. }
  388. #endif
  389. //===========================================================================
  390. #if 0
  391. /*
  392. ===============
  393. =
  394. = GivePoints
  395. =
  396. ===============
  397. */
  398. void GivePoints (int points)
  399. {
  400. pointcount = 1;
  401. pointsleft += points;
  402. }
  403. #endif
  404. //===========================================================================
  405. #if 0
  406. /*
  407. ===============
  408. =
  409. = AddPoints
  410. =
  411. ===============
  412. */
  413. void AddPoints (int points)
  414. {
  415. char str[10];
  416. int len,x,i;
  417. gamestate.score += points;
  418. ltoa (gamestate.score,str,10);
  419. len = strlen (str);
  420. x=24+(8-len);
  421. for (i=0;i<len;i++)
  422. DrawChar(x++,40,NUMBERCHARS+str[i]-'0');
  423. }
  424. #endif
  425. //===========================================================================
  426. /*
  427. ===============
  428. =
  429. = DrawHealth
  430. =
  431. ===============
  432. */
  433. void DrawHealth()
  434. {
  435. char picnum;
  436. int percentage;
  437. percentage = PERCENTAGE(100,MAXBODY,gamestate.body,9);
  438. DrawNum(11,57,percentage,3);
  439. if (percentage > 75)
  440. picnum = FACE1PIC;
  441. else
  442. if (percentage > 50)
  443. picnum = FACE2PIC;
  444. else
  445. if (percentage > 25)
  446. picnum = FACE3PIC;
  447. else
  448. if (percentage)
  449. picnum = FACE4PIC;
  450. else
  451. {
  452. picnum = FACE5PIC;
  453. CA_CacheGrChunk (picnum);
  454. }
  455. bufferofs = 0;
  456. if (!percentage)
  457. {
  458. UNMARKGRCHUNK(picnum);
  459. // VW_DrawPic(8,14,picnum);
  460. VW_DrawPic(10,14,picnum);
  461. }
  462. else
  463. LatchDrawPic(10,14,picnum);
  464. }
  465. //===========================================================================
  466. /*
  467. ===============
  468. =
  469. = DrawFreezeTime
  470. =
  471. ===============
  472. */
  473. void DrawFreezeTime()
  474. {
  475. long percentage;
  476. percentage = PERCENTAGE(100,MAXFREEZETIME,(long)FreezeTime,7);
  477. DrawNum(23,70,percentage,3);
  478. }
  479. //===========================================================================
  480. /*
  481. ===============
  482. =
  483. = DrawNum
  484. =
  485. ===============
  486. */
  487. void DrawNum(short x,short y,short value,short maxdigits)
  488. {
  489. char str[10],len,i;
  490. itoa(value,str,10);
  491. len=strlen(str);
  492. for (i=len; i<maxdigits; i++)
  493. DrawChar(x++,y,BLANKCHAR);
  494. for (i=0;i<len;i++)
  495. DrawChar(x++,y,NUMBERCHARS+str[i]-'0');
  496. }
  497. //===========================================================================
  498. /*
  499. ===============
  500. =
  501. = GiveChest
  502. =
  503. ===============
  504. */
  505. void GiveChest(void)
  506. {
  507. char i;
  508. for (i=0;i<random(4);i++)
  509. {
  510. GiveBolt();
  511. SD_WaitSoundDone();
  512. }
  513. for (i=0;i<random(3);i++)
  514. {
  515. GiveNuke();
  516. SD_WaitSoundDone();
  517. }
  518. for (i=0;i<random(2);i++)
  519. {
  520. GivePotion();
  521. SD_WaitSoundDone();
  522. }
  523. }
  524. //===========================================================================
  525. /*
  526. ===============
  527. =
  528. = GiveGoal
  529. =
  530. ===============
  531. */
  532. void GiveGoal (void)
  533. {
  534. SD_PlaySound (GETPOINTSSND);
  535. playstate = ex_victorious;
  536. }
  537. //===========================================================================
  538. #if 0
  539. /*
  540. ===============
  541. =
  542. = DrawLevelNumber
  543. =
  544. ===============
  545. */
  546. void DrawLevelNumber (int number)
  547. {
  548. char str[10];
  549. int len;
  550. unsigned temp;
  551. bufferofs = 0;
  552. if (number<9)
  553. PrintX=13;
  554. else
  555. PrintX = 5;
  556. PrintY = 4;
  557. VW_Bar (5,4,16,9,STATUSCOLOR);
  558. temp = fontcolor;
  559. fontcolor = TEXTCOLOR^STATUSCOLOR;
  560. US_PrintUnsigned (number+1);
  561. fontcolor = temp;
  562. }
  563. #endif
  564. //===========================================================================
  565. /*
  566. ===============
  567. =
  568. = DrawText
  569. =
  570. ===============
  571. */
  572. void DrawText (boolean draw_text_whether_it_needs_it_or_not)
  573. {
  574. unsigned number;
  575. char str[80];
  576. char far *text;
  577. unsigned temp;
  578. //
  579. // draw a new text description if needed
  580. //
  581. number = *(mapsegs[0]+farmapylookup[player->tiley]+player->tilex)-NAMESTART;
  582. if ( number>26 )
  583. number = 0;
  584. if ((number == lasttext) && (!draw_text_whether_it_needs_it_or_not))
  585. return;
  586. lasttext = number;
  587. text = (char _seg *)grsegs[LEVEL1TEXT+mapon]+textstarts[number];
  588. _fmemcpy (str,text,80);
  589. DisplayMsg(str,NULL);
  590. }
  591. //===========================================================================
  592. /*
  593. ===============
  594. =
  595. = DisplayMsg
  596. =
  597. ===============
  598. */
  599. char DisplayMsg(char *text,char *choices)
  600. {
  601. char ch=true;
  602. short temp;
  603. bufferofs = 0;
  604. PrintY = 1;
  605. WindowX = 20;
  606. WindowW = 270;
  607. VW_Bar (WindowX,2,WindowW,8,STATUSCOLOR);
  608. temp = fontcolor;
  609. fontcolor = TEXTCOLOR^STATUSCOLOR;
  610. US_CPrintLine (text);
  611. fontcolor = temp;
  612. if (choices)
  613. {
  614. ch=GetKeyChoice(choices,true);
  615. LastScan = 0;
  616. }
  617. return(ch);
  618. }
  619. /*
  620. ===============
  621. =
  622. = DisplaySMsg
  623. =
  624. ===============
  625. */
  626. char DisplaySMsg(char *text,char *choices)
  627. {
  628. char ch=true;
  629. short temp;
  630. bufferofs = 0;
  631. PrintY = 69;
  632. WindowX = 98;
  633. WindowW = 115;
  634. VW_Bar(WindowX,PrintY+1,WindowW,8,STATUSCOLOR);
  635. temp = fontcolor;
  636. fontcolor = TEXTCOLOR^STATUSCOLOR;
  637. US_CPrintLine (text);
  638. fontcolor = temp;
  639. if (choices)
  640. {
  641. ch=GetKeyChoice(choices,true);
  642. LastScan = 0;
  643. }
  644. return(ch);
  645. }
  646. //===========================================================================
  647. /*
  648. ===============
  649. =
  650. = DrawRadar
  651. =
  652. ===============
  653. */
  654. void DrawRadar (void)
  655. {
  656. int angle,number;
  657. short objnum;
  658. bufferofs = 0;
  659. LatchDrawPic (radarx,radary,RADAR_TOPPIC);
  660. asm cli
  661. asm mov dx,GC_INDEX
  662. asm mov ax,2*256+GC_MODE
  663. asm out dx,ax // write mode 2
  664. asm mov ax,GC_DATAROTATE
  665. asm out dx,ax // no rotation / logical operation
  666. asm mov dx,SC_INDEX
  667. asm mov al,SC_MAPMASK
  668. asm mov ah,15
  669. asm out dx,ax // write to all four planes
  670. asm sti
  671. objnum = 0;
  672. while (RadarXY[objnum][2] != -1)
  673. {
  674. RadarBlip(radar_xcenter+RadarXY[objnum][0],radar_ycenter+RadarXY[objnum][1],RadarXY[objnum][2]);
  675. objnum++;
  676. }
  677. asm cli
  678. asm mov dx,GC_INDEX
  679. asm mov ax,255*256+GC_BITMASK
  680. asm out dx,ax // reset bitmask to %11111111
  681. asm sti
  682. }
  683. //===========================================================================
  684. //--------------------------------------------------------------------------
  685. // DrawNSEWIcons(void)
  686. //--------------------------------------------------------------------------
  687. void DrawRadarObj(short dx, short dy, unsigned sprnum,signed long psin,signed long pcos);
  688. void DrawNSEWIcons()
  689. {
  690. signed x,y;
  691. x = -FixedByFrac(RADAR_X_IRADIUS,costable[player->angle]);
  692. y = -FixedByFrac(RADAR_Y_IRADIUS,sintable[player->angle]);
  693. VWB_DrawSprite(radar_xcenter+x-3,radar_ycenter+y-3,NORTHICONSPR);
  694. }
  695. #if 0
  696. /*
  697. ===============
  698. =
  699. = DrawBars
  700. =
  701. ===============
  702. */
  703. void DrawBars (void)
  704. {
  705. int i;
  706. unsigned source,dest,topline;
  707. for (i=0;i<3;i++)
  708. {
  709. bufferofs = screenloc[i];
  710. VW_Bar (34*8,POWERLINE,40,MAXSHOTPOWER,1);
  711. }
  712. EGAWRITEMODE(1);
  713. asm mov es,[screenseg]
  714. //
  715. // shot power
  716. //
  717. if (gamestate.shotpower)
  718. {
  719. topline = MAXSHOTPOWER - gamestate.shotpower;
  720. source = latchpics[SHOTPOWERPIC-FIRSTLATCHPIC]+topline*SIDEBARWIDTH;
  721. dest = (POWERLINE+topline)*SCREENWIDTH+34;
  722. asm mov si,[source]
  723. asm mov di,[dest]
  724. asm mov cx,[WORD PTR gamestate.shotpower]
  725. newline:
  726. asm mov al,[es:si]
  727. asm mov [es:di+PAGE1START],al
  728. asm mov [es:di+PAGE2START],al
  729. asm mov [es:di+PAGE3START],al
  730. asm mov al,[es:si+1]
  731. asm mov [es:di+1+PAGE1START],al
  732. asm mov [es:di+1+PAGE2START],al
  733. asm mov [es:di+1+PAGE3START],al
  734. asm mov al,[es:si+2]
  735. asm mov [es:di+2+PAGE1START],al
  736. asm mov [es:di+2+PAGE2START],al
  737. asm mov [es:di+2+PAGE3START],al
  738. asm mov al,[es:si+3]
  739. asm mov [es:di+3+PAGE1START],al
  740. asm mov [es:di+3+PAGE2START],al
  741. asm mov [es:di+3+PAGE3START],al
  742. asm mov al,[es:si+4]
  743. asm mov [es:di+4+PAGE1START],al
  744. asm mov [es:di+4+PAGE2START],al
  745. asm mov [es:di+4+PAGE3START],al
  746. asm add di,SCREENWIDTH
  747. asm add si,5
  748. asm loop newline
  749. }
  750. //
  751. // body
  752. //
  753. if (gamestate.body)
  754. {
  755. source = latchpics[BODYPIC-FIRSTLATCHPIC];
  756. dest = BODYLINE*SCREENWIDTH+34;
  757. asm mov si,[source]
  758. asm mov di,[dest]
  759. asm mov cx,[WORD PTR gamestate.body]
  760. newline2:
  761. asm mov al,[es:si]
  762. asm mov [es:di+PAGE1START],al
  763. asm mov [es:di+PAGE2START],al
  764. asm mov [es:di+PAGE3START],al
  765. asm mov al,[es:si+1]
  766. asm mov [es:di+1+PAGE1START],al
  767. asm mov [es:di+1+PAGE2START],al
  768. asm mov [es:di+1+PAGE3START],al
  769. asm mov al,[es:si+2]
  770. asm mov [es:di+2+PAGE1START],al
  771. asm mov [es:di+2+PAGE2START],al
  772. asm mov [es:di+2+PAGE3START],al
  773. asm mov al,[es:si+3]
  774. asm mov [es:di+3+PAGE1START],al
  775. asm mov [es:di+3+PAGE2START],al
  776. asm mov [es:di+3+PAGE3START],al
  777. asm mov al,[es:si+4]
  778. asm mov [es:di+4+PAGE1START],al
  779. asm mov [es:di+4+PAGE2START],al
  780. asm mov [es:di+4+PAGE3START],al
  781. asm add di,SCREENWIDTH
  782. asm add si,5
  783. asm loop newline2
  784. }
  785. if (gamestate.body != MAXBODY)
  786. {
  787. source = latchpics[NOBODYPIC-FIRSTLATCHPIC]+gamestate.body*SIDEBARWIDTH;
  788. dest = (BODYLINE+gamestate.body)*SCREENWIDTH+34;
  789. topline = MAXBODY-gamestate.body;
  790. asm mov si,[source]
  791. asm mov di,[dest]
  792. asm mov cx,[WORD PTR topline]
  793. newline3:
  794. asm mov al,[es:si]
  795. asm mov [es:di+PAGE1START],al
  796. asm mov [es:di+PAGE2START],al
  797. asm mov [es:di+PAGE3START],al
  798. asm mov al,[es:si+1]
  799. asm mov [es:di+1+PAGE1START],al
  800. asm mov [es:di+1+PAGE2START],al
  801. asm mov [es:di+1+PAGE3START],al
  802. asm mov al,[es:si+2]
  803. asm mov [es:di+2+PAGE1START],al
  804. asm mov [es:di+2+PAGE2START],al
  805. asm mov [es:di+2+PAGE3START],al
  806. asm mov al,[es:si+3]
  807. asm mov [es:di+3+PAGE1START],al
  808. asm mov [es:di+3+PAGE2START],al
  809. asm mov [es:di+3+PAGE3START],al
  810. asm mov al,[es:si+4]
  811. asm mov [es:di+4+PAGE1START],al
  812. asm mov [es:di+4+PAGE2START],al
  813. asm mov [es:di+4+PAGE3START],al
  814. asm add di,SCREENWIDTH
  815. asm add si,5
  816. asm loop newline3
  817. }
  818. EGAWRITEMODE(0);
  819. }
  820. #endif
  821. /////////////////////////////////////////////////////////////////////////////
  822. //
  823. // Check the object and make sure it is a monster. Used in making the sound
  824. // of a monster being shot.
  825. //
  826. /////////////////////////////////////////////////////////////////////////////
  827. boolean PlayMonsterSound(classtype objclass)
  828. {
  829. switch (objclass)
  830. {
  831. case solidobj:
  832. case realsolidobj:
  833. return false;
  834. default:
  835. return true;
  836. }
  837. }
  838. /*
  839. =============================================================================
  840. SHOTS
  841. =============================================================================
  842. */
  843. void T_Pshot (objtype *ob);
  844. extern statetype s_pshot1;
  845. extern statetype s_pshot2;
  846. //extern statetype s_bigpshot1;
  847. //extern statetype s_bigpshot2;
  848. statetype s_pshot1 = {PSHOT1PIC,8,&T_Pshot,&s_pshot2};
  849. statetype s_pshot2 = {PSHOT2PIC,8,&T_Pshot,&s_pshot1};
  850. statetype s_pshot_exp1 = {PSHOT_EXP1PIC,7,NULL,&s_pshot_exp2};
  851. statetype s_pshot_exp2 = {PSHOT_EXP2PIC,7,NULL,&s_pshot_exp3};
  852. statetype s_pshot_exp3 = {PSHOT_EXP3PIC,7,NULL,NULL};
  853. //statetype s_shotexplode = {PSHOT2PIC,8,NULL,NULL};
  854. //statetype s_bigpshot1 = {BIGPSHOT1PIC,8,&T_Pshot,&s_bigpshot2};
  855. //statetype s_bigpshot2 = {BIGPSHOT2PIC,8,&T_Pshot,&s_bigpshot1};
  856. /*
  857. ===================
  858. =
  859. = SpawnPShot
  860. =
  861. ===================
  862. */
  863. void SpawnPShot (void)
  864. {
  865. DSpawnNewObjFrac (player->x,player->y,&s_pshot1,PIXRADIUS*7);
  866. new->obclass = pshotobj;
  867. new->speed = SHOTSPEED;
  868. new->angle = player->angle;
  869. new->active = always;
  870. }
  871. #if 0
  872. void SpawnBigPShot (void)
  873. {
  874. SpawnNewObjFrac (player->x,player->y,&s_bigpshot1,24*PIXRADIUS);
  875. new->obclass = bigpshotobj;
  876. new->speed = SHOTSPEED;
  877. new->angle = player->angle;
  878. }
  879. #endif
  880. /*
  881. ===================
  882. =
  883. = JimsShotClipMove
  884. =
  885. = Only checks corners, so the object better be less than one tile wide!
  886. =
  887. ===================
  888. */
  889. boolean JimsShotClipMove (objtype *ob, long xmove, long ymove)
  890. {
  891. int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;
  892. long intersect,basex,basey,pointx,pointy;
  893. unsigned inside,total,tile;
  894. objtype *check;
  895. boolean moveok;
  896. //
  897. // move player and check to see if any corners are in solid tiles
  898. //
  899. // basex = ob->x;
  900. // basey = ob->y;
  901. // ob->x += xmove;
  902. // ob->y += ymove;
  903. // CalcBounds (ob);
  904. xl = ob->xl>>TILESHIFT;
  905. yl = ob->yl>>TILESHIFT;
  906. xh = ob->xh>>TILESHIFT;
  907. yh = ob->yh>>TILESHIFT;
  908. for (y=yl;y<=yh;y++)
  909. for (x=xl;x<=xh;x++)
  910. {
  911. check = actorat[x][y];
  912. if ((!check) || (check == player) || (!(check->flags & of_shootable)))
  913. continue;
  914. ob->x -= xmove;
  915. ob->y -= ymove;
  916. if (check->obclass != solidobj && check->obclass != hbunnyobj)
  917. {
  918. if (PlayMonsterSound(check->obclass))
  919. SD_PlaySound (SHOOTMONSTERSND);
  920. if (ob->obclass == bigpshotobj)
  921. ShootActor (check,BIGSHOTDAMAGE);
  922. else
  923. ShootActor (check,SHOTDAMAGE);
  924. }
  925. else
  926. if (check->obclass == solidobj && (check->flags & of_forcefield))
  927. {
  928. if (PlayMonsterSound(check->obclass))
  929. SD_PlaySound (SHOOTMONSTERSND);
  930. if (ob->obclass == bigpshotobj)
  931. ShootActor (check,BIGSHOTDAMAGE);
  932. else
  933. ShootActor (check,SHOTDAMAGE);
  934. }
  935. ob->state = &s_pshot_exp1;
  936. ob->ticcount = ob->state->tictime;
  937. return(true);
  938. }
  939. return(false); // move is OK!
  940. }
  941. /*
  942. ===============
  943. =
  944. = T_Pshot
  945. =
  946. ===============
  947. */
  948. #if 0
  949. void T_Pshot (objtype *ob)
  950. {
  951. objtype *check;
  952. long xmove,ymove,speed;
  953. //
  954. // check current position for monsters having moved into it
  955. //
  956. for (check = player->next; check; check=check->next)
  957. if ((check->flags & of_shootable)
  958. && ob->xl <= check->xh
  959. && ob->xh >= check->xl
  960. && ob->yl <= check->yh
  961. && ob->yh >= check->yl)
  962. {
  963. if (check->obclass != solidobj)
  964. {
  965. if (PlayMonsterSound(check->obclass))
  966. SD_PlaySound (SHOOTMONSTERSND);
  967. if (ob->obclass == bigpshotobj)
  968. ShootActor (check,BIGSHOTDAMAGE);
  969. else
  970. ShootActor (check,SHOTDAMAGE);
  971. }
  972. ob->state = &s_pshot_exp1;
  973. ob->ticcount = ob->state->tictime;
  974. return;
  975. }
  976. //
  977. // move ahead, possibly hitting a wall
  978. //
  979. speed = ob->speed*tics;
  980. xmove = FixedByFrac(speed,costable[ob->angle]);
  981. ymove = -FixedByFrac(speed,sintable[ob->angle]);
  982. if (ShotClipMove(ob,xmove,ymove))
  983. {
  984. ob->state = &s_pshot_exp1;
  985. ob->ticcount = ob->state->tictime;
  986. return;
  987. }
  988. ob->tilex = ob->x >> TILESHIFT;
  989. ob->tiley = ob->y >> TILESHIFT;
  990. //
  991. // check final position for monsters hit
  992. //
  993. for (check = player->next; check; check=check->next)
  994. if ((ob->flags & of_shootable)
  995. && ob->xl <= check->xh
  996. && ob->xh >= check->xl
  997. && ob->yl <= check->yh
  998. && ob->yh >= check->yl)
  999. {
  1000. ShootActor (check,SHOTDAMAGE);
  1001. ob->state = &s_pshot_exp1;
  1002. ob->ticcount = ob->state->tictime;
  1003. return;
  1004. }
  1005. }
  1006. #endif
  1007. void T_Pshot (objtype *ob)
  1008. {
  1009. objtype *check;
  1010. long xmove,ymove,speed;
  1011. int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;
  1012. long intersect,basex,basey,pointx,pointy;
  1013. unsigned inside,total,tile;
  1014. boolean moveok;
  1015. //
  1016. // check current position for monsters having moved into it
  1017. //
  1018. for (check = player->next; check; check=check->next)
  1019. if ((check->flags & of_shootable)
  1020. && ob->xl <= check->xh
  1021. && ob->xh >= check->xl
  1022. && ob->yl <= check->yh
  1023. && ob->yh >= check->yl)
  1024. {
  1025. if (check->obclass != solidobj && check->obclass != hbunnyobj)
  1026. {
  1027. if (PlayMonsterSound(check->obclass))
  1028. SD_PlaySound (SHOOTMONSTERSND);
  1029. if (ob->obclass == bigpshotobj)
  1030. ShootActor (check,BIGSHOTDAMAGE);
  1031. else
  1032. ShootActor (check,SHOTDAMAGE);
  1033. }
  1034. ob->state = &s_pshot_exp1;
  1035. ob->obclass = expobj;
  1036. ob->ticcount = ob->state->tictime;
  1037. return;
  1038. }
  1039. //
  1040. // move ahead, possibly hitting a wall
  1041. //
  1042. speed = ob->speed*tics;
  1043. xmove = FixedByFrac(speed,costable[ob->angle]);
  1044. ymove = -FixedByFrac(speed,sintable[ob->angle]);
  1045. if (ShotClipMove(ob,xmove,ymove))
  1046. {
  1047. ob->state = &s_pshot_exp1;
  1048. ob->obclass = expobj;
  1049. ob->ticcount = ob->state->tictime;
  1050. return;
  1051. }
  1052. ob->tilex = ob->x >> TILESHIFT;
  1053. ob->tiley = ob->y >> TILESHIFT;
  1054. //
  1055. // check final position for monsters hit
  1056. //
  1057. JimsShotClipMove(obj,xmove,ymove);
  1058. }
  1059. /*
  1060. =============================================================================
  1061. PLAYER ACTIONS
  1062. =============================================================================
  1063. */
  1064. /*
  1065. ===============
  1066. =
  1067. = BuildShotPower
  1068. =
  1069. ===============
  1070. */
  1071. void BuildShotPower (void)
  1072. {
  1073. int newlines,topline;
  1074. long i;
  1075. unsigned source,dest;
  1076. if (gamestate.shotpower == MAXSHOTPOWER)
  1077. return;
  1078. newlines = 0;
  1079. for (i=lasttimecount-realtics;i<lasttimecount;i++)
  1080. newlines += (i&1);
  1081. gamestate.shotpower += newlines;
  1082. if (gamestate.shotpower > MAXSHOTPOWER)
  1083. {
  1084. newlines -= (gamestate.shotpower - MAXSHOTPOWER);
  1085. gamestate.shotpower = MAXSHOTPOWER;
  1086. }
  1087. }
  1088. //===========================================================================
  1089. /*
  1090. ===============
  1091. =
  1092. = ClearShotPower
  1093. =
  1094. ===============
  1095. */
  1096. void ClearShotPower (void)
  1097. {
  1098. unsigned source,dest,topline;
  1099. #if 0
  1100. topline = MAXSHOTPOWER - gamestate.shotpower;
  1101. source = latchpics[L_NOSHOT]+topline*SIDEBARWIDTH;
  1102. dest = (POWERLINE+topline)*SCREENWIDTH+34;
  1103. asm mov es,[screenseg]
  1104. asm mov si,[source]
  1105. asm mov di,[dest]
  1106. if (!gamestate.shotpower)
  1107. return;
  1108. EGAWRITEMODE(1);
  1109. asm mov cx,[WORD PTR gamestate.shotpower]
  1110. newline:
  1111. asm mov al,[es:si]
  1112. asm mov [es:di+PAGE1START],al
  1113. asm mov [es:di+PAGE2START],al
  1114. asm mov [es:di+PAGE3START],al
  1115. asm mov al,[es:si+1]
  1116. asm mov [es:di+1+PAGE1START],al
  1117. asm mov [es:di+1+PAGE2START],al
  1118. asm mov [es:di+1+PAGE3START],al
  1119. asm mov al,[es:si+2]
  1120. asm mov [es:di+2+PAGE1START],al
  1121. asm mov [es:di+2+PAGE2START],al
  1122. asm mov [es:di+2+PAGE3START],al
  1123. asm mov al,[es:si+3]
  1124. asm mov [es:di+3+PAGE1START],al
  1125. asm mov [es:di+3+PAGE2START],al
  1126. asm mov [es:di+3+PAGE3START],al
  1127. asm mov al,[es:si+4]
  1128. asm mov [es:di+4+PAGE1START],al
  1129. asm mov [es:di+4+PAGE2START],al
  1130. asm mov [es:di+4+PAGE3START],al
  1131. asm add di,SCREENWIDTH
  1132. asm add si,5
  1133. asm loop newline
  1134. EGAWRITEMODE(0);
  1135. #endif
  1136. gamestate.shotpower = 0;
  1137. }
  1138. //===========================================================================
  1139. /*
  1140. ===============
  1141. =
  1142. = Shoot
  1143. =
  1144. ===============
  1145. */
  1146. void Shoot (void)
  1147. {
  1148. ClearShotPower ();
  1149. SD_PlaySound (SHOOTSND);
  1150. SpawnPShot ();
  1151. }
  1152. //===========================================================================
  1153. #if 0
  1154. /*
  1155. ===============
  1156. =
  1157. = BigShoot
  1158. =
  1159. ===============
  1160. */
  1161. void BigShoot (void)
  1162. {
  1163. ClearShotPower ();
  1164. SD_PlaySound (BIGSHOOTSND);
  1165. SpawnBigPShot ();
  1166. }
  1167. #endif
  1168. //===========================================================================
  1169. /*
  1170. ===============
  1171. =
  1172. = CastBolt
  1173. =
  1174. ===============
  1175. */
  1176. void CastBolt (void)
  1177. {
  1178. if (!gamestate.bolts)
  1179. {
  1180. SD_PlaySound (NOITEMSND);
  1181. return;
  1182. }
  1183. TakeBolt ();
  1184. boltsleft = NUMBOLTS;
  1185. bolttimer = BOLTTICS;
  1186. Shoot ();
  1187. }
  1188. /*
  1189. ===============
  1190. =
  1191. = ContinueBolt
  1192. =
  1193. ===============
  1194. */
  1195. void ContinueBolt (void)
  1196. {
  1197. bolttimer-=realtics;
  1198. if (bolttimer<0)
  1199. {
  1200. boltsleft--;
  1201. bolttimer = BOLTTICS;
  1202. Shoot ();
  1203. }
  1204. }
  1205. //===========================================================================
  1206. /*
  1207. ===============
  1208. =
  1209. = CastNuke
  1210. =
  1211. ===============
  1212. */
  1213. void CastNuke (void)
  1214. {
  1215. extern boolean autofire;
  1216. int angle;
  1217. if (!gamestate.nukes)
  1218. {
  1219. SD_PlaySound (NOITEMSND);
  1220. return;
  1221. }
  1222. if (!autofire)
  1223. TakeNuke ();
  1224. lastnuke = TimeCount;
  1225. for (angle = 0; angle < ANGLES; angle+= ANGLES/16)
  1226. {
  1227. DSpawnNewObjFrac (player->x,player->y,&s_pshot1,24*PIXRADIUS);
  1228. new->obclass = bigpshotobj;
  1229. new->speed = SHOTSPEED;
  1230. new->angle = angle;
  1231. new->active = always;
  1232. }
  1233. }
  1234. //===========================================================================
  1235. /*
  1236. ===============
  1237. =
  1238. = DrinkPotion
  1239. =
  1240. ===============
  1241. */
  1242. void DrinkPotion (void)
  1243. {
  1244. unsigned source,dest,topline;
  1245. if (!gamestate.potions)
  1246. {
  1247. SD_PlaySound (NOITEMSND);
  1248. return;
  1249. }
  1250. DisplaySMsg("Curing", NULL);
  1251. TakePotion ();
  1252. gamestate.body = MAXBODY;
  1253. VW_WaitVBL(30);
  1254. status_flag = S_NONE;
  1255. #if 0
  1256. //
  1257. // draw a full up bar
  1258. //
  1259. source = latchpics[L_BODYBAR];
  1260. dest = BODYLINE*SCREENWIDTH+34;
  1261. asm mov es,[screenseg]
  1262. asm mov si,[source]
  1263. asm mov di,[dest]
  1264. EGAWRITEMODE(1);
  1265. asm mov cx,MAXBODY
  1266. newline:
  1267. asm mov al,[es:si]
  1268. asm mov [es:di+PAGE1START],al
  1269. asm mov [es:di+PAGE2START],al
  1270. asm mov [es:di+PAGE3START],al
  1271. asm mov al,[es:si+1]
  1272. asm mov [es:di+1+PAGE1START],al
  1273. asm mov [es:di+1+PAGE2START],al
  1274. asm mov [es:di+1+PAGE3START],al
  1275. asm mov al,[es:si+2]
  1276. asm mov [es:di+2+PAGE1START],al
  1277. asm mov [es:di+2+PAGE2START],al
  1278. asm mov [es:di+2+PAGE3START],al
  1279. asm mov al,[es:si+3]
  1280. asm mov [es:di+3+PAGE1START],al
  1281. asm mov [es:di+3+PAGE2START],al
  1282. asm mov [es:di+3+PAGE3START],al
  1283. asm mov al,[es:si+4]
  1284. asm mov [es:di+4+PAGE1START],al
  1285. asm mov [es:di+4+PAGE2START],al
  1286. asm mov [es:di+4+PAGE3START],al
  1287. asm add di,SCREENWIDTH
  1288. asm add si,5
  1289. asm loop newline
  1290. EGAWRITEMODE(0);
  1291. #endif
  1292. }
  1293. //===========================================================================
  1294. #if 0
  1295. ////////////////////////////////////////////////////////////////////////////
  1296. //
  1297. // GetScrollText
  1298. //
  1299. // parms - scroll -- the number of the scroll to display
  1300. // returns - a far pointer to the scroll text
  1301. //
  1302. ////////////////////////////////////////////////////////////////////////////
  1303. char far *GetScrollText (int scroll)
  1304. {
  1305. boolean found;
  1306. int i;
  1307. char far *txt;
  1308. unsigned ofset;
  1309. CA_CacheGrChunk(SCROLLTEXT);
  1310. found = false;
  1311. i = 0;
  1312. txt = (char _seg *)grsegs[SCROLLTEXT];
  1313. while (!found)
  1314. {
  1315. while (*txt != '\n')
  1316. {
  1317. if (*txt == '\r')
  1318. *txt = 0;
  1319. txt++;
  1320. }
  1321. txt++;
  1322. if (i == scroll)
  1323. {
  1324. found = true;
  1325. ofset = FP_OFF(txt);
  1326. while (*txt != '\n')
  1327. {
  1328. if (*txt == '\r')
  1329. *txt = 0;
  1330. txt++;
  1331. }
  1332. }
  1333. i++;
  1334. }
  1335. txt = (char _seg *)grsegs[SCROLLTEXT]+ofset;
  1336. UNMARKGRCHUNK(SCROLLTEXT);
  1337. return(txt);
  1338. } //End of GetScrollText
  1339. //===========================================================================
  1340. /*
  1341. ===============
  1342. =
  1343. = ReadScroll
  1344. =
  1345. ===============
  1346. */
  1347. extern boolean tileneeded[NUMFLOORS];
  1348. void ReadScroll (int scroll)
  1349. {
  1350. PresenterInfo pi;
  1351. int i;
  1352. unsigned *skytemp,*gndtemp,blackcolor=0;
  1353. char far *scrolltext;
  1354. DisplaySMsg("Reading Scroll", NULL);
  1355. bufferofs = displayofs = screenloc[screenpage];
  1356. if (status_flag != S_TIMESTOP)
  1357. status_flag = S_NONE;
  1358. FreeUpMemory();
  1359. CA_CacheGrChunk (SCROLLTOPPIC);
  1360. CA_CacheGrChunk (SCROLL1PIC);
  1361. CA_CacheGrChunk (SCROLLBOTTOMPIC);
  1362. skytemp = skycolor;
  1363. gndtemp = groundcolor;
  1364. skycolor = groundcolor = &blackcolor;
  1365. VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);
  1366. VW_DrawPic (10,0,SCROLLTOPPIC);
  1367. VW_DrawPic (10,32,SCROLL1PIC);
  1368. VW_DrawPic (10,88,SCROLLBOTTOMPIC);
  1369. scrolltext = GetScrollText(scroll);
  1370. pi.xl = LEFTEDGE;
  1371. pi.yl = PRNY;
  1372. pi.xh = RIGHTEDGE;
  1373. pi.yh = PRNY+1;
  1374. pi.bgcolor = 7;
  1375. pi.script[0] = (char far *)scrolltext;
  1376. Presenter(&pi);
  1377. skycolor = skytemp;
  1378. groundcolor = gndtemp;
  1379. UNMARKGRCHUNK(SCROLL1PIC);
  1380. UNMARKGRCHUNK(SCROLLTOPPIC);
  1381. UNMARKGRCHUNK(SCROLLBOTTOMPIC);
  1382. MM_FreePtr (&grsegs[SCROLL1PIC]);
  1383. MM_FreePtr (&grsegs[SCROLLTOPPIC]);
  1384. MM_FreePtr (&grsegs[SCROLLBOTTOMPIC]);
  1385. CacheScaleds();
  1386. IN_ClearKeysDown ();
  1387. lasttext = -1;
  1388. DisplayMsg("Press ENTER or ESC to exit.",NULL);
  1389. while ((!Keyboard[sc_Escape]) && (!Keyboard[sc_Enter]));
  1390. IN_ClearKeysDown ();
  1391. if (status_flag == S_TIMESTOP)
  1392. DisplaySMsg("Time Stopped: ",NULL);
  1393. }
  1394. #endif
  1395. //===============
  1396. //
  1397. // StopTime()
  1398. //
  1399. //
  1400. //===============
  1401. void StopTime()
  1402. {
  1403. FreezeTime = MAXFREEZETIME;
  1404. SD_PlaySound(FREEZETIMESND);
  1405. DisplaySMsg("Time Stopped: ",NULL);
  1406. status_flag = S_TIMESTOP;
  1407. }
  1408. /*
  1409. ===============
  1410. =
  1411. = TakeDamage
  1412. =
  1413. ===============
  1414. */
  1415. void TakeDamage (int points)
  1416. {
  1417. unsigned source,dest,topline;
  1418. if (!gamestate.body || (bordertime && bcolor==FLASHCOLOR) || godmode)
  1419. return;
  1420. if (points != 1)
  1421. points = EasyDoDamage(points);
  1422. if (points >= gamestate.body)
  1423. {
  1424. points = gamestate.body;
  1425. Flags |= FL_DEAD;
  1426. }
  1427. bordertime = FLASHTICS<<2;
  1428. bcolor = FLASHCOLOR;
  1429. VW_ColorBorder (FLASHCOLOR);
  1430. DisplaySMsg("Damaging blows!", NULL);
  1431. status_flag = S_NONE;
  1432. status_delay = 80;
  1433. if (gamestate.body<MAXBODY/3)
  1434. SD_PlaySound (TAKEDMGHURTSND);
  1435. else
  1436. SD_PlaySound (TAKEDAMAGESND);
  1437. gamestate.body -= points;
  1438. }
  1439. /*
  1440. =============================================================================
  1441. INTERACTION
  1442. =============================================================================
  1443. */
  1444. #if 0
  1445. /*
  1446. ==================
  1447. =
  1448. = OpenDoor
  1449. =
  1450. ==================
  1451. */
  1452. void OpenDoor (unsigned bx, unsigned by, unsigned doorbase)
  1453. {
  1454. int x,y;
  1455. unsigned far *map;
  1456. x=bx;
  1457. y=by;
  1458. map = mapsegs[0]+farmapylookup[y]+x;
  1459. while (tilemap[x][y]-doorbase<4)
  1460. {
  1461. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1462. map--;
  1463. x--;
  1464. }
  1465. x=bx+1;
  1466. map = mapsegs[0]+farmapylookup[y]+x;
  1467. while (tilemap[x][y]-doorbase<4)
  1468. {
  1469. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1470. map++;
  1471. x++;
  1472. }
  1473. x=bx;
  1474. y=by-1;
  1475. map = mapsegs[0]+farmapylookup[y]+x;
  1476. while (tilemap[x][y]-doorbase<4)
  1477. {
  1478. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1479. map-=mapwidth;
  1480. y--;
  1481. }
  1482. y=by+1;
  1483. map = mapsegs[0]+farmapylookup[y]+x;
  1484. while (tilemap[x][y]-doorbase<4)
  1485. {
  1486. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1487. map+=mapwidth;
  1488. y++;
  1489. }
  1490. }
  1491. #endif
  1492. #if 0
  1493. /*
  1494. ==================
  1495. =
  1496. = RemoveWalls - similar to OpenDoor(), but on a different plane
  1497. =
  1498. ==================
  1499. */
  1500. void RemoveWalls (unsigned bx, unsigned by, unsigned remove_code)
  1501. {
  1502. int x,y;
  1503. unsigned far *map,*p2;
  1504. x=bx;
  1505. y=by;
  1506. p2 = *(mapsegs[2]+farmapylookup[y]+x);
  1507. map = mapsegs[0]+farmapylookup[y]+x;
  1508. while (*p2 == remove_code)
  1509. {
  1510. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1511. map--;
  1512. p2--;
  1513. x--;
  1514. }
  1515. x=bx+1;
  1516. p2 = *(mapsegs[2]+farmapylookup[y]+x);
  1517. map = mapsegs[0]+farmapylookup[y]+x;
  1518. while (*p2 == remove_code)
  1519. {
  1520. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1521. map++;
  1522. p2++;
  1523. x++;
  1524. }
  1525. x=bx;
  1526. y=by-1;
  1527. p2 = *(mapsegs[2]+farmapylookup[y]+x);
  1528. map = mapsegs[0]+farmapylookup[y]+x;
  1529. while (*p2 == remove_code)
  1530. {
  1531. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1532. map-=mapwidth;
  1533. p2 -= mapwidth;
  1534. y--;
  1535. }
  1536. y=by+1;
  1537. p2 = *(mapsegs[2]+farmapylookup[y]+x);
  1538. map = mapsegs[0]+farmapylookup[y]+x;
  1539. while (*p2 == remove_code)
  1540. {
  1541. tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;
  1542. map+=mapwidth;
  1543. p2 += mapwidth;
  1544. y++;
  1545. }
  1546. }
  1547. #endif
  1548. /*
  1549. ==================
  1550. =
  1551. = HitSpecialTile
  1552. =
  1553. = Returns true if the move is blocked
  1554. =
  1555. ==================
  1556. */
  1557. boolean HitSpecialTile (unsigned x, unsigned y, unsigned tile)
  1558. {
  1559. objtype *check;
  1560. short keyspot;
  1561. unsigned temp,spot,curmap=gamestate.mapon,newlevel;
  1562. char *key_colors[] = {"a RED key",
  1563. "a YELLOW key",
  1564. "a GREEN key",
  1565. "a BLUE key"};
  1566. switch (tile)
  1567. {
  1568. case 65:
  1569. playstate = ex_victorious;
  1570. break;
  1571. case 9:
  1572. case 15:
  1573. case 27:
  1574. case 30:
  1575. case 40:
  1576. case 42:
  1577. case 43:
  1578. case 45:
  1579. case 46:
  1580. case 47:
  1581. case 49:
  1582. case 76:
  1583. case 77:
  1584. if (!playstate && !FreezeTime)
  1585. {
  1586. // Is this an openable door? (Is "openable" a word?)
  1587. //
  1588. spot = (*(mapsegs[2]+farmapylookup[y]+x)) >> 8;
  1589. if (spot == CANT_OPEN_CODE) // CAN'T EVER OPEN (it's just for looks)
  1590. {
  1591. CenterWindow(30,4);
  1592. US_CPrint("\nThis door is permanently blocked");
  1593. VW_UpdateScreen();
  1594. IN_ClearKeysDown();
  1595. IN_Ack();
  1596. return;
  1597. }
  1598. // make sure player has key to get into door
  1599. //
  1600. if (TILE_FLAGS(tile) & tf_EMBEDDED_KEY_COLOR)
  1601. keyspot = GATE_KEY_COLOR(tile);
  1602. else
  1603. keyspot = (*(mapsegs[2]+farmapylookup[y+1]+x)) >> 8;
  1604. if (keyspot--)
  1605. if (!gamestate.keys[keyspot])
  1606. {
  1607. SD_PlaySound(HIT_GATESND);
  1608. CenterWindow(20,5);
  1609. US_CPrint("\nYou need\n");
  1610. US_CPrint(key_colors[keyspot]);
  1611. VW_UpdateScreen();
  1612. IN_ClearKeysDown();
  1613. IN_Ack();
  1614. return;
  1615. }
  1616. //
  1617. // deal with this gate (warp? simply open? whatever...)
  1618. //
  1619. switch (spot)
  1620. {
  1621. case NEXT_LEVEL_CODE: // WARP TO NEXT LEVEL
  1622. newlevel = gamestate.mapon+1;
  1623. playstate = ex_warped;
  1624. break;
  1625. case REMOVE_DOOR_CODE: // REMOVE DOOR
  1626. (unsigned)actorat[x][y] = tilemap[x][y] = *(mapsegs[0]+farmapylookup[y]+x) = 0;
  1627. *(mapsegs[2]+farmapylookup[y+1]+x) = 0; // key no longer needed
  1628. if (keyspot>=0)
  1629. TakeKey(keyspot);
  1630. break;
  1631. default: // WARP TO A LEVEL
  1632. newlevel = spot;
  1633. playstate = ex_warped;
  1634. break;
  1635. }
  1636. if (playstate == ex_warped)
  1637. {
  1638. SD_PlaySound(HIT_GATESND);
  1639. // levelinfo *li=&gamestate.levels[curmap];
  1640. // OldAngle = FaceDoor(x,y);
  1641. if (!VerifyGateExit())
  1642. {
  1643. IN_ClearKeysDown ();
  1644. playstate = ex_stillplaying;
  1645. break;
  1646. }
  1647. // FaceAngle(OldAngle);
  1648. if (keyspot>=0)
  1649. TakeKey(keyspot);
  1650. *(mapsegs[2]+farmapylookup[y+1]+x) = 0; // key no longer needed
  1651. gamestate.mapon = newlevel;
  1652. SD_PlaySound(WARPUPSND);
  1653. IN_ClearKeysDown ();
  1654. // li->x = player->tilex;
  1655. // li->y = player->tiley;
  1656. // li->angle = player->angle+180;
  1657. // if (li->angle > 360)
  1658. // li->angle -= 360;
  1659. }
  1660. }
  1661. break;
  1662. }
  1663. return true;
  1664. }
  1665. //-------------------------------------------------------------------------
  1666. // VerifyGateExit()
  1667. //-------------------------------------------------------------------------
  1668. boolean VerifyGateExit()
  1669. {
  1670. char choices[] = {sc_Escape,sc_Y,sc_N,0},ch;
  1671. ch=DisplayMsg("Pass this way? Y/N",choices);
  1672. DrawText(true);
  1673. return(ch == sc_Y);
  1674. }
  1675. /*
  1676. ==================
  1677. =
  1678. = TouchActor
  1679. =
  1680. = Returns true if the move is blocked
  1681. =
  1682. ==================
  1683. */
  1684. boolean TouchActor (objtype *ob, objtype *check)
  1685. {
  1686. if (ob->xh < check->xl || ob->xl > check->xh ||
  1687. ob->yh < check->yl || ob->yl > check->yh)
  1688. return false; // not quite touching
  1689. switch (check->obclass)
  1690. {
  1691. case bonusobj:
  1692. switch (check->temp1)
  1693. {
  1694. case B_BOLT: GiveBolt (); break;
  1695. case B_NUKE: GiveNuke (); break;
  1696. case B_POTION: GivePotion (); break;
  1697. // case B_RKEY2: GiveKey(B_RKEY-B_RKEY); break;
  1698. case B_RKEY:
  1699. case B_YKEY:
  1700. case B_GKEY:
  1701. case B_BKEY: GiveKey (check->temp1-B_RKEY); break;
  1702. #if 0
  1703. case B_SCROLL1:
  1704. case B_SCROLL2:
  1705. case B_SCROLL3:
  1706. case B_SCROLL4:
  1707. case B_SCROLL5:
  1708. case B_SCROLL6:
  1709. case B_SCROLL7:
  1710. case B_SCROLL8: GiveScroll (check->temp1-B_SCROLL1,true); break;
  1711. #endif
  1712. case B_CHEST: GiveChest (); break;
  1713. case B_RGEM:
  1714. case B_YGEM:
  1715. case B_GGEM:
  1716. case B_BGEM:
  1717. case B_PGEM:
  1718. SD_PlaySound(GETGEMSND);
  1719. gamestate.gems[check->temp1-B_RGEM] = GEM_DELAY_TIME;
  1720. redraw_gems = true;
  1721. break;
  1722. default:
  1723. Quit("TouchActor(): INVALID BONUS");
  1724. break;
  1725. }
  1726. (unsigned)actorat[check->tilex][check->tiley] = 0;
  1727. RemoveObj (check);
  1728. return false;
  1729. case freezeobj:
  1730. StopTime();
  1731. (unsigned)actorat[check->tilex][check->tiley] = 0;
  1732. RemoveObj(check);
  1733. return(false);
  1734. case cloudobj:
  1735. TakeDamage(2);
  1736. return false;
  1737. }
  1738. return true;
  1739. }
  1740. /*
  1741. ==================
  1742. =
  1743. = CalcBounds
  1744. =
  1745. ==================
  1746. */
  1747. void CalcBounds (objtype *ob)
  1748. {
  1749. //
  1750. // calculate hit rect
  1751. //
  1752. ob->xl = ob->x - ob->size;
  1753. ob->xh = ob->x + ob->size;
  1754. ob->yl = ob->y - ob->size;
  1755. ob->yh = ob->y + ob->size;
  1756. }
  1757. /*
  1758. ===================
  1759. =
  1760. = LocationInActor
  1761. =
  1762. ===================
  1763. */
  1764. boolean LocationInActor (objtype *ob)
  1765. {
  1766. int x,y,xmin,ymin,xmax,ymax;
  1767. objtype *check;
  1768. CalcBounds (ob);
  1769. xmin = (ob->x >> TILESHIFT)-2;
  1770. ymin = (ob->y >> TILESHIFT)-2;
  1771. xmax = xmin+5;
  1772. ymax = ymin+5;
  1773. for (x=xmin;x<xmax;x++)
  1774. for (y=ymin;y<ymax;y++)
  1775. {
  1776. check = actorat[x][y];
  1777. if (check>(objtype *)LASTTILE
  1778. && (check->flags & of_shootable)
  1779. && (check->obclass != bonusobj)
  1780. && (check->obclass != freezeobj)
  1781. && (check->obclass != solidobj)
  1782. && ob->xl-SIZE_TEST <= check->xh
  1783. && ob->xh+SIZE_TEST >= check->xl
  1784. && ob->yl-SIZE_TEST <= check->yh
  1785. && ob->yh+SIZE_TEST >= check->yl)
  1786. return true;
  1787. }
  1788. return false;
  1789. }
  1790. /*
  1791. ===================
  1792. =
  1793. = ClipXMove
  1794. =
  1795. = Only checks corners, so the object better be less than one tile wide!
  1796. =
  1797. ===================
  1798. */
  1799. void ClipXMove (objtype *ob, long xmove)
  1800. {
  1801. int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;
  1802. long intersect,basex,basey,pointx,pointy;
  1803. unsigned inside,total,tile;
  1804. objtype *check;
  1805. boolean moveok;
  1806. boolean invisible_present = false;
  1807. //
  1808. // move player and check to see if any corners are in solid tiles
  1809. //
  1810. basex = ob->x;
  1811. basey = ob->y;
  1812. ob->x += xmove;
  1813. CalcBounds (ob);
  1814. xl = ob->xl>>TILESHIFT;
  1815. yl = ob->yl>>TILESHIFT;
  1816. xh = ob->xh>>TILESHIFT;
  1817. yh = ob->yh>>TILESHIFT;
  1818. for (y=yl;y<=yh;y++)
  1819. for (x=xl;x<=xh;x++)
  1820. {
  1821. check = actorat[x][y];
  1822. if (!check)
  1823. continue; // blank floor, walk ok
  1824. if ((unsigned)check <= LASTTILE)
  1825. {
  1826. if (TILE_FLAGS((unsigned)check) & tf_SPECIAL)
  1827. {
  1828. HitSpecialTile(x,y,(unsigned)check-SPECTILESTART);
  1829. goto blockmove;
  1830. }
  1831. if (TILE_FLAGS((unsigned)check) & tf_INVISIBLE_WALL)
  1832. {
  1833. invisible_present = true;
  1834. goto blockmove;
  1835. }
  1836. if (TILE_FLAGS((unsigned)check) & tf_SOLID)
  1837. {
  1838. goto blockmove; // solid wall
  1839. }
  1840. }
  1841. TouchActor(ob,check); // pick up items
  1842. }
  1843. //
  1844. // check nearby actors
  1845. //
  1846. if (LocationInActor(ob))
  1847. {
  1848. ob->x -= xmove;
  1849. if (LocationInActor(ob))
  1850. {
  1851. ob->x += xmove;
  1852. if (LocationInActor(ob))
  1853. ob->x -= xmove;
  1854. }
  1855. }
  1856. return; // move is OK!
  1857. blockmove:
  1858. // if (!SD_SoundPlaying())
  1859. // SD_PlaySound (HITWALLSND);
  1860. moveok = false;
  1861. do
  1862. {
  1863. xmove /= 2;
  1864. if (moveok)
  1865. {
  1866. ob->x += xmove;
  1867. }
  1868. else
  1869. {
  1870. ob->x -= xmove;
  1871. }
  1872. CalcBounds (ob);
  1873. xl = ob->xl>>TILESHIFT;
  1874. yl = ob->yl>>TILESHIFT;
  1875. xh = ob->xh>>TILESHIFT;
  1876. yh = ob->yh>>TILESHIFT;
  1877. if (tilemap[xl][yl] || tilemap[xh][yl]
  1878. || tilemap[xh][yh] || tilemap[xl][yh] )
  1879. {
  1880. moveok = false;
  1881. if (xmove>=-2048 && xmove <=2048)
  1882. {
  1883. ob->x = basex;
  1884. ob->y = basey;
  1885. return;
  1886. }
  1887. }
  1888. else
  1889. if (invisible_present)
  1890. {
  1891. moveok = false;
  1892. if (xmove>=-2048 && xmove <=2048)
  1893. {
  1894. ob->x = basex;
  1895. ob->y = basey;
  1896. return;
  1897. }
  1898. }
  1899. else
  1900. if (xmove>=-2048 && xmove <=2048)
  1901. return;
  1902. moveok = true;
  1903. } while (1);
  1904. }
  1905. /*
  1906. ===================
  1907. =
  1908. = ClipYMove
  1909. =
  1910. = Only checks corners, so the object better be less than one tile wide!
  1911. =
  1912. ===================
  1913. */
  1914. void ClipYMove (objtype *ob, long ymove)
  1915. {
  1916. int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;
  1917. long intersect,basex,basey,pointx,pointy;
  1918. unsigned inside,total,tile;
  1919. objtype *check;
  1920. boolean moveok;
  1921. boolean invisible_present = false;
  1922. //
  1923. // move player and check to see if any corners are in solid tiles
  1924. //
  1925. basex = ob->x;
  1926. basey = ob->y;
  1927. ob->y += ymove;
  1928. CalcBounds (ob);
  1929. xl = ob->xl>>TILESHIFT;
  1930. yl = ob->yl>>TILESHIFT;
  1931. xh = ob->xh>>TILESHIFT;
  1932. yh = ob->yh>>TILESHIFT;
  1933. for (y=yl;y<=yh;y++)
  1934. for (x=xl;x<=xh;x++)
  1935. {
  1936. check = actorat[x][y];
  1937. if (!check)
  1938. continue; // blank floor, walk ok
  1939. if ((unsigned)check <= LASTTILE)
  1940. {
  1941. if (TILE_FLAGS((unsigned)check) & tf_SPECIAL) // <=LASTSPECIALTILE)
  1942. {
  1943. HitSpecialTile (x,y,(unsigned)check-SPECTILESTART);
  1944. goto blockmove;
  1945. }
  1946. if (TILE_FLAGS((unsigned)check) & tf_INVISIBLE_WALL)
  1947. {
  1948. invisible_present = true;
  1949. goto blockmove;
  1950. }
  1951. if (TILE_FLAGS((unsigned)check) & tf_SOLID) // LASTWALLTILE)
  1952. {
  1953. goto blockmove; // solid wall
  1954. }
  1955. }
  1956. TouchActor(ob,check); // pick up items
  1957. }
  1958. //
  1959. // check nearby actors
  1960. //
  1961. if (LocationInActor(ob))
  1962. {
  1963. if (LocationInActor(ob))
  1964. {
  1965. ob->y -= ymove;
  1966. }
  1967. }
  1968. return; // move is OK!
  1969. blockmove:
  1970. // if (!SD_SoundPlaying())
  1971. // SD_PlaySound (HITWALLSND);
  1972. moveok = false;
  1973. do
  1974. {
  1975. ymove /= 2;
  1976. if (moveok)
  1977. {
  1978. ob->y += ymove;
  1979. }
  1980. else
  1981. {
  1982. ob->y -= ymove;
  1983. }
  1984. CalcBounds (ob);
  1985. xl = ob->xl>>TILESHIFT;
  1986. yl = ob->yl>>TILESHIFT;
  1987. xh = ob->xh>>TILESHIFT;
  1988. yh = ob->yh>>TILESHIFT;
  1989. if (tilemap[xl][yl] || tilemap[xh][yl]
  1990. || tilemap[xh][yh] || tilemap[xl][yh] )
  1991. {
  1992. moveok = false;
  1993. if (ymove>=-2048 && ymove <=2048)
  1994. {
  1995. ob->x = basex;
  1996. ob->y = basey;
  1997. return;
  1998. }
  1999. }
  2000. else
  2001. if (invisible_present)
  2002. {
  2003. moveok = false;
  2004. if (ymove>=-2048 && ymove <=2048)
  2005. {
  2006. ob->x = basex;
  2007. ob->y = basey;
  2008. return;
  2009. }
  2010. }
  2011. else
  2012. if (ymove>=-2048 && ymove <=2048)
  2013. return;
  2014. moveok = true;
  2015. } while (1);
  2016. }
  2017. //==========================================================================
  2018. /*
  2019. ===================
  2020. =
  2021. = ShotClipMove
  2022. =
  2023. = Only checks corners, so the object better be less than one tile wide!
  2024. =
  2025. ===================
  2026. */
  2027. boolean ShotClipMove (objtype *ob, long xmove, long ymove)
  2028. {
  2029. int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;
  2030. long intersect,basex,basey,pointx,pointy;
  2031. unsigned inside,total,spot,tile;
  2032. objtype *check;
  2033. boolean moveok;
  2034. //
  2035. // move shot and check to see if any corners are in solid tiles
  2036. //
  2037. basex = ob->x;
  2038. basey = ob->y;
  2039. ob->x += xmove;
  2040. ob->y += ymove;
  2041. CalcBounds (ob);
  2042. xl = ob->xl>>TILESHIFT;
  2043. yl = ob->yl>>TILESHIFT;
  2044. xh = ob->xh>>TILESHIFT;
  2045. yh = ob->yh>>TILESHIFT;
  2046. for (y=yl;y<=yh;y++)
  2047. for (x=xl;x<=xh;x++)
  2048. {
  2049. spot = (*(mapsegs[2]+farmapylookup[y]+x)) >> 8;
  2050. if (spot == EXP_WALL_CODE)
  2051. switch (ob->obclass)
  2052. {
  2053. case pshotobj:
  2054. case bigpshotobj:
  2055. ExplodeWall (x,y);
  2056. goto blockmove;
  2057. break;
  2058. }
  2059. tile = *(mapsegs[0]+farmapylookup[y]+x);
  2060. if (TILE_FLAGS(tile) & tf_SOLID)
  2061. goto blockmove;
  2062. }
  2063. return false; // move is OK!
  2064. blockmove:
  2065. SD_PlaySound (SHOOTWALLSND);
  2066. moveok = false;
  2067. do
  2068. {
  2069. xmove /= 2;
  2070. ymove /= 2;
  2071. if (moveok)
  2072. {
  2073. ob->x += xmove;
  2074. ob->y += ymove;
  2075. }
  2076. else
  2077. {
  2078. ob->x -= xmove;
  2079. ob->y -= ymove;
  2080. }
  2081. CalcBounds (ob);
  2082. xl = ob->xl>>TILESHIFT;
  2083. yl = ob->yl>>TILESHIFT;
  2084. xh = ob->xh>>TILESHIFT;
  2085. yh = ob->yh>>TILESHIFT;
  2086. if (tilemap[xl][yl] || tilemap[xh][yl]
  2087. || tilemap[xh][yh] || tilemap[xl][yh] )
  2088. {
  2089. moveok = false;
  2090. if (xmove>=-2048 && xmove <=2048 && ymove>=-2048 && ymove <=2048)
  2091. {
  2092. ob->x = basex;
  2093. ob->y = basey;
  2094. return true;
  2095. }
  2096. }
  2097. else
  2098. {
  2099. if (xmove>=-2048 && xmove <=2048 && ymove>=-2048 && ymove <=2048)
  2100. return true;
  2101. moveok = true;
  2102. }
  2103. } while (1);
  2104. }
  2105. /*
  2106. =============================================================================
  2107. PLAYER CONTROL
  2108. =============================================================================
  2109. */
  2110. void T_Player (objtype *ob);
  2111. statetype s_player = {0,0,&T_Player,&s_player};
  2112. /*
  2113. ===============
  2114. =
  2115. = SpawnPlayer
  2116. =
  2117. ===============
  2118. */
  2119. void SpawnPlayer (int tilex, int tiley, int dir)
  2120. {
  2121. #if 0
  2122. levelinfo *li=&gamestate.levels[gamestate.mapon];
  2123. if (li->x != -1)
  2124. {
  2125. tilex = li->x;
  2126. tiley = li->y;
  2127. player->angle = li->angle;
  2128. }
  2129. else
  2130. player->angle = (1-dir)*90;
  2131. #endif
  2132. player->obclass = playerobj;
  2133. player->active = always;
  2134. player->tilex = tilex;
  2135. player->tiley = tiley;
  2136. player->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;
  2137. player->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;
  2138. player->state = &s_player;
  2139. player->size = MINDIST;
  2140. CalcBounds(player);
  2141. player->angle = (1-dir)*90;
  2142. if (player->angle<0)
  2143. player->angle += ANGLES;
  2144. }
  2145. /*
  2146. ===================
  2147. =
  2148. = Thrust
  2149. =
  2150. ===================
  2151. */
  2152. void Thrust (int angle, unsigned speed)
  2153. {
  2154. long xmove,ymove;
  2155. if (lasttimecount>>5 != ((lasttimecount-tics)>>5) )
  2156. {
  2157. //
  2158. // walk sound
  2159. //
  2160. if (lasttimecount&32)
  2161. SD_PlaySound (WALK1SND);
  2162. else
  2163. SD_PlaySound (WALK2SND);
  2164. }
  2165. xmove = FixedByFrac(speed,costable[angle]);
  2166. ymove = -FixedByFrac(speed,sintable[angle]);
  2167. ClipXMove(player,xmove);
  2168. ClipYMove(player,ymove);
  2169. player->tilex = player->x >> TILESHIFT;
  2170. player->tiley = player->y >> TILESHIFT;
  2171. }
  2172. /*
  2173. =======================
  2174. =
  2175. = ControlMovement
  2176. =
  2177. =======================
  2178. */
  2179. void ControlMovement (objtype *ob)
  2180. {
  2181. int angle;
  2182. long speed;
  2183. if (control.button1)
  2184. {
  2185. //
  2186. // strafing
  2187. //
  2188. //
  2189. // side to side move
  2190. //
  2191. if (!mousexmove)
  2192. speed = 0;
  2193. else if (mousexmove<0)
  2194. speed = -(long)mousexmove*300;
  2195. else
  2196. speed = -(long)mousexmove*300;
  2197. if (control.xaxis == -1)
  2198. {
  2199. speed += PLAYERSPEED*tics;
  2200. }
  2201. else if (control.xaxis == 1)
  2202. {
  2203. speed -= PLAYERSPEED*tics;
  2204. }
  2205. if (speed > 0)
  2206. {
  2207. if (speed >= TILEGLOBAL)
  2208. speed = TILEGLOBAL-1;
  2209. angle = ob->angle + ANGLES/4;
  2210. if (angle >= ANGLES)
  2211. angle -= ANGLES;
  2212. Thrust (angle,speed); // move to left
  2213. }
  2214. else if (speed < 0)
  2215. {
  2216. if (speed <= -TILEGLOBAL)
  2217. speed = -TILEGLOBAL+1;
  2218. angle = ob->angle - ANGLES/4;
  2219. if (angle < 0)
  2220. angle += ANGLES;
  2221. Thrust (angle,-speed); // move to right
  2222. }
  2223. }
  2224. else
  2225. {
  2226. //
  2227. // not strafing
  2228. //
  2229. //
  2230. // turning
  2231. //
  2232. if (control.xaxis == 1)
  2233. {
  2234. ob->angle -= tics;
  2235. if (running) // fast turn
  2236. ob->angle -= (tics<<1);
  2237. }
  2238. else if (control.xaxis == -1)
  2239. {
  2240. ob->angle+= tics;
  2241. if (running) // fast turn
  2242. ob->angle += (tics<<1);
  2243. }
  2244. ob->angle -= (mousexmove/10);
  2245. if (ob->angle >= ANGLES)
  2246. ob->angle -= ANGLES;
  2247. if (ob->angle < 0)
  2248. ob->angle += ANGLES;
  2249. }
  2250. //
  2251. // forward/backwards move
  2252. //
  2253. if (!mouseymove)
  2254. speed = 0;
  2255. else if (mouseymove<0)
  2256. speed = -(long)mouseymove*500;
  2257. else
  2258. speed = -(long)mouseymove*200;
  2259. if (control.yaxis == -1)
  2260. {
  2261. speed += PLAYERSPEED*tics;
  2262. }
  2263. else if (control.yaxis == 1)
  2264. {
  2265. speed -= PLAYERSPEED*tics;
  2266. }
  2267. if (speed > 0)
  2268. {
  2269. if (speed >= TILEGLOBAL)
  2270. speed = TILEGLOBAL-1;
  2271. Thrust (ob->angle,speed); // move forwards
  2272. }
  2273. else if (speed < 0)
  2274. {
  2275. if (speed <= -TILEGLOBAL)
  2276. speed = -TILEGLOBAL+1;
  2277. angle = ob->angle + ANGLES/2;
  2278. if (angle >= ANGLES)
  2279. angle -= ANGLES;
  2280. Thrust (angle,-speed); // move backwards
  2281. }
  2282. }
  2283. /*
  2284. ===============
  2285. =
  2286. = T_Player
  2287. =
  2288. ===============
  2289. */
  2290. void T_Player (objtype *ob)
  2291. {
  2292. extern boolean autofire;
  2293. int angle,speed,scroll,loop;
  2294. unsigned text,tilex,tiley;
  2295. long lspeed;
  2296. // boolean radar_moved=false;
  2297. ControlMovement (ob);
  2298. //
  2299. // firing
  2300. //
  2301. if (boltsleft)
  2302. {
  2303. handheight+=(realtics<<2);
  2304. if (handheight>MAXHANDHEIGHT)
  2305. handheight = MAXHANDHEIGHT;
  2306. ContinueBolt ();
  2307. lasthand = lasttimecount;
  2308. }
  2309. else
  2310. {
  2311. if (control.button0)
  2312. {
  2313. handheight+=(realtics<<2);
  2314. if (handheight>MAXHANDHEIGHT)
  2315. handheight = MAXHANDHEIGHT;
  2316. lasthand = lasttimecount;
  2317. if (!button0down)
  2318. Shoot();
  2319. if (!autofire)
  2320. button0down=true;
  2321. }
  2322. else
  2323. {
  2324. if (lasttimecount > lasthand+HANDPAUSE)
  2325. {
  2326. handheight-=(realtics<<1);
  2327. if (handheight<0)
  2328. handheight = 0;
  2329. }
  2330. button0down = false;
  2331. }
  2332. }
  2333. #if 0
  2334. if (control.button0)
  2335. {
  2336. handheight+=(realtics<<2);
  2337. if (handheight>MAXHANDHEIGHT)
  2338. handheight = MAXHANDHEIGHT;
  2339. if ((unsigned)TimeCount/FIRETIME != lastfiretime)
  2340. BuildShotPower ();
  2341. lasthand = lasttimecount;
  2342. }
  2343. else
  2344. {
  2345. if (lasttimecount > lasthand+HANDPAUSE)
  2346. {
  2347. handheight-=(realtics<<1);
  2348. if (handheight<0)
  2349. handheight = 0;
  2350. }
  2351. if (gamestate.shotpower)
  2352. {
  2353. lastfiretime = (unsigned)TimeCount/FIRETIME;
  2354. Shoot ();
  2355. }
  2356. }
  2357. }
  2358. #endif
  2359. //
  2360. // special actions
  2361. //
  2362. if ((Keyboard[sc_Space] || Keyboard[sc_C]) && gamestate.body != MAXBODY)
  2363. DrinkPotion ();
  2364. if (Keyboard[sc_Z] && !boltsleft)
  2365. CastBolt ();
  2366. if ( (Keyboard[sc_Enter] || Keyboard[sc_X]) && ((TimeCount-lastnuke > NUKETIME) || (autofire)))
  2367. CastNuke ();
  2368. #if 0
  2369. scroll = LastScan-2;
  2370. if ( scroll>=0 && scroll<NUMSCROLLS && gamestate.scrolls[scroll])
  2371. ReadScroll (scroll);
  2372. #endif
  2373. DrawText(false);
  2374. DrawHealth();
  2375. if (FreezeTime)
  2376. DrawFreezeTime();
  2377. DrawRadar();
  2378. EGAWRITEMODE(0);
  2379. DrawNSEWIcons();
  2380. if (redraw_gems)
  2381. DrawGems();
  2382. #if 0
  2383. // gems fade out over time...
  2384. //
  2385. for (loop=0; loop<5; loop++)
  2386. if (gamestate.gems[loop])
  2387. {
  2388. gamestate.gems[loop] -= realtics;
  2389. if (gamestate.gems[loop] < 0)
  2390. {
  2391. gamestate.gems[loop] = 0;
  2392. redraw_gems = true;
  2393. }
  2394. }
  2395. #endif
  2396. }
  2397. #if 0
  2398. //------------------------------------------------------------------------
  2399. // FaceDir() -
  2400. //
  2401. // PARAMS : x,y - pixle coords to bring in to view.
  2402. //
  2403. // NOTE : Params CAN NOT be shifted fracs!
  2404. //------------------------------------------------------------------------
  2405. void FaceDir(short x,short y,boolean StopTime)
  2406. {
  2407. short diff;
  2408. RotateAngle = CalcAngle(x-(player->x>>16l),(player->y>>16l)-y);
  2409. FreezeTime = StopTime;
  2410. diff = player->angle - RotateAngle;
  2411. if (((diff>0) && (diff<180)) || ((diff<0) && (diff>-180)))
  2412. RotateSpeed = -ROTATE_SPEED;
  2413. else
  2414. RotateSpeed = ROTATE_SPEED;
  2415. }
  2416. #endif
  2417. #if 0
  2418. //------------------------------------------------------------------------
  2419. // CalcAngle() -
  2420. //
  2421. // DESC: Calculates the angle from a given dy & dx
  2422. //------------------------------------------------------------------------
  2423. short CalcAngle(short dx,short dy)
  2424. {
  2425. #define degtorad (180/PI)
  2426. float angle;
  2427. short diff;
  2428. float rad_angle;
  2429. if (dx)
  2430. {
  2431. angle = atan((float)dy/dx)* degtorad;
  2432. if (angle<=0)
  2433. angle += 180;
  2434. if (dy>0)
  2435. angle += 180;
  2436. }
  2437. else
  2438. {
  2439. // 90 Deg shift
  2440. if (dy < 0)
  2441. angle = 0 + 90; // Above player (NORTH)
  2442. else
  2443. angle = 180 + 90; // Below player (SOUTH)
  2444. }
  2445. if (!angle) // HACK
  2446. angle++;
  2447. return((short)abs(angle));
  2448. }
  2449. #endif
  2450. #if 0
  2451. //-------------------------------------------------------------------------
  2452. // RotateView() -
  2453. //
  2454. // DESC : Rotates view (current view of game) to a dest angle.
  2455. //-------------------------------------------------------------------------
  2456. void RotateView()
  2457. {
  2458. short LastPos;
  2459. // Store old angle position then change angle...
  2460. //
  2461. LastPos = player->angle;
  2462. player->angle += RotateSpeed;
  2463. // Check to see if we cranked past out dest angle...
  2464. //
  2465. if ((player->angle>ANGLES) || (!player->angle))
  2466. player->angle = 1;
  2467. else
  2468. if (player->angle<1)
  2469. player->angle = ANGLES;
  2470. // Check to see if we over shot our dest angle...
  2471. //
  2472. if (((LastPos < RotateAngle) && (player->angle > RotateAngle) && (RotateSpeed > 0)) ||
  2473. ((LastPos > RotateAngle) && (player->angle < RotateAngle) && (RotateSpeed < 0)))
  2474. player->angle = RotateAngle;
  2475. // Check for ending force turn....
  2476. //
  2477. if (player->angle == RotateAngle)
  2478. RotateAngle = -1;
  2479. }
  2480. //--------------------------------------------------------------------------
  2481. // InitRotate()
  2482. //--------------------------------------------------------------------------
  2483. void InitRotate(short DestAngle)
  2484. {
  2485. if (player->angle != DestAngle)
  2486. {
  2487. RotateAngle = DestAngle;
  2488. if (player->angle > DestAngle)
  2489. RotateSpeed = -ROTATE_SPEED;
  2490. else
  2491. RotateSpeed = ROTATE_SPEED;
  2492. if (abs(player->angle - RotateAngle) > 180)
  2493. RotateSpeed =- RotateSpeed;
  2494. }
  2495. }
  2496. //------------------------------------------------------------------------
  2497. // FaceAngle() -
  2498. //
  2499. // PARAMS : DestAngle - Destination angle to turn to
  2500. //------------------------------------------------------------------------
  2501. void FaceAngle(short DestAngle)
  2502. {
  2503. signed long dx,dy,radius,psin,pcos,newx,newy;
  2504. int give;
  2505. short objnum,LastPos;
  2506. signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;
  2507. short o_radius;
  2508. void (*think)();
  2509. // Calculate the direction we want to turn to...
  2510. //
  2511. InitRotate(DestAngle);
  2512. RedrawStatusWindow();
  2513. while (RotateAngle != -1)
  2514. {
  2515. RotateView();
  2516. // PollControls();
  2517. objnum=0;
  2518. for (obj = player;obj;obj = obj->next)
  2519. {
  2520. if (obj->active >= yes)
  2521. {
  2522. // keep a list of objects around the player for radar updates
  2523. //
  2524. if (obj == player)
  2525. {
  2526. px = player->x;
  2527. py = player->y;
  2528. psin = sintable[player->angle];
  2529. pcos = costable[player->angle];
  2530. xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;
  2531. xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;
  2532. yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;
  2533. yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;
  2534. }
  2535. if (objnum > MAX_RADAR_BLIPS-2)
  2536. objnum = MAX_RADAR_BLIPS-2;
  2537. ox = obj->x;
  2538. oy = obj->y;
  2539. if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))
  2540. {
  2541. norm_dx = (dx = px-ox)>>TILESHIFT;
  2542. norm_dy = (dy = oy-py)>>TILESHIFT;
  2543. o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));
  2544. if (o_radius < RADAR_RADIUS)
  2545. {
  2546. newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);
  2547. newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);
  2548. RadarXY[objnum][0]=newx>>TILESHIFT;
  2549. RadarXY[objnum][1]=newy>>TILESHIFT;
  2550. // Define color to use for this object...
  2551. //
  2552. switch (obj->obclass)
  2553. {
  2554. case playerobj:
  2555. RadarXY[objnum++][2]=15;
  2556. break;
  2557. // RED GEM
  2558. //
  2559. case godessobj:
  2560. if (gamestate.gems[B_RGEM-B_RGEM])
  2561. if (obj->active == always)
  2562. RadarXY[objnum++][2]=12;
  2563. break;
  2564. // GREEN GEM
  2565. //
  2566. case fatdemonobj:
  2567. if (gamestate.gems[B_GGEM-B_RGEM])
  2568. if (obj->active == always)
  2569. RadarXY[objnum++][2]=10;
  2570. break;
  2571. // YELLOW GEM
  2572. //
  2573. case skeletonobj:
  2574. if (gamestate.gems[B_YGEM-B_RGEM])
  2575. if (obj->active == always)
  2576. RadarXY[objnum++][2]=14;
  2577. break;
  2578. // BLUE GEM
  2579. //
  2580. case mageobj:
  2581. case wetobj:
  2582. if (gamestate.gems[B_BGEM-B_RGEM])
  2583. if (obj->active == always)
  2584. RadarXY[objnum++][2]=9;
  2585. break;
  2586. // PURPLE GEM
  2587. //
  2588. case zombieobj:
  2589. if (gamestate.gems[B_PGEM-B_RGEM])
  2590. if (obj->active == always)
  2591. RadarXY[objnum++][2]=13;
  2592. break;
  2593. }
  2594. }
  2595. }
  2596. }
  2597. }
  2598. RadarXY[objnum][2]=-1; // Signals end of RadarXY list...
  2599. // refresh all
  2600. //
  2601. ThreeDRefresh();
  2602. DrawRadar();
  2603. EGAWRITEMODE(0);
  2604. DrawNSEWIcons();
  2605. // CheckKeys();
  2606. }
  2607. }
  2608. //-------------------------------------------------------------------------
  2609. // FaceDoor() - Turns the player to face a door (a tile) at a given TILE x & y
  2610. //
  2611. // RETURNS : Returns the orginal angle of the player.
  2612. //------------------------------------------------------------------------
  2613. short FaceDoor(short x, short y)
  2614. {
  2615. short p_x,p_y,angle,old_angle;
  2616. old_angle = player->angle;
  2617. p_x = player->x>>16l;
  2618. p_y = player->y>>16l;
  2619. if (p_x != x)
  2620. {
  2621. if (p_x > x)
  2622. angle = 180; // Face Left
  2623. else
  2624. angle = 1; // Face Right
  2625. }
  2626. if (p_y != y)
  2627. {
  2628. if (p_y > y)
  2629. angle = 90; // Face Up
  2630. else
  2631. angle = 270; // Face Down
  2632. }
  2633. FaceAngle(angle);
  2634. return(old_angle);
  2635. }
  2636. #endif
  2637. /*==========================================================================
  2638. EXPLOSION SPAWNING ROUTINES
  2639. ===========================================================================*/
  2640. statetype s_explode = {0,1,T_ExpThink,&s_explode};
  2641. //-------------------------------------------------------------------------
  2642. // SpawnExplosion()
  2643. //------------------------------------------------------------------------
  2644. void SpawnExplosion(fixed x, fixed y, short Delay)
  2645. {
  2646. DSpawnNewObjFrac(x,y,&s_explode,PIXRADIUS*7);
  2647. new->obclass = expobj;
  2648. new->active = always;
  2649. new->temp1 = Delay;
  2650. }
  2651. //---------------------------------------------------------------------------
  2652. // T_ExpThink()
  2653. //---------------------------------------------------------------------------
  2654. void T_ExpThink(objtype *obj)
  2655. {
  2656. if (obj->temp1)
  2657. {
  2658. if ((obj->temp1-=realtics) <= 0)
  2659. obj->temp1 = 0;
  2660. }
  2661. else
  2662. {
  2663. obj->state = &s_pshot_exp1;
  2664. obj->ticcount = obj->state->tictime;
  2665. SD_PlaySound(BOOMSND);
  2666. }
  2667. }
  2668. //-------------------------------------------------------------------------
  2669. // SpawnBigExplosion()
  2670. //------------------------------------------------------------------------
  2671. void SpawnBigExplosion(fixed x, fixed y, short Delay, fixed Range)
  2672. {
  2673. SpawnExplosion(x-random(Range),y+random(Range),random(Delay));
  2674. SpawnExplosion(x+random(Range),y-random(Range),random(Delay));
  2675. SpawnExplosion(x-random(Range),y-random(Range),random(Delay));
  2676. SpawnExplosion(x+random(Range),y+random(Range),random(Delay));
  2677. }