AM_MAP.C 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. // AM_map.c
  2. #include "DoomDef.h"
  3. #include "P_local.h"
  4. #include "AM_map.h"
  5. #include "AM_data.h"
  6. #include <stdio.h>
  7. vertex_t KeyPoints[NUMKEYS];
  8. #define NUMALIAS 3 // Number of antialiased lines.
  9. char *LevelNames[] =
  10. {
  11. // EPISODE 1 - THE CITY OF THE DAMNED
  12. "E1M1: THE DOCKS",
  13. "E1M2: THE DUNGEONS",
  14. "E1M3: THE GATEHOUSE",
  15. "E1M4: THE GUARD TOWER",
  16. "E1M5: THE CITADEL",
  17. "E1M6: THE CATHEDRAL",
  18. "E1M7: THE CRYPTS",
  19. "E1M8: HELL'S MAW",
  20. "E1M9: THE GRAVEYARD",
  21. // EPISODE 2 - HELL'S MAW
  22. "E2M1: THE CRATER",
  23. "E2M2: THE LAVA PITS",
  24. "E2M3: THE RIVER OF FIRE",
  25. "E2M4: THE ICE GROTTO",
  26. "E2M5: THE CATACOMBS",
  27. "E2M6: THE LABYRINTH",
  28. "E2M7: THE GREAT HALL",
  29. "E2M8: THE PORTALS OF CHAOS",
  30. "E2M9: THE GLACIER",
  31. // EPISODE 3 - THE DOME OF D'SPARIL
  32. "E3M1: THE STOREHOUSE",
  33. "E3M2: THE CESSPOOL",
  34. "E3M3: THE CONFLUENCE",
  35. "E3M4: THE AZURE FORTRESS",
  36. "E3M5: THE OPHIDIAN LAIR",
  37. "E3M6: THE HALLS OF FEAR",
  38. "E3M7: THE CHASM",
  39. "E3M8: D'SPARIL'S KEEP",
  40. "E3M9: THE AQUIFER",
  41. // EPISODE 4: THE OSSUARY
  42. "E4M1: CATAFALQUE",
  43. "E4M2: BLOCKHOUSE",
  44. "E4M3: AMBULATORY",
  45. "E4M4: SEPULCHER",
  46. "E4M5: GREAT STAIR",
  47. "E4M6: HALLS OF THE APOSTATE",
  48. "E4M7: RAMPARTS OF PERDITION",
  49. "E4M8: SHATTERED BRIDGE",
  50. "E4M9: MAUSOLEUM",
  51. // EPISODE 5: THE STAGNANT DEMESNE
  52. "E5M1: OCHRE CLIFFS",
  53. "E5M2: RAPIDS",
  54. "E5M3: QUAY",
  55. "E5M4: COURTYARD",
  56. "E5M5: HYDRATYR",
  57. "E5M6: COLONNADE",
  58. "E5M7: FOETID MANSE",
  59. "E5M8: FIELD OF JUDGEMENT",
  60. "E5M9: SKEIN OF D'SPARIL"
  61. };
  62. static int cheating = 0;
  63. static int grid = 0;
  64. static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
  65. boolean automapactive = false;
  66. static int finit_width = SCREENWIDTH;
  67. static int finit_height = SCREENHEIGHT-42;
  68. static int f_x, f_y; // location of window on screen
  69. static int f_w, f_h; // size of window on screen
  70. static int lightlev; // used for funky strobing effect
  71. static byte *fb; // pseudo-frame buffer
  72. static int amclock;
  73. static mpoint_t m_paninc; // how far the window pans each tic (map coords)
  74. static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
  75. static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
  76. static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords)
  77. static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
  78. // width/height of window on map (map coords)
  79. static fixed_t m_w, m_h;
  80. static fixed_t min_x, min_y; // based on level size
  81. static fixed_t max_x, max_y; // based on level size
  82. static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y
  83. static fixed_t min_w, min_h; // based on player size
  84. static fixed_t min_scale_mtof; // used to tell when to stop zooming out
  85. static fixed_t max_scale_mtof; // used to tell when to stop zooming in
  86. // old stuff for recovery later
  87. static fixed_t old_m_w, old_m_h;
  88. static fixed_t old_m_x, old_m_y;
  89. // old location used by the Follower routine
  90. static mpoint_t f_oldloc;
  91. // used by MTOF to scale from map-to-frame-buffer coords
  92. static fixed_t scale_mtof = INITSCALEMTOF;
  93. // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
  94. static fixed_t scale_ftom;
  95. static player_t *plr; // the player represented by an arrow
  96. static vertex_t oldplr;
  97. //static patch_t *marknums[10]; // numbers used for marking by the automap
  98. //static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
  99. //static int markpointnum = 0; // next point to be assigned
  100. static int followplayer = 1; // specifies whether to follow the player around
  101. static char cheat_amap[] = { 'r','a','v','m','a','p' };
  102. static byte cheatcount=0;
  103. extern boolean viewactive;
  104. static byte antialias[NUMALIAS][8]=
  105. {
  106. {96, 97, 98, 99, 100, 101, 102, 103},
  107. {110, 109, 108, 107, 106, 105, 104, 103},
  108. {75, 76, 77, 78, 79, 80, 81, 103}
  109. };
  110. /*
  111. static byte *aliasmax[NUMALIAS] = {
  112. &antialias[0][7], &antialias[1][7], &antialias[2][7]
  113. };*/
  114. static byte *maplump; // pointer to the raw data for the automap background.
  115. static short mapystart=0; // y-value for the start of the map bitmap...used in the paralax stuff.
  116. static short mapxstart=0; //x-value for the bitmap.
  117. //byte screens[][SCREENWIDTH*SCREENHEIGHT];
  118. //void V_MarkRect (int x, int y, int width, int height);
  119. // Functions
  120. void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
  121. int NumLevels, unsigned short IntensityBits);
  122. // Calculates the slope and slope according to the x-axis of a line
  123. // segment in map coordinates (with the upright y-axis n' all) so
  124. // that it can be used with the brain-dead drawing stuff.
  125. // Ripped out for Heretic
  126. /*
  127. void AM_getIslope(mline_t *ml, islope_t *is)
  128. {
  129. int dx, dy;
  130. dy = ml->a.y - ml->b.y;
  131. dx = ml->b.x - ml->a.x;
  132. if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
  133. else is->islp = FixedDiv(dx, dy);
  134. if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
  135. else is->slp = FixedDiv(dy, dx);
  136. }
  137. */
  138. void AM_activateNewScale(void)
  139. {
  140. m_x += m_w/2;
  141. m_y += m_h/2;
  142. m_w = FTOM(f_w);
  143. m_h = FTOM(f_h);
  144. m_x -= m_w/2;
  145. m_y -= m_h/2;
  146. m_x2 = m_x + m_w;
  147. m_y2 = m_y + m_h;
  148. }
  149. void AM_saveScaleAndLoc(void)
  150. {
  151. old_m_x = m_x;
  152. old_m_y = m_y;
  153. old_m_w = m_w;
  154. old_m_h = m_h;
  155. }
  156. void AM_restoreScaleAndLoc(void)
  157. {
  158. m_w = old_m_w;
  159. m_h = old_m_h;
  160. if (!followplayer)
  161. {
  162. m_x = old_m_x;
  163. m_y = old_m_y;
  164. } else {
  165. m_x = plr->mo->x - m_w/2;
  166. m_y = plr->mo->y - m_h/2;
  167. }
  168. m_x2 = m_x + m_w;
  169. m_y2 = m_y + m_h;
  170. // Change the scaling multipliers
  171. scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
  172. scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  173. }
  174. // adds a marker at the current location
  175. /*
  176. void AM_addMark(void)
  177. {
  178. markpoints[markpointnum].x = m_x + m_w/2;
  179. markpoints[markpointnum].y = m_y + m_h/2;
  180. markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
  181. }
  182. */
  183. void AM_findMinMaxBoundaries(void)
  184. {
  185. int i;
  186. fixed_t a, b;
  187. min_x = min_y = MAXINT;
  188. max_x = max_y = -MAXINT;
  189. for (i=0;i<numvertexes;i++)
  190. {
  191. if (vertexes[i].x < min_x) min_x = vertexes[i].x;
  192. else if (vertexes[i].x > max_x) max_x = vertexes[i].x;
  193. if (vertexes[i].y < min_y) min_y = vertexes[i].y;
  194. else if (vertexes[i].y > max_y) max_y = vertexes[i].y;
  195. }
  196. max_w = max_x - min_x;
  197. max_h = max_y - min_y;
  198. min_w = 2*PLAYERRADIUS;
  199. min_h = 2*PLAYERRADIUS;
  200. a = FixedDiv(f_w<<FRACBITS, max_w);
  201. b = FixedDiv(f_h<<FRACBITS, max_h);
  202. min_scale_mtof = a < b ? a : b;
  203. max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
  204. }
  205. void AM_changeWindowLoc(void)
  206. {
  207. if (m_paninc.x || m_paninc.y)
  208. {
  209. followplayer = 0;
  210. f_oldloc.x = MAXINT;
  211. }
  212. m_x += m_paninc.x;
  213. m_y += m_paninc.y;
  214. if (m_x + m_w/2 > max_x)
  215. {
  216. m_x = max_x - m_w/2;
  217. m_paninc.x=0;
  218. }
  219. else if (m_x + m_w/2 < min_x)
  220. {
  221. m_x = min_x - m_w/2;
  222. m_paninc.x=0;
  223. }
  224. if (m_y + m_h/2 > max_y)
  225. {
  226. m_y = max_y - m_h/2;
  227. m_paninc.y=0;
  228. }
  229. else if (m_y + m_h/2 < min_y)
  230. {
  231. m_y = min_y - m_h/2;
  232. m_paninc.y=0;
  233. }
  234. /*
  235. mapxstart += MTOF(m_paninc.x+FRACUNIT/2);
  236. mapystart -= MTOF(m_paninc.y+FRACUNIT/2);
  237. if(mapxstart >= finit_width)
  238. mapxstart -= finit_width;
  239. if(mapxstart < 0)
  240. mapxstart += finit_width;
  241. if(mapystart >= finit_height)
  242. mapystart -= finit_height;
  243. if(mapystart < 0)
  244. mapystart += finit_height;
  245. */
  246. m_x2 = m_x + m_w;
  247. m_y2 = m_y + m_h;
  248. }
  249. void AM_initVariables(void)
  250. {
  251. int pnum;
  252. thinker_t *think;
  253. mobj_t *mo;
  254. //static event_t st_notify = { ev_keyup, AM_MSGENTERED };
  255. automapactive = true;
  256. fb = screen;
  257. f_oldloc.x = MAXINT;
  258. amclock = 0;
  259. lightlev = 0;
  260. m_paninc.x = m_paninc.y = 0;
  261. ftom_zoommul = FRACUNIT;
  262. mtof_zoommul = FRACUNIT;
  263. m_w = FTOM(f_w);
  264. m_h = FTOM(f_h);
  265. // find player to center on initially
  266. if (!playeringame[pnum = consoleplayer])
  267. for (pnum=0;pnum<MAXPLAYERS;pnum++) if (playeringame[pnum]) break;
  268. plr = &players[pnum];
  269. oldplr.x = plr->mo->x;
  270. oldplr.y = plr->mo->y;
  271. m_x = plr->mo->x - m_w/2;
  272. m_y = plr->mo->y - m_h/2;
  273. AM_changeWindowLoc();
  274. // for saving & restoring
  275. old_m_x = m_x;
  276. old_m_y = m_y;
  277. old_m_w = m_w;
  278. old_m_h = m_h;
  279. // load in the location of keys, if in baby mode
  280. memset(KeyPoints, 0, sizeof(vertex_t)*3);
  281. if(gameskill == sk_baby)
  282. {
  283. for(think = thinkercap.next; think != &thinkercap; think = think->next)
  284. {
  285. if(think->function != P_MobjThinker)
  286. { //not a mobj
  287. continue;
  288. }
  289. mo = (mobj_t *)think;
  290. if(mo->type == MT_CKEY)
  291. {
  292. KeyPoints[0].x = mo->x;
  293. KeyPoints[0].y = mo->y;
  294. }
  295. else if(mo->type == MT_AKYY)
  296. {
  297. KeyPoints[1].x = mo->x;
  298. KeyPoints[1].y = mo->y;
  299. }
  300. else if(mo->type == MT_BKYY)
  301. {
  302. KeyPoints[2].x = mo->x;
  303. KeyPoints[2].y = mo->y;
  304. }
  305. }
  306. }
  307. // inform the status bar of the change
  308. //c ST_Responder(&st_notify);
  309. }
  310. void AM_loadPics(void)
  311. {
  312. //int i;
  313. //char namebuf[9];
  314. /* for (i=0;i<10;i++)
  315. {
  316. sprintf(namebuf, "AMMNUM%d", i);
  317. marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
  318. }*/
  319. maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC);
  320. }
  321. /*void AM_unloadPics(void)
  322. {
  323. int i;
  324. for (i=0;i<10;i++) Z_ChangeTag(marknums[i], PU_CACHE);
  325. }*/
  326. /*
  327. void AM_clearMarks(void)
  328. {
  329. int i;
  330. for (i=0;i<AM_NUMMARKPOINTS;i++) markpoints[i].x = -1; // means empty
  331. markpointnum = 0;
  332. }
  333. */
  334. // should be called at the start of every level
  335. // right now, i figure it out myself
  336. void AM_LevelInit(void)
  337. {
  338. leveljuststarted = 0;
  339. f_x = f_y = 0;
  340. f_w = finit_width;
  341. f_h = finit_height;
  342. mapxstart = mapystart = 0;
  343. // AM_clearMarks();
  344. AM_findMinMaxBoundaries();
  345. scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
  346. if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof;
  347. scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  348. }
  349. static boolean stopped = true;
  350. void AM_Stop (void)
  351. {
  352. //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
  353. // AM_unloadPics();
  354. automapactive = false;
  355. // ST_Responder(&st_notify);
  356. stopped = true;
  357. BorderNeedRefresh = true;
  358. }
  359. void AM_Start (void)
  360. {
  361. static int lastlevel = -1, lastepisode = -1;
  362. if (!stopped) AM_Stop();
  363. stopped = false;
  364. if(gamestate != GS_LEVEL)
  365. {
  366. return; // don't show automap if we aren't in a game!
  367. }
  368. if (lastlevel != gamemap || lastepisode != gameepisode)
  369. {
  370. AM_LevelInit();
  371. lastlevel = gamemap;
  372. lastepisode = gameepisode;
  373. }
  374. AM_initVariables();
  375. AM_loadPics();
  376. }
  377. // set the window scale to the maximum size
  378. void AM_minOutWindowScale(void)
  379. {
  380. scale_mtof = min_scale_mtof;
  381. scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  382. AM_activateNewScale();
  383. }
  384. // set the window scale to the minimum size
  385. void AM_maxOutWindowScale(void)
  386. {
  387. scale_mtof = max_scale_mtof;
  388. scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  389. AM_activateNewScale();
  390. }
  391. boolean AM_Responder (event_t *ev)
  392. {
  393. int rc;
  394. static int cheatstate=0;
  395. static int bigstate=0;
  396. rc = false;
  397. if (!automapactive)
  398. {
  399. if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY
  400. && gamestate == GS_LEVEL)
  401. {
  402. AM_Start ();
  403. viewactive = false;
  404. // viewactive = true;
  405. rc = true;
  406. }
  407. }
  408. else if (ev->type == ev_keydown)
  409. {
  410. rc = true;
  411. switch(ev->data1)
  412. {
  413. case AM_PANRIGHTKEY: // pan right
  414. if (!followplayer) m_paninc.x = FTOM(F_PANINC);
  415. else rc = false;
  416. break;
  417. case AM_PANLEFTKEY: // pan left
  418. if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
  419. else rc = false;
  420. break;
  421. case AM_PANUPKEY: // pan up
  422. if (!followplayer) m_paninc.y = FTOM(F_PANINC);
  423. else rc = false;
  424. break;
  425. case AM_PANDOWNKEY: // pan down
  426. if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
  427. else rc = false;
  428. break;
  429. case AM_ZOOMOUTKEY: // zoom out
  430. mtof_zoommul = M_ZOOMOUT;
  431. ftom_zoommul = M_ZOOMIN;
  432. break;
  433. case AM_ZOOMINKEY: // zoom in
  434. mtof_zoommul = M_ZOOMIN;
  435. ftom_zoommul = M_ZOOMOUT;
  436. break;
  437. case AM_ENDKEY:
  438. bigstate = 0;
  439. viewactive = true;
  440. AM_Stop ();
  441. break;
  442. case AM_GOBIGKEY:
  443. bigstate = !bigstate;
  444. if (bigstate)
  445. {
  446. AM_saveScaleAndLoc();
  447. AM_minOutWindowScale();
  448. }
  449. else AM_restoreScaleAndLoc();
  450. break;
  451. case AM_FOLLOWKEY:
  452. followplayer = !followplayer;
  453. f_oldloc.x = MAXINT;
  454. P_SetMessage(plr, followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, true);
  455. break;
  456. /*
  457. case AM_GRIDKEY:
  458. grid = !grid;
  459. plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF;
  460. break;
  461. case AM_MARKKEY:
  462. sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum);
  463. plr->message = buffer;
  464. AM_addMark();
  465. break;
  466. case AM_CLEARMARKKEY:
  467. AM_clearMarks();
  468. plr->message = AMSTR_MARKSCLEARED;
  469. break;
  470. */
  471. default:
  472. cheatstate=0;
  473. rc = false;
  474. }
  475. if(cheat_amap[cheatcount]==ev->data1 && !netgame)
  476. cheatcount++;
  477. else
  478. cheatcount=0;
  479. if(cheatcount==6)
  480. {
  481. cheatcount=0;
  482. rc = false;
  483. cheating = (cheating+1) % 3;
  484. }
  485. }
  486. else if (ev->type == ev_keyup)
  487. {
  488. rc = false;
  489. switch (ev->data1)
  490. {
  491. case AM_PANRIGHTKEY:
  492. if (!followplayer) m_paninc.x = 0;
  493. break;
  494. case AM_PANLEFTKEY:
  495. if (!followplayer) m_paninc.x = 0;
  496. break;
  497. case AM_PANUPKEY:
  498. if (!followplayer) m_paninc.y = 0;
  499. break;
  500. case AM_PANDOWNKEY:
  501. if (!followplayer) m_paninc.y = 0;
  502. break;
  503. case AM_ZOOMOUTKEY:
  504. case AM_ZOOMINKEY:
  505. mtof_zoommul = FRACUNIT;
  506. ftom_zoommul = FRACUNIT;
  507. break;
  508. }
  509. }
  510. return rc;
  511. }
  512. void AM_changeWindowScale(void)
  513. {
  514. // Change the scaling multipliers
  515. scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
  516. scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  517. if (scale_mtof < min_scale_mtof) AM_minOutWindowScale();
  518. else if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale();
  519. else AM_activateNewScale();
  520. }
  521. void AM_doFollowPlayer(void)
  522. {
  523. if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
  524. {
  525. // m_x = FTOM(MTOF(plr->mo->x - m_w/2));
  526. // m_y = FTOM(MTOF(plr->mo->y - m_h/2));
  527. // m_x = plr->mo->x - m_w/2;
  528. // m_y = plr->mo->y - m_h/2;
  529. m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
  530. m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
  531. m_x2 = m_x + m_w;
  532. m_y2 = m_y + m_h;
  533. // do the parallax parchment scrolling.
  534. /*
  535. dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point
  536. dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y));
  537. if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
  538. dmapx=0; //goes into the automap.
  539. mapxstart += dmapx;
  540. mapystart += dmapy;
  541. while(mapxstart >= finit_width)
  542. mapxstart -= finit_width;
  543. while(mapxstart < 0)
  544. mapxstart += finit_width;
  545. while(mapystart >= finit_height)
  546. mapystart -= finit_height;
  547. while(mapystart < 0)
  548. mapystart += finit_height;
  549. */
  550. f_oldloc.x = plr->mo->x;
  551. f_oldloc.y = plr->mo->y;
  552. }
  553. }
  554. // Ripped out for Heretic
  555. /*
  556. void AM_updateLightLev(void)
  557. {
  558. static nexttic = 0;
  559. //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
  560. static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
  561. static int litelevelscnt = 0;
  562. // Change light level
  563. if (amclock>nexttic)
  564. {
  565. lightlev = litelevels[litelevelscnt++];
  566. if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0;
  567. nexttic = amclock + 6 - (amclock % 6);
  568. }
  569. }
  570. */
  571. void AM_Ticker (void)
  572. {
  573. if (!automapactive) return;
  574. amclock++;
  575. if (followplayer) AM_doFollowPlayer();
  576. // Change the zoom if necessary
  577. if (ftom_zoommul != FRACUNIT) AM_changeWindowScale();
  578. // Change x,y location
  579. if (m_paninc.x || m_paninc.y) AM_changeWindowLoc();
  580. // Update light level
  581. // AM_updateLightLev();
  582. }
  583. void AM_clearFB(int color)
  584. {
  585. int i, j;
  586. int dmapx;
  587. int dmapy;
  588. if(followplayer)
  589. {
  590. dmapx = (MTOF(plr->mo->x)-MTOF(oldplr.x)); //fixed point
  591. dmapy = (MTOF(oldplr.y)-MTOF(plr->mo->y));
  592. oldplr.x = plr->mo->x;
  593. oldplr.y = plr->mo->y;
  594. // if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
  595. // dmapx=0; //goes into the automap.
  596. mapxstart += dmapx>>1;
  597. mapystart += dmapy>>1;
  598. while(mapxstart >= finit_width)
  599. mapxstart -= finit_width;
  600. while(mapxstart < 0)
  601. mapxstart += finit_width;
  602. while(mapystart >= finit_height)
  603. mapystart -= finit_height;
  604. while(mapystart < 0)
  605. mapystart += finit_height;
  606. }
  607. else
  608. {
  609. mapxstart += (MTOF(m_paninc.x)>>1);
  610. mapystart -= (MTOF(m_paninc.y)>>1);
  611. if(mapxstart >= finit_width)
  612. mapxstart -= finit_width;
  613. if(mapxstart < 0)
  614. mapxstart += finit_width;
  615. if(mapystart >= finit_height)
  616. mapystart -= finit_height;
  617. if(mapystart < 0)
  618. mapystart += finit_height;
  619. }
  620. //blit the automap background to the screen.
  621. j=mapystart*finit_width;
  622. for(i=0;i<finit_height;i++)
  623. {
  624. memcpy(screen+i*finit_width, maplump+j+mapxstart, finit_width-mapxstart);
  625. memcpy(screen+i*finit_width+finit_width-mapxstart, maplump+j, mapxstart);
  626. j += finit_width;
  627. if(j >= finit_height*finit_width)
  628. j=0;
  629. }
  630. // memcpy(screen, maplump, finit_width*finit_height);
  631. // memset(fb, color, f_w*f_h);
  632. }
  633. // Based on Cohen-Sutherland clipping algorithm but with a slightly
  634. // faster reject and precalculated slopes. If I need the speed, will
  635. // hash algorithm to the common cases.
  636. boolean AM_clipMline(mline_t *ml, fline_t *fl)
  637. {
  638. enum { LEFT=1, RIGHT=2, BOTTOM=4, TOP=8 };
  639. register outcode1 = 0, outcode2 = 0, outside;
  640. fpoint_t tmp;
  641. int dx, dy;
  642. #define DOOUTCODE(oc, mx, my) \
  643. (oc) = 0; \
  644. if ((my) < 0) (oc) |= TOP; \
  645. else if ((my) >= f_h) (oc) |= BOTTOM; \
  646. if ((mx) < 0) (oc) |= LEFT; \
  647. else if ((mx) >= f_w) (oc) |= RIGHT
  648. // do trivial rejects and outcodes
  649. if (ml->a.y > m_y2) outcode1 = TOP;
  650. else if (ml->a.y < m_y) outcode1 = BOTTOM;
  651. if (ml->b.y > m_y2) outcode2 = TOP;
  652. else if (ml->b.y < m_y) outcode2 = BOTTOM;
  653. if (outcode1 & outcode2) return false; // trivially outside
  654. if (ml->a.x < m_x) outcode1 |= LEFT;
  655. else if (ml->a.x > m_x2) outcode1 |= RIGHT;
  656. if (ml->b.x < m_x) outcode2 |= LEFT;
  657. else if (ml->b.x > m_x2) outcode2 |= RIGHT;
  658. if (outcode1 & outcode2) return false; // trivially outside
  659. // transform to frame-buffer coordinates.
  660. fl->a.x = CXMTOF(ml->a.x);
  661. fl->a.y = CYMTOF(ml->a.y);
  662. fl->b.x = CXMTOF(ml->b.x);
  663. fl->b.y = CYMTOF(ml->b.y);
  664. DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  665. DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  666. if (outcode1 & outcode2) return false;
  667. while (outcode1 | outcode2)
  668. {
  669. // may be partially inside box
  670. // find an outside point
  671. if (outcode1) outside = outcode1;
  672. else outside = outcode2;
  673. // clip to each side
  674. if (outside & TOP)
  675. {
  676. dy = fl->a.y - fl->b.y;
  677. dx = fl->b.x - fl->a.x;
  678. tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
  679. tmp.y = 0;
  680. }
  681. else if (outside & BOTTOM)
  682. {
  683. dy = fl->a.y - fl->b.y;
  684. dx = fl->b.x - fl->a.x;
  685. tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
  686. tmp.y = f_h-1;
  687. }
  688. else if (outside & RIGHT)
  689. {
  690. dy = fl->b.y - fl->a.y;
  691. dx = fl->b.x - fl->a.x;
  692. tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
  693. tmp.x = f_w-1;
  694. }
  695. else if (outside & LEFT)
  696. {
  697. dy = fl->b.y - fl->a.y;
  698. dx = fl->b.x - fl->a.x;
  699. tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
  700. tmp.x = 0;
  701. }
  702. if (outside == outcode1)
  703. {
  704. fl->a = tmp;
  705. DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  706. } else {
  707. fl->b = tmp;
  708. DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  709. }
  710. if (outcode1 & outcode2) return false; // trivially outside
  711. }
  712. return true;
  713. }
  714. #undef DOOUTCODE
  715. // Classic Bresenham w/ whatever optimizations I need for speed
  716. void AM_drawFline(fline_t *fl, int color)
  717. {
  718. register int x, y, dx, dy, sx, sy, ax, ay, d;
  719. static fuck = 0;
  720. switch(color)
  721. {
  722. case WALLCOLORS:
  723. DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[0][0], 8, 3);
  724. break;
  725. case FDWALLCOLORS:
  726. DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[1][0], 8, 3);
  727. break;
  728. case CDWALLCOLORS:
  729. DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[2][0], 8, 3);
  730. break;
  731. default:
  732. {
  733. // For debugging only
  734. if ( fl->a.x < 0 || fl->a.x >= f_w
  735. || fl->a.y < 0 || fl->a.y >= f_h
  736. || fl->b.x < 0 || fl->b.x >= f_w
  737. || fl->b.y < 0 || fl->b.y >= f_h)
  738. {
  739. fprintf(stderr, "fuck %d \r", fuck++);
  740. return;
  741. }
  742. #define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO!
  743. dx = fl->b.x - fl->a.x;
  744. ax = 2 * (dx<0 ? -dx : dx);
  745. sx = dx<0 ? -1 : 1;
  746. dy = fl->b.y - fl->a.y;
  747. ay = 2 * (dy<0 ? -dy : dy);
  748. sy = dy<0 ? -1 : 1;
  749. x = fl->a.x;
  750. y = fl->a.y;
  751. if (ax > ay)
  752. {
  753. d = ay - ax/2;
  754. while (1)
  755. {
  756. DOT(x,y,color);
  757. if (x == fl->b.x) return;
  758. if (d>=0)
  759. {
  760. y += sy;
  761. d -= ax;
  762. }
  763. x += sx;
  764. d += ay;
  765. }
  766. } else {
  767. d = ax - ay/2;
  768. while (1)
  769. {
  770. DOT(x, y, color);
  771. if (y == fl->b.y) return;
  772. if (d >= 0)
  773. {
  774. x += sx;
  775. d -= ay;
  776. }
  777. y += sy;
  778. d += ax;
  779. }
  780. }
  781. }
  782. }
  783. }
  784. /* Wu antialiased line drawer.
  785. * (X0,Y0),(X1,Y1) = line to draw
  786. * BaseColor = color # of first color in block used for antialiasing, the
  787. * 100% intensity version of the drawing color
  788. * NumLevels = size of color block, with BaseColor+NumLevels-1 being the
  789. * 0% intensity version of the drawing color
  790. * IntensityBits = log base 2 of NumLevels; the # of bits used to describe
  791. * the intensity of the drawing color. 2**IntensityBits==NumLevels
  792. */
  793. void PUTDOT(short xx,short yy,byte *cc, byte *cm)
  794. {
  795. static int oldyy;
  796. static int oldyyshifted;
  797. byte *oldcc=cc;
  798. if(xx < 32)
  799. cc += 7-(xx>>2);
  800. else if(xx > (finit_width - 32))
  801. cc += 7-((finit_width-xx) >> 2);
  802. // if(cc==oldcc) //make sure that we don't double fade the corners.
  803. // {
  804. if(yy < 32)
  805. cc += 7-(yy>>2);
  806. else if(yy > (finit_height - 32))
  807. cc += 7-((finit_height-yy) >> 2);
  808. // }
  809. if(cc > cm && cm != NULL)
  810. {
  811. cc = cm;
  812. }
  813. else if(cc > oldcc+6) // don't let the color escape from the fade table...
  814. {
  815. cc=oldcc+6;
  816. }
  817. if(yy == oldyy+1)
  818. {
  819. oldyy++;
  820. oldyyshifted += 320;
  821. }
  822. else if(yy == oldyy-1)
  823. {
  824. oldyy--;
  825. oldyyshifted -= 320;
  826. }
  827. else if(yy != oldyy)
  828. {
  829. oldyy = yy;
  830. oldyyshifted = yy*320;
  831. }
  832. fb[oldyyshifted+xx] = *(cc);
  833. // fb[(yy)*f_w+(xx)]=*(cc);
  834. }
  835. void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
  836. int NumLevels, unsigned short IntensityBits)
  837. {
  838. unsigned short IntensityShift, ErrorAdj, ErrorAcc;
  839. unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
  840. short DeltaX, DeltaY, Temp, XDir;
  841. /* Make sure the line runs top to bottom */
  842. if (Y0 > Y1) {
  843. Temp = Y0; Y0 = Y1; Y1 = Temp;
  844. Temp = X0; X0 = X1; X1 = Temp;
  845. }
  846. /* Draw the initial pixel, which is always exactly intersected by
  847. the line and so needs no weighting */
  848. PUTDOT(X0, Y0, &BaseColor[0], NULL);
  849. if ((DeltaX = X1 - X0) >= 0) {
  850. XDir = 1;
  851. } else {
  852. XDir = -1;
  853. DeltaX = -DeltaX; /* make DeltaX positive */
  854. }
  855. /* Special-case horizontal, vertical, and diagonal lines, which
  856. require no weighting because they go right through the center of
  857. every pixel */
  858. if ((DeltaY = Y1 - Y0) == 0) {
  859. /* Horizontal line */
  860. while (DeltaX-- != 0) {
  861. X0 += XDir;
  862. PUTDOT(X0, Y0, &BaseColor[0], NULL);
  863. }
  864. return;
  865. }
  866. if (DeltaX == 0) {
  867. /* Vertical line */
  868. do {
  869. Y0++;
  870. PUTDOT(X0, Y0, &BaseColor[0], NULL);
  871. } while (--DeltaY != 0);
  872. return;
  873. }
  874. //diagonal line.
  875. if (DeltaX == DeltaY) {
  876. do {
  877. X0 += XDir;
  878. Y0++;
  879. PUTDOT(X0, Y0, &BaseColor[0], NULL);
  880. } while (--DeltaY != 0);
  881. return;
  882. }
  883. /* Line is not horizontal, diagonal, or vertical */
  884. ErrorAcc = 0; /* initialize the line error accumulator to 0 */
  885. /* # of bits by which to shift ErrorAcc to get intensity level */
  886. IntensityShift = 16 - IntensityBits;
  887. /* Mask used to flip all bits in an intensity weighting, producing the
  888. result (1 - intensity weighting) */
  889. WeightingComplementMask = NumLevels - 1;
  890. /* Is this an X-major or Y-major line? */
  891. if (DeltaY > DeltaX) {
  892. /* Y-major line; calculate 16-bit fixed-point fractional part of a
  893. pixel that X advances each time Y advances 1 pixel, truncating the
  894. result so that we won't overrun the endpoint along the X axis */
  895. ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
  896. /* Draw all pixels other than the first and last */
  897. while (--DeltaY) {
  898. ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
  899. ErrorAcc += ErrorAdj; /* calculate error for next pixel */
  900. if (ErrorAcc <= ErrorAccTemp) {
  901. /* The error accumulator turned over, so advance the X coord */
  902. X0 += XDir;
  903. }
  904. Y0++; /* Y-major, so always advance Y */
  905. /* The IntensityBits most significant bits of ErrorAcc give us the
  906. intensity weighting for this pixel, and the complement of the
  907. weighting for the paired pixel */
  908. Weighting = ErrorAcc >> IntensityShift;
  909. PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
  910. PUTDOT(X0 + XDir, Y0,
  911. &BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
  912. }
  913. /* Draw the final pixel, which is always exactly intersected by the line
  914. and so needs no weighting */
  915. PUTDOT(X1, Y1, &BaseColor[0], NULL);
  916. return;
  917. }
  918. /* It's an X-major line; calculate 16-bit fixed-point fractional part of a
  919. pixel that Y advances each time X advances 1 pixel, truncating the
  920. result to avoid overrunning the endpoint along the X axis */
  921. ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
  922. /* Draw all pixels other than the first and last */
  923. while (--DeltaX) {
  924. ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
  925. ErrorAcc += ErrorAdj; /* calculate error for next pixel */
  926. if (ErrorAcc <= ErrorAccTemp) {
  927. /* The error accumulator turned over, so advance the Y coord */
  928. Y0++;
  929. }
  930. X0 += XDir; /* X-major, so always advance X */
  931. /* The IntensityBits most significant bits of ErrorAcc give us the
  932. intensity weighting for this pixel, and the complement of the
  933. weighting for the paired pixel */
  934. Weighting = ErrorAcc >> IntensityShift;
  935. PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
  936. PUTDOT(X0, Y0 + 1,
  937. &BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
  938. }
  939. /* Draw the final pixel, which is always exactly intersected by the line
  940. and so needs no weighting */
  941. PUTDOT(X1, Y1, &BaseColor[0], NULL);
  942. }
  943. void AM_drawMline(mline_t *ml, int color)
  944. {
  945. static fline_t fl;
  946. if (AM_clipMline(ml, &fl))
  947. AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
  948. }
  949. void AM_drawGrid(int color)
  950. {
  951. fixed_t x, y;
  952. fixed_t start, end;
  953. mline_t ml;
  954. // Figure out start of vertical gridlines
  955. start = m_x;
  956. if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
  957. start += (MAPBLOCKUNITS<<FRACBITS)
  958. - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
  959. end = m_x + m_w;
  960. // draw vertical gridlines
  961. ml.a.y = m_y;
  962. ml.b.y = m_y+m_h;
  963. for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
  964. {
  965. ml.a.x = x;
  966. ml.b.x = x;
  967. AM_drawMline(&ml, color);
  968. }
  969. // Figure out start of horizontal gridlines
  970. start = m_y;
  971. if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
  972. start += (MAPBLOCKUNITS<<FRACBITS)
  973. - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
  974. end = m_y + m_h;
  975. // draw horizontal gridlines
  976. ml.a.x = m_x;
  977. ml.b.x = m_x + m_w;
  978. for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
  979. {
  980. ml.a.y = y;
  981. ml.b.y = y;
  982. AM_drawMline(&ml, color);
  983. }
  984. }
  985. void AM_drawWalls(void)
  986. {
  987. int i;
  988. static mline_t l;
  989. for (i=0;i<numlines;i++)
  990. {
  991. l.a.x = lines[i].v1->x;
  992. l.a.y = lines[i].v1->y;
  993. l.b.x = lines[i].v2->x;
  994. l.b.y = lines[i].v2->y;
  995. if (cheating || (lines[i].flags & ML_MAPPED))
  996. {
  997. if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
  998. continue;
  999. if (!lines[i].backsector)
  1000. {
  1001. AM_drawMline(&l, WALLCOLORS+lightlev);
  1002. } else {
  1003. if (lines[i].special == 39)
  1004. { // teleporters
  1005. AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
  1006. } else if (lines[i].flags & ML_SECRET) // secret door
  1007. {
  1008. if (cheating) AM_drawMline(&l, 0);
  1009. else AM_drawMline(&l, WALLCOLORS+lightlev);
  1010. }
  1011. else if(lines[i].special > 25 && lines[i].special < 35)
  1012. {
  1013. switch(lines[i].special)
  1014. {
  1015. case 26:
  1016. case 32:
  1017. AM_drawMline(&l, BLUEKEY);
  1018. break;
  1019. case 27:
  1020. case 34:
  1021. AM_drawMline(&l, YELLOWKEY);
  1022. break;
  1023. case 28:
  1024. case 33:
  1025. AM_drawMline(&l, GREENKEY);
  1026. break;
  1027. default:
  1028. break;
  1029. }
  1030. }
  1031. else if (lines[i].backsector->floorheight
  1032. != lines[i].frontsector->floorheight) {
  1033. AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
  1034. } else if (lines[i].backsector->ceilingheight
  1035. != lines[i].frontsector->ceilingheight) {
  1036. AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
  1037. } else if (cheating) {
  1038. AM_drawMline(&l, TSWALLCOLORS+lightlev);
  1039. }
  1040. }
  1041. } else if (plr->powers[pw_allmap])
  1042. {
  1043. if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
  1044. }
  1045. }
  1046. }
  1047. void AM_rotate(fixed_t *x, fixed_t *y, angle_t a)
  1048. {
  1049. fixed_t tmpx;
  1050. tmpx = FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
  1051. - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
  1052. *y = FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
  1053. + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
  1054. *x = tmpx;
  1055. }
  1056. void AM_drawLineCharacter(mline_t *lineguy, int lineguylines, fixed_t scale,
  1057. angle_t angle, int color, fixed_t x, fixed_t y)
  1058. {
  1059. int i;
  1060. mline_t l;
  1061. for (i=0;i<lineguylines;i++)
  1062. {
  1063. l.a.x = lineguy[i].a.x;
  1064. l.a.y = lineguy[i].a.y;
  1065. if (scale)
  1066. {
  1067. l.a.x = FixedMul(scale, l.a.x);
  1068. l.a.y = FixedMul(scale, l.a.y);
  1069. }
  1070. if (angle) AM_rotate(&l.a.x, &l.a.y, angle);
  1071. l.a.x += x;
  1072. l.a.y += y;
  1073. l.b.x = lineguy[i].b.x;
  1074. l.b.y = lineguy[i].b.y;
  1075. if (scale)
  1076. {
  1077. l.b.x = FixedMul(scale, l.b.x);
  1078. l.b.y = FixedMul(scale, l.b.y);
  1079. }
  1080. if (angle) AM_rotate(&l.b.x, &l.b.y, angle);
  1081. l.b.x += x;
  1082. l.b.y += y;
  1083. AM_drawMline(&l, color);
  1084. }
  1085. }
  1086. void AM_drawPlayers(void)
  1087. {
  1088. int i;
  1089. player_t *p;
  1090. static int their_colors[] = { GREENKEY, YELLOWKEY, BLOODRED, BLUEKEY };
  1091. int their_color = -1;
  1092. int color;
  1093. if (!netgame)
  1094. {
  1095. /*
  1096. if (cheating) AM_drawLineCharacter(cheat_player_arrow, NUMCHEATPLYRLINES, 0,
  1097. plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
  1098. */ //cheat key player pointer is the same as non-cheat pointer..
  1099. AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle,
  1100. WHITE, plr->mo->x, plr->mo->y);
  1101. return;
  1102. }
  1103. for (i=0;i<MAXPLAYERS;i++)
  1104. {
  1105. their_color++;
  1106. p = &players[i];
  1107. if(deathmatch && !singledemo && p != plr)
  1108. {
  1109. continue;
  1110. }
  1111. if (!playeringame[i]) continue;
  1112. if (p->powers[pw_invisibility]) color = 102; // *close* to the automap color
  1113. else color = their_colors[their_color];
  1114. AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle,
  1115. color, p->mo->x, p->mo->y);
  1116. }
  1117. }
  1118. void AM_drawThings(int colors, int colorrange)
  1119. {
  1120. int i;
  1121. mobj_t *t;
  1122. for (i=0;i<numsectors;i++)
  1123. {
  1124. t = sectors[i].thinglist;
  1125. while (t)
  1126. {
  1127. AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
  1128. 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
  1129. t = t->snext;
  1130. }
  1131. }
  1132. }
  1133. /*
  1134. void AM_drawMarks(void)
  1135. {
  1136. int i, fx, fy, w, h;
  1137. for (i=0;i<AM_NUMMARKPOINTS;i++)
  1138. {
  1139. if (markpoints[i].x != -1)
  1140. {
  1141. w = SHORT(marknums[i]->width);
  1142. h = SHORT(marknums[i]->height);
  1143. fx = CXMTOF(markpoints[i].x);
  1144. fy = CYMTOF(markpoints[i].y);
  1145. if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
  1146. V_DrawPatch(fx, fy, marknums[i]);
  1147. }
  1148. }
  1149. }
  1150. */
  1151. void AM_drawkeys(void)
  1152. {
  1153. if(KeyPoints[0].x != 0 || KeyPoints[0].y != 0)
  1154. {
  1155. AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY,
  1156. KeyPoints[0].x, KeyPoints[0].y);
  1157. }
  1158. if(KeyPoints[1].x != 0 || KeyPoints[1].y != 0)
  1159. {
  1160. AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY,
  1161. KeyPoints[1].x, KeyPoints[1].y);
  1162. }
  1163. if(KeyPoints[2].x != 0 || KeyPoints[2].y != 0)
  1164. {
  1165. AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY,
  1166. KeyPoints[2].x, KeyPoints[2].y);
  1167. }
  1168. }
  1169. void AM_drawCrosshair(int color)
  1170. {
  1171. fb[(f_w*(f_h+1))/2] = color; // single point for now
  1172. }
  1173. void AM_Drawer(void)
  1174. {
  1175. int highestEpisode;
  1176. if (!automapactive) return;
  1177. UpdateState |= I_FULLSCRN;
  1178. AM_clearFB(BACKGROUND);
  1179. if (grid) AM_drawGrid(GRIDCOLORS);
  1180. AM_drawWalls();
  1181. AM_drawPlayers();
  1182. if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE);
  1183. // AM_drawCrosshair(XHAIRCOLORS);
  1184. // AM_drawMarks();
  1185. if(gameskill == sk_baby)
  1186. {
  1187. AM_drawkeys();
  1188. }
  1189. if((gameepisode < (ExtendedWAD ? 6 : 4)) && gamemap < 10)
  1190. {
  1191. MN_DrTextA(LevelNames[(gameepisode-1)*9+gamemap-1], 20, 145);
  1192. }
  1193. // I_Update();
  1194. // V_MarkRect(f_x, f_y, f_w, f_h);
  1195. }