1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *   the automap code
31  *
32  *-----------------------------------------------------------------------------
33  */
34 
35 #include "config.h"
36 
37 #include "doomstat.h"
38 #include "st_stuff.h"
39 #include "r_main.h"
40 #include "p_setup.h"
41 #include "p_maputl.h"
42 #include "w_wad.h"
43 #include "v_video.h"
44 #include "p_spec.h"
45 #include "am_map.h"
46 #include "dstrings.h"
47 #include "d_deh.h"    // Ty 03/27/98 - externalizations
48 #include "lprintf.h"  // jff 08/03/98 - declaration of lprintf
49 #include "g_game.h"
50 #include "v_video.h"
51 
52 //jff 1/7/98 default automap colors added
53 int mapcolor_back;    // map background
54 int mapcolor_grid;    // grid lines color
55 int mapcolor_wall;    // normal 1s wall color
56 int mapcolor_fchg;    // line at floor height change color
57 int mapcolor_cchg;    // line at ceiling height change color
58 int mapcolor_clsd;    // line at sector with floor=ceiling color
59 int mapcolor_rkey;    // red key color
60 int mapcolor_bkey;    // blue key color
61 int mapcolor_ykey;    // yellow key color
62 int mapcolor_rdor;    // red door color  (diff from keys to allow option)
63 int mapcolor_bdor;    // blue door color (of enabling one but not other )
64 int mapcolor_ydor;    // yellow door color
65 int mapcolor_tele;    // teleporter line color
66 int mapcolor_secr;    // secret sector boundary color
67 int mapcolor_exit;    // jff 4/23/98 add exit line color
68 int mapcolor_unsn;    // computer map unseen line color
69 int mapcolor_flat;    // line with no floor/ceiling changes
70 int mapcolor_sprt;    // general sprite color
71 int mapcolor_item;    // item sprite color
72 int mapcolor_frnd;    // friendly sprite color
73 int mapcolor_enemy;   // enemy sprite color
74 int mapcolor_hair;    // crosshair color
75 int mapcolor_sngl;    // single player arrow color
76 int mapcolor_plyr[4] = { 112, 88, 64, 32 }; // colors for player arrows in multiplayer
77 
78 //jff 3/9/98 add option to not show secret sectors until entered
79 int map_secret_after;
80 //jff 4/3/98 add symbols for "no-color" for disable and "black color" for black
81 #define NC 0
82 #define BC 247
83 
84 // drawing stuff
85 #define FB    0
86 
87 // scale on entry
88 #define INITSCALEMTOF (.2*FRACUNIT)
89 // how much the automap moves window per tic in frame-buffer coordinates
90 // moves 140 pixels in 1 second
91 #define F_PANINC  4
92 // how much zoom-in per tic
93 // goes to 2x in 1 second
94 #define M_ZOOMIN        ((int) (1.02*FRACUNIT))
95 // how much zoom-out per tic
96 // pulls out to 0.5x in 1 second
97 #define M_ZOOMOUT       ((int) (FRACUNIT/1.02))
98 
99 #define PLAYERRADIUS    (16*(1<<MAPBITS)) // e6y
100 
101 // translates between frame-buffer and map distances
102 #define FTOM(x) FixedMul(((x)<<16),scale_ftom)
103 #define MTOF(x) (FixedMul((x),scale_mtof)>>16)
104 // translates between frame-buffer and map coordinates
105 #define CXMTOF(x)  (f_x + MTOF((x)-m_x))
106 #define CYMTOF(y)  (f_y + (f_h - MTOF((y)-m_y)))
107 
108 typedef struct
109 {
110     mpoint_t a, b;
111 } mline_t;
112 
113 //
114 // The vector graphics for the automap.
115 //  A line drawing of the player pointing right,
116 //   starting from the middle.
117 //
118 #define R ((8*PLAYERRADIUS)/7)
119 mline_t player_arrow[] =
120 {
121   { { -R+R/8, 0 }, { R, 0 } }, // -----
122   { { R, 0 }, { R-R/2, R/4 } },  // ----->
123   { { R, 0 }, { R-R/2, -R/4 } },
124   { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
125   { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
126   { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
127   { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } }
128 };
129 #undef R
130 #define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t))
131 
132 #define R ((8*PLAYERRADIUS)/7)
133 mline_t cheat_player_arrow[] =
134 { // killough 3/22/98: He's alive, Jim :)
135   { { -R+R/8, 0 }, { R, 0 } }, // -----
136   { { R, 0 }, { R-R/2, R/4 } },  // ----->
137   { { R, 0 }, { R-R/2, -R/4 } },
138   { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >---->
139   { { -R+R/8, 0 }, { -R-R/8, -R/4 } },
140   { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>--->
141   { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } },
142   { { -R/10-R/6, R/4}, {-R/10-R/6, -R/4} },  // J
143   { { -R/10-R/6, -R/4}, {-R/10-R/6-R/8, -R/4} },
144   { { -R/10-R/6-R/8, -R/4}, {-R/10-R/6-R/8, -R/8} },
145   { { -R/10, R/4}, {-R/10, -R/4}},           // F
146   { { -R/10, R/4}, {-R/10+R/8, R/4}},
147   { { -R/10+R/4, R/4}, {-R/10+R/4, -R/4}},   // F
148   { { -R/10+R/4, R/4}, {-R/10+R/4+R/8, R/4}},
149 };
150 #undef R
151 #define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t))
152 
153 #define R (FRACUNIT)
154 mline_t triangle_guy[] =
155 {
156 { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)( .867*R), (fixed_t)(-.5*R) } },
157 { { (fixed_t)( .867*R), (fixed_t)(-.5*R) }, { (fixed_t)(0      ), (fixed_t)(    R) } },
158 { { (fixed_t)(0      ), (fixed_t)(    R) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } }
159 };
160 #undef R
161 #define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t))
162 
163 //jff 1/5/98 new symbol for keys on automap
164 #define R (FRACUNIT)
165 mline_t cross_mark[] =
166 {
167   { { -R, 0 }, { R, 0} },
168   { { 0, -R }, { 0, R } },
169 };
170 #undef R
171 #define NUMCROSSMARKLINES (sizeof(cross_mark)/sizeof(mline_t))
172 //jff 1/5/98 end of new symbol
173 
174 #define R (FRACUNIT)
175 mline_t thintriangle_guy[] =
176 {
177 { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(    R), (fixed_t)(    0) } },
178 { { (fixed_t)(    R), (fixed_t)(    0) }, { (fixed_t)(-.5*R), (fixed_t)( .7*R) } },
179 { { (fixed_t)(-.5*R), (fixed_t)( .7*R) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } }
180 };
181 #undef R
182 #define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t))
183 
184 int ddt_cheating = 0;         // killough 2/7/98: make global, rename to ddt_*
185 
186 static int leveljuststarted = 1;       // kluge until AM_LevelInit() is called
187 
188 enum automapmode_e automapmode; // Mode that the automap is in
189 
190 // location of window on screen
191 static int  f_x;
192 static int  f_y;
193 
194 // size of window on screen
195 static int  f_w;
196 static int  f_h;
197 
198 static mpoint_t m_paninc;    // how far the window pans each tic (map coords)
199 static fixed_t mtof_zoommul; // how far the window zooms each tic (map coords)
200 static fixed_t ftom_zoommul; // how far the window zooms each tic (fb coords)
201 
202 static fixed_t m_x, m_y;     // LL x,y window location on the map (map coords)
203 static fixed_t m_x2, m_y2;   // UR x,y window location on the map (map coords)
204 
205 //
206 // width/height of window on map (map coords)
207 //
208 static fixed_t  m_w;
209 static fixed_t  m_h;
210 
211 // based on level size
212 static fixed_t  min_x;
213 static fixed_t  min_y;
214 static fixed_t  max_x;
215 static fixed_t  max_y;
216 
217 static fixed_t  max_w;          // max_x-min_x,
218 static fixed_t  max_h;          // max_y-min_y
219 
220 // based on player size
221 static fixed_t  min_w;
222 static fixed_t  min_h;
223 
224 
225 static fixed_t  min_scale_mtof; // used to tell when to stop zooming out
226 static fixed_t  max_scale_mtof; // used to tell when to stop zooming in
227 
228 // old stuff for recovery later
229 static fixed_t old_m_w, old_m_h;
230 static fixed_t old_m_x, old_m_y;
231 
232 // old location used by the Follower routine
233 static mpoint_t f_oldloc;
234 
235 // used by MTOF to scale from map-to-frame-buffer coords
236 static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
237 // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
238 static fixed_t scale_ftom;
239 
240 static player_t *plr;           // the player represented by an arrow
241 
242 // killough 2/22/98: Remove limit on automap marks,
243 // and make variables external for use in savegames.
244 
245 mpoint_t *markpoints = NULL;    // where the points are
246 int markpointnum = 0; // next point to be assigned (also number of points now)
247 int markpointnum_max = 0;       // killough 2/22/98
248 
249 static dbool   stopped = TRUE;
250 
251 //
252 // AM_activateNewScale()
253 //
254 // Changes the map scale after zooming or translating
255 //
256 // Passed nothing, returns nothing
257 //
AM_activateNewScale(void)258 static void AM_activateNewScale(void)
259 {
260   m_x  += m_w/2;
261   m_y  += m_h/2;
262   m_w   = FTOM(f_w);
263   m_h   = FTOM(f_h);
264   m_x  -= m_w/2;
265   m_y  -= m_h/2;
266   m_x2  = m_x + m_w;
267   m_y2  = m_y + m_h;
268 }
269 
270 //
271 // AM_saveScaleAndLoc()
272 //
273 // Saves the current center and zoom
274 // Affects the variables that remember old scale and loc
275 //
276 // Passed nothing, returns nothing
277 //
AM_saveScaleAndLoc(void)278 static void AM_saveScaleAndLoc(void)
279 {
280    old_m_x = m_x;
281    old_m_y = m_y;
282    old_m_w = m_w;
283    old_m_h = m_h;
284 }
285 
286 //
287 // AM_restoreScaleAndLoc()
288 //
289 // restores the center and zoom from locally saved values
290 // Affects global variables for location and scale
291 //
292 // Passed nothing, returns nothing
293 //
AM_restoreScaleAndLoc(void)294 static void AM_restoreScaleAndLoc(void)
295 {
296   m_w = old_m_w;
297   m_h = old_m_h;
298   if (!(automapmode & am_follow))
299   {
300     m_x = old_m_x;
301     m_y = old_m_y;
302   }
303   else
304   {
305     m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;//e6y
306     m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;//e6y
307   }
308   m_x2 = m_x + m_w;
309   m_y2 = m_y + m_h;
310 
311   /* Change the scaling multipliers */
312   scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
313   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
314 }
315 
316 /*
317  * AM_addMark()
318  *
319  * Adds a marker at the current location
320  * Affects global variables for marked points
321  *
322  * Passed nothing, returns nothing
323 */
AM_addMark(void)324 static void AM_addMark(void)
325 {
326    if (markpointnum >= markpointnum_max)
327       markpoints = realloc(markpoints,
328             (markpointnum_max = markpointnum_max ?
329              markpointnum_max*2 : 16) * sizeof(*markpoints));
330 
331    markpoints[markpointnum].x = m_x + m_w/2;
332    markpoints[markpointnum].y = m_y + m_h/2;
333    markpointnum++;
334 }
335 
336 /*
337  * AM_findMinMaxBoundaries()
338  *
339  * Determines bounding box of all vertices,
340  * sets global variables controlling zoom range.
341  *
342  * Passed nothing, returns nothing
343 */
AM_findMinMaxBoundaries(void)344 static void AM_findMinMaxBoundaries(void)
345 {
346   int i;
347   fixed_t a;
348   fixed_t b;
349 
350   min_x = min_y =  INT_MAX;
351   max_x = max_y = -INT_MAX;
352 
353   for (i=0;i<numvertexes;i++)
354   {
355     if (vertexes[i].x < min_x)
356       min_x = vertexes[i].x;
357     else if (vertexes[i].x > max_x)
358       max_x = vertexes[i].x;
359 
360     if (vertexes[i].y < min_y)
361       min_y = vertexes[i].y;
362     else if (vertexes[i].y > max_y)
363       max_y = vertexes[i].y;
364   }
365 
366   max_w          = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS);//e6y
367   max_h          = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS);//e6y
368   min_w          = 2 * PLAYERRADIUS;
369   min_h          = 2 * PLAYERRADIUS;
370 
371   a              = FixedDiv(f_w<<FRACBITS, max_w);
372   b              = FixedDiv(f_h<<FRACBITS, max_h);
373   min_scale_mtof = a < b ? a : b;
374   max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
375 }
376 
377 //
378 // AM_changeWindowLoc()
379 //
380 // Moves the map window by the global variables m_paninc.x, m_paninc.y
381 //
382 // Passed nothing, returns nothing
383 //
AM_changeWindowLoc(void)384 static void AM_changeWindowLoc(void)
385 {
386   if (m_paninc.x || m_paninc.y)
387   {
388     automapmode &= ~am_follow;
389     f_oldloc.x = INT_MAX;
390   }
391 
392   m_x += m_paninc.x;
393   m_y += m_paninc.y;
394 
395   if (m_x + m_w/2 > max_x)
396     m_x = max_x - m_w/2;
397   else if (m_x + m_w/2 < min_x)
398     m_x = min_x - m_w/2;
399 
400   if (m_y + m_h/2 > max_y)
401     m_y = max_y - m_h/2;
402   else if (m_y + m_h/2 < min_y)
403     m_y = min_y - m_h/2;
404 
405   m_x2 = m_x + m_w;
406   m_y2 = m_y + m_h;
407 }
408 
409 
410 /*
411  * AM_initVariables()
412  *
413  * Initialize the variables for the automap
414  *
415  * Affects the automap global variables
416  * Status bar is notified that the automap has been entered
417  * Passed nothing, returns nothing
418 */
AM_initVariables(void)419 static void AM_initVariables(void)
420 {
421   int pnum;
422   static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 };
423 
424   automapmode |= am_active;
425 
426   f_oldloc.x   = INT_MAX;
427 
428   m_paninc.x   = m_paninc.y = 0;
429   ftom_zoommul = FRACUNIT;
430   mtof_zoommul = FRACUNIT;
431 
432   m_w          = FTOM(f_w);
433   m_h          = FTOM(f_h);
434 
435   /* find player to center on initially */
436   if (!playeringame[pnum = consoleplayer])
437   {
438      for (pnum=0;pnum<MAXPLAYERS;pnum++)
439      {
440         if (playeringame[pnum])
441            break;
442      }
443   }
444 
445   plr = &players[pnum];
446   m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;//e6y
447   m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;//e6y
448   AM_changeWindowLoc();
449 
450   /* for saving & restoring */
451   old_m_x = m_x;
452   old_m_y = m_y;
453   old_m_w = m_w;
454   old_m_h = m_h;
455 
456   /* inform the status bar of the change */
457   ST_Responder(&st_notify);
458 }
459 
460 /*
461  * AM_loadPics()
462 */
AM_loadPics(void)463 static void AM_loadPics(void)
464 {
465 }
466 
467 /*
468  * AM_unloadPics()
469 */
AM_unloadPics(void)470 static void AM_unloadPics(void)
471 {
472 }
473 
474 /*
475  * AM_clearMarks()
476  *
477  * Sets the number of marks to 0, thereby clearing them from the display
478  *
479  * Affects the global variable markpointnum
480  * Passed nothing, returns nothing
481 */
AM_clearMarks(void)482 void AM_clearMarks(void)
483 {
484   markpointnum = 0;
485 }
486 
487 /*
488  * AM_LevelInit()
489  *
490  * Initialize the automap at the start of a new level
491  * should be called at the start of every level
492  *
493  * Passed nothing, returns nothing
494  * Affects automap's global variables
495  *
496  * CPhipps - get status bar height from status bar code
497 */
AM_LevelInit(void)498 static void AM_LevelInit(void)
499 {
500   leveljuststarted = 0;
501 
502   f_x              = f_y = 0;
503   f_w              = SCREENWIDTH;
504   f_h              = SCREENHEIGHT-ST_SCALED_HEIGHT;
505 
506   AM_findMinMaxBoundaries();
507   scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
508   if (scale_mtof > max_scale_mtof)
509     scale_mtof = min_scale_mtof;
510   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
511 }
512 
513 /*
514  * AM_Stop()
515  *
516  * Cease automap operations, unload patches, notify status bar
517  *
518  * Passed nothing, returns nothing
519 */
AM_Stop(void)520 void AM_Stop (void)
521 {
522   static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 };
523 
524   AM_unloadPics();
525   automapmode &= ~am_active;
526   ST_Responder(&st_notify);
527   stopped = true;
528 }
529 
530 /*
531  * AM_Start()
532  *
533  * Start up automap operations,
534  *  if a new level, or game start, (re)initialize level variables
535  *  init map variables
536  *  load mark patches
537  *
538  * Passed nothing, returns nothing
539 */
AM_Start(void)540 void AM_Start(void)
541 {
542   static int lastlevel = -1, lastepisode = -1;
543 
544   if (!stopped)
545     AM_Stop();
546   stopped = false;
547 
548   if (lastlevel != gamemap || lastepisode != gameepisode)
549   {
550     AM_LevelInit();
551     lastlevel   = gamemap;
552     lastepisode = gameepisode;
553   }
554 
555   AM_initVariables();
556   AM_loadPics();
557 }
558 
559 /*
560  * AM_minOutWindowScale()
561  *
562  * Set the window scale to the maximum size
563  *
564  * Passed nothing, returns nothing
565 */
AM_minOutWindowScale(void)566 static void AM_minOutWindowScale(void)
567 {
568   scale_mtof = min_scale_mtof;
569   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
570   AM_activateNewScale();
571 }
572 
573 /*
574  * AM_maxOutWindowScale(void)
575  *
576  * Set the window scale to the minimum size
577  *
578  * Passed nothing, returns nothing
579 */
AM_maxOutWindowScale(void)580 static void AM_maxOutWindowScale(void)
581 {
582   scale_mtof = max_scale_mtof;
583   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
584   AM_activateNewScale();
585 }
586 
587 //
588 // AM_Responder()
589 //
590 // Handle events (user inputs) in automap mode
591 //
592 // Passed an input event, returns TRUE if its handled
593 //
AM_Responder(event_t * ev)594 dbool   AM_Responder
595 ( event_t*  ev )
596 {
597    //static int cheatstate=0;
598    static int bigstate=0;
599    int ch;                                                       // phares
600    int rc = FALSE;
601 
602    if (!(automapmode & am_active))
603    {
604       if (ev->type == ev_keydown && ev->data1 == key_map)         // phares
605       {
606          AM_Start ();
607          rc = TRUE;
608       }
609    }
610    else if (ev->type == ev_keydown)
611    {
612       rc = TRUE;
613       ch = ev->data1;                                             // phares
614       if (ch == key_map_right)                                    //    |
615          if (!(automapmode & am_follow))                           //    V
616             m_paninc.x = FTOM(F_PANINC);
617          else
618             rc = FALSE;
619       else if (ch == key_map_left)
620          if (!(automapmode & am_follow))
621             m_paninc.x = -FTOM(F_PANINC);
622          else
623             rc = FALSE;
624       else if (ch == key_map_up)
625          if (!(automapmode & am_follow))
626             m_paninc.y = FTOM(F_PANINC);
627          else
628             rc = FALSE;
629       else if (ch == key_map_down)
630          if (!(automapmode & am_follow))
631             m_paninc.y = -FTOM(F_PANINC);
632          else
633             rc = FALSE;
634       else if (ch == key_map_zoomout)
635       {
636          mtof_zoommul = M_ZOOMOUT;
637          ftom_zoommul = M_ZOOMIN;
638       }
639       else if (ch == key_map_zoomin)
640       {
641          mtof_zoommul = M_ZOOMIN;
642          ftom_zoommul = M_ZOOMOUT;
643       }
644       else if (ch == key_map)
645       {
646          bigstate = 0;
647          AM_Stop ();
648       }
649       else if (ch == key_map_gobig)
650       {
651          bigstate = !bigstate;
652          if (bigstate)
653          {
654             AM_saveScaleAndLoc();
655             AM_minOutWindowScale();
656          }
657          else
658             AM_restoreScaleAndLoc();
659       }
660       else if (ch == key_map_follow)
661       {
662          automapmode ^= am_follow;     // CPhipps - put all automap mode stuff into one enum
663          f_oldloc.x = INT_MAX;
664          // Ty 03/27/98 - externalized
665          plr->message = (automapmode & am_follow) ? s_AMSTR_FOLLOWON : s_AMSTR_FOLLOWOFF;
666       }
667       else if (ch == key_map_grid)
668       {
669          automapmode ^= am_grid;      // CPhipps
670          // Ty 03/27/98 - *not* externalized
671          plr->message = (automapmode & am_grid) ? s_AMSTR_GRIDON : s_AMSTR_GRIDOFF;
672       }
673       else if (ch == key_map_mark)
674       {
675          /* Ty 03/27/98 - *not* externalized
676           * cph 2001/11/20 - use doom_printf so we don't have our own buffer */
677          doom_printf("%s %d", s_AMSTR_MARKEDSPOT, markpointnum);
678          AM_addMark();
679       }
680       else if (ch == key_map_clear)
681       {
682          AM_clearMarks();  // Ty 03/27/98 - *not* externalized
683          plr->message = s_AMSTR_MARKSCLEARED;                      //    ^
684       }                                                           //    |
685       else if (ch == key_map_rotate) {
686          automapmode ^= am_rotate;
687          plr->message = (automapmode & am_rotate) ? s_AMSTR_ROTATEON : s_AMSTR_ROTATEOFF;
688       }
689       else if (ch == key_map_overlay) {
690          automapmode ^= am_overlay;
691          plr->message = (automapmode & am_overlay) ? s_AMSTR_OVERLAYON : s_AMSTR_OVERLAYOFF;
692       }
693       else                                                        // phares
694       {
695          //cheatstate=0;
696          rc = FALSE;
697       }
698    }
699    else if (ev->type == ev_keyup)
700    {
701       rc = FALSE;
702       ch = ev->data1;
703       if (ch == key_map_right)
704       {
705          if (!(automapmode & am_follow))
706             m_paninc.x = 0;
707       }
708       else if (ch == key_map_left)
709       {
710          if (!(automapmode & am_follow))
711             m_paninc.x = 0;
712       }
713       else if (ch == key_map_up)
714       {
715          if (!(automapmode & am_follow))
716             m_paninc.y = 0;
717       }
718       else if (ch == key_map_down)
719       {
720          if (!(automapmode & am_follow))
721             m_paninc.y = 0;
722       }
723       else if ((ch == key_map_zoomout) || (ch == key_map_zoomin))
724       {
725          mtof_zoommul = FRACUNIT;
726          ftom_zoommul = FRACUNIT;
727       }
728    }
729    return rc;
730 }
731 
732 //
733 // AM_rotate()
734 //
735 // Rotation in 2D.
736 // Used to rotate player arrow line character.
737 //
738 // Passed the coordinates of a point, and an angle
739 // Returns the coordinates rotated by the angle
740 //
741 // CPhipps - made static & enhanced for automap rotation
742 
AM_rotate(fixed_t * x,fixed_t * y,angle_t a,fixed_t xorig,fixed_t yorig)743 static void AM_rotate(fixed_t* x,  fixed_t* y, angle_t a, fixed_t xorig, fixed_t yorig)
744 {
745   fixed_t tmpx;
746 
747   //e6y
748   xorig>>=FRACTOMAPBITS;
749   yorig>>=FRACTOMAPBITS;
750 
751   tmpx =
752     FixedMul(*x - xorig,finecosine[a>>ANGLETOFINESHIFT])
753       - FixedMul(*y - yorig,finesine[a>>ANGLETOFINESHIFT]);
754 
755   *y   = yorig +
756     FixedMul(*x - xorig,finesine[a>>ANGLETOFINESHIFT])
757       + FixedMul(*y - yorig,finecosine[a>>ANGLETOFINESHIFT]);
758 
759   *x = tmpx + xorig;
760 }
761 
762 //
763 // AM_changeWindowScale()
764 //
765 // Automap zooming
766 //
767 // Passed nothing, returns nothing
768 //
AM_changeWindowScale(void)769 static void AM_changeWindowScale(void)
770 {
771   // Change the scaling multipliers
772   scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
773   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
774 
775   if (scale_mtof < min_scale_mtof)
776     AM_minOutWindowScale();
777   else if (scale_mtof > max_scale_mtof)
778     AM_maxOutWindowScale();
779   else
780     AM_activateNewScale();
781 }
782 
783 //
784 // AM_doFollowPlayer()
785 //
786 // Turn on follow mode - the map scrolls opposite to player motion
787 //
788 // Passed nothing, returns nothing
789 //
AM_doFollowPlayer(void)790 static void AM_doFollowPlayer(void)
791 {
792   if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
793   {
794     m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;//e6y
795     m_y = FTOM(MTOF(plr->mo->y >> FRACTOMAPBITS)) - m_h/2;//e6y
796     m_x2 = m_x + m_w;
797     m_y2 = m_y + m_h;
798     f_oldloc.x = plr->mo->x;
799     f_oldloc.y = plr->mo->y;
800   }
801 }
802 
803 //
804 // AM_Ticker()
805 //
806 // Updates on gametic - enter follow mode, zoom, or change map location
807 //
808 // Passed nothing, returns nothing
809 //
AM_Ticker(void)810 void AM_Ticker (void)
811 {
812   if (!(automapmode & am_active))
813     return;
814 
815   if (automapmode & am_follow)
816     AM_doFollowPlayer();
817 
818   // Change the zoom if necessary
819   if (ftom_zoommul != FRACUNIT)
820     AM_changeWindowScale();
821 
822   // Change x,y location
823   if (m_paninc.x || m_paninc.y)
824     AM_changeWindowLoc();
825 }
826 
827 //
828 // AM_clipMline()
829 //
830 // Automap clipping of lines.
831 //
832 // Based on Cohen-Sutherland clipping algorithm but with a slightly
833 // faster reject and precalculated slopes. If the speed is needed,
834 // use a hash algorithm to handle the common cases.
835 //
836 // Passed the line's coordinates on map and in the frame buffer performs
837 // clipping on them in the lines frame coordinates.
838 // Returns TRUE if any part of line was not clipped
839 //
AM_clipMline(mline_t * ml,fline_t * fl)840 static dbool   AM_clipMline
841 ( mline_t*  ml,
842   fline_t*  fl )
843 {
844   enum
845   {
846     LEFT    =1,
847     RIGHT   =2,
848     BOTTOM  =4,
849     TOP     =8
850   };
851 
852   register int outcode1 = 0;
853   register int outcode2 = 0;
854   register int outside;
855 
856   fpoint_t  tmp;
857   int   dx;
858   int   dy;
859 
860 
861 #define DOOUTCODE(oc, mx, my) \
862   (oc) = 0; \
863   if ((my) < 0) (oc) |= TOP; \
864   else if ((my) >= f_h) (oc) |= BOTTOM; \
865   if ((mx) < 0) (oc) |= LEFT; \
866   else if ((mx) >= f_w) (oc) |= RIGHT;
867 
868 
869   // do trivial rejects and outcodes
870   if (ml->a.y > m_y2)
871   outcode1 = TOP;
872   else if (ml->a.y < m_y)
873   outcode1 = BOTTOM;
874 
875   if (ml->b.y > m_y2)
876   outcode2 = TOP;
877   else if (ml->b.y < m_y)
878   outcode2 = BOTTOM;
879 
880   if (outcode1 & outcode2)
881   return FALSE; // trivially outside
882 
883   if (ml->a.x < m_x)
884   outcode1 |= LEFT;
885   else if (ml->a.x > m_x2)
886   outcode1 |= RIGHT;
887 
888   if (ml->b.x < m_x)
889   outcode2 |= LEFT;
890   else if (ml->b.x > m_x2)
891   outcode2 |= RIGHT;
892 
893   if (outcode1 & outcode2)
894   return FALSE; // trivially outside
895 
896   // transform to frame-buffer coordinates.
897   fl->a.x = CXMTOF(ml->a.x);
898   fl->a.y = CYMTOF(ml->a.y);
899   fl->b.x = CXMTOF(ml->b.x);
900   fl->b.y = CYMTOF(ml->b.y);
901 
902   DOOUTCODE(outcode1, fl->a.x, fl->a.y);
903   DOOUTCODE(outcode2, fl->b.x, fl->b.y);
904 
905   if (outcode1 & outcode2)
906   return FALSE;
907 
908   while (outcode1 | outcode2)
909   {
910     // may be partially inside box
911     // find an outside point
912     if (outcode1)
913       outside = outcode1;
914     else
915       outside = outcode2;
916 
917     // clip to each side
918     if (outside & TOP)
919     {
920       dy = fl->a.y - fl->b.y;
921       dx = fl->b.x - fl->a.x;
922       tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
923       tmp.y = 0;
924     }
925     else if (outside & BOTTOM)
926     {
927       dy = fl->a.y - fl->b.y;
928       dx = fl->b.x - fl->a.x;
929       tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
930       tmp.y = f_h-1;
931     }
932     else if (outside & RIGHT)
933     {
934       dy = fl->b.y - fl->a.y;
935       dx = fl->b.x - fl->a.x;
936       tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
937       tmp.x = f_w-1;
938     }
939     else if (outside & LEFT)
940     {
941       dy = fl->b.y - fl->a.y;
942       dx = fl->b.x - fl->a.x;
943       tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
944       tmp.x = 0;
945     }
946 
947     if (outside == outcode1)
948     {
949       fl->a = tmp;
950       DOOUTCODE(outcode1, fl->a.x, fl->a.y);
951     }
952     else
953     {
954       fl->b = tmp;
955       DOOUTCODE(outcode2, fl->b.x, fl->b.y);
956     }
957 
958     if (outcode1 & outcode2)
959       return FALSE; // trivially outside
960   }
961 
962   return TRUE;
963 }
964 #undef DOOUTCODE
965 
966 //
967 // AM_drawMline()
968 //
969 // Clip lines, draw visible parts of lines.
970 //
971 // Passed the map coordinates of the line, and the color to draw it
972 // Color -1 is special and prevents drawing. Color 247 is special and
973 // is translated to black, allowing Color 0 to represent feature disable
974 // in the defaults file.
975 // Returns nothing.
976 //
AM_drawMline(mline_t * ml,int color)977 static void AM_drawMline
978 ( mline_t*  ml,
979   int   color )
980 {
981   static fline_t fl;
982 
983   if (color==-1)  // jff 4/3/98 allow not drawing any sort of line
984     return;       // by setting its color to -1
985   if (color==247) // jff 4/3/98 if color is 247 (xparent), use black
986     color=0;
987 
988   if (AM_clipMline(ml, &fl))
989     V_DrawLine(&fl, color); // draws it on frame buffer using fb coords
990 }
991 
992 //
993 // AM_drawGrid()
994 //
995 // Draws blockmap aligned grid lines.
996 //
997 // Passed the color to draw the grid lines
998 // Returns nothing
999 //
AM_drawGrid(int color)1000 static void AM_drawGrid(int color)
1001 {
1002   fixed_t x, y;
1003   fixed_t start, end;
1004   mline_t ml;
1005 
1006   // Figure out start of vertical gridlines
1007   start = m_x;
1008   if ((start-bmaporgx)%(MAPBLOCKUNITS<<MAPBITS))//e6y
1009     start += (MAPBLOCKUNITS<<MAPBITS)//e6y
1010       - ((start-bmaporgx)%(MAPBLOCKUNITS<<MAPBITS));//e6y
1011   end = m_x + m_w;
1012 
1013   // draw vertical gridlines
1014   ml.a.y = m_y;
1015   ml.b.y = m_y+m_h;
1016   for (x=start; x<end; x+=(MAPBLOCKUNITS<<MAPBITS))//e6y
1017   {
1018     ml.a.x = x;
1019     ml.b.x = x;
1020     AM_drawMline(&ml, color);
1021   }
1022 
1023   // Figure out start of horizontal gridlines
1024   start = m_y;
1025   if ((start-bmaporgy)%(MAPBLOCKUNITS<<MAPBITS))//e6y
1026     start += (MAPBLOCKUNITS<<MAPBITS)//e6y
1027       - ((start-bmaporgy)%(MAPBLOCKUNITS<<MAPBITS));//e6y
1028   end = m_y + m_h;
1029 
1030   // draw horizontal gridlines
1031   ml.a.x = m_x;
1032   ml.b.x = m_x + m_w;
1033   for (y=start; y<end; y+=(MAPBLOCKUNITS<<MAPBITS))//e6y
1034   {
1035     ml.a.y = y;
1036     ml.b.y = y;
1037     AM_drawMline(&ml, color);
1038   }
1039 }
1040 
1041 //
1042 // AM_DoorColor()
1043 //
1044 // Returns the 'color' or key needed for a door linedef type
1045 //
1046 // Passed the type of linedef, returns:
1047 //   -1 if not a keyed door
1048 //    0 if a red key required
1049 //    1 if a blue key required
1050 //    2 if a yellow key required
1051 //    3 if a multiple keys required
1052 //
1053 // jff 4/3/98 add routine to get color of generalized keyed door
1054 //
AM_DoorColor(int type)1055 static int AM_DoorColor(int type)
1056 {
1057   if (GenLockedBase <= type && type< GenDoorBase)
1058   {
1059     type -= GenLockedBase;
1060     type = (type & LockedKey) >> LockedKeyShift;
1061     if (!type || type==7)
1062       return 3;  //any or all keys
1063     else return (type-1)%3;
1064   }
1065   switch (type)  // closed keyed door
1066   {
1067     case 26: case 32: case 99: case 133:
1068       /*bluekey*/
1069       return 1;
1070     case 27: case 34: case 136: case 137:
1071       /*yellowkey*/
1072       return 2;
1073     case 28: case 33: case 134: case 135:
1074       /*redkey*/
1075       return 0;
1076     default:
1077       return -1; //not a keyed door
1078   }
1079 }
1080 
1081 //
1082 // Determines visible lines, draws them.
1083 // This is LineDef based, not LineSeg based.
1084 //
1085 // jff 1/5/98 many changes in this routine
1086 // backward compatibility not needed, so just changes, no ifs
1087 // addition of clauses for:
1088 //    doors opening, keyed door id, secret sectors,
1089 //    teleports, exit lines, key things
1090 // ability to suppress any of added features or lines with no height changes
1091 //
1092 // support for gamma correction in automap abandoned
1093 //
1094 // jff 4/3/98 changed mapcolor_xxxx=0 as control to disable feature
1095 // jff 4/3/98 changed mapcolor_xxxx=-1 to disable drawing line completely
1096 //
AM_drawWalls(void)1097 static void AM_drawWalls(void)
1098 {
1099   int i;
1100   static mline_t l;
1101 
1102   // draw the unclipped visible portions of all lines
1103   for (i=0;i<numlines;i++)
1104   {
1105     l.a.x = lines[i].v1->x >> FRACTOMAPBITS;//e6y
1106     l.a.y = lines[i].v1->y >> FRACTOMAPBITS;//e6y
1107     l.b.x = lines[i].v2->x >> FRACTOMAPBITS;//e6y
1108     l.b.y = lines[i].v2->y >> FRACTOMAPBITS;//e6y
1109 
1110     if (automapmode & am_rotate) {
1111       AM_rotate(&l.a.x, &l.a.y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1112       AM_rotate(&l.b.x, &l.b.y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1113     }
1114 
1115     // if line has been seen or IDDT has been used
1116     if (ddt_cheating || (lines[i].flags & ML_MAPPED))
1117     {
1118       if ((lines[i].flags & ML_DONTDRAW) && !ddt_cheating)
1119         continue;
1120       {
1121         /* cph - show keyed doors and lines */
1122         int amd;
1123         if ((mapcolor_bdor || mapcolor_ydor || mapcolor_rdor) &&
1124             !(lines[i].flags & ML_SECRET) &&    /* non-secret */
1125           (amd = AM_DoorColor(lines[i].special)) != -1
1126         )
1127         {
1128           {
1129             switch (amd) /* closed keyed door */
1130             {
1131               case 1:
1132                 /*bluekey*/
1133                 AM_drawMline(&l,
1134                   mapcolor_bdor? mapcolor_bdor : mapcolor_cchg);
1135                 continue;
1136               case 2:
1137                 /*yellowkey*/
1138                 AM_drawMline(&l,
1139                   mapcolor_ydor? mapcolor_ydor : mapcolor_cchg);
1140                 continue;
1141               case 0:
1142                 /*redkey*/
1143                 AM_drawMline(&l,
1144                   mapcolor_rdor? mapcolor_rdor : mapcolor_cchg);
1145                 continue;
1146               case 3:
1147                 /*any or all*/
1148                 AM_drawMline(&l,
1149                   mapcolor_clsd? mapcolor_clsd : mapcolor_cchg);
1150                 continue;
1151             }
1152           }
1153         }
1154       }
1155       if /* jff 4/23/98 add exit lines to automap */
1156         (
1157           mapcolor_exit &&
1158           (
1159             lines[i].special==11 ||
1160             lines[i].special==52 ||
1161             lines[i].special==197 ||
1162             lines[i].special==51  ||
1163             lines[i].special==124 ||
1164             lines[i].special==198
1165           )
1166         ) {
1167           AM_drawMline(&l, mapcolor_exit); /* exit line */
1168           continue;
1169         }
1170 
1171       if (!lines[i].backsector)
1172       {
1173         // jff 1/10/98 add new color for 1S secret sector boundary
1174         if (mapcolor_secr && //jff 4/3/98 0 is disable
1175             (
1176              (
1177               map_secret_after &&
1178               P_WasSecret(lines[i].frontsector) &&
1179               !P_IsSecret(lines[i].frontsector)
1180              )
1181              ||
1182              (
1183               !map_secret_after &&
1184               P_WasSecret(lines[i].frontsector)
1185              )
1186             )
1187           )
1188           AM_drawMline(&l, mapcolor_secr); // line bounding secret sector
1189         else                               //jff 2/16/98 fixed bug
1190           AM_drawMline(&l, mapcolor_wall); // special was cleared
1191       }
1192       else /* now for 2S lines */
1193       {
1194         // jff 1/10/98 add color change for all teleporter types
1195         if
1196         (
1197             mapcolor_tele && !(lines[i].flags & ML_SECRET) &&
1198             (lines[i].special == 39 || lines[i].special == 97 ||
1199             lines[i].special == 125 || lines[i].special == 126)
1200         )
1201         { // teleporters
1202           AM_drawMline(&l, mapcolor_tele);
1203         }
1204         else if (lines[i].flags & ML_SECRET)    // secret door
1205         {
1206           AM_drawMline(&l, mapcolor_wall);      // wall color
1207         }
1208         else if
1209         (
1210             mapcolor_clsd &&
1211             !(lines[i].flags & ML_SECRET) &&    // non-secret closed door
1212             ((lines[i].backsector->floorheight==lines[i].backsector->ceilingheight) ||
1213             (lines[i].frontsector->floorheight==lines[i].frontsector->ceilingheight))
1214         )
1215         {
1216           AM_drawMline(&l, mapcolor_clsd);      // non-secret closed door
1217         } //jff 1/6/98 show secret sector 2S lines
1218         else if
1219         (
1220             mapcolor_secr && //jff 2/16/98 fixed bug
1221             (                    // special was cleared after getting it
1222               (map_secret_after &&
1223                (
1224                 (P_WasSecret(lines[i].frontsector)
1225                  && !P_IsSecret(lines[i].frontsector)) ||
1226                 (P_WasSecret(lines[i].backsector)
1227                  && !P_IsSecret(lines[i].backsector))
1228                )
1229               )
1230               ||  //jff 3/9/98 add logic to not show secret til after entered
1231               (   // if map_secret_after is TRUE
1232                 !map_secret_after &&
1233                  (P_WasSecret(lines[i].frontsector) ||
1234                   P_WasSecret(lines[i].backsector))
1235               )
1236             )
1237         )
1238         {
1239           AM_drawMline(&l, mapcolor_secr); // line bounding secret sector
1240         } //jff 1/6/98 end secret sector line change
1241         else if (lines[i].backsector->floorheight !=
1242                   lines[i].frontsector->floorheight)
1243         {
1244           AM_drawMline(&l, mapcolor_fchg); // floor level change
1245         }
1246         else if (lines[i].backsector->ceilingheight !=
1247                   lines[i].frontsector->ceilingheight)
1248         {
1249           AM_drawMline(&l, mapcolor_cchg); // ceiling level change
1250         }
1251         else if (mapcolor_flat && ddt_cheating)
1252         {
1253           AM_drawMline(&l, mapcolor_flat); //2S lines that appear only in IDDT
1254         }
1255       }
1256     } // now draw the lines only visible because the player has computermap
1257     else if (plr->powers[pw_allmap]) // computermap visible lines
1258     {
1259       if (!(lines[i].flags & ML_DONTDRAW)) // invisible flag lines do not show
1260       {
1261         if
1262         (
1263           mapcolor_flat
1264           ||
1265           !lines[i].backsector
1266           ||
1267           lines[i].backsector->floorheight
1268           != lines[i].frontsector->floorheight
1269           ||
1270           lines[i].backsector->ceilingheight
1271           != lines[i].frontsector->ceilingheight
1272         )
1273           AM_drawMline(&l, mapcolor_unsn);
1274       }
1275     }
1276   }
1277 }
1278 
1279 //
1280 // AM_drawLineCharacter()
1281 //
1282 // Draws a vector graphic according to numerous parameters
1283 //
1284 // Passed the structure defining the vector graphic shape, the number
1285 // of vectors in it, the scale to draw it at, the angle to draw it at,
1286 // the color to draw it with, and the map coordinates to draw it at.
1287 // Returns nothing
1288 //
AM_drawLineCharacter(mline_t * lineguy,int lineguylines,fixed_t scale,angle_t angle,int color,fixed_t x,fixed_t y)1289 static void AM_drawLineCharacter
1290 ( mline_t*  lineguy,
1291   int   lineguylines,
1292   fixed_t scale,
1293   angle_t angle,
1294   int   color,
1295   fixed_t x,
1296   fixed_t y )
1297 {
1298   int   i;
1299   mline_t l;
1300 
1301   if (automapmode & am_rotate) angle -= plr->mo->angle - ANG90; // cph
1302 
1303   for (i=0;i<lineguylines;i++)
1304   {
1305     l.a.x = lineguy[i].a.x;
1306     l.a.y = lineguy[i].a.y;
1307 
1308     if (scale)
1309     {
1310       l.a.x = FixedMul(scale, l.a.x);
1311       l.a.y = FixedMul(scale, l.a.y);
1312     }
1313 
1314     if (angle)
1315       AM_rotate(&l.a.x, &l.a.y, angle, 0, 0);
1316 
1317     l.a.x += x;
1318     l.a.y += y;
1319 
1320     l.b.x = lineguy[i].b.x;
1321     l.b.y = lineguy[i].b.y;
1322 
1323     if (scale)
1324     {
1325       l.b.x = FixedMul(scale, l.b.x);
1326       l.b.y = FixedMul(scale, l.b.y);
1327     }
1328 
1329     if (angle)
1330       AM_rotate(&l.b.x, &l.b.y, angle, 0, 0);
1331 
1332     l.b.x += x;
1333     l.b.y += y;
1334 
1335     AM_drawMline(&l, color);
1336   }
1337 }
1338 
1339 //
1340 // AM_drawPlayers()
1341 //
1342 // Draws the player arrow in single player,
1343 // or all the player arrows in a netgame.
1344 //
1345 // Passed nothing, returns nothing
1346 //
AM_drawPlayers(void)1347 static void AM_drawPlayers(void)
1348 {
1349   int   i;
1350 
1351   if (!netgame)
1352   {
1353     if (ddt_cheating)
1354       AM_drawLineCharacter
1355       (
1356         cheat_player_arrow,
1357         NUMCHEATPLYRLINES,
1358         0,
1359         plr->mo->angle,
1360         mapcolor_sngl,      //jff color
1361         plr->mo->x >> FRACTOMAPBITS,//e6y
1362         plr->mo->y >> FRACTOMAPBITS//e6y
1363       );
1364     else
1365       AM_drawLineCharacter
1366       (
1367         player_arrow,
1368         NUMPLYRLINES,
1369         0,
1370         plr->mo->angle,
1371         mapcolor_sngl,      //jff color
1372         plr->mo->x >> FRACTOMAPBITS,//e6y
1373         plr->mo->y >> FRACTOMAPBITS);//e6y
1374     return;
1375   }
1376 
1377   for (i=0;i<MAXPLAYERS;i++) {
1378     player_t* p = &players[i];
1379 
1380     if ( (deathmatch && !demoplayback) && p != plr)
1381       continue;
1382 
1383     if (playeringame[i]) {
1384       fixed_t x = p->mo->x >> FRACTOMAPBITS, y = p->mo->y >> FRACTOMAPBITS;//e6y
1385       if (automapmode & am_rotate)
1386         AM_rotate(&x, &y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1387 
1388       AM_drawLineCharacter (player_arrow, NUMPLYRLINES, 0, p->mo->angle,
1389           p->powers[pw_invisibility] ? 246 /* *close* to black */
1390           : mapcolor_plyr[i], //jff 1/6/98 use default color
1391           x, y);
1392     }
1393   }
1394 }
1395 
1396 /*
1397  * AM_drawThings()
1398  *
1399  * Draws the things on the automap in double IDDT cheat mode
1400  *
1401  * Passed colors and colorrange, no longer used
1402  * Returns nothing
1403 */
AM_drawThings(void)1404 static void AM_drawThings(void)
1405 {
1406    int   i;
1407    mobj_t* t;
1408 
1409    // for all sectors
1410    for (i=0;i<numsectors;i++)
1411    {
1412       t = sectors[i].thinglist;
1413 
1414       while (t) // for all things in that sector
1415       {
1416          fixed_t x = t->x >> FRACTOMAPBITS, y = t->y >> FRACTOMAPBITS;//e6y
1417 
1418          if (automapmode & am_rotate)
1419             AM_rotate(&x, &y, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1420 
1421          //jff 1/5/98 case over doomednum of thing being drawn
1422          if (mapcolor_rkey || mapcolor_ykey || mapcolor_bkey)
1423          {
1424             switch(t->info->doomednum)
1425             {
1426                //jff 1/5/98 treat keys special
1427                case 38: case 13: //jff  red key
1428                   AM_drawLineCharacter
1429                      (
1430                       cross_mark,
1431                       NUMCROSSMARKLINES,
1432                       16<<MAPBITS,//e6y
1433                       t->angle,
1434                       mapcolor_rkey!=-1? mapcolor_rkey : mapcolor_sprt,
1435                       x, y
1436                      );
1437                   t = t->snext;
1438                   continue;
1439                case 39: case 6: //jff yellow key
1440                   AM_drawLineCharacter
1441                      (
1442                       cross_mark,
1443                       NUMCROSSMARKLINES,
1444                       16<<MAPBITS,//e6y
1445                       t->angle,
1446                       mapcolor_ykey!=-1? mapcolor_ykey : mapcolor_sprt,
1447                       x, y
1448                      );
1449                   t = t->snext;
1450                   continue;
1451                case 40: case 5: //jff blue key
1452                   AM_drawLineCharacter
1453                      (
1454                       cross_mark,
1455                       NUMCROSSMARKLINES,
1456                       16<<MAPBITS,//e6y
1457                       t->angle,
1458                       mapcolor_bkey!=-1? mapcolor_bkey : mapcolor_sprt,
1459                       x, y
1460                      );
1461                   t = t->snext;
1462                   continue;
1463                default:
1464                   break;
1465             }
1466          }
1467          //jff 1/5/98 end added code for keys
1468          //jff previously entire code
1469          AM_drawLineCharacter
1470             (
1471              thintriangle_guy,
1472              NUMTHINTRIANGLEGUYLINES,
1473              16<<MAPBITS,//e6y
1474              t->angle,
1475              t->flags & MF_FRIEND && !t->player ? mapcolor_frnd :
1476              /* cph 2006/07/30 - Show count-as-kills in red. */
1477              ((t->flags & (MF_COUNTKILL | MF_CORPSE)) == MF_COUNTKILL) ? mapcolor_enemy :
1478              /* bbm 2/28/03 Show countable items in yellow. */
1479              t->flags & MF_COUNTITEM ? mapcolor_item : mapcolor_sprt,
1480              x, y
1481             );
1482          t = t->snext;
1483       }
1484    }
1485 }
1486 
1487 /*
1488  * AM_drawMarks()
1489  *
1490  * Draw the marked locations on the automap
1491  *
1492  * Passed nothing, returns nothing
1493  *
1494  * killough 2/22/98:
1495  * Rewrote AM_drawMarks(). Removed limit on marks.
1496 */
AM_drawMarks(void)1497 static void AM_drawMarks(void)
1498 {
1499   int i;
1500 
1501   for (i=0;i<markpointnum;i++) // killough 2/22/98: remove automap mark limit
1502   {
1503      if (markpoints[i].x == -1)
1504         continue;
1505 
1506      {
1507         int w = 5;
1508         int h = 6;
1509         int fx = markpoints[i].x;
1510         int fy = markpoints[i].y;
1511         int j = i;
1512 
1513         if (automapmode & am_rotate)
1514            AM_rotate(&fx, &fy, ANG90-plr->mo->angle, plr->mo->x, plr->mo->y);
1515 
1516         fx = CXMTOF(fx); fy = CYMTOF(fy);
1517 
1518         do
1519         {
1520            int d = j % 10;
1521            if (d==1)           // killough 2/22/98: less spacing for '1'
1522               fx++;
1523 
1524            if (fx >= f_x && fx < f_w - w && fy >= f_y && fy < f_h - h) {
1525               // cph - construct patch name and draw marker
1526               char namebuf[] = { 'A', 'M', 'M', 'N', 'U', 'M', '0'+d, 0 };
1527 
1528               V_DrawNamePatch(fx, fy, FB, namebuf, CR_DEFAULT, VPT_NONE);
1529            }
1530            fx -= w-1;          // killough 2/22/98: 1 space backwards
1531            j /= 10;
1532         }
1533         while (j>0);
1534      }
1535   }
1536 }
1537 
1538 /*
1539  * AM_drawCrosshair()
1540  *
1541  * Draw the single point crosshair representing map center
1542  *
1543  * Passed the color to draw the pixel with
1544  * Returns nothing
1545  *
1546 */
1547 
AM_drawCrosshair(int color)1548 static INLINE void AM_drawCrosshair(int color)
1549 {
1550    fline_t line;
1551 
1552    line.a.x = (f_w/2)-1;
1553    line.a.y = (f_h/2);
1554    line.b.x = (f_w/2)+1;
1555    line.b.y = (f_h/2);
1556    V_DrawLine(&line, color);
1557 
1558    line.a.x = (f_w/2);
1559    line.a.y = (f_h/2)-1;
1560    line.b.x = (f_w/2);
1561    line.b.y = (f_h/2)+1;
1562    V_DrawLine(&line, color);
1563 }
1564 
1565 //
1566 // AM_Drawer()
1567 //
1568 // Draws the entire automap
1569 //
1570 // Passed nothing, returns nothing
1571 //
AM_Drawer(void)1572 void AM_Drawer (void)
1573 {
1574   if (!(automapmode & am_active))
1575      return;
1576 
1577   if (!(automapmode & am_overlay)) // cph - If not overlay mode, clear background for the automap
1578     V_FillRect(f_x, f_y, f_w, f_h, (uint8_t)mapcolor_back); //jff 1/5/98 background default color
1579   if (automapmode & am_grid)
1580     AM_drawGrid(mapcolor_grid);      //jff 1/7/98 grid default color
1581   AM_drawWalls();
1582   AM_drawPlayers();
1583   if (ddt_cheating==2)
1584     AM_drawThings(); //jff 1/5/98 default double IDDT sprite
1585   AM_drawCrosshair(mapcolor_hair);   //jff 1/7/98 default crosshair color
1586 
1587   AM_drawMarks();
1588 }
1589