1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
4 // Copyright(C) 1993-1996 Id Software, Inc.
5 // Copyright(C) 2005 Simon Howard
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 // DESCRIPTION: the automap code
25 //-----------------------------------------------------------------------------
41 // Needs access to LFB.
54 // For use if I do walls with outsides/insides
55 #define REDS (256-5*16)
57 #define BLUES (256-4*16+8)
65 #define YELLOWS (256-32+7)
68 #define WHITE (256-47)
71 #define BACKGROUND BLACK
72 #define YOURCOLORS WHITE
74 #define WALLCOLORS REDS
75 #define WALLRANGE REDRANGE
76 #define TSWALLCOLORS GRAYS
77 #define TSWALLRANGE GRAYSRANGE
78 #define FDWALLCOLORS BROWNS
79 #define FDWALLRANGE BROWNRANGE
80 #define CDWALLCOLORS YELLOWS
81 #define CDWALLRANGE YELLOWRANGE
82 #define THINGCOLORS GREENS
83 #define THINGRANGE GREENRANGE
84 #define SECRETWALLCOLORS WALLCOLORS
85 #define SECRETWALLRANGE WALLRANGE
86 #define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
88 #define XHAIRCOLORS GRAYS
93 int key_map_north
= KEY_UPARROW
;
94 int key_map_south
= KEY_DOWNARROW
;
95 int key_map_east
= KEY_RIGHTARROW
;
96 int key_map_west
= KEY_LEFTARROW
;
97 int key_map_zoomin
= '=';
98 int key_map_zoomout
= '-';
99 int key_map_toggle
= KEY_TAB
;
100 int key_map_maxzoom
= '0';
101 int key_map_follow
= 'f';
102 int key_map_grid
= 'g';
103 int key_map_mark
= 'm';
104 int key_map_clearmark
= 'c';
106 #define AM_NUMMARKPOINTS 10
109 #define INITSCALEMTOF (.2*FRACUNIT)
110 // how much the automap moves window per tic in frame-buffer coordinates
111 // moves 140 pixels in 1 second
113 // how much zoom-in per tic
114 // goes to 2x in 1 second
115 #define M_ZOOMIN ((int) (1.02*FRACUNIT))
116 // how much zoom-out per tic
117 // pulls out to 0.5x in 1 second
118 #define M_ZOOMOUT ((int) (FRACUNIT/1.02))
120 // translates between frame-buffer and map distances
121 #define FTOM(x) FixedMul(((x)<<16),scale_ftom)
122 #define MTOF(x) (FixedMul((x),scale_mtof)>>16)
123 // translates between frame-buffer and map coordinates
124 #define CXMTOF(x) (f_x + MTOF((x)-m_x))
125 #define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y)))
127 // the following is crap
128 #define LINE_NEVERSEE ML_DONTDRAW
158 // The vector graphics for the automap.
159 // A line drawing of the player pointing right,
160 // starting from the middle.
162 #define R ((8*PLAYERRADIUS)/7)
163 mline_t player_arrow
[] = {
164 { { -R
+R
/8, 0 }, { R
, 0 } }, // -----
165 { { R
, 0 }, { R
-R
/2, R
/4 } }, // ----->
166 { { R
, 0 }, { R
-R
/2, -R
/4 } },
167 { { -R
+R
/8, 0 }, { -R
-R
/8, R
/4 } }, // >---->
168 { { -R
+R
/8, 0 }, { -R
-R
/8, -R
/4 } },
169 { { -R
+3*R
/8, 0 }, { -R
+R
/8, R
/4 } }, // >>--->
170 { { -R
+3*R
/8, 0 }, { -R
+R
/8, -R
/4 } }
174 #define R ((8*PLAYERRADIUS)/7)
175 mline_t cheat_player_arrow
[] = {
176 { { -R
+R
/8, 0 }, { R
, 0 } }, // -----
177 { { R
, 0 }, { R
-R
/2, R
/6 } }, // ----->
178 { { R
, 0 }, { R
-R
/2, -R
/6 } },
179 { { -R
+R
/8, 0 }, { -R
-R
/8, R
/6 } }, // >----->
180 { { -R
+R
/8, 0 }, { -R
-R
/8, -R
/6 } },
181 { { -R
+3*R
/8, 0 }, { -R
+R
/8, R
/6 } }, // >>----->
182 { { -R
+3*R
/8, 0 }, { -R
+R
/8, -R
/6 } },
183 { { -R
/2, 0 }, { -R
/2, -R
/6 } }, // >>-d--->
184 { { -R
/2, -R
/6 }, { -R
/2+R
/6, -R
/6 } },
185 { { -R
/2+R
/6, -R
/6 }, { -R
/2+R
/6, R
/4 } },
186 { { -R
/6, 0 }, { -R
/6, -R
/6 } }, // >>-dd-->
187 { { -R
/6, -R
/6 }, { 0, -R
/6 } },
188 { { 0, -R
/6 }, { 0, R
/4 } },
189 { { R
/6, R
/4 }, { R
/6, -R
/7 } }, // >>-ddt->
190 { { R
/6, -R
/7 }, { R
/6+R
/32, -R
/7-R
/32 } },
191 { { R
/6+R
/32, -R
/7-R
/32 }, { R
/6+R
/10, -R
/7 } }
196 mline_t triangle_guy
[] = {
197 { { (fixed_t
)(-.867*R
), (fixed_t
)(-.5*R
) }, { (fixed_t
)(.867*R
), (fixed_t
)(-.5*R
) } },
198 { { (fixed_t
)(.867*R
), (fixed_t
)(-.5*R
) }, { (fixed_t
)(0 ), (fixed_t
)(R
) } },
199 { { (fixed_t
)(0 ), (fixed_t
)(R
) }, { (fixed_t
)(-.867*R
), (fixed_t
)(-.5*R
) } }
204 mline_t thintriangle_guy
[] = {
205 { { (fixed_t
)(-.5*R
), (fixed_t
)(-.7*R
) }, { (fixed_t
)(R
), (fixed_t
)(0 ) } },
206 { { (fixed_t
)(R
), (fixed_t
)(0 ) }, { (fixed_t
)(-.5*R
), (fixed_t
)(.7*R
) } },
207 { { (fixed_t
)(-.5*R
), (fixed_t
)(.7*R
) }, { (fixed_t
)(-.5*R
), (fixed_t
)(-.7*R
) } }
214 static int cheating
= 0;
217 static int leveljuststarted
= 1; // kluge until AM_LevelInit() is called
219 boolean automapactive
= false;
220 static int finit_width
= SCREENWIDTH
;
221 static int finit_height
= SCREENHEIGHT
- 32;
223 // location of window on screen
227 // size of window on screen
231 static int lightlev
; // used for funky strobing effect
232 static byte
* fb
; // pseudo-frame buffer
235 static mpoint_t m_paninc
; // how far the window pans each tic (map coords)
236 static fixed_t mtof_zoommul
; // how far the window zooms in each tic (map coords)
237 static fixed_t ftom_zoommul
; // how far the window zooms in each tic (fb coords)
239 static fixed_t m_x
, m_y
; // LL x,y where the window is on the map (map coords)
240 static fixed_t m_x2
, m_y2
; // UR x,y where the window is on the map (map coords)
243 // width/height of window on map (map coords)
248 // based on level size
249 static fixed_t min_x
;
250 static fixed_t min_y
;
251 static fixed_t max_x
;
252 static fixed_t max_y
;
254 static fixed_t max_w
; // max_x-min_x,
255 static fixed_t max_h
; // max_y-min_y
257 // based on player size
258 static fixed_t min_w
;
259 static fixed_t min_h
;
262 static fixed_t min_scale_mtof
; // used to tell when to stop zooming out
263 static fixed_t max_scale_mtof
; // used to tell when to stop zooming in
265 // old stuff for recovery later
266 static fixed_t old_m_w
, old_m_h
;
267 static fixed_t old_m_x
, old_m_y
;
269 // old location used by the Follower routine
270 static mpoint_t f_oldloc
;
272 // used by MTOF to scale from map-to-frame-buffer coords
273 static fixed_t scale_mtof
= (fixed_t
)INITSCALEMTOF
;
274 // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
275 static fixed_t scale_ftom
;
277 static player_t
*plr
; // the player represented by an arrow
279 static patch_t
*marknums
[10]; // numbers used for marking by the automap
280 static mpoint_t markpoints
[AM_NUMMARKPOINTS
]; // where the points are
281 static int markpointnum
= 0; // next point to be assigned
283 static int followplayer
= 1; // specifies whether to follow the player around
285 cheatseq_t cheat_amap
= CHEAT("iddt", 0);
287 static boolean stopped
= true;
289 extern boolean viewactive
;
290 //extern byte screens[][SCREENWIDTH*SCREENHEIGHT];
301 // Calculates the slope and slope according to the x-axis of a line
302 // segment in map coordinates (with the upright y-axis n' all) so
303 // that it can be used with the brain-dead drawing stuff.
312 dy
= ml
->a
.y
- ml
->b
.y
;
313 dx
= ml
->b
.x
- ml
->a
.x
;
314 if (!dy
) is
->islp
= (dx
<0?-INT_MAX
:INT_MAX
);
315 else is
->islp
= FixedDiv(dx
, dy
);
316 if (!dx
) is
->slp
= (dy
<0?-INT_MAX
:INT_MAX
);
317 else is
->slp
= FixedDiv(dy
, dx
);
324 void AM_activateNewScale(void)
339 void AM_saveScaleAndLoc(void)
350 void AM_restoreScaleAndLoc(void)
360 m_x
= plr
->mo
->x
- m_w
/2;
361 m_y
= plr
->mo
->y
- m_h
/2;
366 // Change the scaling multipliers
367 scale_mtof
= FixedDiv(f_w
<<FRACBITS
, m_w
);
368 scale_ftom
= FixedDiv(FRACUNIT
, scale_mtof
);
372 // adds a marker at the current location
374 void AM_addMark(void)
376 markpoints
[markpointnum
].x
= m_x
+ m_w
/2;
377 markpoints
[markpointnum
].y
= m_y
+ m_h
/2;
378 markpointnum
= (markpointnum
+ 1) % AM_NUMMARKPOINTS
;
383 // Determines bounding box of all vertices,
384 // sets global variables controlling zoom range.
386 void AM_findMinMaxBoundaries(void)
392 min_x
= min_y
= INT_MAX
;
393 max_x
= max_y
= -INT_MAX
;
395 for (i
=0;i
<numvertexes
;i
++)
397 if (vertexes
[i
].x
< min_x
)
398 min_x
= vertexes
[i
].x
;
399 else if (vertexes
[i
].x
> max_x
)
400 max_x
= vertexes
[i
].x
;
402 if (vertexes
[i
].y
< min_y
)
403 min_y
= vertexes
[i
].y
;
404 else if (vertexes
[i
].y
> max_y
)
405 max_y
= vertexes
[i
].y
;
408 max_w
= max_x
- min_x
;
409 max_h
= max_y
- min_y
;
411 min_w
= 2*PLAYERRADIUS
; // const? never changed?
412 min_h
= 2*PLAYERRADIUS
;
414 a
= FixedDiv(f_w
<<FRACBITS
, max_w
);
415 b
= FixedDiv(f_h
<<FRACBITS
, max_h
);
417 min_scale_mtof
= a
< b
? a
: b
;
418 max_scale_mtof
= FixedDiv(f_h
<<FRACBITS
, 2*PLAYERRADIUS
);
426 void AM_changeWindowLoc(void)
428 if (m_paninc
.x
|| m_paninc
.y
)
431 f_oldloc
.x
= INT_MAX
;
437 if (m_x
+ m_w
/2 > max_x
)
439 else if (m_x
+ m_w
/2 < min_x
)
442 if (m_y
+ m_h
/2 > max_y
)
444 else if (m_y
+ m_h
/2 < min_y
)
455 void AM_initVariables(void)
458 static event_t st_notify
= { ev_keyup
, AM_MSGENTERED
, 0, 0 };
460 automapactive
= true;
463 f_oldloc
.x
= INT_MAX
;
467 m_paninc
.x
= m_paninc
.y
= 0;
468 ftom_zoommul
= FRACUNIT
;
469 mtof_zoommul
= FRACUNIT
;
474 // find player to center on initially
475 if (playeringame
[consoleplayer
])
477 plr
= &players
[consoleplayer
];
483 for (pnum
=0;pnum
<MAXPLAYERS
;pnum
++)
485 if (playeringame
[pnum
])
487 plr
= &players
[pnum
];
493 m_x
= plr
->mo
->x
- m_w
/2;
494 m_y
= plr
->mo
->y
- m_h
/2;
495 AM_changeWindowLoc();
497 // for saving & restoring
503 // inform the status bar of the change
504 ST_Responder(&st_notify
);
511 void AM_loadPics(void)
518 sprintf(namebuf
, DEH_String("AMMNUM%d"), i
);
519 marknums
[i
] = W_CacheLumpName(namebuf
, PU_STATIC
);
524 void AM_unloadPics(void)
531 sprintf(namebuf
, DEH_String("AMMNUM%d"), i
);
532 W_ReleaseLumpName(namebuf
);
536 void AM_clearMarks(void)
540 for (i
=0;i
<AM_NUMMARKPOINTS
;i
++)
541 markpoints
[i
].x
= -1; // means empty
546 // should be called at the start of every level
547 // right now, i figure it out myself
549 void AM_LevelInit(void)
551 leveljuststarted
= 0;
559 AM_findMinMaxBoundaries();
560 scale_mtof
= FixedDiv(min_scale_mtof
, (int) (0.7*FRACUNIT
));
561 if (scale_mtof
> max_scale_mtof
)
562 scale_mtof
= min_scale_mtof
;
563 scale_ftom
= FixedDiv(FRACUNIT
, scale_mtof
);
574 static event_t st_notify
= { 0, ev_keyup
, AM_MSGEXITED
, 0 };
577 automapactive
= false;
578 ST_Responder(&st_notify
);
587 static int lastlevel
= -1, lastepisode
= -1;
589 if (!stopped
) AM_Stop();
591 if (lastlevel
!= gamemap
|| lastepisode
!= gameepisode
)
595 lastepisode
= gameepisode
;
602 // set the window scale to the maximum size
604 void AM_minOutWindowScale(void)
606 scale_mtof
= min_scale_mtof
;
607 scale_ftom
= FixedDiv(FRACUNIT
, scale_mtof
);
608 AM_activateNewScale();
612 // set the window scale to the minimum size
614 void AM_maxOutWindowScale(void)
616 scale_mtof
= max_scale_mtof
;
617 scale_ftom
= FixedDiv(FRACUNIT
, scale_mtof
);
618 AM_activateNewScale();
623 // Handle events (user inputs) in automap mode
631 static int cheatstate
=0;
632 static int bigstate
=0;
633 static char buffer
[20];
640 if (ev
->type
== ev_keydown
&& ev
->data1
== key_map_toggle
)
647 else if (ev
->type
== ev_keydown
)
652 if (key
== key_map_east
) // pan right
654 if (!followplayer
) m_paninc
.x
= FTOM(F_PANINC
);
657 else if (key
== key_map_west
) // pan left
659 if (!followplayer
) m_paninc
.x
= -FTOM(F_PANINC
);
662 else if (key
== key_map_north
) // pan up
664 if (!followplayer
) m_paninc
.y
= FTOM(F_PANINC
);
667 else if (key
== key_map_south
) // pan down
669 if (!followplayer
) m_paninc
.y
= -FTOM(F_PANINC
);
672 else if (key
== key_map_zoomout
) // zoom out
674 mtof_zoommul
= M_ZOOMOUT
;
675 ftom_zoommul
= M_ZOOMIN
;
677 else if (key
== key_map_zoomin
) // zoom in
679 mtof_zoommul
= M_ZOOMIN
;
680 ftom_zoommul
= M_ZOOMOUT
;
682 else if (key
== key_map_toggle
)
688 else if (key
== key_map_maxzoom
)
690 bigstate
= !bigstate
;
693 AM_saveScaleAndLoc();
694 AM_minOutWindowScale();
696 else AM_restoreScaleAndLoc();
698 else if (key
== key_map_follow
)
700 followplayer
= !followplayer
;
701 f_oldloc
.x
= INT_MAX
;
703 plr
->message
= DEH_String(AMSTR_FOLLOWON
);
705 plr
->message
= DEH_String(AMSTR_FOLLOWOFF
);
707 else if (key
== key_map_grid
)
711 plr
->message
= DEH_String(AMSTR_GRIDON
);
713 plr
->message
= DEH_String(AMSTR_GRIDOFF
);
715 else if (key
== key_map_mark
)
717 sprintf(buffer
, "%s %d", DEH_String(AMSTR_MARKEDSPOT
), markpointnum
);
718 plr
->message
= buffer
;
721 else if (key
== key_map_clearmark
)
724 plr
->message
= DEH_String(AMSTR_MARKSCLEARED
);
732 if (!deathmatch
&& cht_CheckCheat(&cheat_amap
, ev
->data2
))
735 cheating
= (cheating
+1) % 3;
738 else if (ev
->type
== ev_keyup
)
743 if (key
== key_map_east
)
745 if (!followplayer
) m_paninc
.x
= 0;
747 else if (key
== key_map_west
)
749 if (!followplayer
) m_paninc
.x
= 0;
751 else if (key
== key_map_north
)
753 if (!followplayer
) m_paninc
.y
= 0;
755 else if (key
== key_map_south
)
757 if (!followplayer
) m_paninc
.y
= 0;
759 else if (key
== key_map_zoomout
|| key
== key_map_zoomin
)
761 mtof_zoommul
= FRACUNIT
;
762 ftom_zoommul
= FRACUNIT
;
774 void AM_changeWindowScale(void)
777 // Change the scaling multipliers
778 scale_mtof
= FixedMul(scale_mtof
, mtof_zoommul
);
779 scale_ftom
= FixedDiv(FRACUNIT
, scale_mtof
);
781 if (scale_mtof
< min_scale_mtof
)
782 AM_minOutWindowScale();
783 else if (scale_mtof
> max_scale_mtof
)
784 AM_maxOutWindowScale();
786 AM_activateNewScale();
793 void AM_doFollowPlayer(void)
796 if (f_oldloc
.x
!= plr
->mo
->x
|| f_oldloc
.y
!= plr
->mo
->y
)
798 m_x
= FTOM(MTOF(plr
->mo
->x
)) - m_w
/2;
799 m_y
= FTOM(MTOF(plr
->mo
->y
)) - m_h
/2;
802 f_oldloc
.x
= plr
->mo
->x
;
803 f_oldloc
.y
= plr
->mo
->y
;
805 // m_x = FTOM(MTOF(plr->mo->x - m_w/2));
806 // m_y = FTOM(MTOF(plr->mo->y - m_h/2));
807 // m_x = plr->mo->x - m_w/2;
808 // m_y = plr->mo->y - m_h/2;
817 void AM_updateLightLev(void)
819 static int nexttic
= 0;
820 //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
821 static int litelevels
[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
822 static int litelevelscnt
= 0;
824 // Change light level
827 lightlev
= litelevels
[litelevelscnt
++];
828 if (litelevelscnt
== arrlen(litelevels
)) litelevelscnt
= 0;
829 nexttic
= amclock
+ 6 - (amclock
% 6);
836 // Updates on Game Tick
838 void AM_Ticker (void)
849 // Change the zoom if necessary
850 if (ftom_zoommul
!= FRACUNIT
)
851 AM_changeWindowScale();
853 // Change x,y location
854 if (m_paninc
.x
|| m_paninc
.y
)
855 AM_changeWindowLoc();
857 // Update light level
858 // AM_updateLightLev();
864 // Clear automap frame buffer.
866 void AM_clearFB(int color
)
868 memset(fb
, color
, f_w
*f_h
);
873 // Automap clipping of lines.
875 // Based on Cohen-Sutherland clipping algorithm but with a slightly
876 // faster reject and precalculated slopes. If the speed is needed,
877 // use a hash algorithm to handle the common cases.
892 register int outcode1
= 0;
893 register int outcode2
= 0;
894 register int outside
;
901 #define DOOUTCODE(oc, mx, my) \
903 if ((my) < 0) (oc) |= TOP; \
904 else if ((my) >= f_h) (oc) |= BOTTOM; \
905 if ((mx) < 0) (oc) |= LEFT; \
906 else if ((mx) >= f_w) (oc) |= RIGHT;
909 // do trivial rejects and outcodes
912 else if (ml
->a
.y
< m_y
)
917 else if (ml
->b
.y
< m_y
)
920 if (outcode1
& outcode2
)
921 return false; // trivially outside
925 else if (ml
->a
.x
> m_x2
)
930 else if (ml
->b
.x
> m_x2
)
933 if (outcode1
& outcode2
)
934 return false; // trivially outside
936 // transform to frame-buffer coordinates.
937 fl
->a
.x
= CXMTOF(ml
->a
.x
);
938 fl
->a
.y
= CYMTOF(ml
->a
.y
);
939 fl
->b
.x
= CXMTOF(ml
->b
.x
);
940 fl
->b
.y
= CYMTOF(ml
->b
.y
);
942 DOOUTCODE(outcode1
, fl
->a
.x
, fl
->a
.y
);
943 DOOUTCODE(outcode2
, fl
->b
.x
, fl
->b
.y
);
945 if (outcode1
& outcode2
)
948 while (outcode1
| outcode2
)
950 // may be partially inside box
951 // find an outside point
960 dy
= fl
->a
.y
- fl
->b
.y
;
961 dx
= fl
->b
.x
- fl
->a
.x
;
962 tmp
.x
= fl
->a
.x
+ (dx
*(fl
->a
.y
))/dy
;
965 else if (outside
& BOTTOM
)
967 dy
= fl
->a
.y
- fl
->b
.y
;
968 dx
= fl
->b
.x
- fl
->a
.x
;
969 tmp
.x
= fl
->a
.x
+ (dx
*(fl
->a
.y
-f_h
))/dy
;
972 else if (outside
& RIGHT
)
974 dy
= fl
->b
.y
- fl
->a
.y
;
975 dx
= fl
->b
.x
- fl
->a
.x
;
976 tmp
.y
= fl
->a
.y
+ (dy
*(f_w
-1 - fl
->a
.x
))/dx
;
979 else if (outside
& LEFT
)
981 dy
= fl
->b
.y
- fl
->a
.y
;
982 dx
= fl
->b
.x
- fl
->a
.x
;
983 tmp
.y
= fl
->a
.y
+ (dy
*(-fl
->a
.x
))/dx
;
992 if (outside
== outcode1
)
995 DOOUTCODE(outcode1
, fl
->a
.x
, fl
->a
.y
);
1000 DOOUTCODE(outcode2
, fl
->b
.x
, fl
->b
.y
);
1003 if (outcode1
& outcode2
)
1004 return false; // trivially outside
1013 // Classic Bresenham w/ whatever optimizations needed for speed
1030 static int fuck
= 0;
1032 // For debugging only
1033 if ( fl
->a
.x
< 0 || fl
->a
.x
>= f_w
1034 || fl
->a
.y
< 0 || fl
->a
.y
>= f_h
1035 || fl
->b
.x
< 0 || fl
->b
.x
>= f_w
1036 || fl
->b
.y
< 0 || fl
->b
.y
>= f_h
)
1038 fprintf(stderr
, DEH_String("fuck %d \r"), fuck
++);
1042 #define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
1044 dx
= fl
->b
.x
- fl
->a
.x
;
1045 ax
= 2 * (dx
<0 ? -dx
: dx
);
1048 dy
= fl
->b
.y
- fl
->a
.y
;
1049 ay
= 2 * (dy
<0 ? -dy
: dy
);
1061 if (x
== fl
->b
.x
) return;
1076 PUTDOT(x
, y
, color
);
1077 if (y
== fl
->b
.y
) return;
1091 // Clip lines, draw visible part sof lines.
1100 if (AM_clipMline(ml
, &fl
))
1101 AM_drawFline(&fl
, color
); // draws it on frame buffer using fb coords
1107 // Draws flat (floor/ceiling tile) aligned grid lines.
1109 void AM_drawGrid(int color
)
1115 // Figure out start of vertical gridlines
1117 if ((start
-bmaporgx
)%(MAPBLOCKUNITS
<<FRACBITS
))
1118 start
+= (MAPBLOCKUNITS
<<FRACBITS
)
1119 - ((start
-bmaporgx
)%(MAPBLOCKUNITS
<<FRACBITS
));
1122 // draw vertical gridlines
1125 for (x
=start
; x
<end
; x
+=(MAPBLOCKUNITS
<<FRACBITS
))
1129 AM_drawMline(&ml
, color
);
1132 // Figure out start of horizontal gridlines
1134 if ((start
-bmaporgy
)%(MAPBLOCKUNITS
<<FRACBITS
))
1135 start
+= (MAPBLOCKUNITS
<<FRACBITS
)
1136 - ((start
-bmaporgy
)%(MAPBLOCKUNITS
<<FRACBITS
));
1139 // draw horizontal gridlines
1142 for (y
=start
; y
<end
; y
+=(MAPBLOCKUNITS
<<FRACBITS
))
1146 AM_drawMline(&ml
, color
);
1152 // Determines visible lines, draws them.
1153 // This is LineDef based, not LineSeg based.
1155 void AM_drawWalls(void)
1160 for (i
=0;i
<numlines
;i
++)
1162 l
.a
.x
= lines
[i
].v1
->x
;
1163 l
.a
.y
= lines
[i
].v1
->y
;
1164 l
.b
.x
= lines
[i
].v2
->x
;
1165 l
.b
.y
= lines
[i
].v2
->y
;
1166 if (cheating
|| (lines
[i
].flags
& ML_MAPPED
))
1168 if ((lines
[i
].flags
& LINE_NEVERSEE
) && !cheating
)
1170 if (!lines
[i
].backsector
)
1172 AM_drawMline(&l
, WALLCOLORS
+lightlev
);
1176 if (lines
[i
].special
== 39)
1178 AM_drawMline(&l
, WALLCOLORS
+WALLRANGE
/2);
1180 else if (lines
[i
].flags
& ML_SECRET
) // secret door
1182 if (cheating
) AM_drawMline(&l
, SECRETWALLCOLORS
+ lightlev
);
1183 else AM_drawMline(&l
, WALLCOLORS
+lightlev
);
1185 else if (lines
[i
].backsector
->floorheight
1186 != lines
[i
].frontsector
->floorheight
) {
1187 AM_drawMline(&l
, FDWALLCOLORS
+ lightlev
); // floor level change
1189 else if (lines
[i
].backsector
->ceilingheight
1190 != lines
[i
].frontsector
->ceilingheight
) {
1191 AM_drawMline(&l
, CDWALLCOLORS
+lightlev
); // ceiling level change
1193 else if (cheating
) {
1194 AM_drawMline(&l
, TSWALLCOLORS
+lightlev
);
1198 else if (plr
->powers
[pw_allmap
])
1200 if (!(lines
[i
].flags
& LINE_NEVERSEE
)) AM_drawMline(&l
, GRAYS
+3);
1208 // Used to rotate player arrow line character.
1219 FixedMul(*x
,finecosine
[a
>>ANGLETOFINESHIFT
])
1220 - FixedMul(*y
,finesine
[a
>>ANGLETOFINESHIFT
]);
1223 FixedMul(*x
,finesine
[a
>>ANGLETOFINESHIFT
])
1224 + FixedMul(*y
,finecosine
[a
>>ANGLETOFINESHIFT
]);
1230 AM_drawLineCharacter
1242 for (i
=0;i
<lineguylines
;i
++)
1244 l
.a
.x
= lineguy
[i
].a
.x
;
1245 l
.a
.y
= lineguy
[i
].a
.y
;
1249 l
.a
.x
= FixedMul(scale
, l
.a
.x
);
1250 l
.a
.y
= FixedMul(scale
, l
.a
.y
);
1254 AM_rotate(&l
.a
.x
, &l
.a
.y
, angle
);
1259 l
.b
.x
= lineguy
[i
].b
.x
;
1260 l
.b
.y
= lineguy
[i
].b
.y
;
1264 l
.b
.x
= FixedMul(scale
, l
.b
.x
);
1265 l
.b
.y
= FixedMul(scale
, l
.b
.y
);
1269 AM_rotate(&l
.b
.x
, &l
.b
.y
, angle
);
1274 AM_drawMline(&l
, color
);
1278 void AM_drawPlayers(void)
1282 static int their_colors
[] = { GREENS
, GRAYS
, BROWNS
, REDS
};
1283 int their_color
= -1;
1289 AM_drawLineCharacter
1290 (cheat_player_arrow
, arrlen(cheat_player_arrow
), 0,
1291 plr
->mo
->angle
, WHITE
, plr
->mo
->x
, plr
->mo
->y
);
1293 AM_drawLineCharacter
1294 (player_arrow
, arrlen(player_arrow
), 0, plr
->mo
->angle
,
1295 WHITE
, plr
->mo
->x
, plr
->mo
->y
);
1299 for (i
=0;i
<MAXPLAYERS
;i
++)
1304 if ( (deathmatch
&& !singledemo
) && p
!= plr
)
1307 if (!playeringame
[i
])
1310 if (p
->powers
[pw_invisibility
])
1311 color
= 246; // *close* to black
1313 color
= their_colors
[their_color
];
1315 AM_drawLineCharacter
1316 (player_arrow
, arrlen(player_arrow
), 0, p
->mo
->angle
,
1317 color
, p
->mo
->x
, p
->mo
->y
);
1330 for (i
=0;i
<numsectors
;i
++)
1332 t
= sectors
[i
].thinglist
;
1335 AM_drawLineCharacter
1336 (thintriangle_guy
, arrlen(thintriangle_guy
),
1337 16<<FRACBITS
, t
->angle
, colors
+lightlev
, t
->x
, t
->y
);
1343 void AM_drawMarks(void)
1345 int i
, fx
, fy
, w
, h
;
1347 for (i
=0;i
<AM_NUMMARKPOINTS
;i
++)
1349 if (markpoints
[i
].x
!= -1)
1351 // w = SHORT(marknums[i]->width);
1352 // h = SHORT(marknums[i]->height);
1353 w
= 5; // because something's wrong with the wad, i guess
1354 h
= 6; // because something's wrong with the wad, i guess
1355 fx
= CXMTOF(markpoints
[i
].x
);
1356 fy
= CYMTOF(markpoints
[i
].y
);
1357 if (fx
>= f_x
&& fx
<= f_w
- w
&& fy
>= f_y
&& fy
<= f_h
- h
)
1358 V_DrawPatch(fx
, fy
, FB
, marknums
[i
]);
1364 void AM_drawCrosshair(int color
)
1366 fb
[(f_w
*(f_h
+1))/2] = color
; // single point for now
1370 void AM_Drawer (void)
1372 if (!automapactive
) return;
1374 AM_clearFB(BACKGROUND
);
1376 AM_drawGrid(GRIDCOLORS
);
1380 AM_drawThings(THINGCOLORS
, THINGRANGE
);
1381 AM_drawCrosshair(XHAIRCOLORS
);
1385 V_MarkRect(f_x
, f_y
, f_w
, f_h
);