1 /* NetHack may be freely redistributed. See license for details. */
2
3 #include "vulture_sdl.h" /* XXX this must be the first include,
4 no idea why but it won't compile otherwise */
5
6 extern "C" {
7 #include "hack.h"
8
9 extern "C" short glyph2tile[];
10 }
11
12 #include "vulture_gra.h"
13 #include "vulture_gfl.h"
14 #include "vulture_win.h"
15 #include "vulture_txt.h"
16 #include "vulture_mou.h"
17 #include "vulture_tile.h"
18
19 #include "map.h"
20 #include "hotspot.h"
21 #include "levelwin.h"
22 #include "textwin.h"
23 #include "mapdata.h"
24
25 #define SYMBOL_WIDTH 7
26 #define SYMBOL_HEIGHT 14
27
28 window *mapwin = NULL;
29
30
map(levelwin * p,mapdata * data)31 map::map(levelwin *p, mapdata *data) : window(p), map_data(data)
32 {
33 int i;
34 SDL_Surface *image;
35
36 v_type = V_WINTYPE_MAP;
37 autobg = 1;
38 need_redraw = 1;
39 w = 640;
40 h = 480;
41 x = (parent->w - w) / 2;
42 y = (parent->h - h) / 2;
43 abs_x = parent->abs_x + x;
44 abs_y = parent->abs_y + y;
45
46 /* Load map parchment */
47 mapbg = vulture_load_graphic(V_FILENAME_MAP_PARCHMENT);
48
49 /* level title */
50 textwin *txt = new textwin(this, "");
51 txt->x = w/2;
52 txt->y = 48;
53
54 /* close button */
55 hotspot *close = new hotspot(this, 598, 11, 28, 24, 1, "Close map");
56 close->abs_x = abs_x + close->x;
57 close->abs_y = abs_y + close->y;
58
59 /* Load map symbols */
60 image = vulture_load_graphic(V_FILENAME_MAP_SYMBOLS);
61 if (image == NULL)
62 return;
63 else {
64 for (i = 0; i < V_MAX_MAP_SYMBOLS; i++)
65 map_symbols[i] = vulture_get_img_src(
66 (i%40)*SYMBOL_WIDTH,
67 (i/40)*SYMBOL_HEIGHT,
68 (i%40)*SYMBOL_WIDTH + (SYMBOL_WIDTH - 1),
69 (i/40)*SYMBOL_HEIGHT+ (SYMBOL_HEIGHT - 1),
70 image);
71 SDL_FreeSurface(image);
72 }
73 }
74
~map()75 map::~map()
76 {
77 int i;
78
79 /* free the map symbols */
80 for (i = 0; i < V_MAX_MAP_SYMBOLS; i++)
81 SDL_FreeSurface(map_symbols[i]);
82
83 SDL_FreeSurface(mapbg);
84 }
85
draw()86 bool map::draw()
87 {
88 int map_x, map_y;
89 int i, j;
90 window * txt = first_child;
91 char buffer[256];
92
93 /* Draw parchment */
94 vulture_put_img(abs_x, abs_y, mapbg);
95
96 /* Draw the level name */
97 #ifdef VULTURE_SLASHEM
98 describe_level(buffer, TRUE);
99 #else
100 if (!describe_level(buffer))
101 sprintf(buffer, "%s, level %d ", dungeons[u.uz.dnum].dname, depth(&u.uz));
102 #endif
103 txt->set_caption(buffer);
104 txt->x = (w - vulture_text_length(V_FONT_HEADLINE, txt->caption)) / 2;
105 txt->abs_x = abs_x + txt->x;
106 txt->abs_y = abs_y + txt->y;
107 vulture_put_text_shadow(V_FONT_HEADLINE, txt->caption, vulture_screen,
108 txt->abs_x, txt->abs_y, CLR32_BROWN, CLR32_BLACK_A50);
109
110 /* Find upper left corner of map on parchment */
111 map_x = abs_x + 39;
112 map_y = abs_y + 91;
113
114 /* Draw map on parchment, and create hotspots */
115 for (i = 0; i < ROWNO; i++)
116 for (j = 1; j < COLNO; j++) {
117 int map_glyph = map_data->get_glyph(MAP_GLYPH, j, i);
118 bool is_dark = (map_data->get_glyph(MAP_DARKNESS, j, i) == 2);
119
120 if (map_glyph != NO_GLYPH &&
121 (map_glyph != cmap_to_glyph(S_stone) ||
122 (level.locations[j][i].seenv && is_dark))) {
123 vulture_put_img(
124 map_x + SYMBOL_WIDTH*j,
125 map_y + SYMBOL_HEIGHT*i,
126 map_symbols[glyph2tile[map_glyph]]);
127 }
128 }
129
130 vulture_invalidate_region(abs_x, abs_y, w, h);
131
132 return false;
133 }
134
135
toggle(void)136 void map::toggle(void)
137 {
138 if (!mapwin) {
139 mapwin = new map(levwin, ::map_data);
140
141 mapwin->x = (mapwin->parent->w - mapwin->w) / 2;
142 mapwin->y = (mapwin->parent->h - mapwin->h) / 2;
143 }
144 else {
145 mapwin->hide();
146 delete mapwin;
147 mapwin = NULL;
148 }
149 }
150
151
handle_timer_event(window * target,void * result,int time)152 eventresult map::handle_timer_event(window* target, void* result, int time)
153 {
154 std::string ttext;
155 point mappos = get_mouse_mappos();
156
157 if (time < HOVERTIMEOUT)
158 return V_EVENT_HANDLED_NOREDRAW;
159
160 /* draw the tooltip for the close button */
161 if (this != target && target->menu_id == 1)
162 vulture_mouse_set_tooltip(target->caption);
163 /* draw a tooltip for the map location */
164 else if (mappos.x != -1) {
165 ttext = map_data->map_square_description(mappos, 1);
166 if(!ttext.empty())
167 vulture_mouse_set_tooltip(ttext);
168 }
169
170 return V_EVENT_HANDLED_NOREDRAW;
171 }
172
173
handle_mousemotion_event(window * target,void * result,int xrel,int yrel,int state)174 eventresult map::handle_mousemotion_event(window* target, void* result, int xrel,
175 int yrel, int state)
176 {
177 vulture_set_mcursor(V_CURSOR_NORMAL);
178 return V_EVENT_HANDLED_NOREDRAW;
179 }
180
181
handle_mousebuttonup_event(window * target,void * result,int mouse_x,int mouse_y,int button,int state)182 eventresult map::handle_mousebuttonup_event(window* target, void* result,
183 int mouse_x, int mouse_y, int button, int state)
184 {
185 point mappos = get_mouse_mappos();
186
187 /* handler != target if the user clicked on the X in the upper right corner */
188 if (this != target && target->menu_id == 1) {
189 toggle();
190 vulture_mouse_invalidate_tooltip(1);
191 return V_EVENT_HANDLED_REDRAW;
192 }
193
194 /* only handle clicks on valid map locations */
195 if (mappos.x != -1)
196 return map_data->handle_click(result, button, mappos);
197
198 return V_EVENT_HANDLED_NOREDRAW;
199 }
200
201
handle_resize_event(window * target,void * result,int res_w,int res_h)202 eventresult map::handle_resize_event(window* target, void* result, int res_w, int res_h)
203 {
204 x = (parent->w - w) / 2;
205 y = (parent->h - h) / 2;
206 return V_EVENT_HANDLED_NOREDRAW;
207 }
208
209
get_mouse_mappos(void)210 point map::get_mouse_mappos(void)
211 {
212 point mouse, mappos;
213
214 mouse = vulture_get_mouse_pos();
215 mappos.x = (mouse.x - abs_x - 39) / SYMBOL_WIDTH;
216 mappos.y = (mouse.y - abs_y - 91) / SYMBOL_HEIGHT;
217
218 if (mappos.x < 1 || mappos.x >= COLNO ||
219 mappos.y < 0 || mappos.y >= ROWNO) {
220 mappos.x = -1;
221 mappos.y = -1;
222 }
223
224 return mappos;
225 }
226