home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / am_map.c next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  33.7 KB  |  1,627 lines

  1. /*  Emacs style mode select   -*- C++ -*-  */
  2. /* ----------------------------------------------------------------------------- */
  3. /*  */
  4. /*  $Id:$ */
  5. /*  */
  6. /*  Copyright (C) 1993-1996 by id Software, Inc. */
  7. /*  */
  8. /*  This source is available for distribution and/or modification */
  9. /*  only under the terms of the DOOM Source Code License as */
  10. /*  published by id Software. All rights reserved. */
  11. /*  */
  12. /*  The source is distributed in the hope that it will be useful, */
  13. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of */
  14. /*  FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License */
  15. /*  for more details. */
  16. /*  */
  17. /*  */
  18. /*  $Log:$ */
  19. /*  */
  20. /*  DESCRIPTION:  the automap code */
  21. /*  */
  22. /* ----------------------------------------------------------------------------- */
  23.  
  24. #include <stdio.h>
  25.  
  26.  
  27. #include "z_zone.h"
  28. #include "doomdef.h"
  29. #include "st_stuff.h"
  30. #include "p_local.h"
  31. #include "w_wad.h"
  32.  
  33. #include "m_cheat.h"
  34. #include "i_system.h"
  35.  
  36. /*  Needs access to LFB. */
  37. #include "v_video.h"
  38. #include "i_video.h"
  39.  
  40. /*  State. */
  41. #include "doomstat.h"
  42. #include "r_state.h"
  43.  
  44. /*  Data. */
  45. #include "dstrings.h"
  46.  
  47. #include "am_map.h"
  48.  
  49.  
  50. /*  For use if I do walls with outsides/insides */
  51. #define REDS        (256-5*16)
  52. #define REDRANGE    16
  53. #define BLUES        (256-4*16+8)
  54. #define BLUERANGE    8
  55. #define GREENS        (7*16)
  56. #define GREENRANGE    16
  57. #define GRAYS        (6*16)
  58. #define GRAYSRANGE    16
  59. #define BROWNS        (4*16)
  60. #define BROWNRANGE    16
  61. #define YELLOWS        (256-32+7)
  62. #define YELLOWRANGE    1
  63. #define BLACK        0
  64. #define WHITE        (256-47)
  65.  
  66. /*  Automap colors */
  67. #define BACKGROUND    BLACK
  68. #define YOURCOLORS    WHITE
  69. #define YOURRANGE    0
  70. #define WALLCOLORS    REDS
  71. #define WALLRANGE    REDRANGE
  72. #define TSWALLCOLORS    GRAYS
  73. #define TSWALLRANGE    GRAYSRANGE
  74. #define FDWALLCOLORS    BROWNS
  75. #define FDWALLRANGE    BROWNRANGE
  76. #define CDWALLCOLORS    YELLOWS
  77. #define CDWALLRANGE    YELLOWRANGE
  78. #define THINGCOLORS    GREENS
  79. #define THINGRANGE    GREENRANGE
  80. #define SECRETWALLCOLORS WALLCOLORS
  81. #define SECRETWALLRANGE WALLRANGE
  82. #define GRIDCOLORS    (GRAYS + GRAYSRANGE/2)
  83. #define GRIDRANGE    0
  84. #define XHAIRCOLORS    GRAYS
  85.  
  86. /*  drawing stuff */
  87. #define    FB        0
  88.  
  89. #define AM_PANDOWNKEY    KEY_DOWNARROW
  90. #define AM_PANUPKEY    KEY_UPARROW
  91. #define AM_PANRIGHTKEY    KEY_RIGHTARROW
  92. #define AM_PANLEFTKEY    KEY_LEFTARROW
  93. #define AM_ZOOMINKEY    '='
  94. #define AM_ZOOMOUTKEY    '-'
  95. #define AM_STARTKEY    KEY_TAB
  96. #define AM_ENDKEY    KEY_TAB
  97. #define AM_GOBIGKEY    '0'
  98. #define AM_FOLLOWKEY    'f'
  99. #define AM_GRIDKEY    'g'
  100. #define AM_MARKKEY    'm'
  101. #define AM_CLEARMARKKEY    'c'
  102.  
  103. #define AM_NUMMARKPOINTS 10
  104.  
  105. /*  scale on entry */
  106. #define INITSCALEMTOF (.2*FRACUNIT)
  107. /*  how much the automap moves window per tic in frame-buffer coordinates */
  108. /*  moves 140 pixels in 1 second */
  109. #define F_PANINC    4
  110. /*  how much zoom-in per tic */
  111. /*  goes to 2x in 1 second */
  112. #define M_ZOOMIN        ((int) (1.02*FRACUNIT))
  113. /*  how much zoom-out per tic */
  114. /*  pulls out to 0.5x in 1 second */
  115. #define M_ZOOMOUT       ((int) (FRACUNIT/1.02))
  116.  
  117. /*  translates between frame-buffer and map distances */
  118. #define FTOM(x) FixedMul(((x)<<16),scale_ftom)
  119. #define MTOF(x) (FixedMul((x),scale_mtof)>>16)
  120. /*  translates between frame-buffer and map coordinates */
  121. #define CXMTOF(x)  (f_x + MTOF((x)-m_x))
  122. #define CYMTOF(y)  (f_y + (f_h - MTOF((y)-m_y)))
  123.  
  124. /*  the following is crap */
  125. #define LINE_NEVERSEE ML_DONTDRAW
  126.  
  127. /*  */
  128. /*  The vector graphics for the automap. */
  129. /*   A line drawing of the player pointing right, */
  130. /*    starting from the middle. */
  131. /*  */
  132. #define R ((8*PLAYERRADIUS)/7)
  133. mline_t player_arrow[] = {
  134.     { { -R+R/8, 0 }, { R, 0 } }, /*  ----- */
  135.     { { R, 0 }, { R-R/2, R/4 } },  /*  -----> */
  136.     { { R, 0 }, { R-R/2, -R/4 } },
  137.     { { -R+R/8, 0 }, { -R-R/8, R/4 } }, /*  >----> */
  138.     { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
  139.     { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, /*  >>---> */
  140.     { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
  141. };
  142. #undef R
  143. #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
  144.  
  145. #define R ((8*PLAYERRADIUS)/7)
  146. mline_t cheat_player_arrow[] = {
  147.     { { -R+R/8, 0 }, { R, 0 } }, /*  ----- */
  148.     { { R, 0 }, { R-R/2, R/6 } },  /*  -----> */
  149.     { { R, 0 }, { R-R/2, -R/6 } },
  150.     { { -R+R/8, 0 }, { -R-R/8, R/6 } }, /*  >-----> */
  151.     { { -R+R/8, 0 }, { -R-R/8, -R/6 } },
  152.     { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, /*  >>-----> */
  153.     { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } },
  154.     { { -R/2, 0 }, { -R/2, -R/6 } }, /*  >>-d---> */
  155.     { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } },
  156.     { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } },
  157.     { { -R/6, 0 }, { -R/6, -R/6 } }, /*  >>-dd--> */
  158.     { { -R/6, -R/6 }, { 0, -R/6 } },
  159.     { { 0, -R/6 }, { 0, R/4 } },
  160.     { { R/6, R/4 }, { R/6, -R/7 } }, /*  >>-ddt-> */
  161.     { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } },
  162.     { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } }
  163. };
  164. #undef R
  165. #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
  166.  
  167. #define R (FRACUNIT)
  168. mline_t triangle_guy[] = {
  169.     { { -.867*R, -.5*R }, { .867*R, -.5*R } },
  170.     { { .867*R, -.5*R } , { 0, R } },
  171.     { { 0, R }, { -.867*R, -.5*R } }
  172. };
  173. #undef R
  174. #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
  175.  
  176. #define R (FRACUNIT)
  177. mline_t thintriangle_guy[] = {
  178.     { { -.5*R, -.7*R }, { R, 0 } },
  179.     { { R, 0 }, { -.5*R, .7*R } },
  180.     { { -.5*R, .7*R }, { -.5*R, -.7*R } }
  181. };
  182. #undef R
  183. #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
  184.  
  185.  
  186.  
  187.  
  188. static int     cheating = 0;
  189. static int     grid = 0;
  190.  
  191. static int     leveljuststarted = 1;     /*  kluge until AM_LevelInit() is called */
  192.  
  193. boolean        automapactive = false;
  194. static int     finit_width = SCREENWIDTH;
  195. static int     finit_height = SCREENHEIGHT - 32;
  196.  
  197. /*  location of window on screen */
  198. static int     f_x;
  199. static int    f_y;
  200.  
  201. /*  size of window on screen */
  202. static int     f_w;
  203. static int    f_h;
  204.  
  205. static int     lightlev;         /*  used for funky strobing effect */
  206. static byte*    fb;             /*  pseudo-frame buffer */
  207. static int     amclock;
  208.  
  209. static mpoint_t m_paninc; /*  how far the window pans each tic (map coords) */
  210. static fixed_t     mtof_zoommul; /*  how far the window zooms in each tic (map coords) */
  211. static fixed_t     ftom_zoommul; /*  how far the window zooms in each tic (fb coords) */
  212.  
  213. static fixed_t     m_x, m_y;   /*  LL x,y where the window is on the map (map coords) */
  214. static fixed_t     m_x2, m_y2; /*  UR x,y where the window is on the map (map coords) */
  215.  
  216. /*  */
  217. /*  width/height of window on map (map coords) */
  218. /*  */
  219. static fixed_t     m_w;
  220. static fixed_t    m_h;
  221.  
  222. /*  based on level size */
  223. static fixed_t     min_x;
  224. static fixed_t    min_y; 
  225. static fixed_t     max_x;
  226. static fixed_t  max_y;
  227.  
  228. static fixed_t     max_w; /*  max_x-min_x, */
  229. static fixed_t  max_h; /*  max_y-min_y */
  230.  
  231. /*  based on player size */
  232. static fixed_t     min_w;
  233. static fixed_t  min_h;
  234.  
  235.  
  236. static fixed_t     min_scale_mtof; /*  used to tell when to stop zooming out */
  237. static fixed_t     max_scale_mtof; /*  used to tell when to stop zooming in */
  238.  
  239. /*  old stuff for recovery later */
  240. static fixed_t old_m_w, old_m_h;
  241. static fixed_t old_m_x, old_m_y;
  242.  
  243. /*  old location used by the Follower routine */
  244. static mpoint_t f_oldloc;
  245.  
  246. /*  used by MTOF to scale from map-to-frame-buffer coords */
  247. static fixed_t scale_mtof = INITSCALEMTOF;
  248. /*  used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) */
  249. static fixed_t scale_ftom;
  250.  
  251. static player_t *plr; /*  the player represented by an arrow */
  252.  
  253. static patch_t *marknums[10]; /*  numbers used for marking by the automap */
  254. static mpoint_t markpoints[AM_NUMMARKPOINTS]; /*  where the points are */
  255. static int markpointnum = 0; /*  next point to be assigned */
  256.  
  257. static int followplayer = 1; /*  specifies whether to follow the player around */
  258.  
  259. static unsigned char cheat_amap_seq[] = { 0xb2, 0x26, 0x26, 0x2e, 0xff };
  260. static cheatseq_t cheat_amap = { cheat_amap_seq, 0 };
  261.  
  262. static boolean stopped = true;
  263.  
  264. extern boolean viewactive;
  265. /* extern byte screens[][SCREENWIDTH*SCREENHEIGHT]; */
  266.  
  267.  
  268.  
  269. void
  270. V_MarkRect
  271. ( int    x,
  272.   int    y,
  273.   int    width,
  274.   int    height );
  275.  
  276. /*  Calculates the slope and slope according to the x-axis of a line */
  277. /*  segment in map coordinates (with the upright y-axis n' all) so */
  278. /*  that it can be used with the brain-dead drawing stuff. */
  279.  
  280. void
  281. AM_getIslope
  282. ( mline_t*    ml,
  283.   islope_t*    is )
  284. {
  285.     int dx, dy;
  286.  
  287.     dy = ml->a.y - ml->b.y;
  288.     dx = ml->b.x - ml->a.x;
  289.     if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
  290.     else is->islp = FixedDiv(dx, dy);
  291.     if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
  292.     else is->slp = FixedDiv(dy, dx);
  293.  
  294. }
  295.  
  296. /*  */
  297. /*  */
  298. /*  */
  299. void AM_activateNewScale(void)
  300. {
  301.     m_x += m_w/2;
  302.     m_y += m_h/2;
  303.     m_w = FTOM(f_w);
  304.     m_h = FTOM(f_h);
  305.     m_x -= m_w/2;
  306.     m_y -= m_h/2;
  307.     m_x2 = m_x + m_w;
  308.     m_y2 = m_y + m_h;
  309. }
  310.  
  311. /*  */
  312. /*  */
  313. /*  */
  314. void AM_saveScaleAndLoc(void)
  315. {
  316.     old_m_x = m_x;
  317.     old_m_y = m_y;
  318.     old_m_w = m_w;
  319.     old_m_h = m_h;
  320. }
  321.  
  322. /*  */
  323. /*  */
  324. /*  */
  325. void AM_restoreScaleAndLoc(void)
  326. {
  327.  
  328.     m_w = old_m_w;
  329.     m_h = old_m_h;
  330.     if (!followplayer)
  331.     {
  332.     m_x = old_m_x;
  333.     m_y = old_m_y;
  334.     } else {
  335.     m_x = plr->mo->x - m_w/2;
  336.     m_y = plr->mo->y - m_h/2;
  337.     }
  338.     m_x2 = m_x + m_w;
  339.     m_y2 = m_y + m_h;
  340.  
  341.     /*  Change the scaling multipliers */
  342.     scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
  343.     scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  344. }
  345.  
  346. /*  */
  347. /*  adds a marker at the current location */
  348. /*  */
  349. void AM_addMark(void)
  350. {
  351.     markpoints[markpointnum].x = m_x + m_w/2;
  352.     markpoints[markpointnum].y = m_y + m_h/2;
  353.     markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
  354.  
  355. }
  356.  
  357. /*  */
  358. /*  Determines bounding box of all vertices, */
  359. /*  sets global variables controlling zoom range. */
  360. /*  */
  361. void AM_findMinMaxBoundaries(void)
  362. {
  363.     int i;
  364.     fixed_t a;
  365.     fixed_t b;
  366.  
  367.     min_x = min_y =  MAXINT;
  368.     max_x = max_y = -MAXINT;
  369.   
  370.     for (i=0;i<numvertexes;i++)
  371.     {
  372.     if (vertexes[i].x < min_x)
  373.         min_x = vertexes[i].x;
  374.     else if (vertexes[i].x > max_x)
  375.         max_x = vertexes[i].x;
  376.     
  377.     if (vertexes[i].y < min_y)
  378.         min_y = vertexes[i].y;
  379.     else if (vertexes[i].y > max_y)
  380.         max_y = vertexes[i].y;
  381.     }
  382.   
  383.     max_w = max_x - min_x;
  384.     max_h = max_y - min_y;
  385.  
  386.     min_w = 2*PLAYERRADIUS; /*  const? never changed? */
  387.     min_h = 2*PLAYERRADIUS;
  388.  
  389.     a = FixedDiv(f_w<<FRACBITS, max_w);
  390.     b = FixedDiv(f_h<<FRACBITS, max_h);
  391.   
  392.     min_scale_mtof = a < b ? a : b;
  393.     max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
  394.  
  395. }
  396.  
  397.  
  398. /*  */
  399. /*  */
  400. /*  */
  401. void AM_changeWindowLoc(void)
  402. {
  403.     if (m_paninc.x || m_paninc.y)
  404.     {
  405.     followplayer = 0;
  406.     f_oldloc.x = MAXINT;
  407.     }
  408.  
  409.     m_x += m_paninc.x;
  410.     m_y += m_paninc.y;
  411.  
  412.     if (m_x + m_w/2 > max_x)
  413.     m_x = max_x - m_w/2;
  414.     else if (m_x + m_w/2 < min_x)
  415.     m_x = min_x - m_w/2;
  416.   
  417.     if (m_y + m_h/2 > max_y)
  418.     m_y = max_y - m_h/2;
  419.     else if (m_y + m_h/2 < min_y)
  420.     m_y = min_y - m_h/2;
  421.  
  422.     m_x2 = m_x + m_w;
  423.     m_y2 = m_y + m_h;
  424. }
  425.  
  426.  
  427. /*  */
  428. /*  */
  429. /*  */
  430. void AM_initVariables(void)
  431. {
  432.     int pnum;
  433.     static event_t st_notify = { ev_keyup, AM_MSGENTERED };
  434.  
  435.     automapactive = true;
  436.     fb = screens[0];
  437.  
  438.     f_oldloc.x = MAXINT;
  439.     amclock = 0;
  440.     lightlev = 0;
  441.  
  442.     m_paninc.x = m_paninc.y = 0;
  443.     ftom_zoommul = FRACUNIT;
  444.     mtof_zoommul = FRACUNIT;
  445.  
  446.     m_w = FTOM(f_w);
  447.     m_h = FTOM(f_h);
  448.  
  449.     /*  find player to center on initially */
  450.     if (!playeringame[pnum = consoleplayer])
  451.     for (pnum=0;pnum<MAXPLAYERS;pnum++)
  452.         if (playeringame[pnum])
  453.         break;
  454.   
  455.     plr = &players[pnum];
  456.     m_x = plr->mo->x - m_w/2;
  457.     m_y = plr->mo->y - m_h/2;
  458.     AM_changeWindowLoc();
  459.  
  460.     /*  for saving & restoring */
  461.     old_m_x = m_x;
  462.     old_m_y = m_y;
  463.     old_m_w = m_w;
  464.     old_m_h = m_h;
  465.  
  466.     /*  inform the status bar of the change */
  467.     ST_Responder(&st_notify);
  468.  
  469. }
  470.  
  471. /*  */
  472. /*   */
  473. /*  */
  474. void AM_loadPics(void)
  475. {
  476.     int i;
  477.     char namebuf[9];
  478.   
  479.     for (i=0;i<10;i++)
  480.     {
  481.     sprintf(namebuf, "AMMNUM%d", i);
  482.     marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
  483.     }
  484.  
  485. }
  486.  
  487. void AM_unloadPics(void)
  488. {
  489.     int i;
  490.   
  491.     for (i=0;i<10;i++)
  492.     Z_ChangeTag(marknums[i], PU_CACHE);
  493.  
  494. }
  495.  
  496. void AM_clearMarks(void)
  497. {
  498.     int i;
  499.  
  500.     for (i=0;i<AM_NUMMARKPOINTS;i++)
  501.     markpoints[i].x = -1; /*  means empty */
  502.     markpointnum = 0;
  503. }
  504.  
  505. /*  */
  506. /*  should be called at the start of every level */
  507. /*  right now, i figure it out myself */
  508. /*  */
  509. void AM_LevelInit(void)
  510. {
  511.     leveljuststarted = 0;
  512.  
  513.     f_x = f_y = 0;
  514.     f_w = finit_width;
  515.     f_h = finit_height;
  516.  
  517.     AM_clearMarks();
  518.  
  519.     AM_findMinMaxBoundaries();
  520.     scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
  521.     if (scale_mtof > max_scale_mtof)
  522.     scale_mtof = min_scale_mtof;
  523.     scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  524. }
  525.  
  526.  
  527.  
  528.  
  529. /*  */
  530. /*  */
  531. /*  */
  532. void AM_Stop (void)
  533. {
  534.     static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
  535.  
  536.     AM_unloadPics();
  537.     automapactive = false;
  538.     ST_Responder(&st_notify);
  539.     stopped = true;
  540. }
  541.  
  542. /*  */
  543. /*  */
  544. /*  */
  545. extern boolean st_firsttime[2];
  546.  
  547. void AM_Start (void)
  548. {
  549.     static int lastlevel = -1, lastepisode = -1;
  550.  
  551.     if (dblbuffer)
  552.         st_firsttime[0]=st_firsttime[1]=true;
  553.  
  554.     if (!stopped) AM_Stop();
  555.     stopped = false;
  556.     if (lastlevel != gamemap || lastepisode != gameepisode)
  557.     {
  558.     AM_LevelInit();
  559.     lastlevel = gamemap;
  560.     lastepisode = gameepisode;
  561.     }
  562.     AM_initVariables();
  563.     AM_loadPics();
  564. }
  565.  
  566. /*  */
  567. /*  set the window scale to the maximum size */
  568. /*  */
  569. void AM_minOutWindowScale(void)
  570. {
  571.     scale_mtof = min_scale_mtof;
  572.     scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  573.     AM_activateNewScale();
  574. }
  575.  
  576. /*  */
  577. /*  set the window scale to the minimum size */
  578. /*  */
  579. void AM_maxOutWindowScale(void)
  580. {
  581.     scale_mtof = max_scale_mtof;
  582.     scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  583.     AM_activateNewScale();
  584. }
  585.  
  586.  
  587. /*  */
  588. /*  Handle events (user inputs) in automap mode */
  589. /*  */
  590. boolean
  591. AM_Responder
  592. ( event_t*    ev )
  593. {
  594.  
  595.     int rc;
  596.     static int cheatstate=0;
  597.     static int bigstate=0;
  598.     static char buffer[20];
  599.  
  600.     rc = false;
  601.  
  602.     if (!automapactive)
  603.     {
  604.     if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
  605.     {
  606.         AM_Start ();
  607.         viewactive = false;
  608.         rc = true;
  609.     }
  610.     }
  611.  
  612.     else if (ev->type == ev_keydown)
  613.     {
  614.  
  615.     rc = true;
  616.     switch(ev->data1)
  617.     {
  618.       case AM_PANRIGHTKEY: /*  pan right */
  619.         if (!followplayer) m_paninc.x = FTOM(F_PANINC);
  620.         else rc = false;
  621.         break;
  622.       case AM_PANLEFTKEY: /*  pan left */
  623.         if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
  624.         else rc = false;
  625.         break;
  626.       case AM_PANUPKEY: /*  pan up */
  627.         if (!followplayer) m_paninc.y = FTOM(F_PANINC);
  628.         else rc = false;
  629.         break;
  630.       case AM_PANDOWNKEY: /*  pan down */
  631.         if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
  632.         else rc = false;
  633.         break;
  634.       case AM_ZOOMOUTKEY: /*  zoom out */
  635.         mtof_zoommul = M_ZOOMOUT;
  636.         ftom_zoommul = M_ZOOMIN;
  637.         break;
  638.       case AM_ZOOMINKEY: /*  zoom in */
  639.         mtof_zoommul = M_ZOOMIN;
  640.         ftom_zoommul = M_ZOOMOUT;
  641.         break;
  642.       case AM_ENDKEY:
  643.         bigstate = 0;
  644.         viewactive = true;
  645.         AM_Stop ();
  646.         break;
  647.       case AM_GOBIGKEY:
  648.         bigstate = !bigstate;
  649.         if (bigstate)
  650.         {
  651.         AM_saveScaleAndLoc();
  652.         AM_minOutWindowScale();
  653.         }
  654.         else AM_restoreScaleAndLoc();
  655.         break;
  656.       case AM_FOLLOWKEY:
  657.         followplayer = !followplayer;
  658.         f_oldloc.x = MAXINT;
  659.         plr->message = followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF;
  660.         break;
  661.       case AM_GRIDKEY:
  662.         grid = !grid;
  663.         plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF;
  664.         break;
  665.       case AM_MARKKEY:
  666.         sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum);
  667.         plr->message = buffer;
  668.         AM_addMark();
  669.         break;
  670.       case AM_CLEARMARKKEY:
  671.         AM_clearMarks();
  672.         plr->message = AMSTR_MARKSCLEARED;
  673.         break;
  674.       default:
  675.         cheatstate=0;
  676.         rc = false;
  677.     }
  678.     if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data1))
  679.     {
  680.         rc = false;
  681.         cheating = (cheating+1) % 3;
  682.     }
  683.     }
  684.  
  685.     else if (ev->type == ev_keyup)
  686.     {
  687.     rc = false;
  688.     switch (ev->data1)
  689.     {
  690.       case AM_PANRIGHTKEY:
  691.         if (!followplayer) m_paninc.x = 0;
  692.         break;
  693.       case AM_PANLEFTKEY:
  694.         if (!followplayer) m_paninc.x = 0;
  695.         break;
  696.       case AM_PANUPKEY:
  697.         if (!followplayer) m_paninc.y = 0;
  698.         break;
  699.       case AM_PANDOWNKEY:
  700.         if (!followplayer) m_paninc.y = 0;
  701.         break;
  702.       case AM_ZOOMOUTKEY:
  703.       case AM_ZOOMINKEY:
  704.         mtof_zoommul = FRACUNIT;
  705.         ftom_zoommul = FRACUNIT;
  706.         break;
  707.     }
  708.     }
  709.  
  710.     return rc;
  711.  
  712. }
  713.  
  714.  
  715. /*  */
  716. /*  Zooming */
  717. /*  */
  718. void AM_changeWindowScale(void)
  719. {
  720.  
  721.     /*  Change the scaling multipliers */
  722.     scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
  723.     scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  724.  
  725.     if (scale_mtof < min_scale_mtof)
  726.     AM_minOutWindowScale();
  727.     else if (scale_mtof > max_scale_mtof)
  728.     AM_maxOutWindowScale();
  729.     else
  730.     AM_activateNewScale();
  731. }
  732.  
  733.  
  734. /*  */
  735. /*  */
  736. /*  */
  737. void AM_doFollowPlayer(void)
  738. {
  739.  
  740.     if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
  741.     {
  742.     m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
  743.     m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
  744.     m_x2 = m_x + m_w;
  745.     m_y2 = m_y + m_h;
  746.     f_oldloc.x = plr->mo->x;
  747.     f_oldloc.y = plr->mo->y;
  748.  
  749.     /*   m_x = FTOM(MTOF(plr->mo->x - m_w/2)); */
  750.     /*   m_y = FTOM(MTOF(plr->mo->y - m_h/2)); */
  751.     /*   m_x = plr->mo->x - m_w/2; */
  752.     /*   m_y = plr->mo->y - m_h/2; */
  753.  
  754.     }
  755.  
  756. }
  757.  
  758. /*  */
  759. /*  */
  760. /*  */
  761. void AM_updateLightLev(void)
  762. {
  763.     static nexttic = 0;
  764.     /* static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; */
  765.     static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
  766.     static int litelevelscnt = 0;
  767.    
  768.     /*  Change light level */
  769.     if (amclock>nexttic)
  770.     {
  771.     lightlev = litelevels[litelevelscnt++];
  772.     if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0;
  773.     nexttic = amclock + 6 - (amclock % 6);
  774.     }
  775.  
  776. }
  777.  
  778.  
  779. /*  */
  780. /*  Updates on Game Tick */
  781. /*  */
  782. void AM_Ticker (void)
  783. {
  784.  
  785.     if (!automapactive)
  786.     return;
  787.  
  788.     amclock++;
  789.  
  790.     if (followplayer)
  791.     AM_doFollowPlayer();
  792.  
  793.     /*  Change the zoom if necessary */
  794.     if (ftom_zoommul != FRACUNIT)
  795.     AM_changeWindowScale();
  796.  
  797.     /*  Change x,y location */
  798.     if (m_paninc.x || m_paninc.y)
  799.     AM_changeWindowLoc();
  800.  
  801.     /*  Update light level */
  802.     /*  AM_updateLightLev(); */
  803.  
  804. }
  805.  
  806.  
  807. /*  */
  808. /*  Clear automap frame buffer. */
  809. /*  */
  810. void AM_clearFB(int color)
  811. {
  812.     int x,y;
  813.     unsigned short *fbscr,color16;
  814.     unsigned long *fbscr32,mapcolor32;    
  815.     byte    *fb1;
  816.     byte    r,v,b;
  817.  
  818.     if (dblbuffer)
  819.         fb=screens[0];    /* for double buffer */
  820.  
  821.     switch (pixel_size)
  822.     {
  823.         case 1:
  824.             memset(fb, color, f_w*f_h);
  825.             break;
  826.         case 2:
  827.             fbscr=(unsigned short *) fb;
  828.             color16=truecolor_palette[color];
  829.             for (y=0;y<f_h;y++)
  830.                 for (x=0;x<f_w;x++)
  831.                     *fbscr++ = color16;
  832.             break;
  833.         case 3:
  834.             fb1=fb;
  835.             r=truecolor_palette[color] >> 16;
  836.             v=truecolor_palette[color] >> 8;
  837.             b=truecolor_palette[color];
  838.             
  839.             for (y=0;y<f_h;y++)
  840.             {
  841.                 for (x=0;x<f_w;x++)
  842.                 {
  843.                     *fb1++ = b;
  844.                     *fb1++ = v;
  845.                     *fb1++ = r;
  846.                 }
  847.             }
  848.             break;
  849.         case 4:
  850.             fbscr32=(unsigned long *) fb;
  851.             mapcolor32=truecolor_palette[color];
  852.             for (y=0;y<f_h;y++)
  853.                 for (x=0;x<f_w;x++)
  854.                     *fbscr32++ = mapcolor32;
  855.             break;
  856.     }
  857. }
  858.  
  859.  
  860. /*  */
  861. /*  Automap clipping of lines. */
  862. /*  */
  863. /*  Based on Cohen-Sutherland clipping algorithm but with a slightly */
  864. /*  faster reject and precalculated slopes.  If the speed is needed, */
  865. /*  use a hash algorithm to handle  the common cases. */
  866. /*  */
  867. boolean
  868. AM_clipMline
  869. ( mline_t*    ml,
  870.   fline_t*    fl )
  871. {
  872.     enum
  873.     {
  874.     LEFT    =1,
  875.     RIGHT    =2,
  876.     BOTTOM    =4,
  877.     TOP    =8
  878.     };
  879.     
  880.     register    outcode1 = 0;
  881.     register    outcode2 = 0;
  882.     register    outside;
  883.     
  884.     fpoint_t    tmp;
  885.     int        dx;
  886.     int        dy;
  887.  
  888.     
  889. #define DOOUTCODE(oc, mx, my) \
  890.     (oc) = 0; \
  891.     if ((my) < 0) (oc) |= TOP; \
  892.     else if ((my) >= f_h) (oc) |= BOTTOM; \
  893.     if ((mx) < 0) (oc) |= LEFT; \
  894.     else if ((mx) >= f_w) (oc) |= RIGHT;
  895.  
  896.     
  897.     /*  do trivial rejects and outcodes */
  898.     if (ml->a.y > m_y2)
  899.     outcode1 = TOP;
  900.     else if (ml->a.y < m_y)
  901.     outcode1 = BOTTOM;
  902.  
  903.     if (ml->b.y > m_y2)
  904.     outcode2 = TOP;
  905.     else if (ml->b.y < m_y)
  906.     outcode2 = BOTTOM;
  907.     
  908.     if (outcode1 & outcode2)
  909.     return false; /*  trivially outside */
  910.  
  911.     if (ml->a.x < m_x)
  912.     outcode1 |= LEFT;
  913.     else if (ml->a.x > m_x2)
  914.     outcode1 |= RIGHT;
  915.     
  916.     if (ml->b.x < m_x)
  917.     outcode2 |= LEFT;
  918.     else if (ml->b.x > m_x2)
  919.     outcode2 |= RIGHT;
  920.     
  921.     if (outcode1 & outcode2)
  922.     return false; /*  trivially outside */
  923.  
  924.     /*  transform to frame-buffer coordinates. */
  925.     fl->a.x = CXMTOF(ml->a.x);
  926.     fl->a.y = CYMTOF(ml->a.y);
  927.     fl->b.x = CXMTOF(ml->b.x);
  928.     fl->b.y = CYMTOF(ml->b.y);
  929.  
  930.     DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  931.     DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  932.  
  933.     if (outcode1 & outcode2)
  934.     return false;
  935.  
  936.     while (outcode1 | outcode2)
  937.     {
  938.     /*  may be partially inside box */
  939.     /*  find an outside point */
  940.     if (outcode1)
  941.         outside = outcode1;
  942.     else
  943.         outside = outcode2;
  944.     
  945.     /*  clip to each side */
  946.     if (outside & TOP)
  947.     {
  948.         dy = fl->a.y - fl->b.y;
  949.         dx = fl->b.x - fl->a.x;
  950.         tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
  951.         tmp.y = 0;
  952.     }
  953.     else if (outside & BOTTOM)
  954.     {
  955.         dy = fl->a.y - fl->b.y;
  956.         dx = fl->b.x - fl->a.x;
  957.         tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
  958.         tmp.y = f_h-1;
  959.     }
  960.     else if (outside & RIGHT)
  961.     {
  962.         dy = fl->b.y - fl->a.y;
  963.         dx = fl->b.x - fl->a.x;
  964.         tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
  965.         tmp.x = f_w-1;
  966.     }
  967.     else if (outside & LEFT)
  968.     {
  969.         dy = fl->b.y - fl->a.y;
  970.         dx = fl->b.x - fl->a.x;
  971.         tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
  972.         tmp.x = 0;
  973.     }
  974.  
  975.     if (outside == outcode1)
  976.     {
  977.         fl->a = tmp;
  978.         DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  979.     }
  980.     else
  981.     {
  982.         fl->b = tmp;
  983.         DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  984.     }
  985.     
  986.     if (outcode1 & outcode2)
  987.         return false; /*  trivially outside */
  988.     }
  989.  
  990.     return true;
  991. }
  992. #undef DOOUTCODE
  993.  
  994.  
  995. /*  */
  996. /*  Classic Bresenham w/ whatever optimizations needed for speed */
  997. /*  */
  998. void
  999. AM_drawFline8
  1000. ( fline_t*    fl,
  1001.   int        color )
  1002. {
  1003.     register int x;
  1004.     register int y;
  1005.     register int dx;
  1006.     register int dy;
  1007.     register int sx;
  1008.     register int sy;
  1009.     register int ax;
  1010.     register int ay;
  1011.     register int d;
  1012.     
  1013.     static fuck = 0;
  1014.  
  1015.     /*  For debugging only */
  1016.     if (      fl->a.x < 0 || fl->a.x >= f_w
  1017.        || fl->a.y < 0 || fl->a.y >= f_h
  1018.        || fl->b.x < 0 || fl->b.x >= f_w
  1019.        || fl->b.y < 0 || fl->b.y >= f_h)
  1020.     {
  1021.     fprintf(stderr, "fuck %d \r", fuck++);
  1022.     return;
  1023.     }
  1024.  
  1025. #define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
  1026.  
  1027.     dx = fl->b.x - fl->a.x;
  1028.     ax = 2 * (dx<0 ? -dx : dx);
  1029.     sx = dx<0 ? -1 : 1;
  1030.  
  1031.     dy = fl->b.y - fl->a.y;
  1032.     ay = 2 * (dy<0 ? -dy : dy);
  1033.     sy = dy<0 ? -1 : 1;
  1034.  
  1035.     x = fl->a.x;
  1036.     y = fl->a.y;
  1037.  
  1038.     if (ax > ay)
  1039.     {
  1040.     d = ay - ax/2;
  1041.     for(;;)
  1042.     {
  1043.         PUTDOT(x,y,color);
  1044.         if (x == fl->b.x) return;
  1045.         if (d>=0)
  1046.         {
  1047.         y += sy;
  1048.         d -= ax;
  1049.         }
  1050.         x += sx;
  1051.         d += ay;
  1052.     }
  1053.     }
  1054.     else
  1055.     {
  1056.     d = ax - ay/2;
  1057.     for(;;)
  1058.     {
  1059.         PUTDOT(x, y, color);
  1060.         if (y == fl->b.y) return;
  1061.         if (d >= 0)
  1062.         {
  1063.         x += sx;
  1064.         d -= ay;
  1065.         }
  1066.         y += sy;
  1067.         d += ax;
  1068.     }
  1069.     }
  1070. }
  1071.  
  1072. void AM_drawFline16
  1073. ( fline_t*    fl,
  1074.   int        color )
  1075. {
  1076.     register int x;
  1077.     register int y;
  1078.     register int dx;
  1079.     register int dy;
  1080.     register int sx;
  1081.     register int sy;
  1082.     register int ax;
  1083.     register int ay;
  1084.     register int d;
  1085.     unsigned short *fbscr;
  1086.     
  1087.     static fuck = 0;
  1088.  
  1089.     fbscr=(unsigned short *)fb;
  1090.  
  1091.     /*  For debugging only */
  1092.     if (      fl->a.x < 0 || fl->a.x >= f_w
  1093.        || fl->a.y < 0 || fl->a.y >= f_h
  1094.        || fl->b.x < 0 || fl->b.x >= f_w
  1095.        || fl->b.y < 0 || fl->b.y >= f_h)
  1096.     {
  1097.     fprintf(stderr, "fuck %d \r", fuck++);
  1098.     return;
  1099.     }
  1100.  
  1101. #define PUTDOT16(xx,yy,cc) fbscr[(yy)*f_w+(xx)]=truecolor_palette[cc]
  1102.  
  1103.     dx = fl->b.x - fl->a.x;
  1104.     ax = 2 * (dx<0 ? -dx : dx);
  1105.     sx = dx<0 ? -1 : 1;
  1106.  
  1107.     dy = fl->b.y - fl->a.y;
  1108.     ay = 2 * (dy<0 ? -dy : dy);
  1109.     sy = dy<0 ? -1 : 1;
  1110.  
  1111.     x = fl->a.x;
  1112.     y = fl->a.y;
  1113.  
  1114.     if (ax > ay)
  1115.     {
  1116.     d = ay - ax/2;
  1117.     for(;;)
  1118.     {
  1119.         PUTDOT16(x,y,color);
  1120.         if (x == fl->b.x) return;
  1121.         if (d>=0)
  1122.         {
  1123.         y += sy;
  1124.         d -= ax;
  1125.         }
  1126.         x += sx;
  1127.         d += ay;
  1128.     }
  1129.     }
  1130.     else
  1131.     {
  1132.     d = ax - ay/2;
  1133.     for(;;)
  1134.     {
  1135.         PUTDOT16(x, y, color);
  1136.         if (y == fl->b.y) return;
  1137.         if (d >= 0)
  1138.         {
  1139.         x += sx;
  1140.         d -= ay;
  1141.         }
  1142.         y += sy;
  1143.         d += ax;
  1144.     }
  1145.     }
  1146. }
  1147.  
  1148. void AM_drawFline24
  1149. ( fline_t*    fl,
  1150.   int        color )
  1151. {
  1152.     unsigned char    r,v,b;
  1153.  
  1154.     register int x;
  1155.     register int y;
  1156.     register int dx;
  1157.     register int dy;
  1158.     register int sx;
  1159.     register int sy;
  1160.     register int ax;
  1161.     register int ay;
  1162.     register int d;
  1163.     
  1164.     static fuck = 0;
  1165.     
  1166.     r=truecolor_palette[color] >> 16;
  1167.     v=truecolor_palette[color] >> 8;
  1168.     b=truecolor_palette[color];
  1169.  
  1170.     /*  For debugging only */
  1171.     if (      fl->a.x < 0 || fl->a.x >= f_w
  1172.        || fl->a.y < 0 || fl->a.y >= f_h
  1173.        || fl->b.x < 0 || fl->b.x >= f_w
  1174.        || fl->b.y < 0 || fl->b.y >= f_h)
  1175.     {
  1176.     fprintf(stderr, "fuck %d \r", fuck++);
  1177.     return;
  1178.     }
  1179.  
  1180. #define PUTDOT24(xx,yy,rr,vv,bb) \
  1181.     fb[((yy)*f_w+(xx))*3]=bb; \
  1182.     fb[((yy)*f_w+(xx))*3+1]=vv; \
  1183.     fb[((yy)*f_w+(xx))*3+2]=rr;
  1184.  
  1185.     dx = fl->b.x - fl->a.x;
  1186.     ax = 2 * (dx<0 ? -dx : dx);
  1187.     sx = dx<0 ? -1 : 1;
  1188.  
  1189.     dy = fl->b.y - fl->a.y;
  1190.     ay = 2 * (dy<0 ? -dy : dy);
  1191.     sy = dy<0 ? -1 : 1;
  1192.  
  1193.     x = fl->a.x;
  1194.     y = fl->a.y;
  1195.  
  1196.     if (ax > ay)
  1197.     {
  1198.     d = ay - ax/2;
  1199.     for(;;)
  1200.     {
  1201.         PUTDOT24(x,y,r,v,b);
  1202.         if (x == fl->b.x) return;
  1203.         if (d>=0)
  1204.         {
  1205.         y += sy;
  1206.         d -= ax;
  1207.         }
  1208.         x += sx;
  1209.         d += ay;
  1210.     }
  1211.     }
  1212.     else
  1213.     {
  1214.     d = ax - ay/2;
  1215.     for(;;)
  1216.     {
  1217.         PUTDOT24(x, y,r,v,b);
  1218.         if (y == fl->b.y) return;
  1219.         if (d >= 0)
  1220.         {
  1221.         x += sx;
  1222.         d -= ay;
  1223.         }
  1224.         y += sy;
  1225.         d += ax;
  1226.     }
  1227.     }
  1228. }
  1229.  
  1230. void AM_drawFline32
  1231. ( fline_t*    fl,
  1232.   int        color )
  1233. {
  1234.     register int x;
  1235.     register int y;
  1236.     register int dx;
  1237.     register int dy;
  1238.     register int sx;
  1239.     register int sy;
  1240.     register int ax;
  1241.     register int ay;
  1242.     register int d;
  1243.     unsigned long *fbscr;
  1244.     
  1245.     static fuck = 0;
  1246.  
  1247.     fbscr=(unsigned long *)fb;
  1248.  
  1249.     /*  For debugging only */
  1250.     if (      fl->a.x < 0 || fl->a.x >= f_w
  1251.        || fl->a.y < 0 || fl->a.y >= f_h
  1252.        || fl->b.x < 0 || fl->b.x >= f_w
  1253.        || fl->b.y < 0 || fl->b.y >= f_h)
  1254.     {
  1255.     fprintf(stderr, "fuck %d \r", fuck++);
  1256.     return;
  1257.     }
  1258.  
  1259. #define PUTDOT32(xx,yy,cc) fbscr[(yy)*f_w+(xx)]=truecolor_palette[cc]
  1260.  
  1261.     dx = fl->b.x - fl->a.x;
  1262.     ax = 2 * (dx<0 ? -dx : dx);
  1263.     sx = dx<0 ? -1 : 1;
  1264.  
  1265.     dy = fl->b.y - fl->a.y;
  1266.     ay = 2 * (dy<0 ? -dy : dy);
  1267.     sy = dy<0 ? -1 : 1;
  1268.  
  1269.     x = fl->a.x;
  1270.     y = fl->a.y;
  1271.  
  1272.     if (ax > ay)
  1273.     {
  1274.     d = ay - ax/2;
  1275.     for(;;)
  1276.     {
  1277.         PUTDOT32(x,y,color);
  1278.         if (x == fl->b.x) return;
  1279.         if (d>=0)
  1280.         {
  1281.         y += sy;
  1282.         d -= ax;
  1283.         }
  1284.         x += sx;
  1285.         d += ay;
  1286.     }
  1287.     }
  1288.     else
  1289.     {
  1290.     d = ax - ay/2;
  1291.     for(;;)
  1292.     {
  1293.         PUTDOT32(x, y, color);
  1294.         if (y == fl->b.y) return;
  1295.         if (d >= 0)
  1296.         {
  1297.         x += sx;
  1298.         d -= ay;
  1299.         }
  1300.         y += sy;
  1301.         d += ax;
  1302.     }
  1303.     }
  1304. }
  1305.  
  1306. /*  */
  1307. /*  Clip lines, draw visible part sof lines. */
  1308. /*  */
  1309. void
  1310. AM_drawMline
  1311. ( mline_t*    ml,
  1312.   int        color )
  1313. {
  1314.     static fline_t fl;
  1315.  
  1316.     if (AM_clipMline(ml, &fl))
  1317.     AM_DrawFline(&fl, color); /*  draws it on frame buffer using fb coords */
  1318. }
  1319.  
  1320.  
  1321.  
  1322. /*  */
  1323. /*  Draws flat (floor/ceiling tile) aligned grid lines. */
  1324. /*  */
  1325. void AM_drawGrid(int color)
  1326. {
  1327.     fixed_t x, y;
  1328.     fixed_t start, end;
  1329.     mline_t ml;
  1330.  
  1331.     /*  Figure out start of vertical gridlines */
  1332.     start = m_x;
  1333.     if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
  1334.     start += (MAPBLOCKUNITS<<FRACBITS)
  1335.         - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
  1336.     end = m_x + m_w;
  1337.  
  1338.     /*  draw vertical gridlines */
  1339.     ml.a.y = m_y;
  1340.     ml.b.y = m_y+m_h;
  1341.     for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
  1342.     {
  1343.     ml.a.x = x;
  1344.     ml.b.x = x;
  1345.     AM_drawMline(&ml, color);
  1346.     }
  1347.  
  1348.     /*  Figure out start of horizontal gridlines */
  1349.     start = m_y;
  1350.     if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
  1351.     start += (MAPBLOCKUNITS<<FRACBITS)
  1352.         - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
  1353.     end = m_y + m_h;
  1354.  
  1355.     /*  draw horizontal gridlines */
  1356.     ml.a.x = m_x;
  1357.     ml.b.x = m_x + m_w;
  1358.     for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
  1359.     {
  1360.     ml.a.y = y;
  1361.     ml.b.y = y;
  1362.     AM_drawMline(&ml, color);
  1363.     }
  1364.  
  1365. }
  1366.  
  1367. /*  */
  1368. /*  Determines visible lines, draws them. */
  1369. /*  This is LineDef based, not LineSeg based. */
  1370. /*  */
  1371. void AM_drawWalls(void)
  1372. {
  1373.     int i;
  1374.     static mline_t l;
  1375.  
  1376.     for (i=0;i<numlines;i++)
  1377.     {
  1378.     l.a.x = lines[i].v1->x;
  1379.     l.a.y = lines[i].v1->y;
  1380.     l.b.x = lines[i].v2->x;
  1381.     l.b.y = lines[i].v2->y;
  1382.     if (cheating || (lines[i].flags & ML_MAPPED))
  1383.     {
  1384.         if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
  1385.         continue;
  1386.         if (!lines[i].backsector)
  1387.         {
  1388.         AM_drawMline(&l, WALLCOLORS+lightlev);
  1389.         }
  1390.         else
  1391.         {
  1392.         if (lines[i].special == 39)
  1393.         { /*  teleporters */
  1394.             AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
  1395.         }
  1396.         else if (lines[i].flags & ML_SECRET) /*  secret door */
  1397.         {
  1398.             if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev);
  1399.             else AM_drawMline(&l, WALLCOLORS+lightlev);
  1400.         }
  1401.         else if (lines[i].backsector->floorheight
  1402.                != lines[i].frontsector->floorheight) {
  1403.             AM_drawMline(&l, FDWALLCOLORS + lightlev); /*  floor level change */
  1404.         }
  1405.         else if (lines[i].backsector->ceilingheight
  1406.                != lines[i].frontsector->ceilingheight) {
  1407.             AM_drawMline(&l, CDWALLCOLORS+lightlev); /*  ceiling level change */
  1408.         }
  1409.         else if (cheating) {
  1410.             AM_drawMline(&l, TSWALLCOLORS+lightlev);
  1411.         }
  1412.         }
  1413.     }
  1414.     else if (plr->powers[pw_allmap])
  1415.     {
  1416.         if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
  1417.     }
  1418.     }
  1419. }
  1420.  
  1421.  
  1422. /*  */
  1423. /*  Rotation in 2D. */
  1424. /*  Used to rotate player arrow line character. */
  1425. /*  */
  1426. void
  1427. AM_rotate
  1428. ( fixed_t*    x,
  1429.   fixed_t*    y,
  1430.   angle_t    a )
  1431. {
  1432.     fixed_t tmpx;
  1433.  
  1434.     tmpx =
  1435.     FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
  1436.     - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
  1437.     
  1438.     *y   =
  1439.     FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
  1440.     + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
  1441.  
  1442.     *x = tmpx;
  1443. }
  1444.  
  1445. void
  1446. AM_drawLineCharacter
  1447. ( mline_t*    lineguy,
  1448.   int        lineguylines,
  1449.   fixed_t    scale,
  1450.   angle_t    angle,
  1451.   int        color,
  1452.   fixed_t    x,
  1453.   fixed_t    y )
  1454. {
  1455.     int        i;
  1456.     mline_t    l;
  1457.  
  1458.     for (i=0;i<lineguylines;i++)
  1459.     {
  1460.     l.a.x = lineguy[i].a.x;
  1461.     l.a.y = lineguy[i].a.y;
  1462.  
  1463.     if (scale)
  1464.     {
  1465.         l.a.x = FixedMul(scale, l.a.x);
  1466.         l.a.y = FixedMul(scale, l.a.y);
  1467.     }
  1468.  
  1469.     if (angle)
  1470.         AM_rotate(&l.a.x, &l.a.y, angle);
  1471.  
  1472.     l.a.x += x;
  1473.     l.a.y += y;
  1474.  
  1475.     l.b.x = lineguy[i].b.x;
  1476.     l.b.y = lineguy[i].b.y;
  1477.  
  1478.     if (scale)
  1479.     {
  1480.         l.b.x = FixedMul(scale, l.b.x);
  1481.         l.b.y = FixedMul(scale, l.b.y);
  1482.     }
  1483.  
  1484.     if (angle)
  1485.         AM_rotate(&l.b.x, &l.b.y, angle);
  1486.     
  1487.     l.b.x += x;
  1488.     l.b.y += y;
  1489.  
  1490.     AM_drawMline(&l, color);
  1491.     }
  1492. }
  1493.  
  1494. void AM_drawPlayers(void)
  1495. {
  1496.     int        i;
  1497.     player_t*    p;
  1498.     static int     their_colors[] = { GREENS, GRAYS, BROWNS, REDS };
  1499.     int        their_color = -1;
  1500.     int        color;
  1501.  
  1502.     if (!netgame)
  1503.     {
  1504.     if (cheating)
  1505.         AM_drawLineCharacter
  1506.         (cheat_player_arrow, NUMCHEATPLYRLINES, 0,
  1507.          plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
  1508.     else
  1509.         AM_drawLineCharacter
  1510.         (player_arrow, NUMPLYRLINES, 0, plr->mo->angle,
  1511.          WHITE, plr->mo->x, plr->mo->y);
  1512.     return;
  1513.     }
  1514.  
  1515.     for (i=0;i<MAXPLAYERS;i++)
  1516.     {
  1517.     their_color++;
  1518.     p = &players[i];
  1519.  
  1520.     if ( (deathmatch && !singledemo) && p != plr)
  1521.         continue;
  1522.  
  1523.     if (!playeringame[i])
  1524.         continue;
  1525.  
  1526.     if (p->powers[pw_invisibility])
  1527.         color = 246; /*  *close* to black */
  1528.     else
  1529.         color = their_colors[their_color];
  1530.     
  1531.     AM_drawLineCharacter
  1532.         (player_arrow, NUMPLYRLINES, 0, p->mo->angle,
  1533.          color, p->mo->x, p->mo->y);
  1534.     }
  1535.  
  1536. }
  1537.  
  1538. void
  1539. AM_drawThings
  1540. ( int    colors,
  1541.   int     colorrange)
  1542. {
  1543.     int        i;
  1544.     mobj_t*    t;
  1545.  
  1546.     for (i=0;i<numsectors;i++)
  1547.     {
  1548.     t = sectors[i].thinglist;
  1549.     while (t)
  1550.     {
  1551.         AM_drawLineCharacter
  1552.         (thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
  1553.          16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
  1554.         t = t->snext;
  1555.     }
  1556.     }
  1557. }
  1558.  
  1559. void AM_drawMarks(void)
  1560. {
  1561.     int i, fx, fy, w, h;
  1562.  
  1563.     for (i=0;i<AM_NUMMARKPOINTS;i++)
  1564.     {
  1565.     if (markpoints[i].x != -1)
  1566.     {
  1567.         /*       w = SHORT(marknums[i]->width); */
  1568.         /*       h = SHORT(marknums[i]->height); */
  1569.         w = 5; /*  because something's wrong with the wad, i guess */
  1570.         h = 6; /*  because something's wrong with the wad, i guess */
  1571.         fx = CXMTOF(markpoints[i].x);
  1572.         fy = CYMTOF(markpoints[i].y);
  1573.         if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
  1574.         V_DrawPatch(fx, fy, FB, marknums[i]);
  1575.     }
  1576.     }
  1577.  
  1578. }
  1579.  
  1580. void AM_drawCrosshair(int color)
  1581. {
  1582.     unsigned short    *fbscr;
  1583.     unsigned long *fbscr32;
  1584.     byte    *fb1;
  1585.  
  1586.     switch (pixel_size)
  1587.     {
  1588.         case 1:
  1589.             fb[(f_w*(f_h+1))/2] = color; /*  single point for now */
  1590.             break;
  1591.         case 2:
  1592.             fbscr=(unsigned short *) fb;
  1593.             fbscr[(f_w*(f_h+1))/2]=truecolor_palette[color];
  1594.             break;
  1595.         case 3:
  1596.             fb1=fb + ((f_w*(f_h+1))/2)*pixel_size ;
  1597.  
  1598.             *fb1++ = truecolor_palette[color];
  1599.             *fb1++ = truecolor_palette[color] >> 8;
  1600.             *fb1 = truecolor_palette[color] >> 16;
  1601.             break;
  1602.         case 4:
  1603.             fbscr32=(unsigned long *) fb;
  1604.             fbscr32[(f_w*(f_h+1))/2]=truecolor_palette[color];
  1605.             break;
  1606.     }
  1607. }
  1608.  
  1609. void AM_Drawer (void)
  1610. {
  1611.     if (!automapactive) return;
  1612.  
  1613.     AM_clearFB(BACKGROUND);
  1614.     if (grid)
  1615.     AM_drawGrid(GRIDCOLORS);
  1616.     AM_drawWalls();
  1617.     AM_drawPlayers();
  1618.     if (cheating==2)
  1619.     AM_drawThings(THINGCOLORS, THINGRANGE);
  1620.     AM_drawCrosshair(XHAIRCOLORS);
  1621.  
  1622.     AM_drawMarks();
  1623.  
  1624.     V_MarkRect(f_x, f_y, f_w, f_h);
  1625.  
  1626. }
  1627.