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