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