added worldarea -> will be responsible for world map rendering
[dboe.git] / gutils.c
blob7fcb47f5568e37bab7cc7e831decd64e43f84117
2 #include <windows.h>
4 #include "global.h"
5 #include "gutils.h"
6 #include "text.h"
7 #include "fields.h"
8 #include "locutils.h"
9 #include "graphics.h"
10 #include "infodlgs.h"
11 #include "monster.h"
12 #include "dlogtool.h"
13 #include "exlsound.h"
14 #include "graphutl.h"
15 #include "stdio.h"
17 extern HWND mainPtr;
18 extern RECT windRect;
19 extern short stat_window,give_delays,overall_mode;
20 extern short current_spell_range,town_type;
21 extern Boolean in_startup_mode,anim_onscreen,registered,play_sounds,frills_on,startup_loaded,cartoon_happening;
22 extern short town_size[3];
23 extern party_record_type far party;
24 extern piles_of_stuff_dumping_type *data_store;
25 extern piles_of_stuff_dumping_type2 *data_store2;
26 extern talking_record_type far talking;
27 extern scenario_data_type far scenario;
29 extern pc_record_type far adven[6];
30 extern big_tr_type far t_d;
31 extern outdoor_record_type far outdoors[2][2];
32 extern current_town_type far c_town;
33 extern town_item_list far t_i;
34 extern unsigned char far out[96][96];
35 extern unsigned char far out_e[96][96];
36 extern unsigned char far combat_terrain[64][64];
37 extern effect_pat_type current_pat;
38 extern Boolean web,crate,barrel,fire_barrier,force_barrier,quickfire,force_wall,fire_wall,antimagic,scloud,ice_wall,blade_wall;
39 extern Boolean sleep_field;
40 extern unsigned char far misc_i[64][64],sfx[64][64];
41 extern short on_monst_menu[256];
42 extern HWND modeless_dialogs[18];
43 extern short monst_target[T_M]; // 0-5 target that pc 6 - no target 100 + x - target monster x
44 extern short combat_posing_monster , current_working_monster ; // 0-5 PC 100 + x - monster x
45 extern Boolean cat,cow,chicken,dog,sheep;
47 extern HBITMAP storage_gworld,terrain_screen_gworld,party_template_gworld,items_gworld,tiny_obj_gworld;
48 extern HBITMAP fields_gworld,mixed_gworld,small_temp_gworld,spec_scen_g;
49 extern short far which_g_stored[STORED_GRAPHICS];
50 extern short far wish_list[STORED_GRAPHICS];
51 extern short far storage_status[STORED_GRAPHICS]; // 0 - empty 1 - in use 2 - there, not in use
52 extern short terrain_there[9][9];
54 extern short ulx,uly;
55 extern location pc_pos[6],center;
56 extern short which_combat_type,pc_dir[6],current_pc;
57 extern Boolean monsters_going,anim_onscreen;
59 extern short pc_moves[6];
60 extern short num_targets_left;
61 extern location spell_targets[8];
62 extern short display_mode;
64 extern long anim_ticks;
66 extern short far terrain_pic[256];
67 extern char spot_seen[9][9];
68 extern char far out_trim[96][96];
69 extern char far town_trim[64][64];
70 extern short monster_index[21];
72 extern Boolean supressing_some_spaces;
73 extern location ok_space[4];
74 extern Boolean can_draw_pcs;
76 extern HPALETTE hpal;
77 extern far PALETTEENTRY ape[256];
78 extern HDC main_dc,main_dc2,main_dc3;
80 extern HFONT font,small_bold_font,italic_font,underline_font,bold_font;
83 RECT boat_rects[4] = {{0,0,28,36}, {28,0,56,36},{56,0,84,36},{84,0,112,36}}; /**/
84 Boolean gave_no_g_error = FALSE;
86 unsigned char m_pic_index[200] = {////
87 1,2,3,4,5,6,7,8,9,10,
88 11,12,13,14,15,16,17,18,19,20,
90 21,22,23,24,25, 26,27,28,29,30,
91 31,32,33,34,35, 36,37,38,39,40,
93 41,42,43,44,46,47,48,49,50,51,
94 53,55,57,59,60,61,62,63,64,65,
96 66,67,68,69,70, 71,72,73,74,75,
97 76,77,78,79,81, 82,83,85,86,87,
99 88,89,90,91,92, 93,94,95,96,97,
100 98,99,100,101,102, 103,104,105,106,107,
102 108,109,111,112,113, 114,116,117,118,119, //100
103 120,122,123,125,127, 128,129,130,131,135,
105 136,137,139,140,141,142,143,144,145,146,
106 147,148,149,150,151,152,152,154,155,159,
108 160,164,166,168,170,171,172,173,174,175,
109 176,177,178,179,180,181,182,183,184,185,
111 186,187,188,189,190,191,192,193,194,195,
112 196,197,198,0,0,0,0,0,0,0,
114 0,0,0,0,0,0,0,0,0,0,
115 0,0,0,0,0,0,0,0,0,0};
117 unsigned char m_pic_index_x[200] = {
119 1,1,1,1,1,1,1,1,1,1,
120 1,1,1,1,1,1,1,1,1,1,
121 1,1,1,1,1,1,1,1,1,1,
122 1,1,1,1,1,1,1,1,1,1,
123 1,1,1,1,1,1,1,1,1,1,
124 1,1,1,1,1,1,1,1,1,1,
125 1,1,1,1,1,1,1,1,1,1,
126 1,1,1,2,1,1,1,1,1,1,
127 1,1,1,1,1,1,1,1,1,1,
128 1,1,1,1,1,1,1,1,1,1,
130 1,2,1,1,1,2,1,1,1,1, // 100
131 2,1,1,1,1,1,1,1,2,1,
132 1,2,1,1,1,1,1,1,1,1,
133 1,1,1,1,1,1,1,1,2,1,
135 2,2,2,1,1,1,1,1,1,1,
136 1,1,1,1,1,1,1,1,1,1,
137 1,1,1,1,1,1,1,1,1,1,
138 1,1,1,1,1,1,1,1,1,1,
139 1,1,1,1,1,1,1,1,1,1,
140 1,1,1,1,1,1,1,1,1,1};
142 unsigned char m_pic_index_y[200] = {
143 1,1,1,1,1,1,1,1,1,1,
144 1,1,1,1,1,1,1,1,1,1,
145 1,1,1,1,1,1,1,1,1,1,
146 1,1,1,1,1,1,1,1,1,1,
147 1,1,1,1,1,1,1,1,1,2,
148 2,2,2,1,1,1,1,1,1,1,
149 1,1,1,1,1,1,1,1,1,1,
150 1,1,1,1,1,1,2,1,1,1,
151 1,1,1,1,1,1,1,1,1,1,
152 1,1,1,1,1,1,1,1,1,1,
154 1,1,1,1,1,1,1,1,1,1,
155 1,1,2,2,1,1,1,1,2,1,
156 1,1,1,1,1,1,1,1,1,1,
157 1,1,1,1,1,1,1,1,2,1,
158 2,1,1,2,1,1,1,1,1,1,
160 1,1,1,1,1,1,1,1,1,1,
161 1,1,1,1,1,1,1,1,1,1,
162 1,1,1,1,1,1,1,1,1,1,
163 1,1,1,1,1,1,1,1,1,1,
164 1,1,1,1,1,1,1,1,1,1};
167 void draw_one_terrain_spot (short i,short j,short terrain_to_draw,short dest)
168 //short dest; // 0 - terrain gworld 1 - screen
169 // if terrain_to_draw is -1, do black
170 // if terrain_to_draw >= 1000, force to draw graphic which is terrain_to_draw - 1000
172 RECT where_draw;
173 RECT source_rect;
174 RECT anim_rects[4] = {{0,0,28,36},{28,0,56,36},{56,0,84,36},{84,0,112,36}}; /**/
175 HBITMAP ter_source_gworld,source_gworld;
176 short anim_type = 0;
177 location l;
178 HDC hdc;
179 HBITMAP store_bmp;
181 source_gworld = storage_gworld;
183 l.x = i; l.y = j;
184 if ((supressing_some_spaces == TRUE) &&
185 (same_point(l,ok_space[0]) == FALSE) &&
186 (same_point(l,ok_space[1]) == FALSE) &&
187 (same_point(l,ok_space[2]) == FALSE) &&
188 (same_point(l,ok_space[3]) == FALSE))
189 return;
191 where_draw = calc_rect(i,j);
192 OffsetRect(&where_draw,13,13);
193 if (terrain_to_draw == -1) {
194 if ((cartoon_happening == FALSE) && (terrain_there[i][j] == 300)) {
195 return;
197 terrain_there[i][j] = 300;
198 hdc = CreateCompatibleDC(main_dc);
199 store_bmp = SelectObject(hdc,terrain_screen_gworld);
200 SelectObject(hdc,GetStockObject(BLACK_BRUSH));
201 Rectangle(hdc,where_draw.left,where_draw.top,where_draw.right,where_draw.bottom);
202 SelectObject(hdc,store_bmp);
203 DeleteObject(hdc);
205 return;
207 if (terrain_to_draw >= 10000) { // force using a specific graphic
208 if (terrain_there[i][j] == terrain_to_draw - 10000)
209 return;
210 terrain_there[i][j] = terrain_to_draw - 10000;
211 source_rect = return_item_rect(terrain_to_draw - 10000);
212 anim_type = -1;
214 else if (terrain_pic[terrain_to_draw] >= 2000) { // custom
215 source_gworld = spec_scen_g;
216 source_rect = get_custom_rect(terrain_pic[terrain_to_draw] - 2000 + (anim_ticks % 4));
217 anim_type = 0;
218 terrain_there[i][j] = -1;
220 else if (terrain_pic[terrain_to_draw] >= 1000) { // custom
221 source_gworld = spec_scen_g;
222 source_rect = get_custom_rect(terrain_pic[terrain_to_draw] - 1000);
223 terrain_there[i][j] = -1;
225 else if (terrain_pic[terrain_to_draw] >= 400) { // animated
226 source_rect = return_item_rect(terrain_pic[terrain_to_draw] + 600 + 100 * (anim_ticks % 4));
227 terrain_there[i][j] = -1;
228 anim_type = 0;
230 else {
231 if (cartoon_happening == FALSE) {
232 if (terrain_there[i][j] == terrain_pic[terrain_to_draw]) {
233 return;
235 terrain_there[i][j] = terrain_pic[terrain_to_draw];
237 source_rect = return_item_rect(terrain_pic[terrain_to_draw]);
238 anim_type = -1;
241 if (anim_type >= 0)
243 if ((is_town()) || (is_out()))
244 anim_onscreen = TRUE;
247 if (dest == 0)
248 rect_draw_some_item(source_gworld, source_rect, terrain_screen_gworld, where_draw, (unsigned char) 0, 0);
249 else rect_draw_some_item(source_gworld, source_rect, terrain_screen_gworld, where_draw, (unsigned char) 0, 1);
252 void draw_monsters()
254 short i,j = 0,k,l;
255 short width,height;
256 RECT source_rect,to_rect;
257 location where_draw,store_loc;
258 char debug[60];
259 short picture_wanted;
260 unsigned char ter;
261 RECT monst_rects[4][4] = {{{0,0,28,36},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
262 {{7,0,21,18},{7,18,21,36},{0,0,0,0},{0,0,0,0}},
263 {{0,9,14,27},{14,9,28,27},{0,0,0,0},{0,0,0,0}},
264 {{0,0,14,18},{14,0,28,18},{0,18,14,36},{14,18,28,36}}};
266 if (is_out())
267 for (i = 0; i < 10; i++)
268 if (party.out_c[i].exists == TRUE) {
269 if ((point_onscreen(party.p_loc, party.out_c[i].m_loc) == TRUE) &&
270 (can_see(party.p_loc, party.out_c[i].m_loc,0) < 5)) {
271 where_draw.x = party.out_c[i].m_loc.x - party.p_loc.x + 4;
272 where_draw.y = party.out_c[i].m_loc.y - party.p_loc.y + 4;
273 terrain_there[where_draw.x][where_draw.y] = -1;
275 j = 0;
276 while ((party.out_c[i].what_monst.monst[j] == 0) && (j < 7)) {
277 j++;
280 if (j == 7) party.out_c[i].exists = FALSE; // begin watch out
281 else {
282 picture_wanted = get_monst_picnum(party.out_c[i].what_monst.monst[j]);
283 } // end watch out
285 if (party.out_c[i].exists == TRUE) {
286 get_monst_dims(party.out_c[i].what_monst.monst[j],&width,&height);
287 if (picture_wanted >= 1000) {
288 for (k = 0; k < width * height; k++) {
289 source_rect = get_custom_rect(picture_wanted % 1000 +
290 ((party.out_c[i].direction < 4) ? 0 : (width * height)) + k);
291 to_rect = monst_rects[(width - 1) * 2 + height - 1][k];
292 rect_draw_some_item(spec_scen_g, source_rect, small_temp_gworld,to_rect, 0, 0);
293 source_rect = to_rect;
294 OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y);
295 rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0);
297 //source_rect = to_rect = monst_rects[0][0];
298 //OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y);
299 //rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0);
301 if (picture_wanted < 1000) {
302 for (k = 0; k < width * height; k++) {
303 source_rect = get_monster_template_rect(party.out_c[i].what_monst.monst[j],
304 (party.out_c[i].direction < 4) ? 0 : 1,k);
305 to_rect = monst_rects[(width - 1) * 2 + height - 1][k];
306 rect_draw_some_item(storage_gworld, source_rect, small_temp_gworld,to_rect, 0, 0);
307 source_rect = to_rect;
308 OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y);
309 rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0);
311 //source_rect = to_rect = monst_rects[0][0];
312 //OffsetRect(&to_rect,13 + 28 * where_draw.x,13 + 36 * where_draw.y);
313 //rect_draw_some_item(small_temp_gworld, source_rect, terrain_screen_gworld,to_rect, 1, 0);
318 if (is_town())
319 for (i = 0; i < T_M; i++)
320 if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].m_d.spec_skill != 11))
321 if (party_can_see_monst(i)) {
322 check_if_monst_seen(c_town.monst.dudes[i].number);
323 where_draw.x = c_town.monst.dudes[i].m_loc.x - center.x + 4;
324 where_draw.y = c_town.monst.dudes[i].m_loc.y - center.y + 4;
325 get_monst_dims(c_town.monst.dudes[i].number,&width,&height);
327 for (k = 0; k < width * height; k++) {
328 store_loc = where_draw;
329 store_loc.x += k % width;
330 store_loc.y += k / width;
331 // customize?
332 if (c_town.monst.dudes[i].m_d.picture_num >= 1000) {
333 source_rect = get_custom_rect((c_town.monst.dudes[i].m_d.picture_num % 1000) +
334 k + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : width * height)
335 + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0));
336 Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0);
338 if (c_town.monst.dudes[i].m_d.picture_num < 1000) {
339 source_rect = get_monster_template_rect(c_town.monst.dudes[i].number,
340 ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : 1) + ((combat_posing_monster == i + 100) ? 10 : 0),k);
341 ter = t_d.terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y];
342 // in bed?
343 if ((store_loc.x >= 0) && (store_loc.x < 9) && (store_loc.y >= 0) && (store_loc.y < 9) &&
344 (scenario.ter_types[ter].picture == 143) &&
345 ((c_town.monst.dudes[i].m_d.m_type < 7)
346 && (c_town.monst.dudes[i].m_d.m_type != 1) && (c_town.monst.dudes[i].m_d.m_type != 2))
347 && ((c_town.monst.dudes[i].active == 1) || (monst_target[i] == 6)) &&
348 (width == 1) && (height == 1)) ////
349 draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10230,0);
350 else Draw_Some_Item(storage_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0);
354 if (is_combat()) {
355 for (i = 0; i < T_M; i++)
356 if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].m_d.spec_skill != 11))
357 if (((point_onscreen(center,c_town.monst.dudes[i].m_loc) == TRUE) && (cartoon_happening == TRUE))
358 || (party_can_see_monst(i) == TRUE)) {
359 check_if_monst_seen(c_town.monst.dudes[i].number);
360 where_draw.x = c_town.monst.dudes[i].m_loc.x - center.x + 4;
361 where_draw.y = c_town.monst.dudes[i].m_loc.y - center.y + 4;
362 get_monst_dims(c_town.monst.dudes[i].number,&width,&height);
364 for (k = 0; k < width * height; k++) {
365 store_loc = where_draw;
366 store_loc.x += k % width;
367 store_loc.y += k / width;
368 // customize?
369 if (c_town.monst.dudes[i].m_d.picture_num >= 1000) {
370 source_rect = get_custom_rect((c_town.monst.dudes[i].m_d.picture_num % 1000) +
371 k + ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : width * height)
372 + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0));
373 Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0);
375 if (c_town.monst.dudes[i].m_d.picture_num < 1000) {
376 source_rect = get_monster_template_rect(c_town.monst.dudes[i].number,
377 ((c_town.monst.dudes[i].m_d.direction < 4) ? 0 : 1) + ((combat_posing_monster == i + 100) ? 10 : 0)
378 ,k);
379 ter = t_d.terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y];
380 if ((store_loc.x >= 0) && (store_loc.x < 9) && (store_loc.y >= 0) && (store_loc.y < 9) &&
381 (scenario.ter_types[ter].picture == 143) &&
382 ((c_town.monst.dudes[i].m_d.m_type < 7)
383 && (c_town.monst.dudes[i].m_d.m_type != 1) && (c_town.monst.dudes[i].m_d.m_type != 2))
384 && ((c_town.monst.dudes[i].active == 1) || (monst_target[i] == 6)) &&
385 (width == 1) && (height == 1))
386 draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10230,0); ////
387 else Draw_Some_Item(storage_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0);
395 void draw_pcs(location center,short mode)
396 //short mode; // 0 - put pcs in gworld 1 - only rectangle around active pc
398 short i;
399 RECT source_rect,active_pc_rect;
400 location where_draw;
402 if (party_toast() == TRUE)
403 return;
404 if (can_draw_pcs == FALSE)
405 return;
407 if ((mode == 1) && (cartoon_happening == TRUE))
408 return;
410 for (i = 0; i < 6; i++)
411 if (adven[i].main_status == 1)
412 if (((point_onscreen(center, pc_pos[i])) == TRUE) &&
413 ((cartoon_happening == TRUE) || (party_can_see(pc_pos[i]) < 6))){
414 where_draw.x = pc_pos[i].x - center.x + 4;
415 where_draw.y = pc_pos[i].y - center.y + 4;
416 source_rect = get_party_template_rect(i,(pc_dir[i] < 4) ? 0 : 1);
417 if (combat_posing_monster == i)
418 OffsetRect(&source_rect,0,108);
420 if (mode == 0) {
421 Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
424 if ((current_pc == i) && (mode == 1) && (monsters_going == FALSE)) {
425 frame_space(pc_pos[current_pc],1,1,1);
429 if (current_pc == 6) {
430 return;
432 // Draw current pc on top
433 if ((current_pc < 6) && ((point_onscreen(center, pc_pos[current_pc])) == TRUE) && (adven[current_pc].main_status == 1)) {
434 where_draw.x = pc_pos[current_pc].x - center.x + 4;
435 where_draw.y = pc_pos[current_pc].y - center.y + 4;
436 source_rect = get_party_template_rect(current_pc,(pc_dir[current_pc] < 4) ? 0 : 1);
437 if (combat_posing_monster == current_pc)
438 OffsetRect(&source_rect,0,108);
440 if (mode == 0)
441 Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
446 void draw_items()
448 short i;
449 RECT source_rect,dest_rect;
450 location where_draw;
453 for (i = 0; i < NUM_TOWN_ITEMS; i++) {
454 if (t_i.items[i].variety != 0) {
455 where_draw.x = t_i.items[i].item_loc.x - center.x + 4;
456 where_draw.y = t_i.items[i].item_loc.y - center.y + 4;
458 if ((supressing_some_spaces == TRUE) &&
459 (same_point(where_draw,ok_space[0]) == FALSE) &&
460 (same_point(where_draw,ok_space[1]) == FALSE) &&
461 (same_point(where_draw,ok_space[2]) == FALSE) &&
462 (same_point(where_draw,ok_space[3]) == FALSE))
464 else if ((point_onscreen(center, t_i.items[i].item_loc) == TRUE) &&
465 (is_contained(t_i.items[i]) == FALSE) &&
466 ((cartoon_happening == TRUE) || (party_can_see(t_i.items[i].item_loc) < 6))) {
467 // safety valve
468 //if ((t_i.items[i].graphic_num < 0) ||
469 // ((t_i.items[i].graphic_num >= NUM_ITEM_G) && (t_i.items[i].graphic_num < 1000))) {
470 // t_i.items[i].variety = 0;
471 // t_i.items[i].graphic_num = 0;
472 // }
473 if (t_i.items[i].graphic_num >= 150) {
474 source_rect = get_custom_rect(t_i.items[i].graphic_num - 150);
475 dest_rect = coord_to_rect(where_draw.x,where_draw.y);
476 terrain_there[where_draw.x][where_draw.y] = -1;
478 rect_draw_some_item(spec_scen_g,
479 source_rect, terrain_screen_gworld, dest_rect, 1, 0);
481 else {
482 source_rect = get_item_template_rect(t_i.items[i].graphic_num);
483 dest_rect = coord_to_rect(where_draw.x,where_draw.y);
484 terrain_there[where_draw.x][where_draw.y] = -1;
485 if (t_i.items[i].graphic_num >= 45) {
486 dest_rect.top += 9;
487 dest_rect.bottom -= 9;
488 dest_rect.left += 5;
489 dest_rect.right -= 5;
491 rect_draw_some_item((t_i.items[i].graphic_num < 45) ? items_gworld : tiny_obj_gworld,
492 source_rect, terrain_screen_gworld, dest_rect, 1, 0);
499 void draw_outd_boats(location center)
501 location where_draw;
502 RECT source_rect;
503 short i;
505 for (i = 0; i < 30; i++)
506 if ((point_onscreen(center, party.boats[i].boat_loc) == TRUE) && (party.boats[i].exists == TRUE) &&
507 (party.boats[i].which_town == 200) &&
508 (can_see(center, party.boats[i].boat_loc,0) < 5) && (party.in_boat != i)) {
509 where_draw.x = party.boats[i].boat_loc.x - center.x + 4;
510 where_draw.y = party.boats[i].boat_loc.y - center.y + 4;
511 source_rect = boat_rects[0];
512 OffsetRect(&source_rect,61,0);
513 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
515 for (i = 0; i < 30; i++)
516 if ((point_onscreen(center, party.horses[i].horse_loc) == TRUE) && (party.horses[i].exists == TRUE) &&
517 (party.horses[i].which_town == 200) &&
518 (can_see(center, party.horses[i].horse_loc,0) < 5) && (party.in_horse != i)) {
519 where_draw.x = party.horses[i].horse_loc.x - center.x + 4;
520 where_draw.y = party.horses[i].horse_loc.y - center.y + 4;
521 source_rect = boat_rects[0];
522 OffsetRect(&source_rect,61,0);
523 OffsetRect(&source_rect,0,74);
524 OffsetRect(&source_rect,56,36);
525 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
529 void draw_town_boat(location center)
531 location where_draw;
532 RECT source_rect;
533 short i;
535 for (i = 0; i < 30; i++)
536 if ((party.boats[i].which_town == c_town.town_num) &&
537 ((point_onscreen(center, party.boats[i].boat_loc) == TRUE) &&
538 (can_see(center, party.boats[i].boat_loc,0) < 5) && (party.in_boat != i)
539 && (pt_in_light(center,party.boats[i].boat_loc) == TRUE))) {
540 where_draw.x = party.boats[i].boat_loc.x - center.x + 4;
541 where_draw.y = party.boats[i].boat_loc.y - center.y + 4;
542 source_rect = boat_rects[0];
543 OffsetRect(&source_rect,61,0);
544 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
546 for (i = 0; i < 30; i++)
547 if ((party.horses[i].which_town == c_town.town_num) &&
548 ((point_onscreen(center, party.horses[i].horse_loc) == TRUE) &&
549 (can_see(center, party.horses[i].horse_loc,0) < 5) && (party.in_horse != i)
550 && (pt_in_light(center,party.horses[i].horse_loc) == TRUE))) {
551 where_draw.x = party.horses[i].horse_loc.x - center.x + 4;
552 where_draw.y = party.horses[i].horse_loc.y - center.y + 4;
554 source_rect = boat_rects[0];
555 OffsetRect(&source_rect,61,0);
556 OffsetRect(&source_rect,0,74);
557 OffsetRect(&source_rect,56,36);
558 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, where_draw, 1, 0);
562 void draw_fields()
564 if (crate == TRUE)
565 draw_one_field(8,6,0);
566 if (barrel == TRUE)
567 draw_one_field(16,7,0);
568 if (web == TRUE)
569 draw_one_field(4,5,0);
570 if (quickfire == TRUE)
571 draw_one_field(128,7,1);
572 if (fire_barrier == TRUE)
573 draw_one_field(32,anim_ticks % 4,2);
574 if (force_barrier == TRUE)
575 draw_one_field(64,anim_ticks % 4,2);
578 void draw_spec_items()
580 if (force_wall == TRUE)
581 draw_one_spec_item(2,0,1);
582 if (fire_wall == TRUE)
583 draw_one_spec_item(4,1,1);
584 if (antimagic == TRUE)
585 draw_one_spec_item(8,2,1);
586 if (scloud == TRUE)
587 draw_one_spec_item(16,3,1);
588 if (ice_wall == TRUE)
589 draw_one_spec_item(32,4,1);
590 if (blade_wall == TRUE)
591 draw_one_spec_item(64,5,1);
592 if (sleep_field == TRUE)
593 draw_one_spec_item(128,6,1);
597 void draw_sfx()
599 short q,r,i,flag;
600 location where_draw,loc;
601 RECT orig_rect = {0,0,28,36},source_rect;
603 if (PSD[306][2] > 0)
604 return;
606 for (q = 0; q < 9; q++)
607 for (r = 0; r < 9; r++)
609 where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4;
611 if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1)
612 || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1))
614 else if (sfx[where_draw.x][where_draw.y] != 0) {
615 for (i = 0; i < 8; i++) {
616 flag = s_pow(2,i);
617 if (sfx[where_draw.x][where_draw.y] & flag)
618 if (spot_seen[q][r] > 0) {
619 loc.x = q; loc.y = r;
620 source_rect = orig_rect;
621 OffsetRect(&source_rect,28 * i,36 * 3);
622 Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc,
623 1,0);
631 void draw_one_field(unsigned char flag,short source_x,short source_y)
633 short q,r;
634 location where_draw,loc;
635 RECT orig_rect = {0,0,28,36},source_rect;
637 for (q = 0; q < 9; q++)
638 for (r = 0; r < 9; r++)
640 where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4;
642 if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1)
643 || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1))
645 else {
646 if (misc_i[where_draw.x][where_draw.y] & flag)
647 if (spot_seen[q][r] > 0) {
648 loc.x = q; loc.y = r;
649 source_rect = orig_rect;
650 OffsetRect(&source_rect,28 * source_x,36 * source_y);
651 Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc,
652 1,0);
653 if ((is_town()) && ((flag == 32) || (flag == 64)))
654 anim_onscreen = TRUE;
660 void draw_one_spec_item(unsigned char flag,short source_x,short source_y)
662 short q,r;
663 location where_draw,loc;
664 RECT orig_rect = {0,0,28,36},source_rect;
666 for (q = 0; q < 9; q++)
667 for (r = 0; r < 9; r++)
669 where_draw = center;where_draw.x += q - 4;where_draw.y += r - 4;
671 if ((where_draw.x < 0) || (where_draw.x > town_size[town_type] - 1)
672 || (where_draw.y < 0) || (where_draw.y > town_size[town_type] - 1))
674 else {
675 if (c_town.explored[where_draw.x][where_draw.y] & flag)
676 if (spot_seen[q][r] > 0) {
677 loc.x = q; loc.y = r;
678 source_rect = orig_rect;
679 OffsetRect(&source_rect,28 * source_x,36 * source_y);
680 Draw_Some_Item(fields_gworld,source_rect,terrain_screen_gworld,loc,
681 1,0);
689 void draw_party_symbol(short mode,location center)
690 // mode currently unused
692 RECT source_rect;
693 location target = {4,4};
694 short i = 0;
695 short dir_array[8] = {0,3,3,3,2,1,1,1};
697 if (can_draw_pcs == FALSE)
698 return;
699 if (party_toast() == TRUE)
700 return;
701 if ((is_town()) && (c_town.p_loc.x > 70))
702 return;
703 if (overall_mode == 36) {
704 target.x += c_town.p_loc.x - center.x;
705 target.y += c_town.p_loc.y - center.y;
709 if ((party.in_boat < 0) && (party.in_horse < 0)) {
710 i = first_active_pc();
711 source_rect = get_party_template_rect(i,(party.direction < 4) ? 0 : 1);
713 // now wedge in bed graphic
714 if ((is_town()) && (scenario.ter_types[t_d.terrain[c_town.p_loc.x][c_town.p_loc.y]].picture == 143))
715 draw_one_terrain_spot((short) target.x,(short) target.y,10230,0);
716 else Draw_Some_Item(party_template_gworld, source_rect, terrain_screen_gworld, target, 1, 0);
718 else if (party.in_boat >= 0) {
719 source_rect = boat_rects[dir_array[party.direction]];
720 OffsetRect(&source_rect,61,0);
721 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, target, 1, 0);
723 else {
724 source_rect = boat_rects[(party.direction < 4) ? 0 : 1];
725 OffsetRect(&source_rect,61,0);
726 OffsetRect(&source_rect,0,74);
727 Draw_Some_Item(mixed_gworld, source_rect, terrain_screen_gworld, target, 1, 0);
733 /* Input terrain currently trying to draw. Get back Rect in terrain template containing
734 desired pixmap, or Rect to darkness if desired map not present */
735 RECT get_terrain_template_rect (unsigned char type_wanted)
737 RECT store_rect;
738 short i,j;
739 short picture_wanted;
741 picture_wanted = terrain_pic[type_wanted];
743 if (picture_wanted >= 400)
744 return return_item_rect(picture_wanted + 700);
745 return return_item_rect(picture_wanted);
748 RECT return_item_rect(short wanted)
750 RECT orig_rect = {0,0,28,36};
751 short i;
752 if (wanted < 50) {
753 OffsetRect(&orig_rect,28 * (wanted % 10),36 * (wanted / 10));
754 return orig_rect;
756 for (i = 50; i < STORED_GRAPHICS; i++)
757 if (which_g_stored[i] == wanted) {
758 OffsetRect(&orig_rect,28 * (i % 10),36 * (i / 10));
759 return orig_rect;
761 // oops it's not here. better try to add it.
762 add_one_graphic(wanted);
763 for (i = 50; i < STORED_GRAPHICS; i++)
764 if (which_g_stored[i] == wanted) {
765 OffsetRect(&orig_rect,28 * (i % 10),36 * (i / 10));
766 return orig_rect;
768 // oh well.
769 if (gave_no_g_error == FALSE) {
770 give_error("Blades of Exile doesn't have enough memory to show all the graphics needed. Some things may look like cave floor. The game can still be played safely - restarting isn't necessary.","",0);
771 gave_no_g_error = TRUE;
773 return orig_rect;
776 // Give the position of the monster graphic in the picture resource
777 // Will store monsters the same in Exile's II and III
778 RECT get_monster_rect (unsigned char type_wanted,short mode)
779 //short mode; // 0 - left 1 - right 2 - both
781 RECT store_rect;
782 short i;
784 i = (short) type_wanted;
785 i = i % 20;
786 store_rect.top = 0 + BITMAP_HEIGHT * (i % 10) ;
787 store_rect.bottom = store_rect.top + BITMAP_HEIGHT;
788 store_rect.left = 0 + (i / 10) * BITMAP_WIDTH * 2 + ((mode != 1) ? 0 : 28);
789 store_rect.right = store_rect.left + BITMAP_WIDTH * ((mode == 2) ? 2 : 1);
791 return store_rect;
794 // Give the position of the monster graphic in the template in memory
795 RECT get_monster_template_rect (unsigned char type_wanted,short mode,short which_part)
796 //mode; // 0 - left 1 - right +10 - combat mode
798 RECT store_rect = {0,0,28,36};
799 short i,j;
800 short picture_wanted;
801 short adj = 0;
803 if (mode >= 10) {adj = 2000; mode -= 10;}
804 picture_wanted = get_monst_picnum(type_wanted);
805 if (picture_wanted >= 1000)
806 return store_rect;
807 picture_wanted = m_pic_index[picture_wanted] + which_part;
808 return return_item_rect(300 + picture_wanted + (300 * mode) + adj);
812 // Returns rect for drawing an item, if num < 25, rect is in big item template,
813 // otherwise in small item template
814 RECT get_item_template_rect (short type_wanted)
816 RECT store_rect;
818 if (type_wanted < 45) {
819 store_rect.top = (type_wanted / 5) * BITMAP_HEIGHT;
820 store_rect.bottom = store_rect.top + BITMAP_HEIGHT;
821 store_rect.left = (type_wanted % 5) * BITMAP_WIDTH;
822 store_rect.right = store_rect.left + BITMAP_WIDTH;
824 else {
825 store_rect.top = (type_wanted / 10) * 18;
826 store_rect.bottom = store_rect.top + 18;
827 store_rect.left = (type_wanted % 10) * 18;
828 store_rect.right = store_rect.left + 18;
831 return store_rect;
835 unsigned char get_t_t(char x,char y) // returns terrain type at where
837 if (is_out())
838 return out[x][y];
839 else if (is_town())
840 return t_d.terrain[x][y];
841 else return combat_terrain[x][y];
844 // Is this is subterranean fluid that gets shore plopped down on it?
845 Boolean is_fluid(unsigned char ter_type)////
848 if (((ter_type >= 71) && (ter_type <= 76)) || (ter_type == 90))
849 return TRUE;
851 return FALSE;
854 // Is this is subterranean beach that gets shore plopped down next to it?
855 Boolean is_shore(unsigned char ter_type)////
857 if (is_fluid(ter_type) == TRUE)
858 return FALSE;
859 if (ter_type == 77)
860 return FALSE;
861 if (ter_type == 90)
862 return FALSE;
863 /* if (ter_type == 240)
864 return FALSE;
865 if ((ter_type >= 117) && (ter_type <= 131))
866 return FALSE;
867 if ((ter_type >= 193) && (ter_type <= 207))
868 return FALSE; */
869 return TRUE;
872 // These two functions used to determine wall round-cornering
873 Boolean is_wall(unsigned char ter_type)////
875 short pic;
877 pic = scenario.ter_types[ter_type].picture;
879 if ((pic >= 88) && (pic <= 120))
880 return TRUE;
882 return FALSE;
884 Boolean is_ground(unsigned char ter_type)
886 short pic;
888 pic = scenario.ter_types[ter_type].picture;
889 if ((pic >= 0) && (pic <= 87))
890 return TRUE;
891 if ((pic >= 121) && (pic <= 122))
892 return TRUE;
893 if ((pic >= 179) && (pic <= 208))
894 return TRUE;
895 if ((pic >= 211) && (pic <= 212))
896 return TRUE;
897 if ((pic >= 215) && (pic <= 246))
898 return TRUE;
900 return FALSE;
903 void make_town_trim(short mode)
904 //mode; // 0 - town 1 - outdoor combat
906 location where;
907 short store_mode;
909 store_mode = overall_mode;
910 overall_mode = (mode == 0) ? 1 : 10;
911 for (where.x = 0; where.x < town_size[town_type]; where.x++)
912 for (where.y = 0; where.y < town_size[town_type]; where.y++)
913 town_trim[where.x][where.y] = add_trim_to_array(where,
914 (mode == 0) ? t_d.terrain[where.x][where.y] : combat_terrain[where.x][where.y]);
915 for (where.x = 0; where.x < town_size[town_type]; where.x++)
916 for (where.y = 0; where.y < town_size[town_type]; where.y++) {
917 if (town_trim[where.x][where.y] & 1)
918 town_trim[where.x][where.y] &= 125;
919 if (town_trim[where.x][where.y] & 4)
920 town_trim[where.x][where.y] &= 245;
921 if (town_trim[where.x][where.y] & 10)
922 town_trim[where.x][where.y] &= 215;
923 if (town_trim[where.x][where.y] & 64)
924 town_trim[where.x][where.y] &= 95;
926 overall_mode = store_mode;
929 void make_out_trim()
931 location where;
932 short store_mode;
934 store_mode = overall_mode;
935 overall_mode = 0;
937 for (where.x = 0; where.x < 96; where.x++)
938 for (where.y = 0; where.y < 96; where.y++)
939 out_trim[where.x][where.y] = add_trim_to_array(where,out[where.x][where.y]);
940 for (where.x = 0; where.x < 96; where.x++)
941 for (where.y = 0; where.y < 96; where.y++) {
942 if (out_trim[where.x][where.y] & 1)
943 out_trim[where.x][where.y] &= 125;
944 if (out_trim[where.x][where.y] & 4)
945 out_trim[where.x][where.y] &= 245;
946 if (out_trim[where.x][where.y] & 10)
947 out_trim[where.x][where.y] &= 215;
948 if (out_trim[where.x][where.y] & 64)
949 out_trim[where.x][where.y] &= 95;
951 overall_mode = store_mode;
955 char add_trim_to_array(location where,unsigned char ter_type)
957 Boolean at_top = FALSE,at_bot = FALSE,at_left = FALSE,at_right = FALSE;
958 unsigned char store,store2,store3,store1;
959 char to_return = 0;
961 if (where.x == 0)
962 at_left = TRUE;
963 if (where.y == 0)
964 at_top = TRUE;
965 if ((overall_mode == 0) || (overall_mode == 35)) {
966 if (where.x == 95)
967 at_right = TRUE;
968 if (where.y == 95)
969 at_bot = TRUE;
971 else {
972 if (where.x == town_size[town_type] - 1)
973 at_right = TRUE;
974 if (where.y == town_size[town_type] - 1)
975 at_bot = TRUE;
978 // Set up trim for fluids
979 if (is_fluid(ter_type) == TRUE) {
980 if (at_left == FALSE) {
981 store = get_t_t(where.x - 1,where.y);
982 if (is_shore(store) == TRUE)
983 to_return |= 64;
985 if (at_right == FALSE) {
986 store = get_t_t(where.x + 1,where.y);
987 if (is_shore(store) == TRUE)
988 to_return |= 4;
990 if (at_top == FALSE) {
991 store = get_t_t(where.x,where.y - 1);
992 if (is_shore(store) == TRUE)
993 to_return |= 1;
995 if (at_bot == FALSE) {
996 store = get_t_t(where.x,where.y + 1);
997 if (is_shore(store) == TRUE)
998 to_return |= 16;
1000 if ((at_left == FALSE) && (at_top == FALSE)) {
1001 store = get_t_t(where.x - 1,where.y - 1);
1002 if (is_shore(store) == TRUE)
1003 to_return |= 128;
1005 if ((at_right == FALSE) && (at_top == FALSE)) {
1006 store = get_t_t(where.x + 1,where.y + 1);
1007 if (is_shore(store) == TRUE)
1008 to_return |= 8;
1010 if ((at_right == FALSE) && (at_bot == FALSE)) {
1011 store = get_t_t(where.x + 1,where.y - 1);
1012 if (is_shore(store) == TRUE)
1013 to_return |= 2;
1015 if ((at_left == FALSE) && (at_bot == FALSE)) {
1016 store = get_t_t(where.x - 1,where.y + 1);
1017 if (is_shore(store) == TRUE)
1018 to_return |= 32;
1022 return to_return;
1025 Boolean pt_in_rect(location loc,RECT rect)
1027 if ((loc.x >= rect.left) && (loc.x <= rect.right) && (loc.y >= rect.top) && (loc.y <= rect.bottom))
1028 return TRUE;
1029 return FALSE;
1032 // Sees if party has seen a monster of this sort, updates menu and gives
1033 // special messages as necessary
1034 void check_if_monst_seen(unsigned char m_num)
1036 // this rule has been changed
1037 return;
1038 if (party.m_seen[m_num] == 0) {
1039 party.m_seen[m_num] = 1;
1040 switch (m_num) {
1043 adjust_monst_menu();
1047 // Time for some chicanery
1048 // The how to item for monsters will be 599
1049 // item 600 + i will mean monster i.
1050 void adjust_monst_menu()
1052 short i,j,monst_pos = 0;
1053 char monst_name[256];
1054 HMENU menu,big_menu;
1055 short total_added = 0;
1057 if (in_startup_mode == TRUE)
1058 return;
1060 big_menu = GetMenu(mainPtr);
1061 menu = GetSubMenu(big_menu,5);
1062 if (menu == NULL)
1063 return;
1064 for (i = 0; i < 256; i++) {
1065 on_monst_menu[i] = -1;
1067 for (i = 1; i < 256; i++)
1068 if ((i == 1) || (party.m_seen[i] > 0)) {
1069 on_monst_menu[monst_pos] = i;
1070 monst_pos++;
1073 for (i = 0; i < 256; i++) {
1074 DeleteMenu(menu,600 + i,MF_BYCOMMAND);
1076 for (i = 0; i < 256; i++)
1077 if (on_monst_menu[i] >= 0) {
1078 //GetIndString(monst_name, 2,on_monst_menu[i]);
1079 sprintf((char *) monst_name,"%s",data_store2->scen_item_list.monst_names[on_monst_menu[i]]); if ((total_added % 24 == 0) && (total_added > 0))
1080 InsertMenu(menu,599,MF_MENUBREAK | MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + i, monst_name);
1081 else InsertMenu(menu,599,MF_BYCOMMAND | MF_ENABLED | MF_STRING, 600 + i, monst_name);
1082 total_added++;
1086 void frame_space(location where,short mode,short width,short height)
1087 //mode; // 0 - red 1 - green
1089 location where_put;
1090 RECT to_frame;
1091 HDC hdc;
1092 // DWORD color[3] = {RGB(255,0,0),RGB(0,255,0),RGB(0,0,255)};
1093 DWORD color[3] = {PALETTEINDEX(43),PALETTEINDEX(2),PALETTEINDEX(22)};
1094 HPEN hpen,old_pen;
1095 COLORREF x[3] = {RGB(200,0,0),RGB(102,255,0),RGB(200,0,200)};//RGB(204,204,204);
1096 UINT c;
1098 if (point_onscreen(center,where) == FALSE)
1099 return;
1101 where_put.x = 4 + where.x - center.x;
1102 where_put.y = 4 + where.y - center.y;
1104 to_frame.top = 18 + where_put.y * 36;
1105 to_frame.left = 18 + where_put.x * 28;
1106 to_frame.bottom = 54 + where_put.y * 36 + 36 * (height - 1);
1107 to_frame.right = 46 + where_put.x * 28 + 28 * (width - 1);
1109 hdc = GetDC(mainPtr);
1110 SetViewportOrg(hdc,ulx,uly);
1111 SelectPalette(hdc,hpal,0);
1112 c = GetNearestPaletteIndex(hpal,x[mode]);
1113 // hbrush = CreateSolidBrush(PALETTEINDEX(c));//59));
1114 // hpen = CreatePen(PS_SOLID,1,color[mode]);
1115 hpen = CreatePen(PS_SOLID,1,PALETTEINDEX(c));
1116 old_pen = SelectObject(hdc,hpen);
1117 // RoundRect(hdc,to_frame.left,to_frame.top,
1118 // to_frame.right,to_frame.bottom, 5,5);
1119 MoveTo(hdc,to_frame.left,to_frame.top);
1120 LineTo(hdc,to_frame.right,to_frame.top);
1121 LineTo(hdc,to_frame.right,to_frame.bottom);
1122 LineTo(hdc,to_frame.left,to_frame.bottom);
1123 LineTo(hdc,to_frame.left,to_frame.top);
1124 SelectObject(hdc,old_pen);
1125 fry_dc(mainPtr,hdc);
1126 DeleteObject(hpen);