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